Bläddra i källkod

Add 'qcom/opensource/audio-kernel/' from commit '0ee387dfadf349618494d6f82ec8cec796ebef70'

git-subtree-dir: qcom/opensource/audio-kernel
git-subtree-mainline: 99ab089c55d053bccf6a2df0bacbc6f6dbd20d33
git-subtree-split: 0ee387dfadf349618494d6f82ec8cec796ebef70
Change-Id:
repo: https://git.codelinaro.org/clo/la/platform/vendor/qcom/opensource/audio-kernel-ar
tag: AUDIO.LA.9.0.r1-07400-lanai.0
David Wronek 8 månader sedan
förälder
incheckning
91a8910061
100 ändrade filer med 76825 tillägg och 0 borttagningar
  1. 43 0
      qcom/opensource/audio-kernel/Android.bp
  2. 575 0
      qcom/opensource/audio-kernel/Android.mk
  3. 50 0
      qcom/opensource/audio-kernel/BUILD.bazel
  4. 153 0
      qcom/opensource/audio-kernel/EnableBazel.mk
  5. 1 0
      qcom/opensource/audio-kernel/Kbuild
  6. 25 0
      qcom/opensource/audio-kernel/Makefile
  7. 96 0
      qcom/opensource/audio-kernel/Makefile.am
  8. 24 0
      qcom/opensource/audio-kernel/NOTICE
  9. 347 0
      qcom/opensource/audio-kernel/asoc/Kbuild
  10. 6 0
      qcom/opensource/audio-kernel/asoc/Makefile
  11. 1704 0
      qcom/opensource/audio-kernel/asoc/auto_spf_dummy.c
  12. 59 0
      qcom/opensource/audio-kernel/asoc/bengal-port-config.h
  13. 1631 0
      qcom/opensource/audio-kernel/asoc/bengal.c
  14. 330 0
      qcom/opensource/audio-kernel/asoc/codecs/Kbuild
  15. 6 0
      qcom/opensource/audio-kernel/asoc/codecs/Makefile
  16. 120 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/Kbuild
  17. 21 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-api.h
  18. 833 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-clsh.c
  19. 107 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-clsh.h
  20. 638 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-core.c
  21. 162 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-internal.h
  22. 283 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-irq.c
  23. 38 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-irq.h
  24. 1088 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-mbhc.c
  25. 63 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-mbhc.h
  26. 1608 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-reg-defaults.h
  27. 873 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-registers.h
  28. 102 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-regmap.c
  29. 166 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-routing.h
  30. 191 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-utils.c
  31. 14 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-utils.h
  32. 3611 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000.c
  33. 221 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000.h
  34. 32 0
      qcom/opensource/audio-kernel/asoc/codecs/aqt1000/pdata.h
  35. 773 0
      qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk-up.c
  36. 12 0
      qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk-up.h
  37. 341 0
      qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk.c
  38. 163 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/Kbuild
  39. 6 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/Makefile
  40. 844 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-registers.h
  41. 877 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-regmap.c
  42. 982 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-tables.c
  43. 172 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-utils.c
  44. 1621 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc.c
  45. 228 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc.h
  46. 768 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-clk-rsc.c
  47. 53 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-clk-rsc.h
  48. 89 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/internal.h
  49. 4310 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/rx-macro.c
  50. 3807 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/tx-macro.c
  51. 3324 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/va-macro.c
  52. 3362 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/wsa-macro.c
  53. 41 0
      qcom/opensource/audio-kernel/asoc/codecs/bolero/wsa-macro.h
  54. 484 0
      qcom/opensource/audio-kernel/asoc/codecs/cpe_cmi.h
  55. 158 0
      qcom/opensource/audio-kernel/asoc/codecs/cpe_err.h
  56. 105 0
      qcom/opensource/audio-kernel/asoc/codecs/csra66x0/Kbuild
  57. 1525 0
      qcom/opensource/audio-kernel/asoc/codecs/csra66x0/csra66x0.c
  58. 231 0
      qcom/opensource/audio-kernel/asoc/codecs/csra66x0/csra66x0.h
  59. 106 0
      qcom/opensource/audio-kernel/asoc/codecs/ep92/Kbuild
  60. 2002 0
      qcom/opensource/audio-kernel/asoc/codecs/ep92/ep92.c
  61. 159 0
      qcom/opensource/audio-kernel/asoc/codecs/ep92/ep92.h
  62. 672 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-bt-swr.c
  63. 183 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/Kbuild
  64. 6 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/Makefile
  65. 112 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/internal.h
  66. 785 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.c
  67. 52 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.h
  68. 117 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-comp.c
  69. 27 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-comp.h
  70. 1426 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-registers.h
  71. 1401 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-regmap.c
  72. 5026 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c
  73. 1245 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-tables.c
  74. 2175 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c
  75. 172 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-utils.c
  76. 2677 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c
  77. 4206 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c
  78. 22 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.h
  79. 4100 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c
  80. 22 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.h
  81. 1571 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc.c
  82. 394 0
      qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc.h
  83. 393 0
      qcom/opensource/audio-kernel/asoc/codecs/msm-cdc-pinctrl.c
  84. 932 0
      qcom/opensource/audio-kernel/asoc/codecs/msm-cdc-supply.c
  85. 946 0
      qcom/opensource/audio-kernel/asoc/codecs/msm_hdmi_codec_rx.c
  86. 92 0
      qcom/opensource/audio-kernel/asoc/codecs/msm_stub.c
  87. 120 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/Kbuild
  88. 168 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/internal.h
  89. 22 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/pm2250-spmi.h
  90. 128 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/pm2250_spmi.c
  91. 1163 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-mbhc.c
  92. 67 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-mbhc.h
  93. 126 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-registers.h
  94. 165 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-regmap.c
  95. 112 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-tables.c
  96. 2819 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur.c
  97. 19 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur.h
  98. 444 0
      qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur_slave.c
  99. 937 0
      qcom/opensource/audio-kernel/asoc/codecs/swr-dmic.c
  100. 17 0
      qcom/opensource/audio-kernel/asoc/codecs/swr-dmic.h

+ 43 - 0
qcom/opensource/audio-kernel/Android.bp

@@ -0,0 +1,43 @@
+headers_src = [
+    "include/uapi/audio/*/**/*.h",
+]
+
+audio_headers_out = [
+    "linux/msm_audio.h",
+    "sound/audio_effects.h",
+    "sound/audio_slimslave.h",
+    "sound/devdep_params.h",
+    "sound/lsm_params.h",
+    "sound/msmcal-hwdep.h",
+    "sound/voice_params.h",
+    "sound/wcd-dsp-glink.h",
+    "linux/msm_audio_calibration.h",
+]
+
+audio_kernel_headers_verbose = "--verbose "
+genrule {
+    name: "qti_generate_audio_kernel_headers",
+    tools: ["headers_install.sh",
+            "unifdef"
+    ],
+    tool_files: [
+         "audio_kernel_headers.py",
+    ],
+    srcs: headers_src,
+    cmd: "python3 -u $(location audio_kernel_headers.py) " +
+        audio_kernel_headers_verbose +
+        "--header_arch arm64 " +
+        "--gen_dir $(genDir) " +
+        "--audio_include_uapi $(locations include/uapi/audio/*/**/*.h) " +
+        "--unifdef $(location unifdef) " +
+        "--headers_install $(location headers_install.sh)",
+    out: audio_headers_out,
+}
+
+cc_library_headers {
+    name: "qti_audio_kernel_uapi",
+    generated_headers: ["qti_generate_audio_kernel_headers"],
+    export_generated_headers: ["qti_generate_audio_kernel_headers"],
+    vendor: true,
+    recovery_available: true
+}

+ 575 - 0
qcom/opensource/audio-kernel/Android.mk

@@ -0,0 +1,575 @@
+# Android makefile for audio kernel modules
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(call is-board-platform-in-list,taro),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_WAIPIO=m
+endif
+
+ifeq ($(call is-board-platform-in-list,kalama),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_KALAMA=m
+endif
+
+ifeq ($(call is-board-platform-in-list,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
+ifeq ($(call is-board-platform-in-list,holi blair),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_HOLI=m
+endif
+
+ifeq ($(call is-board-platform-in-list,pineapple cliffs volcano),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_PINEAPPLE=m
+endif
+
+ifeq ($(call is-board-platform-in-list,volcano),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_VOLCANO=m
+endif
+
+ifeq ($(call is-board-platform-in-list,pitti),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_PITTI=m
+endif
+
+ifeq ($(ENABLE_AUDIO_LEGACY_TECHPACK),true)
+include $(call all-subdir-makefiles)
+LOCAL_PATH := vendor/qcom/opensource/audio-kernel
+endif
+
+# Build/Package only in case of supported target
+ifeq ($(call is-board-platform-in-list,taro kalama bengal pineapple cliffs pitti holi blair gen4 msmnile niobe volcano), true)
+
+# This makefile is only for DLKM
+ifneq ($(findstring vendor,$(LOCAL_PATH)),)
+
+ifneq ($(findstring opensource,$(LOCAL_PATH)),)
+	AUDIO_BLD_DIR := $(abspath .)/vendor/qcom/opensource/audio-kernel
+endif # opensource
+
+include $(AUDIO_BLD_DIR)/EnableBazel.mk
+DLKM_DIR := $(TOP)/device/qcom/common/dlkm
+
+
+###########################################################
+# This is set once per LOCAL_PATH, not per (kernel) module
+KBUILD_OPTIONS := AUDIO_ROOT=$(AUDIO_BLD_DIR)
+
+# We are actually building audio.ko here, as per the
+# requirement we are specifying <chipset>_audio.ko as LOCAL_MODULE.
+# This means we need to rename the module to <chipset>_audio.ko
+# after audio.ko is built.
+KBUILD_OPTIONS += MODNAME=audio_dlkm
+KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
+KBUILD_OPTIONS += $(AUDIO_SELECT)
+
+ifneq ($(call is-board-platform-in-list, bengal holi blair msmnile gen4),true)
+KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,msm-ext-disp-module-symvers)/Module.symvers
+endif
+
+ifeq ($(call is-board-platform-in-list, gen4 msmnile),true)
+KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y
+ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), gen4_gvm msmnile_gvmq))
+KBUILD_OPTIONS +=CONFIG_SND_SOC_GVM=y
+endif
+endif
+
+AUDIO_SRC_FILES := \
+	$(wildcard $(LOCAL_PATH)/*) \
+	$(wildcard $(LOCAL_PATH)/*/*) \
+	$(wildcard $(LOCAL_PATH)/*/*/*) \
+	$(wildcard $(LOCAL_PATH)/*/*/*/*)
+
+ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), gen4_gvm msmnile_gvmq))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := stub_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### ASOC MACHINE ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := machine_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/spf_machine_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### LPASS-CDC CODEC  ###########################
+else
+########################### dsp ################################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := q6_notifier_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/q6_notifier_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := spf_core_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/spf_core_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := audpkt_ion_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/audpkt_ion_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := gpr_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := ipc/gpr_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := audio_pkt_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := ipc/audio_pkt_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := q6_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/q6_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := adsp_loader_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/adsp_loader_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+
+########################### ipc  ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := audio_prm_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/audio_prm_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := q6_pdr_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := dsp/q6_pdr_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+
+############################ soc ###############################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := soc/pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := swr_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := soc/swr_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := swr_ctrl_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := soc/swr_ctrl_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := snd_event_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := soc/snd_event_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################  ASOC CODEC ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd_core_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd_core_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := mbhc_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/mbhc_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+ifneq ($(call is-board-platform-in-list, bengal holi blair pitti),true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := swr_dmic_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/swr_dmic_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd9xxx_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd9xxx_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+ifneq ($(call is-board-platform-in-list, bengal holi blair),true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := swr_haptics_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/swr_haptics_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := stub_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### ASOC MACHINE ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := machine_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/machine_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### LPASS-CDC CODEC  ###########################
+ifneq ($(call is-board-platform-in-list, bengal holi blair),true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_wsa2_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_wsa2_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_wsa_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_wsa_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_va_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_va_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_tx_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_tx_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := lpass_cdc_rx_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/lpass-cdc/lpass_cdc_rx_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+
+ifneq ($(call is-board-platform-in-list, pitti),true)
+########################### WSA884x CODEC  ###########################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wsa884x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wsa884x/wsa884x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+
+########################### WSA883x CODEC  ###########################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wsa883x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wsa883x/wsa883x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+
+########################### WCD937x CODEC  ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd937x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd937x/wcd937x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd937x_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd937x/wcd937x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### WCD938x CODEC  ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd938x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd938x/wcd938x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd938x_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd938x/wcd938x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### WCD939x CODEC  ################################
+endif
+
+ifneq ($(call is-board-platform-in-list, niobe pitti),true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd939x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd939x/wcd939x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd939x_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd939x/wcd939x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd9378_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd9378/wcd9378_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd9378_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd9378/wcd9378_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+ifeq ($(call is-board-platform-in-list, pitti),true)
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wsa881x_analog_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wsa881x_analog_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd9378_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd9378/wcd9378_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd9378_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd9378/wcd9378_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+###########################################################
+ifeq ($(AUDIO_DLKM_ENABLE), true)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := hdmi_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/hdmi_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+LOCAL_REQUIRED_MODULES    := msm-ext-disp-module-symvers
+LOCAL_ADDITIONAL_DEPENDENCIES := $(call intermediates-dir-for,DLKM,msm-ext-disp-module-symvers)/Module.symvers
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+endif
+
+ifeq ($(call is-board-platform-in-list, bengal holi blair),true)
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := bolero_cdc_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/bolero/bolero_cdc_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := va_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/bolero/va_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := tx_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/bolero/tx_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := rx_macro_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/bolero/rx_macro_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wsa881x_analog_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wsa881x_analog_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+########################### WCD937x CODEC  ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd937x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd937x/wcd937x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd937x_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd937x/wcd937x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+
+ifeq ($(call is-board-platform-in-list,holi blair),true)
+########################### WCD938x CODEC  ################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd938x_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd938x/wcd938x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(AUDIO_SRC_FILES)
+LOCAL_MODULE              := wcd938x_slave_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := asoc/codecs/wcd938x/wcd938x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+endif
+##########################################################
+endif # DLKM check
+endif # supported target check
+endif

+ 50 - 0
qcom/opensource/audio-kernel/BUILD.bazel

@@ -0,0 +1,50 @@
+package(
+    default_visibility = [
+        "//visibility:public",
+    ],
+)
+
+load("//build/kernel/kleaf:kernel.bzl", "ddk_headers")
+
+ddk_headers(
+    name = "audio_common_headers",
+    hdrs = glob([
+        "include/asoc/*.h",
+        "include/bindings/*.h",
+        "include/dsp/*.h",
+        "include/ipc/*.h",
+        "include/soc/*.h"
+    ]),
+    includes = ["include"]
+)
+ddk_headers(
+    name = "audio_uapi_headers",
+    hdrs = glob([
+        "include/uapi/audio/**/*.h"
+    ]),
+    includes = ["include/uapi/audio"]
+)
+ddk_headers(
+    name = "audio_src_headers",
+    hdrs = glob([
+        "asoc/**/*.h",
+        "dsp/**/*.h",
+        "ipc/**/*.h",
+        "soc/**/*.h"
+    ])
+)
+ddk_headers(
+    name = "audio_configs",
+    hdrs = glob([
+        "config/*.h"
+    ]),
+    includes = ["config"]
+)
+ddk_headers(
+    name = "audio_headers",
+    hdrs = [":audio_common_headers",  ":audio_uapi_headers", ":audio_src_headers", ":audio_configs"]
+)
+
+load(":build/audio_target.bzl", "define_audio_target")
+
+define_audio_target()

+ 153 - 0
qcom/opensource/audio-kernel/EnableBazel.mk

@@ -0,0 +1,153 @@
+ifeq ($(call is-board-platform-in-list,pineapple cliffs volcano),true)
+LOCAL_MODULE_DDK_BUILD := true
+
+LOCAL_MODULE_DDK_SUBTARGET_REGEX := "$(TARGET_BOARD_PLATFORM)_audio.*"
+
+LOCAL_MODULE_KO_DIRS := dsp/q6_notifier_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/spf_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audpkt_ion_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/gpr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/audio_pkt_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/adsp_loader_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audio_prm_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_pdr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_ctrl_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/snd_event_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/mbhc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/swr_dmic_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9xxx_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/swr_haptics_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/machine_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa2_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_va_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_tx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_rx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa884x/wsa884x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa883x/wsa883x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd939x/wcd939x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd939x/wcd939x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/hdmi_dlkm.ko
+endif
+
+ifeq ($(call is-board-platform-in-list,pitti),true)
+LOCAL_MODULE_DDK_BUILD := true
+
+LOCAL_MODULE_DDK_SUBTARGET_REGEX := "audio.*"
+
+LOCAL_MODULE_KO_DIRS := dsp/q6_notifier_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/spf_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audpkt_ion_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/gpr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/audio_pkt_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/adsp_loader_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audio_prm_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_pdr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_ctrl_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/snd_event_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/mbhc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9xxx_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/swr_haptics_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/machine_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa2_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_va_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_tx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_rx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa881x_analog_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/hdmi_dlkm.ko
+endif
+
+ifeq ($(call is-board-platform-in-list,blair),true)
+LOCAL_MODULE_DDK_BUILD := true
+
+LOCAL_MODULE_DDK_SUBTARGET_REGEX := "audio.*"
+
+LOCAL_MODULE_KO_DIRS := dsp/q6_notifier_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/spf_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audpkt_ion_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/gpr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/audio_pkt_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/adsp_loader_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audio_prm_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_pdr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_ctrl_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/snd_event_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/mbhc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9xxx_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/machine_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/bolero/bolero_cdc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/bolero/va_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/bolero/tx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/bolero/rx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa881x_analog_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_slave_dlkm.ko
+endif
+
+ifeq ($(call is-board-platform-in-list, niobe),true)
+LOCAL_MODULE_DDK_BUILD := true
+
+LOCAL_MODULE_DDK_SUBTARGET_REGEX := "audio.*"
+
+LOCAL_MODULE_KO_DIRS := dsp/q6_notifier_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/spf_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audpkt_ion_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/gpr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += ipc/audio_pkt_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/adsp_loader_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/audio_prm_dlkm.ko
+LOCAL_MODULE_KO_DIRS += dsp/q6_pdr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/pinctrl_lpi_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/swr_ctrl_dlkm.ko
+LOCAL_MODULE_KO_DIRS += soc/snd_event_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd_core_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/mbhc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/swr_dmic_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9xxx_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/swr_haptics_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/stub_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/machine_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa2_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_wsa_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_va_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_tx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/lpass-cdc/lpass_cdc_rx_macro_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa884x/wsa884x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wsa883x/wsa883x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd937x/wcd937x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd938x/wcd938x_slave_dlkm.ko
+LOCAL_MODULE_KO_DIRS += asoc/codecs/hdmi_dlkm.ko
+endif

+ 1 - 0
qcom/opensource/audio-kernel/Kbuild

@@ -0,0 +1 @@
+obj-y := dsp/ ipc/ soc/ asoc/ asoc/codecs/ asoc/codecs/lpass-cdc/ asoc/codecs/bolero/ asoc/codecs/wcd939x/ asoc/codecs/wsa884x/ asoc/codecs/wcd938x/ asoc/codecs/wsa883x/ asoc/codecs/wcd937x/ asoc/codecs/wcd9378/

+ 25 - 0
qcom/opensource/audio-kernel/Makefile

@@ -0,0 +1,25 @@
+ifeq ($(TARGET_SUPPORT), monaco)
+KBUILD_OPTIONS := CONFIG_SND_SOC_AUTO=y
+KBUILD_OPTIONS += CONFIG_SND_SOC_SA7255=m
+KBUILD_OPTIONS += MODNAME=audio_dlkm
+endif
+
+ifeq ($(AUTO_GVM), yes)
+KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y
+KBUILD_OPTIONS += CONFIG_SND_SOC_GVM=y
+KBUILD_OPTIONS += MODNAME=audio_dlkm
+endif
+
+M=$(PWD)
+AUDIO_ROOT=$(KERNEL_SRC)/$(M)
+
+KBUILD_OPTIONS+=  AUDIO_ROOT=$(AUDIO_ROOT)
+
+all: modules
+
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean
+
+%:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
+

+ 96 - 0
qcom/opensource/audio-kernel/Makefile.am

@@ -0,0 +1,96 @@
+AUDIO_ROOT=$(PWD)
+UAPI_OUT=$(PWD)
+HEADER_INSTALL_DIR=$(KERNEL_SRC)/scripts
+KERNEL_BINARY_DIR=$(KERNEL_SRC)/../kernel-build-artifacts
+
+KBUILD_OPTIONS := AUDIO_ROOT=$(PWD)
+KBUILD_OPTIONS += MODNAME=audio
+KBUILD_OPTIONS += UAPI_OUT=$(PWD)
+
+AUDIO_KERNEL_HEADERS_PATH1 =  $(shell ls ./include/uapi/audio/linux/*.h)
+AUDIO_KERNEL_HEADERS_PATH2 =  $(shell ls ./include/uapi/audio/linux/mfd/wcd9xxx/*.h)
+AUDIO_KERNEL_HEADERS_PATH3 =  $(shell ls ./include/uapi/audio/sound/*.h)
+
+ifeq ($(TARGET_SUPPORT),qcs40x)
+KBUILD_OPTIONS += CONFIG_ARCH_QCS405=y
+endif
+ifeq ($(TARGET_SUPPORT), sdmsteppe)
+KBUILD_OPTIONS += CONFIG_ARCH_SM6150=y
+endif
+ifeq ($(TARGET_SUPPORT), sdxlemur))
+KBUILD_OPTIONS += CONFIG_ARCH_SDXLEMUR=y
+endif
+
+subdir-ccflags-y += -I$(AUDIO_ROOT)/include/uapi/
+
+subdir-ccflags-y += -I$(AUDIO_ROOT)/include/uapi/
+
+obj-m := ipc/
+obj-m += dsp/
+obj-m += soc/
+obj-m += asoc/
+obj-m += asoc/codecs/
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sdmsteppe sdxlemur))
+obj-m += asoc/codecs/wcd934x/
+endif
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), qcs40x))
+obj-m += asoc/codecs/bolero/
+obj-m += asoc/codecs/csra66x0/
+obj-m += asoc/codecs/ep92/
+endif
+ifeq ($(TARGET_SUPPORT), sdmsteppe)
+obj-m += asoc/codecs/bolero/
+obj-m += asoc/codecs/wcd937x/
+endif
+
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa8155 sa8155ivi sa6155 sa8195 qtiquingvm))
+KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y
+obj-m := ipc/
+obj-m += dsp/
+obj-m += asoc/
+obj-m += asoc/codecs/
+obj-m += soc/
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa8155 sa8155ivi sa8195 qtiquingvm))
+KBUILD_OPTIONS += CONFIG_SND_SOC_SA8155=m
+endif
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa6155))
+KBUILD_OPTIONS += CONFIG_SND_SOC_SA6155=m
+endif
+endif
+
+define PROCESS_HEADERS
+	$(foreach name,$(1),$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(2)$(name) $(3)$(name)))
+endef
+
+all:
+	$(shell rm -fr $(shell pwd)/soc/core.h)
+	$(shell ln -s $(KERNEL_SRC)/drivers/pinctrl/core.h $(shell pwd)/soc/core.h)
+	$(shell rm -fr $(shell pwd)/include/soc/internal.h)
+	$(shell ln -s $(KERNEL_SRC)/drivers/base/regmap/internal.h $(shell pwd)/include/soc/internal.h)
+	$(shell rm -fr $(shell pwd)/soc/pinctrl-utils.h)
+	$(shell ln -s $(KERNEL_SRC)/drivers/pinctrl/pinctrl-utils.h $(shell pwd)/soc/pinctrl-utils.h)
+	$(shell rm -fr $(shell pwd)/include/soc/qcom/secure_buffer.h)
+	$(shell ln -s $(KERNEL_SRC)/include/soc/qcom/secure_buffer.h $(shell pwd)/include/soc/qcom/secure_buffer.h)
+	$(shell mkdir $(shell pwd)/linux)
+	$(shell mkdir $(shell pwd)/sound)
+	$(shell mkdir $(shell pwd)/linux/mfd)
+	$(shell mkdir $(shell pwd)/linux/mfd/wcd9xxx)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/, $(UAPI_OUT)/linux/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/, $(UAPI_OUT)/linux/mfd/wcd9xxx/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/sound/*.h)), $(AUDIO_ROOT)/include/uapi/audio/sound/, $(UAPI_OUT)/sound/)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/sound)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd/wcd9xxx)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/, $(KERNEL_BINARY_DIR)/usr/include/audio/linux/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/, $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd/wcd9xxx/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/sound/*.h)), $(AUDIO_ROOT)/include/uapi/audio/sound/, $(KERNEL_BINARY_DIR)/usr/include/audio/sound/)
+	$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
+
+modules_install:
+	$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
+
+clean:
+	rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
+	rm -rf .tmp_versions

+ 24 - 0
qcom/opensource/audio-kernel/NOTICE

@@ -0,0 +1,24 @@
+Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 and
+only version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+________________________________________
+
+Copyright (C) 2008 Google, Inc.
+Copyright (C) 2008 HTC Corporation
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.

+ 347 - 0
qcom/opensource/audio-kernel/asoc/Kbuild

@@ -0,0 +1,347 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_GVM
+	    include $(AUDIO_ROOT)/config/gvmauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA7255
+		include $(AUDIO_ROOT)/config/sa7255auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa7255autoconf.h
+	endif
+
+else
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_SM8150), y)
+		ifdef CONFIG_SND_SOC_SA8155
+			include $(AUDIO_ROOT)/config/sa8155auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+		else
+			include $(AUDIO_ROOT)/config/sm8150auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+		endif
+	endif
+	ifeq ($(CONFIG_ARCH_SM6150), y)
+		ifdef CONFIG_SND_SOC_SA6155
+			include $(AUDIO_ROOT)/config/sa6155auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+		else
+			include $(AUDIO_ROOT)/config/sm6150auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+		endif
+	endif
+	ifeq ($(CONFIG_ARCH_TRINKET), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KONA), y)
+		include $(AUDIO_ROOT)/config/konaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/konaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_WAIPIO), y)
+		include $(AUDIO_ROOT)/config/waipioauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/waipioautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KALAMA), y)
+		include $(AUDIO_ROOT)/config/kalamaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/kalamaautoconf.h
+	endif
+	ifeq ($(BOARD_PLATFORM), pineapple)
+		include $(AUDIO_ROOT)/config/pineappleauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pineappleautoconf.h
+	endif
+	ifeq ($(BOARD_PLATFORM), cliffs)
+		include $(AUDIO_ROOT)/config/pineappleauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pineappleautoconf.h
+	endif
+	ifeq ($(BOARD_PLATFORM), volcano)
+		include $(AUDIO_ROOT)/config/volcanoauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/volcanoautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_PITTI), y)
+		include $(AUDIO_ROOT)/config/pittiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pittiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_LITO), y)
+		include $(AUDIO_ROOT)/config/litoauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KHAJE), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_HOLI), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_BLAIR), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
+		ifdef CONFIG_SND_SOC_SA8155
+			include $(AUDIO_ROOT)/config/sa8155auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+		else
+			include $(AUDIO_ROOT)/config/sm8150auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+		endif
+	endif
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_SDXLEMUR), y)
+		include $(AUDIO_ROOT)/config/sdxlemurauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sdxlemurautoconf.h
+	endif
+endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ ASoC Drivers ############
+
+MACHINE_OBJS += msm_common.o
+
+# for SM8150 sound card driver
+ifdef CONFIG_SND_SOC_SM8150
+	MACHINE_OBJS += sm8150.o
+	MACHINE_OBJS += machine_815x_init.o
+endif
+
+# for SM6150 sound card driver
+ifdef CONFIG_SND_SOC_SM6150
+	MACHINE_OBJS += sm6150.o
+	MACHINE_OBJS += machine_615x_init.o
+endif
+
+# For sa6155 sound card driver
+ifdef CONFIG_SND_SOC_SA6155
+	MACHINE_OBJS += sa6155.o
+endif
+
+# for qcs405 sound card driver
+ifdef CONFIG_SND_SOC_QCS405
+	MACHINE_OBJS += qcs405.o
+endif
+
+# for KONA sound card driver
+ifdef CONFIG_SND_SOC_KONA
+	MACHINE_OBJS += kona.o
+endif
+
+# for LAHAINA sound card driver
+ifdef CONFIG_SND_SOC_LAHAINA
+	MACHINE_OBJS += lahaina.o
+endif
+
+# for WAIPIO sound card driver
+ifdef CONFIG_SND_SOC_WAIPIO
+	MACHINE_OBJS += waipio.o
+endif
+
+# for KALAMA sound card driver
+ifdef CONFIG_SND_SOC_KALAMA
+	MACHINE_OBJS += kalama.o
+endif
+
+# for PINEAPPLE sound card driver
+ifdef CONFIG_SND_SOC_PINEAPPLE
+	MACHINE_OBJS += pineapple.o
+endif
+
+# for VOLCANO sound card driver
+ifdef CONFIG_SND_SOC_VOLCANO
+	MACHINE_OBJS += pineapple.o
+endif
+
+# for PITTI sound card driver
+ifdef CONFIG_SND_SOC_PITTI
+	MACHINE_OBJS += pineapple.o
+endif
+
+# for HOLI sound card driver
+ifdef CONFIG_SND_SOC_HOLI
+	MACHINE_OBJS += holi.o
+endif
+
+ifdef CONFIG_SND_SOC_LITO
+	MACHINE_OBJS += kona.o
+endif
+
+# for BENGAL sound card driver
+ifdef CONFIG_SND_SOC_BENGAL
+	MACHINE_OBJS += bengal.o
+endif
+
+# for sa8155 sound card driver
+ifdef CONFIG_SND_SOC_SA8155
+	MACHINE_OBJS += sa8155.o
+endif
+
+# for sa7255 sound card driver
+ifdef CONFIG_SND_SOC_SA7255_AUTO_SPF
+    SPF_MACHINE_OBJS += msm_common.o
+    SPF_MACHINE_OBJS += auto_spf_dummy.o
+endif
+
+ifdef CONFIG_SND_SOC_QDSP6V2
+	PLATFORM_OBJS += platform_init.o
+endif
+
+ifdef CONFIG_SND_SOC_SDX
+	MACHINE_OBJS += sdx-target.o
+endif
+
+ifdef CONFIG_SND_SOC_GVM_AUTO_SPF
+    SPF_MACHINE_OBJS += gvm_auto_spf_dummy.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	obj-y += codecs/
+endif
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_QDSP6V2) += platform_dlkm.o
+platform_dlkm-y := $(PLATFORM_OBJS)
+
+obj-$(CONFIG_SND_SOC_SM8150) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_SM6150) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_SA6155) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_QCS405) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_KONA) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_LAHAINA) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_WAIPIO) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_KALAMA) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_PINEAPPLE) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_VOLCANO) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_PITTI) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_HOLI) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_LITO) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_BENGAL) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_SA8155) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_SDX) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_GVM_AUTO_SPF) += spf_machine_dlkm.o
+spf_machine_dlkm-y := $(SPF_MACHINE_OBJS)
+
+obj-$(CONFIG_SND_SOC_SA7255_AUTO_SPF) += spf_machine_dlkm.o
+spf_machine_dlkm-y := $(SPF_MACHINE_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 6 - 0
qcom/opensource/audio-kernel/asoc/Makefile

@@ -0,0 +1,6 @@
+modules:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) VERBOSE=1
+modules_install:
+	$(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean

+ 1704 - 0
qcom/opensource/audio-kernel/asoc/auto_spf_dummy.c

@@ -0,0 +1,1704 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of_device.h>
+#include <linux/pm_qos.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <dsp/audio_notifier.h>
+#include <dsp/audio_prm.h>
+#include <soc/snd_event.h>
+#include "msm_dailink.h"
+#include "msm_common.h"
+
+
+#define DRV_NAME "spf-asoc-snd"
+#define DRV_PINCTRL_NAME "audio-pcm-pinctrl"
+
+#define __CHIPSET__ "SA8xx5 "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#ifdef CONFIG_MSM_COUPLED_SSR
+enum subsys_state {
+	SUBSYS_DOWN = 0,
+	SUBSYS_UP = 1
+};
+
+enum subsys_doamin {
+	SUBSYS_DOMAIN_ADSP = 0,
+	SUBSYS_DOMAIN_MDSP,
+	SUBSYS_DOMAIN_MAX
+};
+
+static struct dsps_state_t {
+	struct mutex lock;
+	enum subsys_state states[SUBSYS_DOMAIN_MAX];
+} dsps_state;
+#endif
+
+
+enum pinctrl_pin_state {
+	STATE_SLEEP = 0, /* All pins are in sleep state */
+	STATE_ACTIVE,  /* TDM = active */
+};
+
+struct msm_pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *sleep;
+	struct pinctrl_state *active;
+	enum pinctrl_pin_state curr_state;
+};
+
+static const char *const pin_states[] = {"sleep", "active"};
+
+static const char *const tdm_gpio_phandle[] = {"qcom,pri-tdm-gpios",
+						"qcom,sec-tdm-gpios",
+						"qcom,tert-tdm-gpios",
+						"qcom,quat-tdm-gpios",
+						"qcom,quin-tdm-gpios",
+						"qcom,sen-tdm-gpios",
+						"qcom,sep-tdm-gpios",
+						"qcom,oct-tdm-gpios",
+						"qcom,hsif0-tdm-gpios",
+						"qcom,hsif1-tdm-gpios",
+						"qcom,hsif2-tdm-gpios",
+						};
+
+static const char *const mclk_gpio_phandle[] = { "qcom,internal-mclk1-gpios" };
+
+enum {
+	TDM_PRI = 0,
+	TDM_SEC,
+	TDM_TERT,
+	TDM_QUAT,
+	TDM_QUIN,
+	TDM_SEN,
+	TDM_SEP,
+	TDM_OCT,
+	TDM_HSIF0,
+	TDM_HSIF1,
+	TDM_HSIF2,
+	TDM_INTERFACE_MAX,
+};
+
+enum {
+	IDX_PRIMARY_TDM_RX_0,
+	IDX_PRIMARY_TDM_TX_0,
+	IDX_SECONDARY_TDM_RX_0,
+	IDX_SECONDARY_TDM_TX_0,
+	IDX_TERTIARY_TDM_RX_0,
+	IDX_TERTIARY_TDM_TX_0,
+	IDX_QUATERNARY_TDM_RX_0,
+	IDX_QUATERNARY_TDM_TX_0,
+	IDX_QUINARY_TDM_RX_0,
+	IDX_QUINARY_TDM_TX_0,
+	IDX_SENARY_TDM_RX_0,
+	IDX_SENARY_TDM_TX_0,
+	IDX_SEPTENARY_TDM_RX_0,
+	IDX_SEPTENARY_TDM_TX_0,
+	IDX_OCTONARY_TDM_RX_0,
+	IDX_OCTONARY_TDM_TX_0,
+	IDX_HSIF0_TDM_RX_0,
+	IDX_HSIF0_TDM_TX_0,
+	IDX_HSIF1_TDM_RX_0,
+	IDX_HSIF1_TDM_TX_0,
+	IDX_HSIF2_TDM_RX_0,
+	IDX_HSIF2_TDM_TX_0,
+	IDX_HSIF3_TDM_RX_0,
+	IDX_HSIF3_TDM_TX_0,
+	IDX_HSIF4_TDM_RX_0,
+	IDX_HSIF4_TDM_TX_0,
+	IDX_QUATERNARY_TDM_RX_DUMMY_0,
+	IDX_QUATERNARY_TDM_TX_DUMMY_0,
+	IDX_QUINARY_TDM_RX_DUMMY_0,
+	IDX_QUINARY_TDM_TX_DUMMY_0,
+	IDX_GROUP_TDM_MAX,
+};
+
+enum msm_mclk_index {
+	MCLK_NONE = -1,
+	MCLK1 = 0,
+	MCLK_MAX,
+};
+
+enum msm_mclk_status {
+	MCLK_DISABLED = 0,
+	MCLK_ENABLED,
+};
+
+struct msm_mclk_conf {
+	struct mutex lock;
+	enum msm_mclk_status mclk_status;
+};
+
+struct tdm_conf {
+	struct mutex lock;
+	u32 ref_cnt;
+};
+
+struct msm_asoc_mach_data {
+	struct msm_common_pdata *common_pdata;
+	struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX];
+	struct msm_pinctrl_info pinctrl_info[TDM_INTERFACE_MAX];
+	bool mclk_used;
+	struct msm_pinctrl_info mclk_pinctrl_info[MCLK_MAX];
+	struct msm_mclk_conf mclk_conf[MCLK_MAX];
+	struct snd_pcm_hardware hw_params;
+};
+
+static struct platform_device *spdev;
+
+static struct clk_cfg internal_mclk[MCLK_MAX] = {
+	{
+		CLOCK_ID_MCLK_1,
+		IBIT_CLOCK_12_P288_MHZ,
+		CLOCK_ATTRIBUTE_COUPLE_NO,
+		CLOCK_ROOT_DEFAULT,
+	}
+};
+
+struct snd_soc_card sa8155_snd_soc_card_auto_msm = {
+	.name = "sa8155-adp-star-snd-card",
+};
+
+struct snd_soc_card sa8295_snd_soc_card_auto_msm = {
+	.name = "sa8295-adp-star-snd-card",
+};
+
+struct snd_soc_card sa8255_snd_soc_card_auto_msm = {
+	.name = "sa8255-adp-star-snd-card",
+};
+
+struct snd_soc_card sa7255_snd_soc_card_auto_msm = {
+	.name = "sa7255-adp-star-snd-card",
+};
+
+/* FIXME: it may various on different platform,
+ * better to move to dt configuration in future
+ */
+static enum msm_mclk_index msm_get_mclk_index(int intf_idx)
+{
+	switch (intf_idx) {
+/* for sa8255 */
+#ifdef CONFIG_SND_SOC_SA8255_AUTO_SPF
+	case TDM_HSIF2:
+		return MCLK1;
+#endif
+/* for sa7255 */
+#ifdef CONFIG_SND_SOC_SA7255_AUTO_SPF
+	case TDM_HSIF0:
+		return MCLK1;
+#endif
+
+	default: return MCLK_NONE;
+	}
+
+	return MCLK_NONE;
+}
+
+static int msm_tdm_get_intf_idx(u16 id)
+{
+	switch (id) {
+	case IDX_PRIMARY_TDM_RX_0:
+	case IDX_PRIMARY_TDM_TX_0:
+		return TDM_PRI;
+	case IDX_SECONDARY_TDM_RX_0:
+	case IDX_SECONDARY_TDM_TX_0:
+		return TDM_SEC;
+	case IDX_TERTIARY_TDM_RX_0:
+	case IDX_TERTIARY_TDM_TX_0:
+		return TDM_TERT;
+	case IDX_QUATERNARY_TDM_RX_0:
+	case IDX_QUATERNARY_TDM_TX_0:
+	case IDX_QUATERNARY_TDM_RX_DUMMY_0:
+	case IDX_QUATERNARY_TDM_TX_DUMMY_0:
+		return TDM_QUAT;
+	case IDX_QUINARY_TDM_RX_0:
+	case IDX_QUINARY_TDM_TX_0:
+	case IDX_QUINARY_TDM_RX_DUMMY_0:
+	case IDX_QUINARY_TDM_TX_DUMMY_0:
+		return TDM_QUIN;
+	case IDX_SENARY_TDM_RX_0:
+	case IDX_SENARY_TDM_TX_0:
+		return TDM_SEN;
+	case IDX_SEPTENARY_TDM_RX_0:
+	case IDX_SEPTENARY_TDM_TX_0:
+		return TDM_SEP;
+	case IDX_OCTONARY_TDM_RX_0:
+	case IDX_OCTONARY_TDM_TX_0:
+		return TDM_OCT;
+	case IDX_HSIF0_TDM_RX_0:
+	case IDX_HSIF0_TDM_TX_0:
+		return TDM_HSIF0;
+	case IDX_HSIF1_TDM_RX_0:
+	case IDX_HSIF1_TDM_TX_0:
+		return TDM_HSIF1;
+	case IDX_HSIF2_TDM_RX_0:
+	case IDX_HSIF2_TDM_TX_0:
+		return TDM_HSIF2;
+	case IDX_HSIF3_TDM_RX_0:
+	case IDX_HSIF3_TDM_TX_0:
+		return TDM_SEC; //muxed
+	case IDX_HSIF4_TDM_RX_0:
+	case IDX_HSIF4_TDM_TX_0:
+		return TDM_TERT; //muxed
+
+	default: return -EINVAL;
+	}
+}
+
+#ifdef CONFIG_MSM_COUPLED_SSR
+static void set_subsys_state_l(enum subsys_doamin subsys,
+				enum subsys_state state)
+{
+	dsps_state.states[subsys] = state;
+}
+
+static void set_combined_subsystem_state_l(enum subsys_state state)
+{
+	int i;
+
+	for (i = 0; i < SUBSYS_DOMAIN_MAX; i++)
+		dsps_state.states[i] = state;
+}
+
+static enum subsys_state get_combined_dsps_state_l(void)
+{
+	int i;
+
+	for (i = 0; i < SUBSYS_DOMAIN_MAX; i++) {
+		if (!dsps_state.states[i])
+			return SUBSYS_DOWN;
+	}
+	return SUBSYS_UP;
+}
+
+static int modem_notifier_service_cb(struct notifier_block *this,
+			   unsigned long opcode, void *data)
+{
+	pr_info("%s: modem pdr service opcode 0x%lx\n", __func__, opcode);
+	switch (opcode) {
+	case AUDIO_NOTIFIER_SERVICE_DOWN:
+		mutex_lock(&dsps_state.lock);
+		if (get_combined_dsps_state_l() == SUBSYS_UP) {
+			set_combined_subsystem_state_l(SUBSYS_DOWN);
+			pr_info("%s: setting snd_card to ONLINE\n", __func__);
+			snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
+		}
+		mutex_unlock(&dsps_state.lock);
+		break;
+	case AUDIO_NOTIFIER_SERVICE_UP:
+		mutex_lock(&dsps_state.lock);
+		set_subsys_state_l(SUBSYS_DOMAIN_MDSP, SUBSYS_UP);
+		if (get_combined_dsps_state_l() == SUBSYS_UP) {
+			pr_info("%s: setting snd_card to ONLINE\n", __func__);
+			snd_card_notify_user(SND_CARD_STATUS_ONLINE);
+		}
+		mutex_unlock(&dsps_state.lock);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block modem_service_nb = {
+	.notifier_call  = modem_notifier_service_cb,
+	.priority = 0,
+};
+#endif
+
+static int auto_adsp_ssr_enable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+#ifdef CONFIG_MSM_COUPLED_SSR
+	mutex_lock(&dsps_state.lock);
+	set_subsys_state_l(SUBSYS_DOMAIN_ADSP, SUBSYS_UP);
+	if (get_combined_dsps_state_l() == SUBSYS_UP) {
+		dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+		snd_card_notify_user(SND_CARD_STATUS_ONLINE);
+	}
+	mutex_unlock(&dsps_state.lock);
+#else
+	dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+	snd_card_notify_user(SND_CARD_STATUS_ONLINE);
+#endif
+
+err:
+	return ret;
+}
+
+static void auto_adsp_ssr_disable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		return;
+	}
+
+#ifdef CONFIG_MSM_COUPLED_SSR
+	mutex_lock(&dsps_state.lock);
+	if (get_combined_dsps_state_l() == SUBSYS_UP) {
+		set_combined_subsystem_state_l(SUBSYS_DOWN);
+		dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
+		snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
+	}
+	mutex_unlock(&dsps_state.lock);
+#else
+	dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
+	snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
+#endif
+}
+
+static const struct snd_event_ops auto_adsp_ssr_ops = {
+	.enable = auto_adsp_ssr_enable,
+	.disable = auto_adsp_ssr_disable,
+};
+
+
+static int msm_audio_ssr_compare(struct device *dev, void *data)
+{
+	struct device_node *node = data;
+
+	dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
+		__func__, dev->of_node, node);
+	return (dev->of_node && dev->of_node == node);
+}
+
+static int msm_audio_adsp_ssr_register(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct snd_event_clients *ssr_clients = NULL;
+	struct device_node *node = NULL;
+	int ret = 0;
+	int i = 0;
+
+	for (i = 0; ; i++) {
+		node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
+		if (!node)
+			break;
+		snd_event_mstr_add_client(&ssr_clients,
+					msm_audio_ssr_compare, node);
+	}
+
+	ret = snd_event_master_register(dev, &auto_adsp_ssr_ops,
+					ssr_clients, NULL);
+	if (!ret)
+		snd_event_notify(dev, SND_EVENT_UP);
+
+	return ret;
+}
+
+static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
+				enum pinctrl_pin_state new_state)
+{
+	int ret = 0;
+	int curr_state = 0;
+
+	if (pinctrl_info == NULL) {
+		pr_err("%s: pinctrl info is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (pinctrl_info->pinctrl == NULL) {
+		pr_err("%s: pinctrl handle is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	curr_state = pinctrl_info->curr_state;
+	pinctrl_info->curr_state = new_state;
+	pr_debug("%s: curr_state = %s new_state = %s\n", __func__,
+		pin_states[curr_state], pin_states[pinctrl_info->curr_state]);
+
+	if (curr_state == pinctrl_info->curr_state) {
+		pr_err("%s: pin already in same state\n", __func__);
+		goto err;
+	}
+
+	if (curr_state != STATE_SLEEP &&
+		pinctrl_info->curr_state != STATE_SLEEP) {
+		pr_err("%s: pin state is already active, cannot switch\n",
+			__func__);
+		ret = -EIO;
+		goto err;
+	}
+	switch (pinctrl_info->curr_state) {
+	case STATE_ACTIVE:
+		ret = pinctrl_select_state(pinctrl_info->pinctrl,
+					pinctrl_info->active);
+		if (ret) {
+			pr_err("%s: state select to active failed with %d\n",
+				__func__, ret);
+			ret = -EIO;
+			goto err;
+		}
+		break;
+	case STATE_SLEEP:
+		ret = pinctrl_select_state(pinctrl_info->pinctrl,
+					pinctrl_info->sleep);
+		if (ret) {
+			pr_err("%s: state select to sleep failed with %d\n",
+				__func__, ret);
+			ret = -EIO;
+			goto err;
+		}
+		break;
+	default:
+		pr_err("%s: pin state is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+err:
+	return ret;
+}
+
+
+static int msm_mclk_disable(struct snd_soc_card *card,
+		enum msm_mclk_index index)
+{
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int ret = 0;
+
+	if (!card) {
+		pr_err("%s: failed to get snd card!\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = snd_soc_card_get_drvdata(card);
+	if (!pdata) {
+		pr_err("%s: no pdata\n", __func__);
+		return -EINVAL;
+	}
+	if (!pdata->mclk_used) {
+		pr_info("%s: mclk is not used\n", __func__);
+		return 0;
+	}
+
+	mutex_lock(&pdata->mclk_conf[index].lock);
+	pinctrl_info = &pdata->mclk_pinctrl_info[index];
+	if (pinctrl_info && pinctrl_info->pinctrl) {
+		ret = msm_set_pinctrl(pinctrl_info, STATE_SLEEP);
+		if (ret != 0) {
+			pr_err("%s: set pin state to sleep for mclk[%d], failed with %d\n",
+				__func__, index, ret);
+		}
+		pinctrl_info->curr_state = STATE_SLEEP;
+	}
+
+	if (pdata->mclk_conf[index].mclk_status == MCLK_ENABLED) {
+		ret = audio_prm_set_lpass_clk_cfg(&internal_mclk[index], 0);
+		if (ret < 0) {
+			pr_err("%s: audio_prm_set_lpass_clk_cfg failed to disable mclk[%d], err:%d\n",
+				__func__, index, ret);
+		}
+		pdata->mclk_conf[index].mclk_status = MCLK_DISABLED;
+	} else {
+		pr_info("%s: mclk[%d] already disabled\n", __func__, index);
+	}
+	mutex_unlock(&pdata->mclk_conf[index].lock);
+	return ret;
+}
+
+static int msm_mclk_enable(struct snd_soc_card *card,
+		enum msm_mclk_index index)
+{
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int ret = 0;
+
+	if (!card) {
+		pr_err("%s: failed to get snd card!\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = snd_soc_card_get_drvdata(card);
+	if (!pdata) {
+		pr_err("%s: no pdata\n", __func__);
+		return -EINVAL;
+	}
+	if (!pdata->mclk_used) {
+		pr_info("%s: mclk is not used\n", __func__);
+		return 0;
+	}
+
+	mutex_lock(&pdata->mclk_conf[index].lock);
+	if (pdata->mclk_conf[index].mclk_status == MCLK_DISABLED) {
+		ret = audio_prm_set_lpass_clk_cfg(&internal_mclk[index], 1);
+		if (ret < 0) {
+			pr_err("%s: audio_prm_set_lpass_clk_cfg failed to enable mclk[%d], err:%d\n",
+				__func__, index, ret);
+		} else {
+			pdata->mclk_conf[index].mclk_status = MCLK_ENABLED;
+		}
+	} else {
+		pr_info("%s: mclk[%d] already enabled\n", __func__, index);
+	}
+
+	pinctrl_info = &pdata->mclk_pinctrl_info[index];
+	if (pinctrl_info && pinctrl_info->pinctrl) {
+		ret = msm_set_pinctrl(pinctrl_info, STATE_ACTIVE);
+		if (ret != 0) {
+			pr_err("%s: set pin state to active for mclk[%d], failed with %d\n",
+				__func__, index, ret);
+		}
+		pinctrl_info->curr_state = STATE_ACTIVE;
+	}
+	mutex_unlock(&pdata->mclk_conf[index].lock);
+	return ret;
+}
+
+static int tdm_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct tdm_conf *intf_conf = NULL;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int ret_pinctrl = 0;
+	int index, mclk_index;
+
+	if (!dai_link->no_pcm)
+		snd_soc_set_runtime_hwparams(substream, &pdata->hw_params);
+
+	index = msm_tdm_get_intf_idx(dai_link->id);
+	if (index < 0) {
+		ret = -EINVAL;
+		pr_err("%s: DAI link id (%d) out of range\n",
+			__func__, dai_link->id);
+		goto err;
+	}
+
+	if (pdata->mclk_used) {
+		mclk_index = msm_get_mclk_index(index);
+		if (mclk_index != MCLK_NONE)
+			msm_mclk_enable(card, mclk_index);
+	}
+	/*
+	 * Mutex protection in case the same TDM
+	 * interface using for both TX and RX so
+	 * that the same clock won't be enable twice.
+	 */
+	intf_conf = &pdata->tdm_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (++intf_conf->ref_cnt == 1) {
+		pinctrl_info = &pdata->pinctrl_info[index];
+		if (pinctrl_info->pinctrl) {
+			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+						STATE_ACTIVE);
+			if (ret_pinctrl)
+				pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
+					__func__, ret_pinctrl);
+		}
+	}
+	mutex_unlock(&intf_conf->lock);
+
+err:
+	return ret;
+}
+
+static void tdm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct tdm_conf *intf_conf = NULL;
+	int ret_pinctrl = 0;
+	int index, mclk_index;
+
+	pr_debug("%s: substream = %s, stream = %d\n", __func__,
+		substream->name, substream->stream);
+
+	index = msm_tdm_get_intf_idx(dai_link->id);
+	if (index < 0) {
+		pr_err("%s: DAI link id (%d) out of range\n",
+			__func__, dai_link->id);
+		return;
+	}
+
+	if (pdata->mclk_used) {
+		mclk_index = msm_get_mclk_index(index);
+		if (mclk_index != MCLK_NONE)
+			msm_mclk_disable(card, mclk_index);
+	}
+
+	intf_conf = &pdata->tdm_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (--intf_conf->ref_cnt == 0) {
+		pinctrl_info = &pdata->pinctrl_info[index];
+		if (pinctrl_info->pinctrl) {
+			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+							STATE_SLEEP);
+			if (ret_pinctrl)
+				pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
+					__func__, ret_pinctrl);
+		}
+	}
+	mutex_unlock(&intf_conf->lock);
+}
+
+static const struct snd_soc_ops tdm_be_ops = {
+	.startup = tdm_snd_startup,
+	.shutdown = tdm_snd_shutdown
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_common_dai_links[] = {
+/* BackEnd DAI Links */
+{
+	.name = "LPASS_BE_AUXPCM_RX_DUMMY",
+	.stream_name = "AUXPCM-LPAIF-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_PRIMARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(lpass_be_auxpcm_rx_dummy),
+},
+{
+	.name = "LPASS_BE_AUXPCM_TX_DUMMY",
+	.stream_name = "AUXPCM-LPAIF-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_PRIMARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(lpass_be_auxpcm_tx_dummy),
+},
+{
+	.name = "SEC_TDM_RX_0",
+	.stream_name = "TDM-LPAIF-RX-SECONDARY",
+	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SECONDARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(sec_tdm_rx_0),
+},
+{
+	.name = "SEC_TDM_TX_0",
+	.stream_name = "TDM-LPAIF-TX-SECONDARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SECONDARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(sec_tdm_tx_0),
+},
+{
+	.name = "TERT_TDM_RX_0",
+	.stream_name = "TDM-LPAIF-RX-TERTIARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_TERTIARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(tert_tdm_rx_0),
+},
+{
+	.name = "TERT_TDM_TX_0",
+	.stream_name = "TDM-LPAIF-TX-TERTIARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_TERTIARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(tert_tdm_tx_0),
+},
+{
+	.name = "QUAT_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_RXTX-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUATERNARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(quat_tdm_rx_0),
+},
+{
+	.name = "QUAT_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_RXTX-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUATERNARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(quat_tdm_tx_0),
+},
+{
+	.name = "QUIN_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_VA-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUINARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(quin_tdm_rx_0),
+},
+{
+	.name = "QUIN_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_VA-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUINARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(quin_tdm_tx_0),
+},
+{
+	.name = "SEN_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_WSA-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SENARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(sen_tdm_rx_0),
+},
+{
+	.name = "SEN_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_WSA-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SENARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(sen_tdm_tx_0),
+},
+{
+	.name = "SEP_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_AUD-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SEPTENARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(sep_tdm_rx_0),
+},
+{
+	.name = "SEP_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_AUD-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_SEPTENARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(sep_tdm_tx_0),
+},
+{
+	.name = "OCT_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_WSA2-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_OCTONARY_TDM_RX_0,
+	SND_SOC_DAILINK_REG(oct_tdm_rx_0),
+},
+{
+	.name = "OCT_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_WSA2-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_OCTONARY_TDM_TX_0,
+	SND_SOC_DAILINK_REG(oct_tdm_tx_0),
+},
+{
+	.name = "HS_IF0_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_SDR-RX-PRIMARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+		.id = IDX_HSIF0_TDM_RX_0,
+	SND_SOC_DAILINK_REG(hs_if0_tdm_rx_0),
+},
+{
+	.name = "HS_IF0_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_SDR-TX-PRIMARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF0_TDM_TX_0,
+	SND_SOC_DAILINK_REG(hs_if0_tdm_tx_0),
+},
+{
+	.name = "HS_IF1_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_SDR-RX-SECONDARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF1_TDM_RX_0,
+	SND_SOC_DAILINK_REG(hs_if1_tdm_rx_0),
+},
+{
+	.name = "HS_IF1_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_SDR-TX-SECONDARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF1_TDM_TX_0,
+	SND_SOC_DAILINK_REG(hs_if1_tdm_tx_0),
+},
+{
+	.name = "HS_IF2_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_SDR-RX-TERTIARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF2_TDM_RX_0,
+	SND_SOC_DAILINK_REG(hs_if2_tdm_rx_0),
+},
+{
+	.name = "HS_IF2_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_SDR-TX-TERTIARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF2_TDM_TX_0,
+	SND_SOC_DAILINK_REG(hs_if2_tdm_tx_0),
+},
+{
+	.name = "HS_IF3_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_SDR-RX-QUATERNARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF3_TDM_RX_0,
+	SND_SOC_DAILINK_REG(hs_if3_tdm_rx_0),
+},
+{
+	.name = "HS_IF3_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_SDR-TX-QUATERNARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF3_TDM_TX_0,
+	SND_SOC_DAILINK_REG(hs_if3_tdm_tx_0),
+},
+{
+	.name = "HS_IF4_TDM_RX_0",
+	.stream_name = "TDM-LPAIF_SDR-RX-QUINARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF4_TDM_RX_0,
+	SND_SOC_DAILINK_REG(hs_if4_tdm_rx_0),
+},
+{
+	.name = "HS_IF4_TDM_TX_0",
+	.stream_name = "TDM-LPAIF_SDR-TX-QUINARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_HSIF4_TDM_TX_0,
+	SND_SOC_DAILINK_REG(hs_if4_tdm_tx_0),
+},
+{
+	.name = "QUAT_TDM_RX_0_DUMMY",
+	.stream_name = "TDM-LPAIF-RX-QUATERNARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUATERNARY_TDM_RX_DUMMY_0,
+	SND_SOC_DAILINK_REG(quat_tdm_rx_0_dummy),
+},
+{
+	.name = "QUAT_TDM_TX_0_DUMMY",
+	.stream_name = "TDM-LPAIF-TX-QUATERNARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUATERNARY_TDM_TX_DUMMY_0,
+	SND_SOC_DAILINK_REG(quat_tdm_tx_0_dummy),
+},
+{
+	.name = "QUIN_TDM_RX_0_DUMMY",
+	.stream_name = "TDM-LPAIF-RX-QUINARY",
+	.dpcm_playback = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUINARY_TDM_RX_DUMMY_0,
+	SND_SOC_DAILINK_REG(quin_tdm_rx_0_dummy),
+},
+{
+	.name = "QUIN_TDM_TX_0_DUMMY",
+	.stream_name = "TDM-LPAIF-TX-QUINARY",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ops = &tdm_be_ops,
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	.id = IDX_QUINARY_TDM_TX_DUMMY_0,
+	SND_SOC_DAILINK_REG(quin_tdm_tx_0_dummy),
+},
+};
+
+
+static int msm_populate_dai_link_component_of_node(
+					struct snd_soc_card *card)
+{
+	int i, j, index, ret = 0;
+	struct device *cdev = card->dev;
+	struct snd_soc_dai_link *dai_link = card->dai_link;
+	struct device_node *np;
+
+	if (!cdev) {
+		pr_err("%s: Sound card device memory NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < card->num_links; i++) {
+		if (dai_link[i].platforms->of_node && dai_link[i].cpus->of_node)
+			continue;
+
+	/* populate platform_of_node for snd card dai links
+	 * Skip this part for dummy snd card
+	 */
+	if (0) {
+		if (dai_link[i].platforms->name &&
+			!dai_link[i].platforms->of_node) {
+			index = of_property_match_string(cdev->of_node,
+						"asoc-platform-names",
+						dai_link[i].platforms->name);
+			if (index < 0) {
+				pr_err("%s: No match found for platform name: %s\n index: %i cdev_of_node: %s\n",
+					__func__,
+					dai_link[i].platforms->name,
+					index,
+					cdev->of_node);
+				ret = index;
+				goto err;
+			}
+			np = of_parse_phandle(cdev->of_node, "asoc-platform",
+						index);
+			if (!np) {
+				pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
+					__func__, dai_link[i].platforms->name,
+					index);
+				ret = -ENODEV;
+				goto err;
+			}
+			dai_link[i].platforms->of_node = np;
+			dai_link[i].platforms->name = NULL;
+		}
+	}
+
+
+		/* populate cpu_of_node for snd card dai links */
+		if (dai_link[i].cpus->dai_name && !dai_link[i].cpus->of_node) {
+			index = of_property_match_string(cdev->of_node,
+						 "asoc-cpu-names",
+						 dai_link[i].cpus->dai_name);
+			pr_err("%s: retrieving cpu_of_node for %s\n",
+						__func__,
+						dai_link[i].cpus->dai_name);
+			if (index >= 0) {
+				np = of_parse_phandle(cdev->of_node, "asoc-cpu",
+						index);
+				if (!np) {
+					pr_err("%s: retrieving phandle for cpu dai %s failed\n",
+						__func__,
+						dai_link[i].cpus->dai_name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].cpus->of_node = np;
+				dai_link[i].cpus->dai_name = NULL;
+			}
+		}
+
+		/* populate codec_of_node for snd card dai links */
+		if (dai_link[i].num_codecs > 0) {
+			for (j = 0; j < dai_link[i].num_codecs; j++) {
+				if (dai_link[i].codecs[j].of_node ||
+						!dai_link[i].codecs[j].name)
+					continue;
+
+				index = of_property_match_string(cdev->of_node,
+						"asoc-codec-names",
+						dai_link[i].codecs[j].name);
+				if (index < 0)
+					continue;
+				np = of_parse_phandle(cdev->of_node,
+						      "asoc-codec",
+						      index);
+				if (!np) {
+					pr_err("%s: retrieving phandle for codec %s failed\n",
+						__func__,
+						dai_link[i].codecs[j].name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].codecs[j].of_node = np;
+				dai_link[i].codecs[j].name = NULL;
+			}
+		}
+	}
+
+err:
+	return ret;
+}
+
+static const struct of_device_id asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,sa8295-asoc-snd-adp-star",
+	  .data = "adp_star_codec"},
+	{ .compatible = "qcom,sa8155-asoc-snd-adp-star",
+	  .data = "adp_star_codec"},
+	{ .compatible = "qcom,sa8255-asoc-snd-adp-star",
+	  .data = "adp_star_codec"},
+	{ .compatible = "qcom,sa7255-asoc-snd-adp-star",
+	  .data = "adp_star_codec"},
+	{},
+};
+
+static const struct of_device_id audio_pinctrl_dummy_match[] = {
+	{ .compatible = "qcom,msm-pcm-pinctrl" },
+	{ },
+};
+
+static struct snd_soc_dai_link msm_auto_dai_links[
+			 ARRAY_SIZE(msm_common_dai_links)];
+
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+	struct snd_soc_card *card = NULL;
+	struct snd_soc_dai_link *dailink;
+	int total_links;
+	const struct of_device_id *match;
+
+	match = of_match_node(asoc_machine_of_match, dev->of_node);
+	if (!match) {
+		dev_err(dev, "%s: No DT match found for sound card\n",
+			__func__);
+		return NULL;
+	}
+
+	if (!strcmp(match->compatible, "qcom,sa8155-asoc-snd-adp-star"))
+		card = &sa8155_snd_soc_card_auto_msm;
+	else if (!strcmp(match->compatible, "qcom,sa8295-asoc-snd-adp-star"))
+		card = &sa8295_snd_soc_card_auto_msm;
+	else if (!strcmp(match->compatible, "qcom,sa8255-asoc-snd-adp-star"))
+		card = &sa8255_snd_soc_card_auto_msm;
+	else if (!strcmp(match->compatible, "qcom,sa7255-asoc-snd-adp-star"))
+		card = &sa7255_snd_soc_card_auto_msm;
+
+	total_links = ARRAY_SIZE(msm_common_dai_links);
+	memcpy(msm_auto_dai_links,
+		msm_common_dai_links,
+		sizeof(msm_common_dai_links));
+	dailink = msm_auto_dai_links;
+
+	if (card) {
+		card->dai_link = dailink;
+		card->num_links = total_links;
+	}
+
+	return card;
+}
+
+static int msm_get_hwparams(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	u32 pcm_info = 0;
+	u32 buffer_bytes_max = 0;
+	u32 periods_bytes[2] = {0};
+	u32 periods_count[2] = {0};
+	int ret = 0;
+
+	card = platform_get_drvdata(pdev);
+	if (!card) {
+		pr_err("%s: card is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+	pdata = snd_soc_card_get_drvdata(card);
+	if (!pdata) {
+		pr_err("%s: pdata is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,hw_pcm_info",
+			&pcm_info);
+	if (ret) {
+		pr_err("%s: read pcm info failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,hw_buffer_size_max",
+			&buffer_bytes_max);
+	if (ret) {
+		pr_err("%s: read buffer size max failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,hw_period_byte_size",
+			periods_bytes, 2);
+	if (ret) {
+		pr_err("%s: read period byte size failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,hw_period_count_size",
+			periods_count, 2);
+	if (ret) {
+		pr_err("%s: read period count size failed\n",
+			__func__);
+		return ret;
+	}
+
+	pdata->hw_params.info = pcm_info;
+	pdata->hw_params.buffer_bytes_max = buffer_bytes_max;
+	pdata->hw_params.period_bytes_min = periods_bytes[0];
+	pdata->hw_params.period_bytes_max = periods_bytes[1];
+	pdata->hw_params.periods_min = periods_count[0];
+	pdata->hw_params.periods_max = periods_count[1];
+
+	return ret;
+}
+
+struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card)
+{
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return NULL;
+
+	return pdata->common_pdata;
+}
+
+void msm_common_set_pdata(struct snd_soc_card *card,
+			  struct msm_common_pdata *common_pdata)
+{
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return;
+
+	pdata->common_pdata = common_pdata;
+}
+
+/*****************************************************************************
+ * pinctrl
+ *****************************************************************************/
+static void msm_release_pinctrl(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int i;
+
+	for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
+		pinctrl_info = &pdata->pinctrl_info[i];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
+	}
+}
+
+static void msm_release_mclk_pinctrl(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int i;
+
+	for (i = 0; i < MCLK_MAX; i++) {
+		pinctrl_info = &pdata->mclk_pinctrl_info[i];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
+	}
+}
+
+static int msm_get_pinctrl(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct pinctrl *pinctrl = NULL;
+	int i, j;
+	struct device_node *np = NULL;
+	struct platform_device *pdev_np = NULL;
+	int ret = 0;
+
+	for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
+		np = of_parse_phandle(pdev->dev.of_node,
+					tdm_gpio_phandle[i], 0);
+		if (!np) {
+			pr_debug("%s: device node %s is null\n",
+				__func__, tdm_gpio_phandle[i]);
+			continue;
+		}
+
+		pdev_np = of_find_device_by_node(np);
+		if (!pdev_np) {
+			pr_err("%s: platform device not found\n",
+				__func__);
+			continue;
+		}
+
+		pinctrl_info = &pdata->pinctrl_info[i];
+		if (pinctrl_info == NULL) {
+			pr_err("%s: pinctrl info is null\n",
+				__func__);
+			continue;
+		}
+
+		pinctrl = devm_pinctrl_get(&pdev_np->dev);
+		if (IS_ERR_OR_NULL(pinctrl)) {
+			pr_err("%s: fail to get pinctrl handle\n",
+				__func__);
+			goto err;
+		}
+		pinctrl_info->pinctrl = pinctrl;
+
+		/* get all the states handles from Device Tree */
+		pinctrl_info->sleep = pinctrl_lookup_state(pinctrl,
+							"default");
+		if (IS_ERR(pinctrl_info->sleep)) {
+			pr_err("%s: could not get sleep pin state\n",
+				__func__);
+			goto err;
+		}
+		pinctrl_info->active = pinctrl_lookup_state(pinctrl,
+							"active");
+		if (IS_ERR(pinctrl_info->active)) {
+			pr_err("%s: could not get active pin state\n",
+				__func__);
+			goto err;
+		}
+
+		/* Reset the TLMM pins to a sleep state */
+		ret = pinctrl_select_state(pinctrl_info->pinctrl,
+						pinctrl_info->sleep);
+		if (ret != 0) {
+			pr_err("%s: set pin state to sleep failed with %d\n",
+				__func__, ret);
+			ret = -EIO;
+			goto err;
+		}
+		pinctrl_info->curr_state = STATE_SLEEP;
+	}
+	return 0;
+
+err:
+	for (j = i; j >= 0; j--) {
+		pinctrl_info = &pdata->pinctrl_info[j];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
+	}
+	return -EINVAL;
+}
+
+static int msm_get_mclk_pinctrl(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct pinctrl *pinctrl = NULL;
+	int i, j;
+	struct device_node *np = NULL;
+	struct platform_device *pdev_np = NULL;
+	int ret = 0;
+
+	for (i = 0; i < MCLK_MAX; i++) {
+
+		np = of_parse_phandle(pdev->dev.of_node,
+			mclk_gpio_phandle[i],
+			0);
+		if (!np) {
+			pr_err("%s: device node %s is null\n",
+				__func__, mclk_gpio_phandle[i]);
+			continue;
+		}
+		pdev_np = of_find_device_by_node(np);
+		if (!pdev_np) {
+			pr_err("%s: platform device not found\n",
+				__func__);
+			continue;
+		}
+
+		pinctrl_info = &pdata->mclk_pinctrl_info[i];
+		if (pinctrl_info == NULL) {
+			pr_err("%s: pinctrl info is null\n",
+				__func__);
+			continue;
+		}
+
+		pinctrl = devm_pinctrl_get(&pdev_np->dev);
+		if (IS_ERR_OR_NULL(pinctrl)) {
+			pr_err("%s: fail to get pinctrl handle\n",
+				__func__);
+			goto err;
+		}
+		pinctrl_info->pinctrl = pinctrl;
+		/* get all the states handles from Device Tree */
+		pinctrl_info->sleep = pinctrl_lookup_state(pinctrl,
+			"default");
+		if (IS_ERR(pinctrl_info->sleep)) {
+			pr_err("%s: could not get sleep pin state\n",
+				__func__);
+			goto err;
+		}
+		pinctrl_info->active = pinctrl_lookup_state(pinctrl,
+			"active");
+		if (IS_ERR(pinctrl_info->active)) {
+			pr_err("%s: could not get active pin state\n",
+				__func__);
+			goto err;
+		}
+
+		/* Reset the mclk pins to a sleep state */
+		ret = pinctrl_select_state(pinctrl_info->pinctrl,
+						pinctrl_info->sleep);
+		if (ret != 0) {
+			pr_err("%s: set pin state to sleep failed with %d\n",
+				__func__, ret);
+			ret = -EIO;
+			goto err;
+		}
+		pinctrl_info->curr_state = STATE_SLEEP;
+	}
+	return 0;
+
+err:
+	for (j = i; j >= 0; j--) {
+		pinctrl_info = &pdata->mclk_pinctrl_info[i];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
+	}
+	return -EINVAL;
+}
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	int ret = 0;
+	const struct of_device_id *match = NULL;
+
+	dev_err(&pdev->dev, "%s: audio_reach\n",
+		__func__);
+
+	match = of_match_node(asoc_machine_of_match, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "%s: No DT match found for sound card\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No platform supplied from device tree\n");
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	card = populate_snd_card_dailinks(&pdev->dev);
+	if (!card) {
+		dev_err(&pdev->dev, "%s: Card uninitialized\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret) {
+		dev_err(&pdev->dev, "parse card name failed, err:%d\n",
+			ret);
+		pr_err("%s: parse card name failed with err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = msm_populate_dai_link_component_of_node(card);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+
+	if (ret == -EPROBE_DEFER) {
+		goto err;
+	} else if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		pr_err("snd_soc_register_card failed (%d)\n",
+			ret);
+		goto err;
+	}
+
+	msm_common_snd_init(pdev, card);
+
+	/* Parse pinctrl info from devicetree */
+	ret = msm_get_pinctrl(pdev);
+	if (!ret) {
+		pr_err("%s: pinctrl parsing successful\n",
+			__func__);
+	} else {
+		dev_dbg(&pdev->dev,
+			"%s: pinctrl parsing failed with %d\n",
+			__func__, ret);
+		ret = 0;
+	}
+
+	pdata->mclk_used = false;
+	if (strnstr(match->compatible, "sa8295",
+			sizeof(match->compatible)) ||
+		strnstr(match->compatible, "sa8255",
+			sizeof(match->compatible)) ||
+		strnstr(match->compatible, "sa7255",
+			sizeof(match->compatible))) {
+		/* get mclk pinctrl info from devicetree */
+		ret = msm_get_mclk_pinctrl(pdev);
+		if (!ret) {
+			pr_debug("%s: pinctrl mclk parsing successful\n",
+				__func__);
+			pdata->mclk_used = true;
+		} else {
+			dev_err(&pdev->dev,
+				"%s: pinctrl mclk parsing failed with %d\n",
+				__func__, ret);
+			ret = 0;
+		}
+	}
+
+	ret = msm_get_hwparams(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: hwparams get failed with %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	dev_info(&pdev->dev, "Sound card %s registered\n",
+		card->name);
+	pr_err("Sound card %s registered\n",
+		card->name);
+	spdev = pdev;
+
+#ifdef CONFIG_MSM_COUPLED_SSR
+	mutex_init(&dsps_state.lock);
+	ret = audio_notifier_register("auto_modem",
+					AUDIO_NOTIFIER_MODEM_ROOT_DOMAIN,
+					&modem_service_nb);
+	if (ret < 0)
+		pr_err("%s: Registration with modem PDR failed ret = %d\n",
+			__func__, ret);
+#endif
+
+	ret = msm_audio_adsp_ssr_register(&pdev->dev);
+	if (ret)
+		pr_err("%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+
+	snd_card_notify_user(SND_CARD_STATUS_ONLINE);
+	return 0;
+err:
+	msm_release_mclk_pinctrl(pdev);
+	msm_release_pinctrl(pdev);
+	return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+	msm_release_mclk_pinctrl(pdev);
+	msm_release_pinctrl(pdev);
+	snd_event_master_deregister(&pdev->dev);
+#ifdef CONFIG_MSM_COUPLED_SSR
+	audio_notifier_deregister("auto_modem");
+	mutex_destroy(&dsps_state.lock);
+#endif
+	return 0;
+}
+
+static int audio_pinctrl_dummy_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int audio_pinctrl_dummy_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver audio_pinctrl_dummy_driver = {
+	.driver = {
+		.name = DRV_PINCTRL_NAME,
+		.of_match_table = audio_pinctrl_dummy_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = audio_pinctrl_dummy_probe,
+	.remove = audio_pinctrl_dummy_remove,
+};
+
+static struct platform_driver asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = asoc_machine_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_asoc_machine_probe,
+	.remove = msm_asoc_machine_remove,
+};
+
+int __init auto_spf_init(void)
+{
+	snd_card_sysfs_init();
+	platform_driver_register(&audio_pinctrl_dummy_driver);
+	return platform_driver_register(&asoc_machine_driver);
+}
+
+void auto_spf_exit(void)
+{
+	platform_driver_unregister(&audio_pinctrl_dummy_driver);
+	platform_driver_unregister(&asoc_machine_driver);
+}
+
+module_init(auto_spf_init);
+module_exit(auto_spf_exit);
+
+MODULE_DESCRIPTION("ALSA SoC Machine Driver for SPF");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:" DRV_PINCTRL_NAME);
+MODULE_DEVICE_TABLE(of, asoc_machine_of_match);
+MODULE_DEVICE_TABLE(of, audio_pinctrl_dummy_match);

+ 59 - 0
qcom/opensource/audio-kernel/asoc/bengal-port-config.h

@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _BENGAL_PORT_CONFIG
+#define _BENGAL_PORT_CONFIG
+
+#include <soc/swr-common.h>
+
+/*
+ * Add port configuration in the format
+ *{ si, off1, off2, hstart, hstop, wd_len, bp_mode, bgp_ctrl, lane_ctrl}
+ */
+
+static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0},
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0},
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0,    0},
+};
+
+static struct port_params rx_frame_params_rouleur[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0},
+	{31, 1,  0,  0xFF, 0xFF, 4,    1,    0xFF, 0},
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0,    0},
+};
+
+
+static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0},
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0},
+	{7,  9,  0,  0xFF, 0xFF, 0xFF, 0xFF, 1,    0},
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 3,    0},
+};
+
+/* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
+static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX2 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX3 */
+};
+
+static struct swr_mstr_port_map sm_port_map[] = {
+	{VA_MACRO, SWR_UC0, tx_frame_params_default},
+	{RX_MACRO, SWR_UC0, rx_frame_params_default},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+};
+
+static struct swr_mstr_port_map sm_port_map_rouleur[] = {
+	{VA_MACRO, SWR_UC0, tx_frame_params_default},
+	{RX_MACRO, SWR_UC0, rx_frame_params_rouleur},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+};
+#endif /* _BENGAL_PORT_CONFIG */

+ 1631 - 0
qcom/opensource/audio-kernel/asoc/bengal.c

@@ -0,0 +1,1631 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of_device.h>
+#include <linux/soc/qcom/fsa4480-i2c.h>
+#include <linux/pm_qos.h>
+#include <linux/nvmem-consumer.h>
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <soc/snd_event.h>
+#include <dsp/audio_prm.h>
+#include <soc/swr-common.h>
+#include <soc/soundwire.h>
+#include "device_event.h"
+#include "asoc/msm-cdc-pinctrl.h"
+#include "asoc/wcd-mbhc-v2.h"
+#include "codecs/wcd937x/wcd937x-mbhc.h"
+#include "codecs/rouleur/rouleur-mbhc.h"
+#include "codecs/wsa881x-analog.h"
+#include "codecs/wcd937x/wcd937x.h"
+#include "codecs/rouleur/rouleur.h"
+#include "codecs/bolero/bolero-cdc.h"
+#include <bindings/audio-codec-port-types.h>
+#include "bengal-port-config.h"
+#include "msm-audio-defs.h"
+#include "msm_common.h"
+#include "msm_bengal_dailink.h"
+
+#define DRV_NAME "bengal-asoc-snd"
+#define __CHIPSET__ "BENGAL "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#define WCD9XXX_MBHC_DEF_RLOADS     5
+#define WCD9XXX_MBHC_DEF_BUTTONS    8
+#define DEV_NAME_STR_LEN            32
+#define WCD_MBHC_HS_V_MAX           1600
+
+#define WCN_CDC_SLIM_RX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX 3
+
+enum {
+	PRIM_MI2S = 0,
+	SEC_MI2S,
+	TERT_MI2S,
+	QUAT_MI2S,
+	MI2S_MAX,
+};
+
+struct msm_asoc_mach_data {
+	struct snd_info_entry *codec_root;
+	struct msm_common_pdata *common_pdata;
+	int usbc_en2_gpio; /* used by gpio driver API */
+	struct device_node *dmic01_gpio_p; /* used by pinctrl API */
+	struct device_node *dmic23_gpio_p; /* used by pinctrl API */
+	struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
+	atomic_t mi2s_gpio_ref_count[MI2S_MAX]; /* used by pinctrl API */
+	struct device_node *us_euro_gpio_p; /* used by pinctrl API */
+	struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
+	struct device_node *fsa_handle;
+	u32 wsa_max_devs;
+};
+
+static bool va_disable;
+static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime *rtd);
+static int msm_int_wsa_init(struct snd_soc_pcm_runtime *rtd);
+
+static bool is_initial_boot;
+static bool codec_reg_done;
+static struct snd_soc_card snd_soc_card_bengal_msm;
+static int dmic_0_1_gpio_cnt;
+static int dmic_2_3_gpio_cnt;
+
+static void *def_wcd_mbhc_cal(void);
+
+/*
+ * Need to report LINEIN
+ * if R/L channel impedance is larger than 5K ohm
+ */
+static struct wcd_mbhc_config wcd_mbhc_cfg = {
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.detect_extn_cable = true,
+	.mono_stero_detection = false,
+	.swap_gnd_mic = NULL,
+	.hs_ext_micbias = true,
+	.key_code[0] = KEY_MEDIA,
+	.key_code[1] = KEY_VOICECOMMAND,
+	.key_code[2] = KEY_VOLUMEUP,
+	.key_code[3] = KEY_VOLUMEDOWN,
+	.key_code[4] = 0,
+	.key_code[5] = 0,
+	.key_code[6] = 0,
+	.key_code[7] = 0,
+	.linein_th = 5000,
+	.moisture_en = false,
+	.mbhc_micbias = MIC_BIAS_2,
+	.anc_micbias = MIC_BIAS_2,
+	.enable_anc_mic_detect = false,
+	.moisture_duty_cycle_en = true,
+};
+
+static bool msm_usbc_swap_gnd_mic(struct snd_soc_component *component,
+				  bool active)
+{
+	struct snd_soc_card *card = component->card;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(card);
+
+	if (!pdata->fsa_handle)
+		return false;
+
+	return fsa4480_switch_event(pdata->fsa_handle, FSA_MIC_GND_SWAP);
+}
+
+static bool msm_swap_gnd_mic(struct snd_soc_component *component, bool active)
+{
+	int value = 0;
+	bool ret = false;
+	struct snd_soc_card *card;
+	struct msm_asoc_mach_data *pdata;
+
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return false;
+	}
+	card = component->card;
+	pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return false;
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		return msm_usbc_swap_gnd_mic(component, active);
+
+	/* if usbc is not defined, swap using us_euro_gpio_p */
+	if (pdata->us_euro_gpio_p) {
+		value = msm_cdc_pinctrl_get_state(
+				pdata->us_euro_gpio_p);
+		if (value)
+			msm_cdc_pinctrl_select_sleep_state(
+					pdata->us_euro_gpio_p);
+		else
+			msm_cdc_pinctrl_select_active_state(
+					pdata->us_euro_gpio_p);
+		dev_dbg(component->dev, "%s: swap select switch %d to %d\n",
+			__func__, value, !value);
+		ret = true;
+	}
+
+	return ret;
+}
+
+static int msm_dmic_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol, int event)
+{
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct snd_soc_component *component =
+					snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	u32 dmic_idx;
+	int *dmic_gpio_cnt;
+	struct device_node *dmic_gpio;
+	char  *wname;
+
+	wname = strpbrk(w->name, "0123");
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic_idx);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pdata = snd_soc_card_get_drvdata(component->card);
+
+	switch (dmic_idx) {
+	case 0:
+	case 1:
+		dmic_gpio_cnt = &dmic_0_1_gpio_cnt;
+		dmic_gpio = pdata->dmic01_gpio_p;
+		break;
+	case 2:
+	case 3:
+		dmic_gpio_cnt = &dmic_2_3_gpio_cnt;
+		dmic_gpio = pdata->dmic23_gpio_p;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d dmic_gpio_cnt %d\n",
+			__func__, event, dmic_idx, *dmic_gpio_cnt);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		(*dmic_gpio_cnt)++;
+		if (*dmic_gpio_cnt == 1) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		(*dmic_gpio_cnt)--;
+		if (*dmic_gpio_cnt == 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+					dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be de-activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+		break;
+	default:
+		pr_err("%s: invalid DAPM event %d\n", __func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Analog Mic1", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic2", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic3", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic0", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event),
+};
+
+static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
+{
+	unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
+	unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX]  = {159, 160, 161};
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	int ret = 0;
+
+	ret = snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+					   tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+	if (ret)
+                return ret;
+
+        msm_common_dai_link_init(rtd);
+	return ret;
+}
+
+static struct snd_info_entry *msm_snd_info_create_subdir(struct module *mod,
+                                const char *name,
+                                struct snd_info_entry *parent)
+{
+        struct snd_info_entry *entry;
+
+        entry = snd_info_create_module_entry(mod, name, parent);
+        if (!entry)
+                return NULL;
+        entry->mode = S_IFDIR | 0555;
+        if (snd_info_register(entry) < 0) {
+                snd_info_free_entry(entry);
+                return NULL;
+        }
+        return entry;
+}
+
+static void *def_wcd_mbhc_cal(void)
+{
+	void *wcd_mbhc_cal;
+	struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_high;
+
+	wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+				WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
+	if (!wcd_mbhc_cal)
+		return NULL;
+
+	WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->v_hs_max = WCD_MBHC_HS_V_MAX;
+	WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->num_btn = WCD_MBHC_DEF_BUTTONS;
+	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
+	btn_high = ((void *)&btn_cfg->_v_btn_low) +
+		(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+	btn_high[0] = 75;
+	btn_high[1] = 150;
+	btn_high[2] = 237;
+	btn_high[3] = 500;
+	btn_high[4] = 500;
+	btn_high[5] = 500;
+	btn_high[6] = 500;
+	btn_high[7] = 500;
+
+	return wcd_mbhc_cal;
+}
+
+static struct snd_soc_ops msm_common_be_ops = {
+        .hw_params = msm_common_snd_hw_params,
+        .startup = msm_common_snd_startup,
+        .shutdown = msm_common_snd_shutdown,
+};
+
+static struct snd_soc_dai_link msm_common_be_dai_links[] = {
+	/* Backend AFE DAI Links */
+#if 0
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32772",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32771",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32773",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	/* Incall Music 2 BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
+		.stream_name = "Voice2 Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32770",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+#endif
+	/* Proxy Tx BACK END DAI Link */
+	{
+		.name = LPASS_BE_RT_PROXY_PCM_TX,
+		.stream_name = LPASS_BE_RT_PROXY_PCM_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(proxy_tx),
+	},
+	/* Proxy Rx BACK END DAI Link */
+	{
+		.name = LPASS_BE_RT_PROXY_PCM_RX,
+		.stream_name = LPASS_BE_RT_PROXY_PCM_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(proxy_rx),
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_RX,
+		.stream_name = LPASS_BE_USB_AUDIO_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(usb_audio_rx),
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_TX,
+		.stream_name = LPASS_BE_USB_AUDIO_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(usb_audio_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_tdm_be_dai_links[] = {
+	{
+		.name = LPASS_BE_PRI_TDM_RX_0,
+		.stream_name = LPASS_BE_PRI_TDM_RX_0,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(pri_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_PRI_TDM_TX_0,
+		.stream_name = LPASS_BE_PRI_TDM_TX_0,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(pri_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_RX_0,
+		.stream_name = LPASS_BE_SEC_TDM_RX_0,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(sec_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_TX_0,
+		.stream_name = LPASS_BE_SEC_TDM_TX_0,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_RX_0,
+		.stream_name = LPASS_BE_TERT_TDM_RX_0,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(tert_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_TX_0,
+		.stream_name = LPASS_BE_TERT_TDM_TX_0,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_RX_0,
+		.stream_name = LPASS_BE_QUAT_TDM_RX_0,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(quat_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_TX_0,
+		.stream_name = LPASS_BE_QUAT_TDM_TX_0,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_tdm_tx_0),
+	},
+};
+
+static struct snd_soc_dai_link msm_wcn_btfm_be_dai_links[] = {
+	{
+		.name = LPASS_BE_SLIMBUS_7_RX,
+		.stream_name = LPASS_BE_SLIMBUS_7_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.init = &msm_wcn_init,
+		.ops = &msm_common_be_ops,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_7_rx),
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_7_TX,
+		.stream_name = LPASS_BE_SLIMBUS_7_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_7_tx),
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_8_TX,
+		.stream_name = LPASS_BE_SLIMBUS_8_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_8_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
+	{
+		.name = LPASS_BE_PRI_MI2S_RX,
+		.stream_name = LPASS_BE_PRI_MI2S_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(pri_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_PRI_MI2S_TX,
+		.stream_name = LPASS_BE_PRI_MI2S_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(pri_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_RX,
+		.stream_name = LPASS_BE_SEC_MI2S_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(sec_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_TX,
+		.stream_name = LPASS_BE_SEC_MI2S_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_RX,
+		.stream_name = LPASS_BE_TERT_MI2S_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(tert_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_TX,
+		.stream_name = LPASS_BE_TERT_MI2S_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_RX,
+		.stream_name = LPASS_BE_QUAT_MI2S_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(quat_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_TX,
+		.stream_name = LPASS_BE_QUAT_MI2S_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_mi2s_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
+	/* Primary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_PRI_AUXPCM_RX,
+		.stream_name = LPASS_BE_PRI_AUXPCM_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,// TODO for AUX
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_PRI_AUXPCM_TX,
+		.stream_name = LPASS_BE_PRI_AUXPCM_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(auxpcm_tx),
+	},
+	/* Secondary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_SEC_AUXPCM_RX,
+		.stream_name = LPASS_BE_SEC_AUXPCM_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,// TODO for AUX
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_SEC_AUXPCM_TX,
+		.stream_name = LPASS_BE_SEC_AUXPCM_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_auxpcm_tx),
+	},
+	/* Tertiary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_TERT_AUXPCM_RX,
+		.stream_name = LPASS_BE_TERT_AUXPCM_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,// TODO for AUX
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_TERT_AUXPCM_TX,
+		.stream_name = LPASS_BE_TERT_AUXPCM_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_auxpcm_tx),
+	},
+	/* Quaternary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_RX,
+		.stream_name = LPASS_BE_QUAT_AUXPCM_RX,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,// TODO for AUX
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_TX,
+		.stream_name = LPASS_BE_QUAT_AUXPCM_TX,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ops = &msm_common_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_auxpcm_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
+	/* RX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_0,
+		.stream_name = LPASS_BE_RX_CDC_DMA_RX_0,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(rx_dma_rx0),
+		.init = &msm_rx_tx_codec_init,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_1,
+		.stream_name = LPASS_BE_RX_CDC_DMA_RX_1,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(rx_dma_rx1),
+		.init = &msm_int_wsa_init,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_2,
+		.stream_name = LPASS_BE_RX_CDC_DMA_RX_2,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(rx_dma_rx2),
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_3,
+		.stream_name = LPASS_BE_RX_CDC_DMA_RX_3,
+		.playback_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(rx_dma_rx3),
+	},
+	/* TX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_3,
+		.stream_name = LPASS_BE_TX_CDC_DMA_TX_3,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(tx_dma_tx3),
+	},
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_4,
+		.stream_name = LPASS_BE_TX_CDC_DMA_TX_4,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(tx_dma_tx4),
+	},
+};
+
+static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_0,
+		.stream_name = LPASS_BE_VA_CDC_DMA_TX_0,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx0),
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_1,
+		.stream_name = LPASS_BE_VA_CDC_DMA_TX_1,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx1),
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_2,
+		.stream_name = LPASS_BE_VA_CDC_DMA_TX_2,
+		.capture_only = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx2),
+	},
+};
+
+static struct snd_soc_dai_link msm_bengal_dai_links[
+			ARRAY_SIZE(msm_common_be_dai_links) +
+			ARRAY_SIZE(msm_mi2s_be_dai_links) +
+			ARRAY_SIZE(msm_auxpcm_be_dai_links) +
+			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_va_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_wcn_btfm_be_dai_links) +
+			ARRAY_SIZE(msm_tdm_be_dai_links)];
+
+static int msm_populate_dai_link_component_of_node(
+					struct snd_soc_card *card)
+{
+	int i, j, index, ret = 0;
+	struct device *cdev = card->dev;
+	struct snd_soc_dai_link *dai_link = card->dai_link;
+	struct device_node *np = NULL;
+	int codecs_enabled = 0;
+	struct snd_soc_dai_link_component *codecs_comp = NULL;
+
+	if (!cdev) {
+		dev_err(cdev, "%s: Sound card device memory NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < card->num_links; i++) {
+		if (dai_link[i].init == NULL)
+			dai_link[i].init = &msm_common_dai_link_init;
+
+		/* populate codec_of_node for snd card dai links */
+		if (dai_link[i].num_codecs > 0) {
+			for (j = 0; j < dai_link[i].num_codecs; j++) {
+				if (dai_link[i].codecs[j].of_node ||
+					!dai_link[i].codecs[j].name)
+					continue;
+				index = of_property_match_string(cdev->of_node,
+						 "asoc-codec-names",
+						 dai_link[i].codecs[j].name);
+				if (index < 0)
+					continue;
+				np = of_parse_phandle(cdev->of_node, "asoc-codec",
+					      index);
+				if (!np) {
+					dev_err(cdev,
+					"%s: retrieving phandle for codec %s failed\n",
+					__func__, dai_link[i].codecs[j].name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].codecs[j].of_node = np;
+				dai_link[i].codecs[j].name = NULL;
+			}
+		}
+	}
+
+	/* In multi-codec scenario, check if codecs are enabled for this platform */
+	for (i = 0; i < card->num_links; i++) {
+		codecs_enabled = 0;
+		if (dai_link[i].num_codecs > 1) {
+			for (j = 0; j < dai_link[i].num_codecs; j++) {
+				if (!dai_link[i].codecs[j].of_node)
+					continue;
+				np = dai_link[i].codecs[j].of_node;
+				if (!of_device_is_available(np)) {
+					dev_dbg(cdev, "%s: codec is disabled: %s\n",
+						__func__,np->full_name);
+					dai_link[i].codecs[j].of_node = NULL;
+					continue;
+				}
+				codecs_enabled++;
+			}
+			if (codecs_enabled > 0 &&
+				codecs_enabled < dai_link[i].num_codecs) {
+					codecs_comp = devm_kzalloc(cdev,
+						sizeof(struct snd_soc_dai_link_component)
+						* codecs_enabled, GFP_KERNEL);
+					if (!codecs_comp) {
+						dev_err(cdev, "%s: %s dailink codec component alloc failed\n",
+							 __func__, dai_link[i].name);
+						ret = -ENOMEM;
+						goto err;
+					}
+					index = 0;
+					for (j = 0; j < dai_link[i].num_codecs; j++) {
+						if(dai_link[i].codecs[j].of_node) {
+							codecs_comp[index].of_node =
+								dai_link[i].codecs[j].of_node;
+							codecs_comp[index].dai_name =
+								dai_link[i].codecs[j].dai_name;
+							codecs_comp[index].name = NULL;
+							index++;
+						}
+					}
+					dai_link[i].codecs = codecs_comp;
+					dai_link[i].num_codecs = codecs_enabled;
+				}
+			}
+		}
+err:
+	return ret;
+}
+
+struct snd_soc_card snd_soc_card_stub_msm = {
+	.name		= "bengal-stub-snd-card",
+};
+
+static int msm_audrx_stub_init(struct snd_soc_pcm_runtime *rtd)
+{
+	return 0;
+}
+
+static int msm_snd_stub_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	return 0;
+}
+
+static struct snd_soc_ops msm_stub_be_ops = {
+	.hw_params = msm_snd_stub_hw_params,
+};
+
+static struct snd_soc_dai_link msm_stub_be_dai_links[] = {
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_PRI_AUXPCM_RX,
+		.stream_name = LPASS_BE_PRI_AUXPCM_RX,
+		.playback_only = 1,
+		.init = &msm_audrx_stub_init,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+		SND_SOC_DAILINK_REG(auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_PRI_AUXPCM_TX,
+		.stream_name = LPASS_BE_PRI_AUXPCM_TX,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+		SND_SOC_DAILINK_REG(auxpcm_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_stub_dai_links[
+			 ARRAY_SIZE(msm_stub_be_dai_links)];
+
+static struct snd_soc_card snd_soc_card_bengal_msm;
+static const struct of_device_id bengal_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,bengal-asoc-snd",
+	  .data = "codec"},
+	{ .compatible = "qcom,bengal-asoc-snd-stub",
+	  .data = "stub_codec"},
+	{},
+};
+
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+	struct snd_soc_card *card = NULL;
+	struct snd_soc_dai_link *dailink = NULL;
+	int total_links = 0;
+	int len_1 = 0;
+	int rc = 0;
+	u32 mi2s_audio_intf = 0;
+	u32 auxpcm_audio_intf = 0;
+	u32 rxtx_bolero_codec = 0;
+	u32 va_bolero_codec = 0;
+	u32 val = 0;
+	u32 wcn_btfm_intf = 0;
+	const struct of_device_id *match;
+
+	match = of_match_node(bengal_asoc_machine_of_match, dev->of_node);
+	if (!match) {
+		dev_err(dev, "%s: No DT match found for sound card\n",
+			__func__);
+		return NULL;
+	}
+
+	if (!strcmp(match->data, "codec")) {
+		card = &snd_soc_card_bengal_msm;
+
+		memcpy(msm_bengal_dai_links + total_links,
+		       msm_common_be_dai_links,
+		       sizeof(msm_common_be_dai_links));
+		total_links += ARRAY_SIZE(msm_common_be_dai_links);
+
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,rxtx-bolero-codec",
+					  &rxtx_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match RXTX Macro codec\n",
+				__func__);
+		} else {
+			if (rxtx_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_rx_tx_cdc_dma_be_dai_links,
+				       sizeof(msm_rx_tx_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(
+						msm_rx_tx_cdc_dma_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,va-bolero-codec",
+					  &va_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match VA Macro codec\n",
+				__func__);
+		} else {
+			if (va_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_va_cdc_dma_be_dai_links,
+				       sizeof(msm_va_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_va_cdc_dma_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,mi2s-audio-intf",
+					  &mi2s_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match MI2S audio interface\n",
+				__func__);
+		} else {
+			if (mi2s_audio_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_mi2s_be_dai_links,
+					sizeof(msm_mi2s_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_mi2s_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,auxpcm-audio-intf",
+					  &auxpcm_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match Aux PCM interface\n",
+				__func__);
+		} else {
+			if (auxpcm_audio_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_auxpcm_be_dai_links,
+					sizeof(msm_auxpcm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_auxpcm_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,tdm-audio-intf",
+				&val);
+		if (!rc && val) {
+			memcpy(msm_bengal_dai_links + total_links,
+				msm_tdm_be_dai_links,
+				sizeof(msm_tdm_be_dai_links));
+			total_links +=
+				ARRAY_SIZE(msm_tdm_be_dai_links);
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,wcn-btfm",
+					  &wcn_btfm_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match wcn btfm interface\n",
+				__func__);
+		} else {
+			if (wcn_btfm_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_wcn_btfm_be_dai_links,
+					sizeof(msm_wcn_btfm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_wcn_btfm_be_dai_links);
+			}
+		}
+		dailink = msm_bengal_dai_links;
+	} 
+
+	else if (!strcmp(match->data, "stub_codec")) {
+		card = &snd_soc_card_stub_msm;
+		len_1 = ARRAY_SIZE(msm_stub_be_dai_links);
+
+		memcpy(msm_stub_dai_links + len_1,
+		       msm_stub_be_dai_links,
+		       sizeof(msm_stub_be_dai_links));
+
+		dailink = msm_stub_dai_links;
+		total_links = len_1;
+	}
+
+	if (card) {
+		card->dai_link = dailink;
+		card->num_links = total_links;
+	}
+
+	return card;
+}
+
+static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *bolero_component = NULL;
+	struct snd_soc_component *component = NULL;
+	struct snd_soc_dapm_context *dapm = NULL;
+	int ret = 0;
+	void *mbhc_calibration;
+	struct snd_info_entry *entry;
+	struct snd_card *card = NULL;
+	struct msm_asoc_mach_data *pdata =
+			snd_soc_card_get_drvdata(rtd->card);
+
+	pr_err("%s:: enter \n", __func__);
+
+	bolero_component = snd_soc_rtdcom_lookup(rtd, "bolero_codec");
+	if (!bolero_component) {
+		pr_err("%s: could not find component for bolero_codec\n",
+			__func__);
+		return -EINVAL;
+	}
+	pr_err("%s:: bolero comp lookup done\n", __func__);
+
+	dapm = snd_soc_component_get_dapm(bolero_component);
+	snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
+		ARRAY_SIZE(msm_int_dapm_widgets));
+	pr_err("%s:: dapm new controls msm_int_dapm_widgets \n", __func__);
+
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
+
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic3");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
+
+	snd_soc_dapm_sync(dapm);
+	card = rtd->card->snd_card;
+
+	if (!pdata->codec_root) {
+		entry = msm_snd_info_create_subdir(card->module, "codecs",
+				card->proc_root);
+		if (!entry) {
+			pr_debug("%s: Cannot create codecs module entry\n",
+				__func__);
+			ret = 0;
+			goto err;
+		}
+		pdata->codec_root = entry;
+	}
+
+	bolero_info_create_codec_entry(pdata->codec_root, bolero_component);
+	bolero_register_wake_irq(bolero_component, false);
+
+	component = snd_soc_rtdcom_lookup(rtd, WCD937X_DRV_NAME);
+	if (!component)
+		component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dapm = snd_soc_component_get_dapm(component);
+	card = component->card->snd_card;
+
+	pdata = snd_soc_card_get_drvdata(component->card);
+	if (!pdata)
+		return -EINVAL;
+
+	if (!pdata->codec_root) {
+		entry = msm_snd_info_create_subdir(card->module, "codecs",
+						 card->proc_root);
+		if (!entry) {
+			dev_dbg(component->dev, "%s: Cannot create codecs module entry\n",
+				 __func__);
+			ret = 0;
+			goto mbhc_cfg_cal;
+		}
+		pdata->codec_root = entry;
+	}
+
+	if (!strncmp(component->driver->name, WCD937X_DRV_NAME, 13)) {
+		wcd937x_info_create_codec_entry(pdata->codec_root, component);
+		bolero_set_port_map(bolero_component,
+			ARRAY_SIZE(sm_port_map),
+			sm_port_map);
+	}
+
+	snd_soc_dapm_ignore_suspend(dapm, "EAR");
+	snd_soc_dapm_ignore_suspend(dapm, "AUX");
+	snd_soc_dapm_ignore_suspend(dapm, "LO");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
+	snd_soc_dapm_sync(dapm);
+
+        codec_reg_done = true;
+        msm_common_dai_link_init(rtd);
+mbhc_cfg_cal:
+	if (!strncmp(component->driver->name, WCD937X_DRV_NAME, 13)) {
+		mbhc_calibration = def_wcd_mbhc_cal();
+		if (!mbhc_calibration)
+			return -ENOMEM;
+		wcd_mbhc_cfg.calibration = mbhc_calibration;
+		ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+	}
+
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
+			__func__, ret);
+		goto err_hs_detect;
+	}
+	return 0;
+
+err_hs_detect:
+	kfree(mbhc_calibration);
+err:
+	pr_err("%s:: return %d \n", __func__, ret);
+	return ret;
+}
+
+static int msm_int_wsa_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct msm_asoc_mach_data *pdata =
+		snd_soc_card_get_drvdata(rtd->card);
+
+	int ret = 0;
+
+	if (pdata->wsa_max_devs == 0)
+		pr_info("%s: WSA is not enabled\n", __func__);
+
+	msm_common_dai_link_init(rtd);
+
+	return ret;
+}
+
+static int bengal_ssr_enable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (!card) {
+		dev_err_ratelimited(dev, "%s: card is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!strcmp(card->name, "bengal-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO\n", __func__);
+	}
+
+	snd_card_notify_user(SND_CARD_STATUS_ONLINE);
+	dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+
+err:
+	return ret;
+}
+
+static void bengal_ssr_disable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		return;
+	}
+
+	dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
+	snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
+
+	if (!strcmp(card->name, "bengal-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO\n", __func__);
+	}
+}
+
+static const struct snd_event_ops bengal_ssr_ops = {
+	.enable = bengal_ssr_enable,
+	.disable = bengal_ssr_disable,
+};
+
+static int msm_audio_ssr_compare(struct device *dev, void *data)
+{
+	struct device_node *node = data;
+
+	dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
+		__func__, dev->of_node, node);
+	return (dev->of_node && dev->of_node == node);
+}
+
+static int msm_audio_ssr_register(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct snd_event_clients *ssr_clients = NULL;
+	struct device_node *node = NULL;
+	int ret = 0;
+	int i = 0;
+
+	for (i = 0; ; i++) {
+		node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
+		if (!node)
+			break;
+		snd_event_mstr_add_client(&ssr_clients,
+					msm_audio_ssr_compare, node);
+	}
+
+	ret = snd_event_master_register(dev, &bengal_ssr_ops,
+					ssr_clients, NULL);
+	if (!ret)
+		snd_event_notify(dev, SND_EVENT_UP);
+
+	return ret;
+}
+
+struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card)
+{
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return NULL;
+
+	return pdata->common_pdata;
+}
+
+void msm_common_set_pdata(struct snd_soc_card *card,
+                          struct msm_common_pdata *common_pdata)
+{
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return;
+
+	pdata->common_pdata = common_pdata;
+}
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	const char *mbhc_audio_jack_type = NULL;
+	int ret = 0;
+	uint index = 0;
+	struct nvmem_cell *cell;
+	size_t len;
+	u32 *buf;
+	u32 adsp_var_idx = 0;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: No platform supplied from device tree\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	card = populate_snd_card_dailinks(&pdev->dev);
+	if (!card) {
+		dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse card name failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse audio routing failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = msm_populate_dai_link_component_of_node(card);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+        /* Get maximum WSA device count for this platform */
+	ret = of_property_read_u32(pdev->dev.of_node,
+		"qcom,wsa-max-devs", &pdata->wsa_max_devs);
+	if (ret) {
+		dev_info(&pdev->dev,
+		"%s: wsa-max-devs property missing in DT %s, ret = %d\n",
+		__func__, pdev->dev.of_node->full_name, ret);
+		pdata->wsa_max_devs = 0;
+	}
+
+	/* Make sure prefix string passed for each WSA device */
+	ret = of_property_count_strings(pdev->dev.of_node,
+					"qcom,wsa-aux-dev-prefix");
+	if (!ret) {
+		dev_err(&pdev->dev,
+			"property %s not defined in DT\n",
+			__func__, "qcom,wsa-aux-dev-prefix");
+	}
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret == -EPROBE_DEFER) {
+		if (codec_reg_done)
+			ret = -EINVAL;
+		goto err;
+	} else if (ret) {
+		dev_err(&pdev->dev, "%s: snd_soc_register_card failed (%d)\n",
+			__func__, ret);
+		goto err;
+	}
+	dev_info(&pdev->dev, "%s: Sound card %s registered\n",
+		 __func__, card->name);
+
+	pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en1-gpio", 0);
+	if (!pdata->hph_en1_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en1-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en0-gpio", 0);
+	if (!pdata->hph_en0_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en0-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	ret = of_property_read_string(pdev->dev.of_node,
+		"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,mbhc-audio-jack-type",
+			pdev->dev.of_node->full_name);
+		dev_dbg(&pdev->dev, "Jack type properties set to default\n");
+	} else {
+		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
+		} else {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "Unknown value, set to default\n");
+		}
+	}
+	/*
+	 * Parse US-Euro gpio info from DT. Report no error if us-euro
+	 * entry is not found in DT file as some targets do not support
+	 * US-Euro detection
+	 */
+	pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,us-euro-gpios", 0);
+	if (!pdata->us_euro_gpio_p) {
+		dev_dbg(&pdev->dev, "property %s not detected in node %s",
+			"qcom,us-euro-gpios", pdev->dev.of_node->full_name);
+	} else {
+		dev_dbg(&pdev->dev, "%s detected\n",
+			"qcom,us-euro-gpios");
+		wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
+	}
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		wcd_mbhc_cfg.swap_gnd_mic = msm_usbc_swap_gnd_mic;
+
+	pdata->fsa_handle = of_parse_phandle(pdev->dev.of_node,
+					"fsa4480-i2c-handle", 0);
+	if (!pdata->fsa_handle)
+		dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
+			"fsa4480-i2c-handle", pdev->dev.of_node->full_name);
+
+	pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic01-gpios",
+					       0);
+	pdata->dmic23_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic23-gpios",
+					       0);
+
+	pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,pri-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,sec-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[TERT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,tert-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,quat-mi2s-gpios", 0);
+	for (index = PRIM_MI2S; index < MI2S_MAX; index++)
+		atomic_set(&(pdata->mi2s_gpio_ref_count[index]), 0);
+
+	msm_common_snd_init(pdev, card);
+
+	ret = msm_audio_ssr_register(&pdev->dev);
+	if (ret)
+		pr_err("%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+
+	is_initial_boot = true;
+	/* get adsp variant idx */
+	cell = nvmem_cell_get(&pdev->dev, "adsp_variant");
+	if (IS_ERR_OR_NULL(cell)) {
+		dev_dbg(&pdev->dev, "%s: FAILED to get nvmem cell \n", __func__);
+		goto ret;
+	}
+	buf = nvmem_cell_read(cell, &len);
+	nvmem_cell_put(cell);
+	if (IS_ERR_OR_NULL(buf)) {
+		dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__);
+		goto ret;
+	}
+	if (len <= 0 || len > sizeof(u32)) {
+		dev_dbg(&pdev->dev, "%s: nvmem cell length out of range: %d\n",
+			__func__, len);
+		kfree(buf);
+		goto ret;
+	}
+	memcpy(&adsp_var_idx, buf, len);
+	kfree(buf);
+	va_disable = adsp_var_idx;
+
+ret:
+	return 0;
+err:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct msm_common_pdata *common_pdata = NULL;
+
+	if (card)
+		pdata = snd_soc_card_get_drvdata(card);
+
+	if (pdata)
+		common_pdata = pdata->common_pdata;
+
+	msm_common_snd_deinit(common_pdata);
+	snd_event_master_deregister(&pdev->dev);
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver bengal_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = bengal_asoc_machine_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_asoc_machine_probe,
+	.remove = msm_asoc_machine_remove,
+};
+
+static int __init msm_asoc_machine_init(void)
+{
+        snd_card_sysfs_init();
+        return platform_driver_register(&bengal_asoc_machine_driver);
+}
+module_init(msm_asoc_machine_init);
+
+static void __exit msm_asoc_machine_exit(void)
+{
+        platform_driver_unregister(&bengal_asoc_machine_driver);
+}
+module_exit(msm_asoc_machine_exit);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, bengal_asoc_machine_of_match);

+ 330 - 0
qcom/opensource/audio-kernel/asoc/codecs/Kbuild

@@ -0,0 +1,330 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_GVM
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+        INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA7255
+		include $(AUDIO_ROOT)/config/sa7255auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa7255autoconf.h
+	endif
+else
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_SM8150), y)
+		ifdef CONFIG_SND_SOC_SA8155
+			include $(AUDIO_ROOT)/config/sa8155auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+		else
+			include $(AUDIO_ROOT)/config/sm8150auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+		endif
+	endif
+	ifeq ($(CONFIG_ARCH_SM6150), y)
+		ifdef CONFIG_SND_SOC_SA6155
+			include $(AUDIO_ROOT)/config/sa6155auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+		else
+			include $(AUDIO_ROOT)/config/sm6150auto.conf
+			INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+		endif
+	endif
+	ifeq ($(CONFIG_ARCH_TRINKET), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KONA), y)
+		include $(AUDIO_ROOT)/config/konaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/konaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_WAIPIO), y)
+		include $(AUDIO_ROOT)/config/waipioauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/waipioautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KALAMA), y)
+		include $(AUDIO_ROOT)/config/kalamaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/kalamaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_PINEAPPLE), y)
+		include $(AUDIO_ROOT)/config/pineappleauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pineappleautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_PITTI), y)
+		include $(AUDIO_ROOT)/config/pittiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pittiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_LITO), y)
+		include $(AUDIO_ROOT)/config/litoauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KHAJE), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_HOLI), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_BLAIR), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
+		include $(AUDIO_ROOT)/config/sm8150auto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_SDXLEMUR), y)
+		include $(AUDIO_ROOT)/config/sdxlemurauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sdxlemurautoconf.h
+	endif
+endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ ASoC Codecs ############
+ifdef CONFIG_WCD9XXX_CODEC_CORE
+	CORE_OBJS += wcd9xxx-rst.o
+	CORE_OBJS += wcd9xxx-core-init.o
+	CORE_OBJS += wcd9xxx-core.o
+	CORE_OBJS += wcd9xxx-irq.o
+	CORE_OBJS += wcd9xxx-slimslave.o
+	CORE_OBJS += wcd9xxx-utils.o
+	CORE_OBJS += wcd9335-regmap.o
+	CORE_OBJS += wcd9335-tables.o
+	CORE_OBJS += msm-cdc-pinctrl.o
+	CORE_OBJS += msm-cdc-supply.o
+	CORE_OBJS += wcd934x/wcd934x-regmap.o
+	CORE_OBJS += wcd934x/wcd934x-tables.o
+endif
+
+ifdef CONFIG_WCD9XXX_CODEC_CORE_V2
+	CORE_OBJS += wcd9xxx-core-init.o
+	CORE_OBJS += msm-cdc-pinctrl.o
+	CORE_OBJS += msm-cdc-supply.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD9XXX_V2
+ifdef CONFIG_WCD9XXX_CODEC_CORE
+	WCD9XXX_OBJS += wcd9xxx-common-v2.o
+	WCD9XXX_OBJS += wcd9xxx-resmgr-v2.o
+	WCD9XXX_OBJS += wcd-dsp-utils.o
+	WCD9XXX_OBJS += wcd-dsp-mgr.o
+else
+	WCD9XXX_OBJS += wcd-clsh.o
+endif
+	WCD9XXX_OBJS += wcdcal-hwdep.o
+	WCD9XXX_OBJS += wcd9xxx-soc-init.o
+	WCD9XXX_OBJS += audio-ext-clk-up.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD9335
+	WCD9335_OBJS += wcd9335.o
+endif
+
+ifdef CONFIG_SND_SOC_WSA881X
+	WSA881X_OBJS += wsa881x.o
+	WSA881X_OBJS += wsa881x-tables.o
+	WSA881X_OBJS += wsa881x-regmap.o
+	WSA881X_OBJS += wsa881x-temp-sensor.o
+endif
+
+ifdef CONFIG_SND_SOC_SWR_DMIC
+       SWR_DMIC_OBJS += swr-dmic.o
+endif
+
+ifdef CONFIG_SND_SOC_WSA881X_ANALOG
+	INCS += -include $(KERNEL_SRC)/drivers/base/regmap/internal.h
+	WSA881X_ANALOG_OBJS += wsa881x-analog.o
+	WSA881X_ANALOG_OBJS += wsa881x-tables-analog.o
+	WSA881X_ANALOG_OBJS += wsa881x-regmap-analog.o
+ifndef CONFIG_WSA881X_TEMP_SENSOR_DISABLE
+	WSA881X_ANALOG_OBJS += wsa881x-temp-sensor.o
+endif
+endif
+ifdef CONFIG_SND_SOC_MSM_STUB
+	STUB_OBJS += msm_stub.o
+endif
+ifdef CONFIG_SND_SOC_WCD_SPI
+	SPI_OBJS += wcd-spi.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD_CPE
+	WCD_CPE_OBJS += wcd_cpe_core.o
+	WCD_CPE_OBJS += wcd_cpe_services.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD_MBHC
+	MBHC_OBJS += wcd-mbhc-v2.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD_MBHC_ADC
+	MBHC_OBJS += wcd-mbhc-adc.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD_MBHC_LEGACY
+	MBHC_OBJS += wcd-mbhc-legacy.o
+endif
+
+ifdef CONFIG_SND_SOC_MSM_HDMI_CODEC_RX
+	HDMICODEC_OBJS += msm_hdmi_codec_rx.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD_IRQ
+	CORE_OBJS += wcd-irq.o
+endif
+
+ifdef CONFIG_SND_SWR_HAPTICS
+	SWR_HAP_OBJS += swr-haptics.o
+endif
+
+ifdef CONFIG_LPASS_BT_SWR
+	LPASS_BT_SWR_OBJS += lpass-bt-swr.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+
+EXTRA_CFLAGS += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	obj-y	+= wcd934x/
+	obj-y	+= wcd937x/
+	obj-y	+= wcd938x/
+	obj-y	+= wcd939x/
+	obj-y	+= wcd9378/
+	obj-y	+= bolero/
+	obj-y	+= lpass-cdc/
+	obj-y	+= wsa884x/
+	obj-y	+= wsa883x/
+	obj-y	+= rouleur/
+	obj-y	+= ./
+endif
+# Module information used by KBuild framework
+obj-$(CONFIG_WCD9XXX_CODEC_CORE) += wcd_core_dlkm.o
+obj-$(CONFIG_WCD9XXX_CODEC_CORE_V2) += wcd_core_dlkm.o
+wcd_core_dlkm-y := $(CORE_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD9XXX_V2) += wcd9xxx_dlkm.o
+wcd9xxx_dlkm-y := $(WCD9XXX_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD9335) += wcd9335_dlkm.o
+wcd9335_dlkm-y := $(WCD9335_OBJS)
+
+obj-$(CONFIG_SND_SOC_WSA881X) += wsa881x_dlkm.o
+wsa881x_dlkm-y := $(WSA881X_OBJS)
+
+obj-$(CONFIG_SND_SOC_SWR_DMIC) += swr_dmic_dlkm.o
+swr_dmic_dlkm-y := $(SWR_DMIC_OBJS)
+
+obj-$(CONFIG_SND_SOC_WSA881X_ANALOG) += wsa881x_analog_dlkm.o
+wsa881x_analog_dlkm-y := $(WSA881X_ANALOG_OBJS)
+
+obj-$(CONFIG_SND_SOC_MSM_STUB) += stub_dlkm.o
+stub_dlkm-y := $(STUB_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD_CPE) += wcd_cpe_dlkm.o
+wcd_cpe_dlkm-y := $(WCD_CPE_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD_SPI) += wcd_spi_dlkm.o
+wcd_spi_dlkm-y := $(SPI_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD_MBHC) += mbhc_dlkm.o
+mbhc_dlkm-y := $(MBHC_OBJS)
+
+obj-$(CONFIG_SND_SOC_MSM_HDMI_CODEC_RX) += hdmi_dlkm.o
+hdmi_dlkm-y := $(HDMICODEC_OBJS)
+
+obj-$(CONFIG_SND_SWR_HAPTICS) += swr_haptics_dlkm.o
+swr_haptics_dlkm-y := $(SWR_HAP_OBJS)
+
+obj-$(CONFIG_LPASS_BT_SWR) += lpass_bt_swr_dlkm.o
+lpass_bt_swr_dlkm-y := $(LPASS_BT_SWR_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 6 - 0
qcom/opensource/audio-kernel/asoc/codecs/Makefile

@@ -0,0 +1,6 @@
+modules:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) VERBOSE=1
+modules_install:
+	$(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean

+ 120 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/Kbuild

@@ -0,0 +1,120 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+
+	ifeq ($(CONFIG_ARCH_SDM670), y)
+		include $(AUDIO_ROOT)/config/sdm670auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sdm670autoconf.h
+	endif
+
+	ifeq ($(CONFIG_ARCH_SM8150), y)
+		include $(AUDIO_ROOT)/config/sm8150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+	endif
+
+	ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
+		include $(AUDIO_ROOT)/config/sm8150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+# for AQT1000 Codec
+ifeq ($(CONFIG_SND_SOC_AQT1000), m)
+	AQT1000_CDC_OBJS += aqt1000-regmap.o
+	AQT1000_CDC_OBJS += aqt1000-utils.o
+	AQT1000_CDC_OBJS += aqt1000-core.o
+	AQT1000_CDC_OBJS += aqt1000-irq.o
+	AQT1000_CDC_OBJS += aqt1000-clsh.o
+	AQT1000_CDC_OBJS += aqt1000.o
+	AQT1000_CDC_OBJS += aqt1000-mbhc.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=	$(COMMON_INC) \
+	$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/aqt1000/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_AQT1000) += aqt1000_cdc_dlkm.o
+aqt1000_cdc_dlkm-y := $(AQT1000_CDC_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 21 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-api.h

@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef AQT1000_API_H
+#define AQT1000_API_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <sound/soc.h>
+
+extern int aqt_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+					int volt, int micb_num);
+extern int aqt_cdc_mclk_enable(struct snd_soc_component *component,
+			       bool enable);
+extern int aqt_get_micb_vout_ctl_val(u32 micb_mv);
+extern int aqt_micbias_control(struct snd_soc_component *component,
+			       int micb_num, int req, bool is_dapm);
+
+#endif /* AQT1000_API_H */

+ 833 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-clsh.c

@@ -0,0 +1,833 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <sound/soc.h>
+#include "aqt1000-registers.h"
+#include "aqt1000-clsh.h"
+
+#define AQT_USLEEP_RANGE 50
+#define MAX_IMPED_PARAMS 6
+
+enum aqt_vref_dac_sel {
+	VREF_N1P9V = 0,
+	VREF_N1P86V,
+	VREF_N181V,
+	VREF_N1P74V,
+	VREF_N1P7V,
+	VREF_N0P9V,
+	VREF_N1P576V,
+	VREF_N1P827V,
+};
+
+enum aqt_vref_ctl {
+	CONTROLLER = 0,
+	I2C,
+};
+
+enum aqt_hd2_res_div_ctl {
+	DISCONNECT = 0,
+	P5_0P35,
+	P75_0P68,
+	P82_0P77,
+	P9_0P87,
+};
+
+enum aqt_curr_bias_err_amp {
+	I_0P25UA = 0,
+	I_0P5UA,
+	I_0P75UA,
+	I_1UA,
+	I_1P25UA,
+	I_1P5UA,
+	I_1P75UA,
+	I_2UA,
+};
+
+static const struct aqt_reg_mask_val imped_table_aqt[][MAX_IMPED_PARAMS] = {
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xf2},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xf2},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xf4},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xf4},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xf7},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xf7},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xf9},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xf9},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xfa},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xfa},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xfb},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xfb},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xfc},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xfc},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{AQT1000_CDC_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+		{AQT1000_CDC_RX2_RX_VOL_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{AQT1000_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+	},
+};
+
+static const struct aqt_imped_val imped_index[] = {
+	{4, 0},
+	{5, 1},
+	{6, 2},
+	{7, 3},
+	{8, 4},
+	{9, 5},
+	{10, 6},
+	{11, 7},
+	{12, 8},
+	{13, 9},
+};
+
+static void (*clsh_state_fp[NUM_CLSH_STATES])(struct snd_soc_component *,
+					      struct aqt_clsh_cdc_data *,
+					      u8 req_state, bool en, int mode);
+
+static int get_impedance_index(int imped)
+{
+	int i = 0;
+
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than 4 Ohm\n",
+				__func__);
+		i = 0;
+		goto ret;
+	}
+	if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
+		pr_debug("%s, detected impedance is greater than 12 Ohm\n",
+				__func__);
+		i = ARRAY_SIZE(imped_index) - 1;
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+/*
+ * Function: aqt_clsh_imped_config
+ * Params: component, imped, reset
+ * Description:
+ * This function updates HPHL and HPHR gain settings
+ * according to the impedance value.
+ */
+void aqt_clsh_imped_config(struct snd_soc_component *component,
+			   int imped, bool reset)
+{
+	int i;
+	int index = 0;
+	int table_size;
+
+	static const struct aqt_reg_mask_val
+				(*imped_table_ptr)[MAX_IMPED_PARAMS];
+
+	table_size = ARRAY_SIZE(imped_table_aqt);
+	imped_table_ptr = imped_table_aqt;
+
+	/* reset = 1, which means request is to reset the register values */
+	if (reset) {
+		for (i = 0; i < MAX_IMPED_PARAMS; i++)
+			snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask, 0);
+		return;
+	}
+	index = get_impedance_index(imped);
+	if (index >= (ARRAY_SIZE(imped_index) - 1)) {
+		pr_debug("%s, impedance not in range = %d\n", __func__, imped);
+		return;
+	}
+	if (index >= table_size) {
+		pr_debug("%s, impedance index not in range = %d\n", __func__,
+			index);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask,
+				imped_table_ptr[index][i].val);
+}
+EXPORT_SYMBOL(aqt_clsh_imped_config);
+
+static const char *mode_to_str(int mode)
+{
+	switch (mode) {
+	case CLS_H_NORMAL:
+		return "CLS_H_NORMAL";
+	case CLS_H_HIFI:
+		return "CLS_H_HIFI";
+	case CLS_H_LOHIFI:
+		return "CLS_H_LOHIFI";
+	case CLS_H_LP:
+		return "CLS_H_LP";
+	case CLS_H_ULP:
+		return "CLS_H_ULP";
+	case CLS_AB:
+		return "CLS_AB";
+	case CLS_AB_HIFI:
+		return "CLS_AB_HIFI";
+	default:
+		return "CLS_H_INVALID";
+	};
+}
+
+static const char *const state_to_str[] = {
+	[AQT_CLSH_STATE_IDLE] = "STATE_IDLE",
+	[AQT_CLSH_STATE_HPHL] = "STATE_HPH_L",
+	[AQT_CLSH_STATE_HPHR] = "STATE_HPH_R",
+	[AQT_CLSH_STATE_HPH_ST] = "STATE_HPH_ST",
+};
+
+static inline void
+aqt_enable_clsh_block(struct snd_soc_component *component,
+		      struct aqt_clsh_cdc_data *clsh_d, bool enable)
+{
+	if ((enable && ++clsh_d->clsh_users == 1) ||
+	    (!enable && --clsh_d->clsh_users == 0))
+		snd_soc_component_update_bits(component, AQT1000_CDC_CLSH_CRC,
+				0x01, (u8) enable);
+	if (clsh_d->clsh_users < 0)
+		clsh_d->clsh_users = 0;
+	dev_dbg(component->dev, "%s: clsh_users %d, enable %d", __func__,
+		clsh_d->clsh_users, enable);
+}
+
+static inline bool aqt_clsh_enable_status(struct snd_soc_component *component)
+{
+	return snd_soc_component_read32(
+			component, AQT1000_CDC_CLSH_CRC) & 0x01;
+}
+
+static inline int aqt_clsh_get_int_mode(struct aqt_clsh_cdc_data *clsh_d,
+					int clsh_state)
+{
+	int mode;
+
+	if ((clsh_state != AQT_CLSH_STATE_HPHL) &&
+	    (clsh_state != AQT_CLSH_STATE_HPHR))
+		mode = CLS_NONE;
+	else
+		mode = clsh_d->interpolator_modes[ffs(clsh_state)];
+
+	return mode;
+}
+
+static inline void aqt_clsh_set_int_mode(struct aqt_clsh_cdc_data *clsh_d,
+					int clsh_state, int mode)
+{
+	if ((clsh_state != AQT_CLSH_STATE_HPHL) &&
+	    (clsh_state != AQT_CLSH_STATE_HPHR))
+		return;
+
+	clsh_d->interpolator_modes[ffs(clsh_state)] = mode;
+}
+
+static inline void aqt_clsh_set_buck_mode(struct snd_soc_component *component,
+					  int mode)
+{
+	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+	    mode == CLS_AB_HIFI || mode == CLS_AB)
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				0x08, 0x08); /* set to HIFI */
+	else
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				0x08, 0x00); /* set to default */
+}
+
+static inline void aqt_clsh_set_flyback_mode(
+			struct snd_soc_component *component, int mode)
+{
+	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+	    mode == CLS_AB_HIFI || mode == CLS_AB)
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				0x04, 0x04); /* set to HIFI */
+	else
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				0x04, 0x00); /* set to Default */
+}
+
+static inline void aqt_clsh_gm3_boost_disable(
+			struct snd_soc_component *component, int mode)
+{
+	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+	    mode == CLS_AB_HIFI || mode == CLS_AB) {
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_CNP_WG_CTL,
+				0x80, 0x0); /* disable GM3 Boost */
+		snd_soc_component_update_bits(component,
+				AQT1000_FLYBACK_VNEG_CTRL_4,
+				0xF0, 0x80);
+	} else {
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_CNP_WG_CTL,
+				0x80, 0x80); /* set to Default */
+		snd_soc_component_update_bits(component,
+				AQT1000_FLYBACK_VNEG_CTRL_4,
+				0xF0, 0x70);
+	}
+}
+
+static inline void aqt_clsh_flyback_dac_ctl(
+			struct snd_soc_component *component, int vref)
+{
+	snd_soc_component_update_bits(component,
+			AQT1000_FLYBACK_VNEGDAC_CTRL_2,
+			0xE0, (vref << 5));
+}
+
+static inline void aqt_clsh_mode_vref_ctl(struct snd_soc_component *component,
+					  int vref_ctl)
+{
+	if (vref_ctl == I2C) {
+		snd_soc_component_update_bits(component, AQT1000_CLASSH_MODE_3,
+					      0x02, 0x02);
+		snd_soc_component_update_bits(component, AQT1000_CLASSH_MODE_2,
+					      0xFF, 0x1C);
+	} else {
+		snd_soc_component_update_bits(component, AQT1000_CLASSH_MODE_2,
+					      0xFF, 0x3A);
+		snd_soc_component_update_bits(component, AQT1000_CLASSH_MODE_3,
+					      0x02, 0x00);
+	}
+}
+
+static inline void aqt_clsh_buck_current_bias_ctl(
+			struct snd_soc_component *component, bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_IBIAS_CTL_4,
+				0x70, (I_2UA << 4));
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_IBIAS_CTL_4,
+				0x07, I_0P25UA);
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_CTRL_CCL_2,
+				0x3F, 0x3F);
+	} else {
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_IBIAS_CTL_4,
+				0x70, (I_1UA << 4));
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_IBIAS_CTL_4,
+				0x07, I_1UA);
+		snd_soc_component_update_bits(component,
+				AQT1000_BUCK_5V_CTRL_CCL_2,
+				0x3F, 0x20);
+	}
+}
+
+static inline void aqt_clsh_rdac_hd2_ctl(struct snd_soc_component *component,
+					 u8 hd2_div_ctl, u8 state)
+{
+	u16 reg = 0;
+
+	if (state == AQT_CLSH_STATE_HPHL)
+		reg = AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_L;
+	else if (state == AQT_CLSH_STATE_HPHR)
+		reg = AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_R;
+	else
+		dev_err(component->dev, "%s: Invalid state: %d\n",
+			__func__, state);
+	if (!reg)
+		snd_soc_component_update_bits(component, reg,
+					      0x0F, hd2_div_ctl);
+}
+
+static inline void aqt_clsh_force_iq_ctl(struct snd_soc_component *component,
+					 int mode)
+{
+	if (mode == CLS_H_LOHIFI || mode == CLS_AB) {
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_NEW_INT_PA_MISC2,
+				0x20, 0x20);
+		snd_soc_component_update_bits(component,
+				AQT1000_RX_BIAS_HPH_LOWPOWER,
+				0xF0, 0xC0);
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_PA_CTL1,
+				0x0E, 0x02);
+	} else {
+
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_NEW_INT_PA_MISC2,
+				0x20, 0x0);
+		snd_soc_component_update_bits(component,
+				AQT1000_RX_BIAS_HPH_LOWPOWER,
+				0xF0, 0x80);
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_PA_CTL1,
+				0x0E, 0x06);
+	}
+}
+
+static void aqt_clsh_buck_ctrl(struct snd_soc_component *component,
+			       struct aqt_clsh_cdc_data *clsh_d,
+			       int mode,
+			       bool enable)
+{
+	/* enable/disable buck */
+	if ((enable && (++clsh_d->buck_users == 1)) ||
+	   (!enable && (--clsh_d->buck_users == 0)))
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				(1 << 7), (enable << 7));
+	dev_dbg(component->dev, "%s: buck_users %d, enable %d, mode: %s",
+		__func__, clsh_d->buck_users, enable, mode_to_str(mode));
+	/*
+	 * 500us sleep is required after buck enable/disable
+	 * as per HW requirement
+	 */
+	usleep_range(500, 500 + AQT_USLEEP_RANGE);
+}
+
+static void aqt_clsh_flyback_ctrl(struct snd_soc_component *component,
+				  struct aqt_clsh_cdc_data *clsh_d,
+				  int mode,
+				  bool enable)
+{
+	/* enable/disable flyback */
+	if ((enable && (++clsh_d->flyback_users == 1)) ||
+	   (!enable && (--clsh_d->flyback_users == 0))) {
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES,
+				(1 << 6), (enable << 6));
+		/* 100usec delay is needed as per HW requirement */
+		usleep_range(100, 110);
+	}
+	dev_dbg(component->dev, "%s: flyback_users %d, enable %d, mode: %s",
+		__func__, clsh_d->flyback_users, enable, mode_to_str(mode));
+	/*
+	 * 500us sleep is required after flyback enable/disable
+	 * as per HW requirement
+	 */
+	usleep_range(500, 500 + AQT_USLEEP_RANGE);
+}
+
+static void aqt_clsh_set_hph_mode(struct snd_soc_component *component,
+				  int mode)
+{
+	u8 val = 0;
+	u8 gain = 0;
+	u8 res_val = VREF_FILT_R_0OHM;
+	u8 ipeak = DELTA_I_50MA;
+
+	switch (mode) {
+	case CLS_H_NORMAL:
+		res_val = VREF_FILT_R_50KOHM;
+		val = 0x00;
+		gain = DAC_GAIN_0DB;
+		ipeak = DELTA_I_50MA;
+		break;
+	case CLS_AB:
+		val = 0x00;
+		gain = DAC_GAIN_0DB;
+		ipeak = DELTA_I_50MA;
+		break;
+	case CLS_AB_HIFI:
+		val = 0x08;
+		break;
+	case CLS_H_HIFI:
+		val = 0x08;
+		gain = DAC_GAIN_M0P2DB;
+		ipeak = DELTA_I_50MA;
+		break;
+	case CLS_H_LOHIFI:
+		val = 0x00;
+		break;
+	case CLS_H_ULP:
+		val = 0x0C;
+		break;
+	case CLS_H_LP:
+		val = 0x04;
+		ipeak = DELTA_I_30MA;
+		break;
+	default:
+		return;
+	};
+
+	if (mode == CLS_H_LOHIFI || mode == CLS_AB)
+		val = 0x04;
+
+	snd_soc_component_update_bits(component, AQT1000_ANA_HPH, 0x0C, val);
+}
+
+static void aqt_clsh_set_buck_regulator_mode(
+			struct snd_soc_component *component, int mode)
+{
+	snd_soc_component_update_bits(component, AQT1000_ANA_RX_SUPPLIES,
+			    0x02, 0x00);
+}
+
+static void aqt_clsh_state_hph_st(struct snd_soc_component *component,
+				  struct aqt_clsh_cdc_data *clsh_d,
+				  u8 req_state, bool is_enable, int mode)
+{
+	dev_dbg(component->dev, "%s: mode: %s, %s\n", __func__,
+		mode_to_str(mode),
+		is_enable ? "enable" : "disable");
+
+	if (mode == CLS_AB || mode == CLS_AB_HIFI)
+		return;
+
+	if (is_enable) {
+		if (req_state == AQT_CLSH_STATE_HPHL)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX1_RX_PATH_CFG0,
+					    0x40, 0x40);
+		if (req_state == AQT_CLSH_STATE_HPHR)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x40, 0x40);
+	} else {
+		if (req_state == AQT_CLSH_STATE_HPHL)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX1_RX_PATH_CFG0,
+					    0x40, 0x00);
+		if (req_state == AQT_CLSH_STATE_HPHR)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x40, 0x00);
+	}
+}
+
+static void aqt_clsh_state_hph_r(struct snd_soc_component *component,
+				 struct aqt_clsh_cdc_data *clsh_d,
+				 u8 req_state, bool is_enable, int mode)
+{
+	dev_dbg(component->dev, "%s: mode: %s, %s\n", __func__,
+		mode_to_str(mode),
+		is_enable ? "enable" : "disable");
+
+	if (mode == CLS_H_NORMAL) {
+		dev_err(component->dev, "%s: Normal mode not applicable for hph_r\n",
+			__func__);
+		return;
+	}
+
+	if (is_enable) {
+		if (mode != CLS_AB && mode != CLS_AB_HIFI) {
+			aqt_enable_clsh_block(component, clsh_d, true);
+			/*
+			 * These K1 values depend on the Headphone Impedance
+			 * For now it is assumed to be 16 ohm
+			 */
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLSH_K1_MSB,
+					0x0F, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLSH_K1_LSB,
+					0xFF, 0xC0);
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x40, 0x40);
+		}
+		aqt_clsh_set_buck_regulator_mode(component, mode);
+		aqt_clsh_set_flyback_mode(component, mode);
+		aqt_clsh_gm3_boost_disable(component, mode);
+		aqt_clsh_flyback_dac_ctl(component, VREF_N0P9V);
+		aqt_clsh_mode_vref_ctl(component, I2C);
+		aqt_clsh_force_iq_ctl(component, mode);
+		aqt_clsh_rdac_hd2_ctl(component, P82_0P77, req_state);
+		aqt_clsh_flyback_ctrl(component, clsh_d, mode, true);
+		aqt_clsh_flyback_dac_ctl(component, VREF_N1P827V);
+		aqt_clsh_set_buck_mode(component, mode);
+		aqt_clsh_buck_ctrl(component, clsh_d, mode, true);
+		aqt_clsh_mode_vref_ctl(component, CONTROLLER);
+		aqt_clsh_buck_current_bias_ctl(component, true);
+		aqt_clsh_set_hph_mode(component, mode);
+	} else {
+		aqt_clsh_set_hph_mode(component, CLS_H_NORMAL);
+		aqt_clsh_buck_current_bias_ctl(component, false);
+
+		if (mode != CLS_AB && mode != CLS_AB_HIFI) {
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x40, 0x00);
+			aqt_enable_clsh_block(component, clsh_d, false);
+		}
+		/* buck and flyback set to default mode and disable */
+		aqt_clsh_buck_ctrl(component, clsh_d, CLS_H_NORMAL, false);
+		aqt_clsh_flyback_ctrl(component, clsh_d, CLS_H_NORMAL, false);
+		aqt_clsh_rdac_hd2_ctl(component, P5_0P35, req_state);
+		aqt_clsh_force_iq_ctl(component, CLS_H_NORMAL);
+		aqt_clsh_gm3_boost_disable(component, CLS_H_NORMAL);
+		aqt_clsh_set_flyback_mode(component, CLS_H_NORMAL);
+		aqt_clsh_set_buck_mode(component, CLS_H_NORMAL);
+		aqt_clsh_set_buck_regulator_mode(component, CLS_H_NORMAL);
+	}
+}
+
+static void aqt_clsh_state_hph_l(struct snd_soc_component *component,
+				 struct aqt_clsh_cdc_data *clsh_d,
+				 u8 req_state, bool is_enable, int mode)
+{
+	dev_dbg(component->dev, "%s: mode: %s, %s\n", __func__,
+		mode_to_str(mode), is_enable ? "enable" : "disable");
+
+	if (mode == CLS_H_NORMAL) {
+		dev_err(component->dev, "%s: Normal mode not applicable for hph_l\n",
+			__func__);
+		return;
+	}
+
+	if (is_enable) {
+		if (mode != CLS_AB && mode != CLS_AB_HIFI) {
+			aqt_enable_clsh_block(component, clsh_d, true);
+			/*
+			 * These K1 values depend on the Headphone Impedance
+			 * For now it is assumed to be 16 ohm
+			 */
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLSH_K1_MSB,
+					0x0F, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLSH_K1_LSB,
+					0xFF, 0xC0);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_RX1_RX_PATH_CFG0,
+					0x40, 0x40);
+		}
+		aqt_clsh_set_buck_regulator_mode(component, mode);
+		aqt_clsh_set_flyback_mode(component, mode);
+		aqt_clsh_gm3_boost_disable(component, mode);
+		aqt_clsh_flyback_dac_ctl(component, VREF_N0P9V);
+		aqt_clsh_mode_vref_ctl(component, I2C);
+		aqt_clsh_force_iq_ctl(component, mode);
+		aqt_clsh_rdac_hd2_ctl(component, P82_0P77, req_state);
+		aqt_clsh_flyback_ctrl(component, clsh_d, mode, true);
+		aqt_clsh_flyback_dac_ctl(component, VREF_N1P827V);
+		aqt_clsh_set_buck_mode(component, mode);
+		aqt_clsh_buck_ctrl(component, clsh_d, mode, true);
+		aqt_clsh_mode_vref_ctl(component, CONTROLLER);
+		aqt_clsh_buck_current_bias_ctl(component, true);
+		aqt_clsh_set_hph_mode(component, mode);
+	} else {
+		aqt_clsh_set_hph_mode(component, CLS_H_NORMAL);
+		aqt_clsh_buck_current_bias_ctl(component, false);
+
+		if (mode != CLS_AB && mode != CLS_AB_HIFI) {
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX1_RX_PATH_CFG0,
+					    0x40, 0x00);
+			aqt_enable_clsh_block(component, clsh_d, false);
+		}
+		/* set buck and flyback to Default Mode */
+		aqt_clsh_buck_ctrl(component, clsh_d, CLS_H_NORMAL, false);
+		aqt_clsh_flyback_ctrl(component, clsh_d, CLS_H_NORMAL, false);
+		aqt_clsh_rdac_hd2_ctl(component, P5_0P35, req_state);
+		aqt_clsh_force_iq_ctl(component, CLS_H_NORMAL);
+		aqt_clsh_gm3_boost_disable(component, CLS_H_NORMAL);
+		aqt_clsh_set_flyback_mode(component, CLS_H_NORMAL);
+		aqt_clsh_set_buck_mode(component, CLS_H_NORMAL);
+		aqt_clsh_set_buck_regulator_mode(component, CLS_H_NORMAL);
+	}
+}
+
+static void aqt_clsh_state_err(struct snd_soc_component *component,
+		struct aqt_clsh_cdc_data *clsh_d,
+		u8 req_state, bool is_enable, int mode)
+{
+	dev_err(component->dev,
+		"%s Wrong request for class H state machine requested to %s %s",
+		__func__, is_enable ? "enable" : "disable",
+		state_to_str[req_state]);
+}
+
+/*
+ * Function: aqt_clsh_is_state_valid
+ * Params: state
+ * Description:
+ * Provides information on valid states of Class H configuration
+ */
+static bool aqt_clsh_is_state_valid(u8 state)
+{
+	switch (state) {
+	case AQT_CLSH_STATE_IDLE:
+	case AQT_CLSH_STATE_HPHL:
+	case AQT_CLSH_STATE_HPHR:
+	case AQT_CLSH_STATE_HPH_ST:
+		return true;
+	default:
+		return false;
+	};
+}
+
+/*
+ * Function: aqt_clsh_fsm
+ * Params: component, cdc_clsh_d, req_state, req_type, clsh_event
+ * Description:
+ * This function handles PRE DAC and POST DAC conditions of different devices
+ * and updates class H configuration of different combination of devices
+ * based on validity of their states. cdc_clsh_d will contain current
+ * class h state information
+ */
+void aqt_clsh_fsm(struct snd_soc_component *component,
+		struct aqt_clsh_cdc_data *cdc_clsh_d,
+		u8 clsh_event, u8 req_state,
+		int int_mode)
+{
+	u8 old_state, new_state;
+
+	switch (clsh_event) {
+	case AQT_CLSH_EVENT_PRE_DAC:
+		old_state = cdc_clsh_d->state;
+		new_state = old_state | req_state;
+
+		if (!aqt_clsh_is_state_valid(new_state)) {
+			dev_err(component->dev,
+				"%s: Class-H not a valid new state: %s\n",
+				__func__, state_to_str[new_state]);
+			return;
+		}
+		if (new_state == old_state) {
+			dev_err(component->dev,
+				"%s: Class-H already in requested state: %s\n",
+				__func__, state_to_str[new_state]);
+			return;
+		}
+		cdc_clsh_d->state = new_state;
+		aqt_clsh_set_int_mode(cdc_clsh_d, req_state, int_mode);
+		(*clsh_state_fp[new_state]) (component, cdc_clsh_d, req_state,
+					     CLSH_REQ_ENABLE, int_mode);
+		dev_dbg(component->dev,
+			"%s: ClassH state transition from %s to %s\n",
+			__func__, state_to_str[old_state],
+			state_to_str[cdc_clsh_d->state]);
+		break;
+	case AQT_CLSH_EVENT_POST_PA:
+		old_state = cdc_clsh_d->state;
+		new_state = old_state & (~req_state);
+		if (new_state < NUM_CLSH_STATES) {
+			if (!aqt_clsh_is_state_valid(old_state)) {
+				dev_err(component->dev,
+					"%s:Invalid old state:%s\n",
+					__func__, state_to_str[old_state]);
+				return;
+			}
+			if (new_state == old_state) {
+				dev_err(component->dev,
+					"%s: Class-H already in requested state: %s\n",
+					__func__,state_to_str[new_state]);
+				return;
+			}
+			(*clsh_state_fp[old_state]) (component, cdc_clsh_d,
+					req_state, CLSH_REQ_DISABLE,
+					int_mode);
+			cdc_clsh_d->state = new_state;
+			aqt_clsh_set_int_mode(cdc_clsh_d, req_state, CLS_NONE);
+			dev_dbg(component->dev, "%s: ClassH state transition from %s to %s\n",
+				__func__, state_to_str[old_state],
+				state_to_str[cdc_clsh_d->state]);
+		}
+		break;
+	};
+}
+EXPORT_SYMBOL(aqt_clsh_fsm);
+
+/*
+ * Function: aqt_clsh_get_clsh_state
+ * Params: clsh
+ * Description:
+ * This function returns the state of the class H controller
+ */
+int aqt_clsh_get_clsh_state(struct aqt_clsh_cdc_data *clsh)
+{
+	return clsh->state;
+}
+EXPORT_SYMBOL(aqt_clsh_get_clsh_state);
+
+/*
+ * Function: aqt_clsh_init
+ * Params: clsh
+ * Description:
+ * This function initializes the class H controller
+ */
+void aqt_clsh_init(struct aqt_clsh_cdc_data *clsh)
+{
+	int i;
+
+	clsh->state = AQT_CLSH_STATE_IDLE;
+
+	for (i = 0; i < NUM_CLSH_STATES; i++)
+		clsh_state_fp[i] = aqt_clsh_state_err;
+
+	clsh_state_fp[AQT_CLSH_STATE_HPHL] = aqt_clsh_state_hph_l;
+	clsh_state_fp[AQT_CLSH_STATE_HPHR] = aqt_clsh_state_hph_r;
+	clsh_state_fp[AQT_CLSH_STATE_HPH_ST] = aqt_clsh_state_hph_st;
+	/* Set interpolator modes to NONE */
+	aqt_clsh_set_int_mode(clsh, AQT_CLSH_STATE_HPHL, CLS_NONE);
+	aqt_clsh_set_int_mode(clsh, AQT_CLSH_STATE_HPHR, CLS_NONE);
+	clsh->flyback_users = 0;
+	clsh->buck_users = 0;
+	clsh->clsh_users = 0;
+}
+EXPORT_SYMBOL(aqt_clsh_init);

+ 107 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-clsh.h

@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _AQT1000_CLSH_H
+#define _AQT1000_CLSH_H
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <linux/kernel.h>
+
+#define CLSH_REQ_ENABLE true
+#define CLSH_REQ_DISABLE false
+
+#define AQT_CLSH_EVENT_PRE_DAC 0x01
+#define AQT_CLSH_EVENT_POST_PA 0x02
+/*
+ * Basic states for Class H state machine.
+ * represented as a bit mask within a u8 data type
+ * bit 0: HPH Left mode
+ * bit 1: HPH Right mode
+ */
+#define	AQT_CLSH_STATE_IDLE 0x00
+#define	AQT_CLSH_STATE_HPHL (0x01 << 0)
+#define	AQT_CLSH_STATE_HPHR (0x01 << 1)
+
+/*
+ * Though number of CLSH states are 2, max state shoulbe be 3
+ * because state array index starts from 1.
+ */
+#define AQT_CLSH_STATE_MAX 3
+#define NUM_CLSH_STATES (0x01 << AQT_CLSH_STATE_MAX)
+
+
+/* Derived State: Bits 1 and 2 should be set for Headphone stereo */
+#define AQT_CLSH_STATE_HPH_ST (AQT_CLSH_STATE_HPHL | \
+			       AQT_CLSH_STATE_HPHR)
+
+enum {
+	CLS_H_NORMAL = 0, /* Class-H Default */
+	CLS_H_HIFI, /* Class-H HiFi */
+	CLS_H_LP, /* Class-H Low Power */
+	CLS_AB, /* Class-AB Low HIFI*/
+	CLS_H_LOHIFI, /* LoHIFI */
+	CLS_H_ULP, /* Ultra Low power */
+	CLS_AB_HIFI, /* Class-AB */
+	CLS_NONE, /* None of the above modes */
+};
+
+enum {
+	DAC_GAIN_0DB = 0,
+	DAC_GAIN_0P2DB,
+	DAC_GAIN_0P4DB,
+	DAC_GAIN_0P6DB,
+	DAC_GAIN_0P8DB,
+	DAC_GAIN_M0P2DB,
+	DAC_GAIN_M0P4DB,
+	DAC_GAIN_M0P6DB,
+};
+
+enum {
+	VREF_FILT_R_0OHM = 0,
+	VREF_FILT_R_25KOHM,
+	VREF_FILT_R_50KOHM,
+	VREF_FILT_R_100KOHM,
+};
+
+enum {
+	DELTA_I_0MA,
+	DELTA_I_10MA,
+	DELTA_I_20MA,
+	DELTA_I_30MA,
+	DELTA_I_40MA,
+	DELTA_I_50MA,
+};
+
+struct aqt_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+struct aqt_clsh_cdc_data {
+	u8 state;
+	int flyback_users;
+	int buck_users;
+	int clsh_users;
+	int interpolator_modes[AQT_CLSH_STATE_MAX];
+};
+
+struct aqt_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+extern void aqt_clsh_fsm(struct snd_soc_component *component,
+		struct aqt_clsh_cdc_data *cdc_clsh_d,
+		u8 clsh_event, u8 req_state,
+		int int_mode);
+
+extern void aqt_clsh_init(struct aqt_clsh_cdc_data *clsh);
+extern int aqt_clsh_get_clsh_state(struct aqt_clsh_cdc_data *clsh);
+extern void aqt_clsh_imped_config(struct snd_soc_component *component,
+		int imped, bool reset);
+
+#endif /* _AQT1000_CLSH_H */

+ 638 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-core.c

@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+#include <linux/mfd/core.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <asoc/msm-cdc-supply.h>
+#include "aqt1000-registers.h"
+#include "aqt1000-internal.h"
+#include "aqt1000.h"
+#include "aqt1000-utils.h"
+#include "aqt1000-irq.h"
+
+static int aqt1000_bringup(struct aqt1000 *aqt)
+{
+	struct aqt1000_pdata *pdata;
+	u8 clk_div = 0, mclk = 1;
+
+	if (!aqt->regmap) {
+		dev_err(aqt->dev, "%s: aqt regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Bringup register write sequence */
+	regmap_update_bits(aqt->regmap, AQT1000_BUCK_5V_CTRL_CCL_1, 0xF0, 0xF0);
+	regmap_update_bits(aqt->regmap, AQT1000_BIAS_CCOMP_FINE_ADJ,
+			   0xF0, 0x90);
+	regmap_update_bits(aqt->regmap, AQT1000_ANA_BIAS, 0x80, 0x80);
+	regmap_update_bits(aqt->regmap, AQT1000_ANA_BIAS, 0x40, 0x40);
+
+	/* Added 1msec sleep as per HW requirement */
+	usleep_range(1000, 1010);
+
+	regmap_update_bits(aqt->regmap, AQT1000_ANA_BIAS, 0x40, 0x00);
+
+	clk_div = 0x04; /* Assumption is CLK DIV 2 */
+	pdata = dev_get_platdata(aqt->dev);
+	if (pdata) {
+		if (pdata->mclk_rate == AQT1000_CLK_12P288MHZ)
+			mclk = 0;
+		clk_div = (((pdata->ext_clk_rate / pdata->mclk_rate) >> 1)
+				<< 2);
+	}
+	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_CLK_CFG_MCLK,
+			   0x03, mclk);
+
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK1_PRG,
+			   0x0C, clk_div);
+
+	/* Source clock enable */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK1_PRG, 0x02, 0x02);
+
+	/* Ungate the source clock */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK1_PRG, 0x10, 0x10);
+
+	/* Set the I2S_HS_CLK reference to CLK DIV 2 */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG,
+			   0x60, 0x20);
+
+	/* Set the PLL preset to CLK9P6M_IN_12P288M_OUT */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_PLL_PRESET, 0x0F, 0x02);
+
+	/* Enable clock PLL */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_PLL_ENABLES,
+			   0x01, 0x01);
+
+	/* Add 100usec delay as per HW requirement */
+	usleep_range(100, 110);
+
+	/* Set AQT to I2S Master */
+	regmap_update_bits(aqt->regmap, AQT1000_I2S_I2S_0_CTL, 0x02, 0x02);
+
+	/* Enable I2S HS clock */
+	regmap_update_bits(aqt->regmap, AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG,
+			   0x01, 0x01);
+
+	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_CLK_CFG_MCLK,
+			   0x04, 0x00);
+
+	/* Add 100usec delay as per HW requirement */
+	usleep_range(100, 110);
+	regmap_update_bits(aqt->regmap, AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
+			   0x01, 0x01);
+	regmap_update_bits(aqt->regmap, AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
+			   0x01, 0x01);
+	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG,
+			   0x01, 0x01);
+
+	/* Codec digital reset */
+	regmap_update_bits(aqt->regmap, AQT1000_CHIP_CFG0_RST_CTL, 0x01, 0x01);
+	/* Add 100usec delay as per HW requirement */
+	usleep_range(100, 110);
+
+	return 0;
+}
+
+static int aqt1000_device_init(struct aqt1000 *aqt)
+{
+	int ret = 0;
+
+	mutex_init(&aqt->io_lock);
+	mutex_init(&aqt->xfer_lock);
+	mutex_init(&aqt->cdc_bg_clk_lock);
+	mutex_init(&aqt->master_bias_lock);
+
+	ret = aqt1000_bringup(aqt);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto done;
+	}
+
+	ret = aqt_irq_init(aqt);
+	if (ret)
+		goto done;
+
+	return ret;
+done:
+	mutex_destroy(&aqt->io_lock);
+	mutex_destroy(&aqt->xfer_lock);
+	mutex_destroy(&aqt->cdc_bg_clk_lock);
+	mutex_destroy(&aqt->master_bias_lock);
+	return ret;
+}
+
+static int aqt1000_i2c_write(struct aqt1000 *aqt1000, unsigned short reg,
+			     void *val, int bytes)
+{
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	u8 data[bytes + 1];
+	struct aqt1000_i2c *aqt1000_i2c;
+	u8 *value = (u8 *)val;
+
+	aqt1000_i2c = &aqt1000->i2c_dev;
+	if (aqt1000_i2c == NULL || aqt1000_i2c->client == NULL) {
+		pr_err("%s: Failed to get device info\n", __func__);
+		return -ENODEV;
+	}
+	reg_addr = (u8)reg;
+	msg = &aqt1000_i2c->xfer_msg[0];
+	msg->addr = aqt1000_i2c->client->addr;
+	msg->len = bytes + 1;
+	msg->flags = 0;
+	data[0] = reg;
+	data[1] = *value;
+	msg->buf = data;
+	ret = i2c_transfer(aqt1000_i2c->client->adapter,
+			   aqt1000_i2c->xfer_msg, 1);
+	/* Try again if the write fails */
+	if (ret != 1) {
+		ret = i2c_transfer(aqt1000_i2c->client->adapter,
+						aqt1000_i2c->xfer_msg, 1);
+		if (ret != 1) {
+			dev_err(aqt1000->dev,
+				"%s: I2C write failed, reg: 0x%x ret: %d\n",
+				__func__, reg, ret);
+			return ret;
+		}
+	}
+	dev_dbg(aqt1000->dev, "%s: write success register = %x val = %x\n",
+		__func__, reg, data[1]);
+	return 0;
+}
+
+static int aqt1000_i2c_read(struct aqt1000 *aqt1000, unsigned short reg,
+				  void *dst, int bytes)
+{
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	struct aqt1000_i2c *aqt1000_i2c;
+	u8 i = 0;
+	unsigned char *dest = (unsigned char *)dst;
+
+	aqt1000_i2c = &aqt1000->i2c_dev;
+	if (aqt1000_i2c == NULL || aqt1000_i2c->client == NULL) {
+		pr_err("%s: Failed to get device info\n", __func__);
+		return -ENODEV;
+	}
+	for (i = 0; i < bytes; i++) {
+		reg_addr = (u8)reg++;
+		msg = &aqt1000_i2c->xfer_msg[0];
+		msg->addr = aqt1000_i2c->client->addr;
+		msg->len = 1;
+		msg->flags = 0;
+		msg->buf = &reg_addr;
+
+		msg = &aqt1000_i2c->xfer_msg[1];
+		msg->addr = aqt1000_i2c->client->addr;
+		msg->len = 1;
+		msg->flags = I2C_M_RD;
+		msg->buf = dest++;
+		ret = i2c_transfer(aqt1000_i2c->client->adapter,
+				aqt1000_i2c->xfer_msg, 2);
+
+		/* Try again if read fails first time */
+		if (ret != 2) {
+			ret = i2c_transfer(aqt1000_i2c->client->adapter,
+					   aqt1000_i2c->xfer_msg, 2);
+			if (ret != 2) {
+				dev_err(aqt1000->dev,
+					"%s: I2C read failed, reg: 0x%x\n",
+					__func__, reg);
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+static int aqt1000_reset(struct device *dev)
+{
+	struct aqt1000 *aqt1000;
+	int rc = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	aqt1000 = dev_get_drvdata(dev);
+	if (!aqt1000)
+		return -EINVAL;
+
+	if (!aqt1000->aqt_rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (!msm_cdc_pinctrl_get_state(aqt1000->aqt_rst_np)) {
+		rc = msm_cdc_pinctrl_select_sleep_state(aqt1000->aqt_rst_np);
+		if (rc) {
+			dev_err(dev, "%s: aqt sleep state request fail!\n",
+				__func__);
+			return rc;
+		}
+
+		/* 20ms sleep required after pulling the reset gpio to LOW */
+		msleep(20);
+
+		rc = msm_cdc_pinctrl_select_active_state(aqt1000->aqt_rst_np);
+		if (rc) {
+			dev_err(dev,
+				"%s: aqt active state request fail, ret: %d\n",
+				__func__, rc);
+			return rc;
+		}
+		/* 20ms sleep required after pulling the reset gpio to HIGH */
+		msleep(20);
+	}
+
+	return rc;
+}
+
+static int aqt1000_read_of_property_u32(struct device *dev, const char *name,
+					u32 *val)
+{
+	int rc = 0;
+
+	rc = of_property_read_u32(dev->of_node, name, val);
+	if (rc)
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, name, dev->of_node->full_name);
+
+	return rc;
+}
+
+static void aqt1000_dt_parse_micbias_info(struct device *dev,
+					  struct aqt1000_micbias_setting *mb)
+{
+	u32 prop_val;
+	int rc;
+
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-ldoh-v", NULL)) {
+		rc = aqt1000_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-ldoh-v",
+						  &prop_val);
+		if (!rc)
+			mb->ldoh_v  =  (u8)prop_val;
+	}
+
+	/* MB1 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-cfilt1-mv",
+			     NULL)) {
+		rc = aqt1000_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-cfilt1-mv",
+						   &prop_val);
+		if (!rc)
+			mb->cfilt1_mv = prop_val;
+
+		rc = aqt1000_read_of_property_u32(dev,
+						"qcom,cdc-micbias1-cfilt-sel",
+						&prop_val);
+		if (!rc)
+			mb->bias1_cfilt_sel = (u8)prop_val;
+
+	} else if (of_find_property(dev->of_node, "qcom,cdc-micbias1-mv",
+				    NULL)) {
+		rc = aqt1000_read_of_property_u32(dev,
+						  "qcom,cdc-micbias1-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb1_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias1 DT property not found\n",
+			__func__);
+	}
+
+	/* Print micbias info */
+	dev_dbg(dev, "%s: ldoh_v %u cfilt1_mv %u micb1_mv %u \n", __func__,
+		(u32)mb->ldoh_v, (u32)mb->cfilt1_mv, (u32)mb->micb1_mv);
+}
+
+static struct aqt1000_pdata *aqt1000_populate_dt_data(struct device *dev)
+{
+	struct aqt1000_pdata *pdata;
+	u32 prop_val;
+
+	if (!dev || !dev->of_node)
+		return NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(struct aqt1000_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	/* Parse power supplies */
+	msm_cdc_get_power_supplies(dev, &pdata->regulator,
+				   &pdata->num_supplies);
+	if (!pdata->regulator || (pdata->num_supplies <= 0)) {
+		dev_err(dev, "%s: no power supplies defined for codec\n",
+			__func__);
+		goto err_power_sup;
+	}
+
+	/* Parse micbias info */
+	aqt1000_dt_parse_micbias_info(dev, &pdata->micbias);
+
+	pdata->aqt_rst_np = of_parse_phandle(dev->of_node,
+					     "qcom,aqt-rst-gpio-node", 0);
+	if (!pdata->aqt_rst_np) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,aqt-rst-gpio-node",
+			dev->of_node->full_name);
+		goto err_parse_dt_prop;
+	}
+
+	if (!(aqt1000_read_of_property_u32(dev, "qcom,cdc-ext-clk-rate",
+					   &prop_val)))
+		pdata->ext_clk_rate = prop_val;
+	if (pdata->ext_clk_rate != AQT1000_CLK_24P576MHZ &&
+	    pdata->ext_clk_rate != AQT1000_CLK_19P2MHZ &&
+	    pdata->ext_clk_rate != AQT1000_CLK_12P288MHZ) {
+		/* Use the default ext_clk_rate if the DT value is wrong */
+		pdata->ext_clk_rate = AQT1000_CLK_9P6MHZ;
+	}
+
+	prop_val = 0;
+	if (!(aqt1000_read_of_property_u32(dev, "qcom,cdc-mclk-clk-rate",
+					   &prop_val)))
+		pdata->mclk_rate = prop_val;
+
+	if (pdata->mclk_rate != AQT1000_CLK_9P6MHZ &&
+	    pdata->mclk_rate != AQT1000_CLK_12P288MHZ) {
+		dev_err(dev, "%s: Invalid mclk_rate = %u\n", __func__,
+			pdata->mclk_rate);
+		goto err_parse_dt_prop;
+	}
+	if (pdata->ext_clk_rate % pdata->mclk_rate) {
+		dev_err(dev,
+			"%s: Invalid clock group, ext_clk = %d mclk = %d\n",
+			__func__, pdata->ext_clk_rate, pdata->mclk_rate);
+		goto err_parse_dt_prop;
+	}
+
+	pdata->irq_gpio = of_get_named_gpio(dev->of_node,
+					    "qcom,gpio-connect", 0);
+	if (!gpio_is_valid(pdata->irq_gpio)) {
+		dev_err(dev, "%s: TLMM connect gpio not found\n", __func__);
+		goto err_parse_dt_prop;
+	}
+
+	return pdata;
+
+err_parse_dt_prop:
+	devm_kfree(dev, pdata->regulator);
+	pdata->regulator = NULL;
+	pdata->num_supplies = 0;
+err_power_sup:
+	devm_kfree(dev, pdata);
+	return NULL;
+}
+
+static int aqt1000_bringdown(struct device *dev)
+{
+	/* No sequence for teardown */
+
+	return 0;
+}
+
+static void aqt1000_device_exit(struct aqt1000 *aqt)
+{
+	aqt_irq_exit(aqt);
+	aqt1000_bringdown(aqt->dev);
+	mutex_destroy(&aqt->io_lock);
+	mutex_destroy(&aqt->xfer_lock);
+	mutex_destroy(&aqt->cdc_bg_clk_lock);
+	mutex_destroy(&aqt->master_bias_lock);
+}
+
+static int aqt1000_i2c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct aqt1000 *aqt1000 = NULL;
+	struct aqt1000_pdata *pdata = NULL;
+	int ret = 0;
+
+	pdata = aqt1000_populate_dt_data(&client->dev);
+	if (!pdata) {
+		dev_err(&client->dev,
+			"%s: Fail to obtain pdata from device tree\n",
+			__func__);
+		ret = -EINVAL;
+		goto fail;
+	}
+	client->dev.platform_data = pdata;
+
+	aqt1000 = devm_kzalloc(&client->dev, sizeof(struct aqt1000),
+			       GFP_KERNEL);
+	if (!aqt1000) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	aqt1000->regmap = aqt1000_regmap_init(&client->dev,
+			&aqt1000_regmap_config);
+	if (IS_ERR(aqt1000->regmap)) {
+		ret = PTR_ERR(aqt1000->regmap);
+		dev_err(&client->dev,
+			"%s: Failed to init register map: %d\n",
+			__func__, ret);
+		goto fail;
+	}
+	aqt1000->aqt_rst_np = pdata->aqt_rst_np;
+	if (!aqt1000->aqt_rst_np) {
+		dev_err(&client->dev, "%s: pinctrl not used for rst_n\n",
+			__func__);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (i2c_check_functionality(client->adapter,
+				    I2C_FUNC_I2C) == 0) {
+		dev_dbg(&client->dev, "%s: can't talk I2C?\n", __func__);
+		ret = -EIO;
+		goto fail;
+	}
+	dev_set_drvdata(&client->dev, aqt1000);
+	aqt1000->dev = &client->dev;
+	aqt1000->dev_up = true;
+	aqt1000->mclk_rate = pdata->mclk_rate;
+	aqt1000->irq = client->irq;
+
+	aqt1000->num_of_supplies = pdata->num_supplies;
+	ret = msm_cdc_init_supplies(aqt1000->dev, &aqt1000->supplies,
+				    pdata->regulator,
+				    pdata->num_supplies);
+	if (!aqt1000->supplies) {
+		dev_err(aqt1000->dev, "%s: Cannot init aqt supplies\n",
+			__func__);
+		goto err_codec;
+	}
+	ret = msm_cdc_enable_static_supplies(aqt1000->dev,
+					     aqt1000->supplies,
+					     pdata->regulator,
+					     pdata->num_supplies);
+	if (ret) {
+		dev_err(aqt1000->dev, "%s: aqt static supply enable failed!\n",
+			__func__);
+		goto err_codec;
+	}
+	/* 5 usec sleep is needed as per HW requirement */
+	usleep_range(5, 10);
+
+	ret = aqt1000_reset(aqt1000->dev);
+	if (ret) {
+		dev_err(aqt1000->dev, "%s: Codec reset failed\n", __func__);
+		goto err_supplies;
+	}
+
+	aqt1000->i2c_dev.client = client;
+	aqt1000->read_dev = aqt1000_i2c_read;
+	aqt1000->write_dev = aqt1000_i2c_write;
+
+	ret = aqt1000_device_init(aqt1000);
+	if (ret) {
+		pr_err("%s: error, initializing device failed (%d)\n",
+		       __func__, ret);
+		goto err_supplies;
+	}
+
+	pm_runtime_set_active(aqt1000->dev);
+	pm_runtime_enable(aqt1000->dev);
+
+	ret = aqt_register_codec(&client->dev);
+	if (ret) {
+		dev_err(aqt1000->dev, "%s: Codec registration failed\n",
+			 __func__);
+		goto err_cdc_register;
+	}
+
+	return ret;
+
+err_cdc_register:
+	pm_runtime_disable(aqt1000->dev);
+	aqt1000_device_exit(aqt1000);
+err_supplies:
+	msm_cdc_release_supplies(aqt1000->dev, aqt1000->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+	pdata->regulator = NULL;
+	pdata->num_supplies = 0;
+err_codec:
+	devm_kfree(&client->dev, aqt1000);
+	dev_set_drvdata(&client->dev, NULL);
+fail:
+	return ret;
+}
+
+static int aqt1000_i2c_remove(struct i2c_client *client)
+{
+	struct aqt1000 *aqt;
+	struct aqt1000_pdata *pdata = client->dev.platform_data;
+
+	aqt = dev_get_drvdata(&client->dev);
+
+	pm_runtime_disable(aqt->dev);
+	msm_cdc_release_supplies(aqt->dev, aqt->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+	aqt1000_device_exit(aqt);
+	dev_set_drvdata(&client->dev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int aqt1000_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "%s system resume\n", __func__);
+
+	return 0;
+}
+
+static int aqt1000_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "%s system suspend\n", __func__);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int aqt1000_i2c_resume(struct device *dev)
+{
+	pr_debug("%s system resume\n", __func__);
+	return 0;
+}
+
+static int aqt1000_i2c_suspend(struct device *dev)
+{
+	pr_debug("%s system suspend\n", __func__);
+	return 0;
+}
+#endif
+
+static struct i2c_device_id aqt1000_id_table[] = {
+	{"aqt1000-i2c", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, aqt1000_id_table);
+
+static const struct dev_pm_ops aqt1000_i2c_pm_ops = {
+	SET_RUNTIME_PM_OPS(aqt1000_runtime_suspend,
+			   aqt1000_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(aqt1000_i2c_suspend,
+				aqt1000_i2c_resume)
+};
+
+static const struct of_device_id aqt_match_table[] = {
+	{.compatible = "qcom,aqt1000-i2c-codec"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, aqt_match_table);
+
+static struct i2c_driver aqt1000_i2c_driver = {
+	.driver                 = {
+		.owner          =       THIS_MODULE,
+		.name           =       "aqt1000-i2c-codec",
+#ifdef CONFIG_PM_SLEEP
+		.pm             =       &aqt1000_i2c_pm_ops,
+#endif
+		.of_match_table =       aqt_match_table,
+	},
+	.id_table               =       aqt1000_id_table,
+	.probe                  =       aqt1000_i2c_probe,
+	.remove                 =       aqt1000_i2c_remove,
+};
+
+static int __init aqt1000_init(void)
+{
+	return i2c_add_driver(&aqt1000_i2c_driver);
+}
+module_init(aqt1000_init);
+
+static void __exit aqt1000_exit(void)
+{
+	i2c_del_driver(&aqt1000_i2c_driver);
+}
+module_exit(aqt1000_exit);
+
+MODULE_DESCRIPTION("AQT1000 Codec driver");
+MODULE_LICENSE("GPL v2");

+ 162 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-internal.h

@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _AQT1000_INTERNAL_H
+#define _AQT1000_INTERNAL_H
+
+#include <linux/types.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#define AQT1000_RATES_MASK (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 AQT1000_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+				 SNDRV_PCM_RATE_176400)
+
+#define AQT1000_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
+				    SNDRV_PCM_FMTBIT_S24_LE)
+
+#define AQT1000_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \
+					SNDRV_PCM_FMTBIT_S24_LE | \
+					SNDRV_PCM_FMTBIT_S32_LE)
+
+#define AQT1000_FORMATS_S16_LE (SNDRV_PCM_FMTBIT_S16_LE)
+
+/* Macros for packing register writes into a U32 */
+#define AQT1000_PACKED_REG_SIZE sizeof(u32)
+#define AQT1000_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+	do { \
+		((reg) = ((packed >> 16) & (0xffff))); \
+		((mask) = ((packed >> 8) & (0xff))); \
+		((val) = ((packed) & (0xff))); \
+	} while (0)
+
+#define STRING(name) #name
+#define AQT_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define AQT_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define AQT_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+
+#define AQT1000_INTERP_MUX_NUM_INPUTS 3
+#define AQT1000_RX_PATH_CTL_OFFSET 20
+
+#define BYTE_BIT_MASK(nr) (1 << ((nr) % BITS_PER_BYTE))
+
+#define AQT1000_REG_BITS 8
+#define AQT1000_MAX_VALID_ADC_MUX  3
+
+#define AQT1000_AMIC_PWR_LEVEL_LP 0
+#define AQT1000_AMIC_PWR_LEVEL_DEFAULT 1
+#define AQT1000_AMIC_PWR_LEVEL_HP 2
+#define AQT1000_AMIC_PWR_LVL_MASK 0x60
+#define AQT1000_AMIC_PWR_LVL_SHIFT 0x5
+
+#define AQT1000_DEC_PWR_LVL_MASK 0x06
+#define AQT1000_DEC_PWR_LVL_DF 0x00
+#define AQT1000_DEC_PWR_LVL_LP 0x02
+#define AQT1000_DEC_PWR_LVL_HP 0x04
+#define AQT1000_STRING_LEN 100
+
+#define AQT1000_CDC_SIDETONE_IIR_COEFF_MAX 5
+
+#define AQT1000_MAX_MICBIAS 1
+#define DAPM_MICBIAS1_STANDALONE "MIC BIAS1 Standalone"
+
+#define  TX_HPF_CUT_OFF_FREQ_MASK    0x60
+#define  CF_MIN_3DB_4HZ              0x0
+#define  CF_MIN_3DB_75HZ             0x1
+#define  CF_MIN_3DB_150HZ            0x2
+
+enum {
+	AUDIO_NOMINAL,
+	HPH_PA_DELAY,
+	CLSH_Z_CONFIG,
+	ANC_MIC_AMIC1,
+	ANC_MIC_AMIC2,
+	ANC_MIC_AMIC3,
+};
+
+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,
+};
+
+enum {
+	INTn_2_INP_SEL_ZERO = 0,
+	INTn_2_INP_SEL_RX0,
+	INTn_2_INP_SEL_RX1,
+	INTn_2_INP_SEL_PROXIMITY,
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+	IIR0 = 0,
+	IIR1,
+	IIR_MAX,
+};
+
+enum {
+	ASRC_IN_HPHL,
+	ASRC_IN_HPHR,
+	ASRC_INVALID,
+};
+
+enum {
+	CONV_88P2K_TO_384K,
+	CONV_96K_TO_352P8K,
+	CONV_352P8K_TO_384K,
+	CONV_384K_TO_352P8K,
+	CONV_384K_TO_384K,
+	CONV_96K_TO_384K,
+};
+
+enum aqt_notify_event {
+	AQT_EVENT_INVALID,
+	/* events for micbias ON and OFF */
+	AQT_EVENT_PRE_MICBIAS_1_OFF,
+	AQT_EVENT_POST_MICBIAS_1_OFF,
+	AQT_EVENT_PRE_MICBIAS_1_ON,
+	AQT_EVENT_POST_MICBIAS_1_ON,
+	AQT_EVENT_PRE_DAPM_MICBIAS_1_OFF,
+	AQT_EVENT_POST_DAPM_MICBIAS_1_OFF,
+	AQT_EVENT_PRE_DAPM_MICBIAS_1_ON,
+	AQT_EVENT_POST_DAPM_MICBIAS_1_ON,
+	/* events for PA ON and OFF */
+	AQT_EVENT_PRE_HPHL_PA_ON,
+	AQT_EVENT_POST_HPHL_PA_OFF,
+	AQT_EVENT_PRE_HPHR_PA_ON,
+	AQT_EVENT_POST_HPHR_PA_OFF,
+	AQT_EVENT_PRE_HPHL_PA_OFF,
+	AQT_EVENT_PRE_HPHR_PA_OFF,
+	AQT_EVENT_OCP_OFF,
+	AQT_EVENT_OCP_ON,
+	AQT_EVENT_LAST,
+};
+
+struct interp_sample_rate {
+	int sample_rate;
+	int rate_val;
+};
+
+extern struct regmap_config aqt1000_regmap_config;
+extern int aqt_register_codec(struct device *dev);
+
+#endif /* _AQT1000_INTERNAL_H */

+ 283 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-irq.c

@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+
+#include "pdata.h"
+#include "aqt1000.h"
+
+#include "aqt1000-registers.h"
+#include "aqt1000-irq.h"
+
+static const struct regmap_irq aqt1000_irqs[AQT1000_NUM_IRQS] = {
+	REGMAP_IRQ_REG(AQT1000_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x01),
+	REGMAP_IRQ_REG(AQT1000_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x02),
+	REGMAP_IRQ_REG(AQT1000_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04),
+	REGMAP_IRQ_REG(AQT1000_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08),
+	REGMAP_IRQ_REG(AQT1000_IRQ_MBHC_SW_DET, 0, 0x10),
+	REGMAP_IRQ_REG(AQT1000_IRQ_HPH_PA_OCPL_FAULT, 0, 0x20),
+	REGMAP_IRQ_REG(AQT1000_IRQ_HPH_PA_OCPR_FAULT, 0, 0x40),
+	REGMAP_IRQ_REG(AQT1000_IRQ_HPH_PA_CNPL_COMPLETE, 0, 0x80),
+	REGMAP_IRQ_REG(AQT1000_IRQ_HPH_PA_CNPR_COMPLETE, 1, 0x01),
+	REGMAP_IRQ_REG(AQT1000_CDC_HPHL_SURGE, 1, 0x02),
+	REGMAP_IRQ_REG(AQT1000_CDC_HPHR_SURGE, 1, 0x04),
+};
+
+static const struct regmap_irq_chip aqt_regmap_irq_chip = {
+	.name = "AQT1000",
+	.irqs = aqt1000_irqs,
+	.num_irqs = ARRAY_SIZE(aqt1000_irqs),
+	.num_regs = 2,
+	.status_base = AQT1000_INTR_CTRL_INT_STATUS_2,
+	.mask_base = AQT1000_INTR_CTRL_INT_MASK_2,
+	.unmask_base = AQT1000_INTR_CTRL_INT_CLEAR_2,
+	.ack_base = AQT1000_INTR_CTRL_INT_STATUS_2,
+	.runtime_pm = true,
+};
+
+static int aqt_map_irq(struct aqt1000 *aqt, int irq)
+{
+	return regmap_irq_get_virq(aqt->irq_chip, irq);
+}
+
+/**
+ * aqt_request_irq: Request a thread handler for the given IRQ
+ * @aqt: pointer to aqt1000 structure
+ * @irq: irq number
+ * @name: name for the IRQ thread
+ * @handler: irq handler
+ * @data: data pointer
+ *
+ * Returns 0 on success or error on failure
+ */
+int aqt_request_irq(struct aqt1000 *aqt, int irq, const char *name,
+			irq_handler_t handler, void *data)
+{
+	irq = aqt_map_irq(aqt, irq);
+	if (irq < 0)
+		return irq;
+
+	return request_threaded_irq(irq, NULL, handler,
+				    IRQF_ONESHOT | IRQF_TRIGGER_RISING,
+				    name, data);
+}
+EXPORT_SYMBOL(aqt_request_irq);
+
+/**
+ * aqt_free_irq: Free the IRQ resources allocated during request_irq
+ * @aqt: pointer to aqt1000 structure
+ * @irq: irq number
+ * @data: data pointer
+ */
+void aqt_free_irq(struct aqt1000 *aqt, int irq, void *data)
+{
+	irq = aqt_map_irq(aqt, irq);
+	if (irq < 0)
+		return;
+
+	free_irq(irq, data);
+}
+EXPORT_SYMBOL(aqt_free_irq);
+
+/**
+ * aqt_enable_irq: Enable the given IRQ
+ * @aqt: pointer to aqt1000 structure
+ * @irq: irq number
+ */
+void aqt_enable_irq(struct aqt1000 *aqt, int irq)
+{
+	if (aqt)
+		enable_irq(aqt_map_irq(aqt, irq));
+}
+EXPORT_SYMBOL(aqt_enable_irq);
+
+/**
+ * aqt_disable_irq: Disable the given IRQ
+ * @aqt: pointer to aqt1000 structure
+ * @irq: irq number
+ */
+void aqt_disable_irq(struct aqt1000 *aqt, int irq)
+{
+	if (aqt)
+		disable_irq(aqt_map_irq(aqt, irq));
+}
+EXPORT_SYMBOL(aqt_disable_irq);
+
+static irqreturn_t aqt_irq_thread(int irq, void *data)
+{
+	int ret = 0;
+	u8 sts[2];
+	struct aqt1000 *aqt = data;
+	int num_irq_regs = aqt->num_irq_regs;
+	struct aqt1000_pdata *pdata;
+
+	pdata = dev_get_platdata(aqt->dev);
+
+	memset(sts, 0, sizeof(sts));
+	ret = regmap_bulk_read(aqt->regmap, AQT1000_INTR_CTRL_INT_STATUS_2,
+				sts, num_irq_regs);
+	if (ret < 0) {
+		dev_err(aqt->dev, "%s: Failed to read intr status: %d\n",
+			__func__, ret);
+	} else if (ret == 0) {
+		while (gpio_get_value_cansleep(pdata->irq_gpio))
+			handle_nested_irq(irq_find_mapping(aqt->virq, 0));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void aqt_irq_disable(struct irq_data *data)
+{
+}
+
+static void aqt_irq_enable(struct irq_data *data)
+{
+}
+
+static struct irq_chip aqt_irq_chip = {
+	.name = "AQT",
+	.irq_disable = aqt_irq_disable,
+	.irq_enable = aqt_irq_enable,
+};
+
+static struct lock_class_key aqt_irq_lock_class;
+static struct lock_class_key aqt_irq_lock_requested_class;
+
+static int aqt_irq_map(struct irq_domain *irqd, unsigned int virq,
+			irq_hw_number_t hw)
+{
+	struct aqt1000 *data = irqd->host_data;
+
+	irq_set_chip_data(virq, data);
+	irq_set_chip_and_handler(virq, &aqt_irq_chip, handle_simple_irq);
+	irq_set_lockdep_class(virq, &aqt_irq_lock_class,
+			      &aqt_irq_lock_requested_class);
+	irq_set_nested_thread(virq, 1);
+	irq_set_noprobe(virq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops aqt_domain_ops = {
+	.map = aqt_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+/**
+ * aqt_irq_init: Initializes IRQ module
+ * @aqt: pointer to aqt1000 structure
+ *
+ * Returns 0 on success or error on failure
+ */
+int aqt_irq_init(struct aqt1000 *aqt)
+{
+	int i, ret;
+	unsigned int flags = IRQF_ONESHOT;
+	struct irq_data *irq_data;
+	struct aqt1000_pdata *pdata;
+
+	if (!aqt) {
+		pr_err("%s: Null pointer handle\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = dev_get_platdata(aqt->dev);
+	if (!pdata) {
+		dev_err(aqt->dev, "%s: Invalid platform data\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Select default if not defined in DT */
+	flags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
+	if (pdata->irq_flags)
+		flags = pdata->irq_flags;
+
+	if (pdata->irq_gpio) {
+		aqt->irq = gpio_to_irq(pdata->irq_gpio);
+		ret = devm_gpio_request_one(aqt->dev, pdata->irq_gpio,
+					    GPIOF_IN, "AQT IRQ");
+		if (ret) {
+			dev_err(aqt->dev, "%s: Failed to request gpio %d\n",
+				__func__, ret);
+			pdata->irq_gpio = 0;
+			return ret;
+		}
+	}
+
+	irq_data = irq_get_irq_data(aqt->irq);
+	if (!irq_data) {
+		dev_err(aqt->dev, "%s: Invalid IRQ: %d\n",
+			__func__, aqt->irq);
+		return -EINVAL;
+	}
+
+	aqt->num_irq_regs = aqt_regmap_irq_chip.num_regs;
+	for (i = 0; i < aqt->num_irq_regs; i++) {
+		regmap_write(aqt->regmap,
+			     (AQT1000_INTR_CTRL_INT_TYPE_2 + i), 0);
+	}
+
+	aqt->virq = irq_domain_add_linear(NULL, 1, &aqt_domain_ops, aqt);
+	if (!aqt->virq) {
+		dev_err(aqt->dev, "%s: Failed to add IRQ domain\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = regmap_add_irq_chip(aqt->regmap,
+				  irq_create_mapping(aqt->virq, 0),
+				  IRQF_ONESHOT, 0, &aqt_regmap_irq_chip,
+				  &aqt->irq_chip);
+	if (ret) {
+		dev_err(aqt->dev, "%s: Failed to add IRQs: %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = request_threaded_irq(aqt->irq, NULL, aqt_irq_thread, flags,
+				   "aqt", aqt);
+	if (ret) {
+		dev_err(aqt->dev, "%s: failed to register irq: %d\n",
+			__func__, ret);
+		goto err_irq;
+	}
+
+	return 0;
+
+err_irq:
+	regmap_del_irq_chip(irq_create_mapping(aqt->virq, 1), aqt->irq_chip);
+err:
+	return ret;
+}
+EXPORT_SYMBOL(aqt_irq_init);
+
+/**
+ * aqt_irq_exit: Uninitialize regmap IRQ and free IRQ resources
+ * @aqt: pointer to aqt1000 structure
+ *
+ * Returns 0 on success or error on failure
+ */
+int aqt_irq_exit(struct aqt1000 *aqt)
+{
+	if (!aqt) {
+		pr_err("%s: Null pointer handle\n", __func__);
+		return -EINVAL;
+	}
+	regmap_del_irq_chip(irq_create_mapping(aqt->virq, 1), aqt->irq_chip);
+	free_irq(aqt->irq, aqt);
+
+	return 0;
+}
+EXPORT_SYMBOL(aqt_irq_exit);

+ 38 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-irq.h

@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __AQT1000_IRQ_H_
+#define __AQT1000_IRQ_H_
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+
+enum {
+	/* INTR_CTRL_INT_MASK_2 */
+	AQT1000_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
+	AQT1000_IRQ_MBHC_BUTTON_PRESS_DET,
+	AQT1000_IRQ_MBHC_ELECT_INS_REM_DET,
+	AQT1000_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	AQT1000_IRQ_MBHC_SW_DET,
+	AQT1000_IRQ_HPH_PA_OCPL_FAULT,
+	AQT1000_IRQ_HPH_PA_OCPR_FAULT,
+	AQT1000_IRQ_HPH_PA_CNPL_COMPLETE,
+
+	/* INTR_CTRL_INT_MASK_3 */
+	AQT1000_IRQ_HPH_PA_CNPR_COMPLETE,
+	AQT1000_CDC_HPHL_SURGE,
+	AQT1000_CDC_HPHR_SURGE,
+	AQT1000_NUM_IRQS,
+};
+
+int aqt_request_irq(struct aqt1000 *aqt, int irq, const char *name,
+			irq_handler_t handler, void *data);
+void aqt_free_irq(struct aqt1000 *aqt, int irq, void *data);
+int aqt_irq_init(struct aqt1000 *aqt);
+int aqt_irq_exit(struct aqt1000 *aqt);
+void aqt_enable_irq(struct aqt1000 *aqt, int irq);
+void aqt_disable_irq(struct aqt1000 *aqt, int irq);
+
+#endif /* __AQT1000_IRQ_H_ */

+ 1088 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-mbhc.c

@@ -0,0 +1,1088 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include "aqt1000.h"
+#include "aqt1000-api.h"
+#include "aqt1000-mbhc.h"
+#include "aqt1000-registers.h"
+#include "aqt1000-irq.h"
+#include "pdata.h"
+#include <asoc/wcdcal-hwdep.h>
+#include <asoc/wcd-mbhc-v2-api.h>
+
+#define AQT_ZDET_SUPPORTED          true
+/* Z value defined in milliohm */
+#define AQT_ZDET_VAL_32             32000
+#define AQT_ZDET_VAL_400            400000
+#define AQT_ZDET_VAL_1200           1200000
+#define AQT_ZDET_VAL_100K           100000000
+/* Z floating defined in ohms */
+#define AQT_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE
+
+#define AQT_ZDET_NUM_MEASUREMENTS   900
+#define AQT_MBHC_GET_C1(c)          ((c & 0xC000) >> 14)
+#define AQT_MBHC_GET_X1(x)          (x & 0x3FFF)
+/* Z value compared in milliOhm */
+#define AQT_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000))
+#define AQT_MBHC_ZDET_CONST         (86 * 16384)
+#define AQT_MBHC_MOISTURE_RREF      R_24_KOHM
+
+static struct wcd_mbhc_register
+	wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
+	WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
+			  AQT1000_ANA_MBHC_MECH, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_DET_EN",
+			  AQT1000_ANA_MBHC_MECH, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MECH_DETECTION_TYPE",
+			  AQT1000_ANA_MBHC_MECH, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_CLAMP_CTL",
+			  AQT1000_MBHC_NEW_PLUG_DETECT_CTL, 0x30, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_DETECTION_TYPE",
+			  AQT1000_ANA_MBHC_ELECT, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_CTRL",
+			  AQT1000_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL",
+			  AQT1000_ANA_MBHC_MECH, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PLUG_TYPE",
+			  AQT1000_ANA_MBHC_MECH, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_PLUG_TYPE",
+			  AQT1000_ANA_MBHC_MECH, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SW_HPH_LP_100K_TO_GND",
+			  AQT1000_ANA_MBHC_MECH, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_SCHMT_ISRC",
+			  AQT1000_ANA_MBHC_ELECT, 0x06, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_EN",
+			  AQT1000_ANA_MBHC_ELECT, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_INSREM_DBNC",
+			  AQT1000_MBHC_NEW_PLUG_DETECT_CTL, 0x0F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_DBNC",
+			  AQT1000_MBHC_NEW_CTL_1, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_VREF",
+			  AQT1000_MBHC_NEW_CTL_2, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_COMP_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_SCHMT_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_SCHMT_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_SCHMT_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_OCP_FSM_EN",
+			  AQT1000_HPH_OCP_CTL, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x07, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_ISRC_CTL",
+			  AQT1000_ANA_MBHC_ELECT, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
+			  AQT1000_ANA_MBHC_RESULT_3, 0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
+			  AQT1000_ANA_MICB1, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
+			  AQT1000_HPH_CNP_WG_TIME, 0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
+			  AQT1000_ANA_HPH, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PA_EN",
+			  AQT1000_ANA_HPH, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_PA_EN",
+			  AQT1000_ANA_HPH, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
+			  AQT1000_ANA_MBHC_RESULT_3, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_PULLDOWN_CTRL",
+			  0, 0, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ANC_DET_EN",
+			  AQT1000_MBHC_CTL_BCS, 0x02, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_STATUS",
+			  AQT1000_MBHC_NEW_FSM_STATUS, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
+			  AQT1000_MBHC_NEW_CTL_2, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_DET_EN",
+			  AQT1000_HPH_L_TEST, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_DET_EN",
+			  AQT1000_HPH_R_TEST, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_STATUS",
+			  AQT1000_INTR_CTRL_INT_STATUS_2, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_STATUS",
+			  AQT1000_INTR_CTRL_INT_STATUS_2, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_EN",
+			  AQT1000_MBHC_NEW_CTL_1, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_COMPLETE", AQT1000_MBHC_NEW_FSM_STATUS,
+			  0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_TIMEOUT", AQT1000_MBHC_NEW_FSM_STATUS,
+			  0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_RESULT", AQT1000_MBHC_NEW_ADC_RESULT,
+			  0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB2_VOUT", AQT1000_ANA_MICB1, 0x3F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_MODE",
+			  AQT1000_MBHC_NEW_CTL_1, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_DETECTION_DONE",
+			  AQT1000_MBHC_NEW_CTL_1, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_ISRC_EN",
+			  AQT1000_ANA_MBHC_ZDET, 0x02, 1, 0),
+};
+
+static const struct wcd_mbhc_intr intr_ids = {
+	.mbhc_sw_intr =  AQT1000_IRQ_MBHC_SW_DET,
+	.mbhc_btn_press_intr = AQT1000_IRQ_MBHC_BUTTON_PRESS_DET,
+	.mbhc_btn_release_intr = AQT1000_IRQ_MBHC_BUTTON_RELEASE_DET,
+	.mbhc_hs_ins_intr = AQT1000_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	.mbhc_hs_rem_intr = AQT1000_IRQ_MBHC_ELECT_INS_REM_DET,
+	.hph_left_ocp = AQT1000_IRQ_HPH_PA_OCPL_FAULT,
+	.hph_right_ocp = AQT1000_IRQ_HPH_PA_OCPR_FAULT,
+};
+
+struct aqt_mbhc_zdet_param {
+	u16 ldo_ctl;
+	u16 noff;
+	u16 nshift;
+	u16 btn5;
+	u16 btn6;
+	u16 btn7;
+};
+
+static int aqt_mbhc_request_irq(struct snd_soc_component *component,
+				  int irq, irq_handler_t handler,
+				  const char *name, void *data)
+{
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+
+	return aqt_request_irq(aqt, irq, name, handler, data);
+}
+
+static void aqt_mbhc_irq_control(struct snd_soc_component *component,
+				   int irq, bool enable)
+{
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+
+	if (enable)
+		aqt_enable_irq(aqt, irq);
+	else
+		aqt_disable_irq(aqt, irq);
+}
+
+static int aqt_mbhc_free_irq(struct snd_soc_component *component,
+			       int irq, void *data)
+{
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+
+	aqt_free_irq(aqt, irq, data);
+
+	return 0;
+}
+
+static void aqt_mbhc_clk_setup(struct snd_soc_component *component,
+				 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component,
+				AQT1000_MBHC_NEW_CTL_1,
+				0x80, 0x80);
+	else
+		snd_soc_component_update_bits(component,
+				AQT1000_MBHC_NEW_CTL_1,
+				0x80, 0x00);
+}
+
+static int aqt_mbhc_btn_to_num(struct snd_soc_component *component)
+{
+	return snd_soc_component_read32(component,
+					AQT1000_ANA_MBHC_RESULT_3) & 0x7;
+}
+
+static void aqt_mbhc_mbhc_bias_control(struct snd_soc_component *component,
+					 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MBHC_ELECT,
+				0x01, 0x01);
+	else
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MBHC_ELECT,
+				0x01, 0x00);
+}
+
+static void aqt_mbhc_program_btn_thr(struct snd_soc_component *component,
+				       s16 *btn_low, s16 *btn_high,
+				       int num_btn, bool is_micbias)
+{
+	int i;
+	int vth;
+
+	if (num_btn > WCD_MBHC_DEF_BUTTONS) {
+		dev_err(component->dev, "%s: invalid number of buttons: %d\n",
+			__func__, num_btn);
+		return;
+	}
+
+	for (i = 0; i < num_btn; i++) {
+		vth = ((btn_high[i] * 2) / 25) & 0x3F;
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MBHC_BTN0 + i,
+				0xFC, vth << 2);
+		dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",
+			__func__, i, btn_high[i], vth);
+	}
+}
+
+static bool aqt_mbhc_lock_sleep(struct wcd_mbhc *mbhc, bool lock)
+{
+	struct snd_soc_component *component = mbhc->component;
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+	bool ret = 0;
+
+	dev_dbg(aqt->dev, "%s: lock: %d\n", __func__, lock);
+
+	return ret;
+}
+
+static int aqt_mbhc_register_notifier(struct wcd_mbhc *mbhc,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct aqt1000_mbhc *aqt_mbhc;
+
+	aqt_mbhc = container_of(mbhc, struct aqt1000_mbhc, wcd_mbhc);
+
+	if (enable)
+		return blocking_notifier_chain_register(&aqt_mbhc->notifier,
+							nblock);
+	else
+		return blocking_notifier_chain_unregister(
+				&aqt_mbhc->notifier, nblock);
+}
+
+static bool aqt_mbhc_micb_en_status(struct wcd_mbhc *mbhc, int micb_num)
+{
+	u8 val;
+
+	if (micb_num == MIC_BIAS_1) {
+		val = ((snd_soc_component_read32(
+				mbhc->component, AQT1000_ANA_MICB1) & 0xC0)
+			>> 6);
+		if (val == 0x01)
+			return true;
+	}
+	return false;
+}
+
+static bool aqt_mbhc_hph_pa_on_status(struct snd_soc_component *component)
+{
+	return (snd_soc_component_read32(component, AQT1000_ANA_HPH) & 0xC0) ?
+		true : false;
+}
+
+static void aqt_mbhc_hph_l_pull_up_control(struct snd_soc_component *component,
+					   int pull_up_cur)
+{
+	/* Default pull up current to 2uA */
+	if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA ||
+	    pull_up_cur == HS_PULLUP_I_DEFAULT)
+		pull_up_cur = HS_PULLUP_I_2P0_UA;
+
+	dev_dbg(component->dev, "%s: HS pull up current:%d\n",
+		__func__, pull_up_cur);
+
+	snd_soc_component_update_bits(component,
+			AQT1000_MBHC_NEW_INT_MECH_DET_CURRENT,
+			0x1F, pull_up_cur);
+}
+
+static int aqt_mbhc_request_micbias(struct snd_soc_component *component,
+				      int micb_num, int req)
+{
+	int ret = 0;
+
+	/*
+	 * If micbias is requested, make sure that there
+	 * is vote to enable mclk
+	 */
+	if (req == MICB_ENABLE)
+		aqt_cdc_mclk_enable(component, true);
+
+	ret = aqt_micbias_control(component, micb_num, req, false);
+
+	/*
+	 * Release vote for mclk while requesting for
+	 * micbias disable
+	 */
+	if (req == MICB_DISABLE)
+		aqt_cdc_mclk_enable(component, false);
+
+	return ret;
+}
+
+static void aqt_mbhc_micb_ramp_control(struct snd_soc_component *component,
+					 bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MICB1_RAMP,
+				0x1C, 0x0C);
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MICB1_RAMP,
+				0x80, 0x80);
+	} else {
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MICB1_RAMP,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				AQT1000_ANA_MICB1_RAMP,
+				0x1C, 0x00);
+	}
+}
+
+static struct firmware_cal *aqt_get_hwdep_fw_cal(struct wcd_mbhc *mbhc,
+						   enum wcd_cal_type type)
+{
+	struct aqt1000_mbhc *aqt_mbhc;
+	struct firmware_cal *hwdep_cal;
+	struct snd_soc_component *component = mbhc->component;
+
+	aqt_mbhc = container_of(mbhc, struct aqt1000_mbhc, wcd_mbhc);
+
+	if (!component) {
+		pr_err("%s: NULL codec pointer\n", __func__);
+		return NULL;
+	}
+	hwdep_cal = wcdcal_get_fw_cal(aqt_mbhc->fw_data, type);
+	if (!hwdep_cal)
+		dev_err(component->dev, "%s: cal not sent by %d\n",
+			__func__, type);
+
+	return hwdep_cal;
+}
+
+static int aqt_mbhc_micb_ctrl_threshold_mic(
+			struct snd_soc_component *component,
+			int micb_num, bool req_en)
+{
+	struct aqt1000_pdata *pdata = dev_get_platdata(component->dev);
+	int rc, micb_mv;
+
+	if (micb_num != MIC_BIAS_1)
+		return -EINVAL;
+
+	/*
+	 * If device tree micbias level is already above the minimum
+	 * voltage needed to detect threshold microphone, then do
+	 * not change the micbias, just return.
+	 */
+	if (pdata->micbias.micb1_mv >= WCD_MBHC_THR_HS_MICB_MV)
+		return 0;
+
+	micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : pdata->micbias.micb1_mv;
+
+	rc = aqt_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_1);
+
+	return rc;
+}
+
+static inline void aqt_mbhc_get_result_params(struct aqt1000 *aqt,
+						s16 *d1_a, u16 noff,
+						int32_t *zdet)
+{
+	int i;
+	int val, val1;
+	s16 c1;
+	s32 x1, d1;
+	int32_t denom;
+	int minCode_param[] = {
+			3277, 1639, 820, 410, 205, 103, 52, 26
+	};
+
+	regmap_update_bits(aqt->regmap, AQT1000_ANA_MBHC_ZDET, 0x20, 0x20);
+	for (i = 0; i < AQT_ZDET_NUM_MEASUREMENTS; i++) {
+		regmap_read(aqt->regmap, AQT1000_ANA_MBHC_RESULT_2, &val);
+		if (val & 0x80)
+			break;
+	}
+	val = val << 0x8;
+	regmap_read(aqt->regmap, AQT1000_ANA_MBHC_RESULT_1, &val1);
+	val |= val1;
+	regmap_update_bits(aqt->regmap, AQT1000_ANA_MBHC_ZDET, 0x20, 0x00);
+	x1 = AQT_MBHC_GET_X1(val);
+	c1 = AQT_MBHC_GET_C1(val);
+	/* If ramp is not complete, give additional 5ms */
+	if ((c1 < 2) && x1)
+		usleep_range(5000, 5050);
+
+	if (!c1 || !x1) {
+		dev_dbg(aqt->dev,
+			"%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
+			__func__, c1, x1);
+		goto ramp_down;
+	}
+	d1 = d1_a[c1];
+	denom = (x1 * d1) - (1 << (14 - noff));
+	if (denom > 0)
+		*zdet = (AQT_MBHC_ZDET_CONST * 1000) / denom;
+	else if (x1 < minCode_param[noff])
+		*zdet = AQT_ZDET_FLOATING_IMPEDANCE;
+
+	dev_dbg(aqt->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+		__func__, d1, c1, x1, *zdet);
+ramp_down:
+	i = 0;
+	while (x1) {
+		regmap_bulk_read(aqt->regmap,
+				 AQT1000_ANA_MBHC_RESULT_1, (u8 *)&val, 2);
+		x1 = AQT_MBHC_GET_X1(val);
+		i++;
+		if (i == AQT_ZDET_NUM_MEASUREMENTS)
+			break;
+	}
+}
+
+static void aqt_mbhc_zdet_ramp(struct snd_soc_component *component,
+				 struct aqt_mbhc_zdet_param *zdet_param,
+				 int32_t *zl, int32_t *zr, s16 *d1_a)
+{
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+	int32_t zdet = 0;
+
+	snd_soc_component_update_bits(component,
+			AQT1000_MBHC_NEW_ZDET_ANA_CTL, 0x70,
+			zdet_param->ldo_ctl << 4);
+	snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_BTN5,
+			0xFC, zdet_param->btn5);
+	snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_BTN6,
+			0xFC, zdet_param->btn6);
+	snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_BTN7,
+			0xFC, zdet_param->btn7);
+	snd_soc_component_update_bits(component, AQT1000_MBHC_NEW_ZDET_ANA_CTL,
+			0x0F, zdet_param->noff);
+	snd_soc_component_update_bits(component, AQT1000_MBHC_NEW_ZDET_RAMP_CTL,
+			0x0F, zdet_param->nshift);
+
+	if (!zl)
+		goto z_right;
+	/* Start impedance measurement for HPH_L */
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_ZDET, 0x80, 0x80);
+	dev_dbg(aqt->dev, "%s: ramp for HPH_L, noff = %d\n",
+		__func__, zdet_param->noff);
+	aqt_mbhc_get_result_params(aqt, d1_a, zdet_param->noff, &zdet);
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_ZDET, 0x80, 0x00);
+
+	*zl = zdet;
+
+z_right:
+	if (!zr)
+		return;
+	/* Start impedance measurement for HPH_R */
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_ZDET, 0x40, 0x40);
+	dev_dbg(aqt->dev, "%s: ramp for HPH_R, noff = %d\n",
+		__func__, zdet_param->noff);
+	aqt_mbhc_get_result_params(aqt, d1_a, zdet_param->noff, &zdet);
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_ZDET, 0x40, 0x00);
+
+	*zr = zdet;
+}
+
+static inline void aqt_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+					    int32_t *z_val, int flag_l_r)
+{
+	s16 q1;
+	int q1_cal;
+
+	if (*z_val < (AQT_ZDET_VAL_400/1000))
+		q1 = snd_soc_component_read32(component,
+			AQT1000_CHIP_CFG0_EFUSE_VAL_OUT1 + (2 * flag_l_r));
+	else
+		q1 = snd_soc_component_read32(component,
+			AQT1000_CHIP_CFG0_EFUSE_VAL_OUT2 + (2 * flag_l_r));
+	if (q1 & 0x80)
+		q1_cal = (10000 - ((q1 & 0x7F) * 25));
+	else
+		q1_cal = (10000 + (q1 * 25));
+	if (q1_cal > 0)
+		*z_val = ((*z_val) * 10000) / q1_cal;
+}
+
+static void aqt_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
+					  uint32_t *zr)
+{
+	struct snd_soc_component *component = mbhc->component;
+	struct aqt1000 *aqt = dev_get_drvdata(component->dev);
+	s16 reg0, reg1, reg2, reg3, reg4;
+	int32_t z1L, z1R, z1Ls;
+	int zMono, z_diff1, z_diff2;
+	bool is_fsm_disable = false;
+	struct aqt_mbhc_zdet_param zdet_param[] = {
+		{4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
+		{2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
+		{1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
+		{1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
+	};
+	struct aqt_mbhc_zdet_param *zdet_param_ptr = NULL;
+	s16 d1_a[][4] = {
+		{0, 30, 90, 30},
+		{0, 30, 30, 5},
+		{0, 30, 30, 5},
+		{0, 30, 30, 5},
+	};
+	s16 *d1 = NULL;
+
+	WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
+
+	reg0 = snd_soc_component_read32(component, AQT1000_ANA_MBHC_BTN5);
+	reg1 = snd_soc_component_read32(component, AQT1000_ANA_MBHC_BTN6);
+	reg2 = snd_soc_component_read32(component, AQT1000_ANA_MBHC_BTN7);
+	reg3 = snd_soc_component_read32(component, AQT1000_MBHC_CTL_CLK);
+	reg4 = snd_soc_component_read32(component,
+					AQT1000_MBHC_NEW_ZDET_ANA_CTL);
+
+	if (snd_soc_component_read32(component,
+				     AQT1000_ANA_MBHC_ELECT) & 0x80) {
+		is_fsm_disable = true;
+		regmap_update_bits(aqt->regmap,
+				   AQT1000_ANA_MBHC_ELECT, 0x80, 0x00);
+	}
+
+	/* For NO-jack, disable L_DET_EN before Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(aqt->regmap,
+				   AQT1000_ANA_MBHC_MECH, 0x80, 0x00);
+
+	/* Turn off 100k pull down on HPHL */
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_MECH, 0x01, 0x00);
+
+	/* First get impedance on Left */
+	d1 = d1_a[1];
+	zdet_param_ptr = &zdet_param[1];
+	aqt_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+	if (!AQT_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
+		goto left_ch_impedance;
+
+	/* Second ramp for left ch */
+	if (z1L < AQT_ZDET_VAL_32) {
+		zdet_param_ptr = &zdet_param[0];
+		d1 = d1_a[0];
+	} else if ((z1L > AQT_ZDET_VAL_400) && (z1L <= AQT_ZDET_VAL_1200)) {
+		zdet_param_ptr = &zdet_param[2];
+		d1 = d1_a[2];
+	} else if (z1L > AQT_ZDET_VAL_1200) {
+		zdet_param_ptr = &zdet_param[3];
+		d1 = d1_a[3];
+	}
+	aqt_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+left_ch_impedance:
+	if ((z1L == AQT_ZDET_FLOATING_IMPEDANCE) ||
+		(z1L > AQT_ZDET_VAL_100K)) {
+		*zl = AQT_ZDET_FLOATING_IMPEDANCE;
+		zdet_param_ptr = &zdet_param[1];
+		d1 = d1_a[1];
+	} else {
+		*zl = z1L/1000;
+		aqt_wcd_mbhc_qfuse_cal(component, zl, 0);
+	}
+	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
+		__func__, *zl);
+
+	/* Start of right impedance ramp and calculation */
+	aqt_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+	if (AQT_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
+		if (((z1R > AQT_ZDET_VAL_1200) &&
+			(zdet_param_ptr->noff == 0x6)) ||
+			((*zl) != AQT_ZDET_FLOATING_IMPEDANCE))
+			goto right_ch_impedance;
+		/* Second ramp for right ch */
+		if (z1R < AQT_ZDET_VAL_32) {
+			zdet_param_ptr = &zdet_param[0];
+			d1 = d1_a[0];
+		} else if ((z1R > AQT_ZDET_VAL_400) &&
+			(z1R <= AQT_ZDET_VAL_1200)) {
+			zdet_param_ptr = &zdet_param[2];
+			d1 = d1_a[2];
+		} else if (z1R > AQT_ZDET_VAL_1200) {
+			zdet_param_ptr = &zdet_param[3];
+			d1 = d1_a[3];
+		}
+		aqt_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+	}
+right_ch_impedance:
+	if ((z1R == AQT_ZDET_FLOATING_IMPEDANCE) ||
+		(z1R > AQT_ZDET_VAL_100K)) {
+		*zr = AQT_ZDET_FLOATING_IMPEDANCE;
+	} else {
+		*zr = z1R/1000;
+		aqt_wcd_mbhc_qfuse_cal(component, zr, 1);
+	}
+	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
+		__func__, *zr);
+
+	/* Mono/stereo detection */
+	if ((*zl == AQT_ZDET_FLOATING_IMPEDANCE) &&
+		(*zr == AQT_ZDET_FLOATING_IMPEDANCE)) {
+		dev_dbg(component->dev,
+			"%s: plug type is invalid or extension cable\n",
+			__func__);
+		goto zdet_complete;
+	}
+	if ((*zl == AQT_ZDET_FLOATING_IMPEDANCE) ||
+	    (*zr == AQT_ZDET_FLOATING_IMPEDANCE) ||
+	    ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||
+	    ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {
+		dev_dbg(component->dev,
+			"%s: Mono plug type with one ch floating or shorted to GND\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_MONO;
+		goto zdet_complete;
+	}
+	snd_soc_component_update_bits(component, AQT1000_HPH_R_ATEST,
+				0x02, 0x02);
+	snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				0x40, 0x01);
+	if (*zl < (AQT_ZDET_VAL_32/1000))
+		aqt_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);
+	else
+		aqt_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);
+	snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				0x40, 0x00);
+	snd_soc_component_update_bits(component, AQT1000_HPH_R_ATEST,
+				0x02, 0x00);
+	z1Ls /= 1000;
+	aqt_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);
+	/* Parallel of left Z and 9 ohm pull down resistor */
+	zMono = ((*zl) * 9) / ((*zl) + 9);
+	z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
+	z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
+	if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
+		dev_dbg(component->dev, "%s: stereo plug type detected\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+	} else {
+		dev_dbg(component->dev, "%s: MONO plug type detected\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_MONO;
+	}
+
+zdet_complete:
+	snd_soc_component_write(component, AQT1000_ANA_MBHC_BTN5, reg0);
+	snd_soc_component_write(component, AQT1000_ANA_MBHC_BTN6, reg1);
+	snd_soc_component_write(component, AQT1000_ANA_MBHC_BTN7, reg2);
+	/* Turn on 100k pull down on HPHL */
+	regmap_update_bits(aqt->regmap,
+			   AQT1000_ANA_MBHC_MECH, 0x01, 0x01);
+
+	/* For NO-jack, re-enable L_DET_EN after Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(aqt->regmap,
+				   AQT1000_ANA_MBHC_MECH, 0x80, 0x80);
+
+	snd_soc_component_write(component, AQT1000_MBHC_NEW_ZDET_ANA_CTL,
+				reg4);
+	snd_soc_component_write(component, AQT1000_MBHC_CTL_CLK, reg3);
+	if (is_fsm_disable)
+		regmap_update_bits(aqt->regmap,
+				   AQT1000_ANA_MBHC_ELECT, 0x80, 0x80);
+}
+
+static void aqt_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
+				  bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_MECH,
+				    0x02, 0x02);
+		snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_MECH,
+				    0x40, 0x40);
+	} else {
+		snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_MECH,
+				    0x40, 0x00);
+		snd_soc_component_update_bits(component, AQT1000_ANA_MBHC_MECH,
+				    0x02, 0x00);
+	}
+}
+
+static void aqt_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
+					  bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				    0x40, 0x40);
+		snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				    0x10, 0x10);
+	} else {
+		snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				    0x40, 0x00);
+		snd_soc_component_update_bits(component, AQT1000_HPH_PA_CTL2,
+				    0x10, 0x00);
+	}
+}
+
+static void aqt_mbhc_moisture_config(struct wcd_mbhc *mbhc)
+{
+	struct snd_soc_component *component = mbhc->component;
+
+	if ((mbhc->moist_rref == R_OFF) ||
+	    (mbhc->mbhc_cfg->enable_usbc_analog)) {
+		snd_soc_component_update_bits(component,
+				AQT1000_MBHC_NEW_CTL_2,
+				0x0C, R_OFF << 2);
+		return;
+	}
+
+	/* Do not enable moisture detection if jack type is NC */
+	if (!mbhc->hphl_swh) {
+		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+			__func__);
+		snd_soc_component_update_bits(component,
+				AQT1000_MBHC_NEW_CTL_2,
+				0x0C, R_OFF << 2);
+		return;
+	}
+
+	snd_soc_component_update_bits(component, AQT1000_MBHC_NEW_CTL_2,
+			    0x0C, mbhc->moist_rref << 2);
+}
+
+static void aqt_update_anc_state(struct snd_soc_component *component,
+				 bool enable, int anc_num)
+{
+	if (enable)
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_RX1_RX_PATH_CFG0 + (20 * anc_num),
+				0x10, 0x10);
+	else
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_RX1_RX_PATH_CFG0 + (20 * anc_num),
+				0x10, 0x00);
+}
+
+static bool aqt_is_anc_on(struct wcd_mbhc *mbhc)
+{
+	bool anc_on = false;
+	u16 ancl, ancr;
+
+	ancl =
+		(snd_soc_component_read32(mbhc->component,
+				AQT1000_CDC_RX1_RX_PATH_CFG0)) & 0x10;
+	ancr =
+		(snd_soc_component_read32(mbhc->component,
+				AQT1000_CDC_RX2_RX_PATH_CFG0)) & 0x10;
+
+	anc_on = !!(ancl | ancr);
+
+	return anc_on;
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+	.request_irq = aqt_mbhc_request_irq,
+	.irq_control = aqt_mbhc_irq_control,
+	.free_irq = aqt_mbhc_free_irq,
+	.clk_setup = aqt_mbhc_clk_setup,
+	.map_btn_code_to_num = aqt_mbhc_btn_to_num,
+	.mbhc_bias = aqt_mbhc_mbhc_bias_control,
+	.set_btn_thr = aqt_mbhc_program_btn_thr,
+	.lock_sleep = aqt_mbhc_lock_sleep,
+	.register_notifier = aqt_mbhc_register_notifier,
+	.micbias_enable_status = aqt_mbhc_micb_en_status,
+	.hph_pa_on_status = aqt_mbhc_hph_pa_on_status,
+	.hph_pull_up_control_v2 = aqt_mbhc_hph_l_pull_up_control,
+	.mbhc_micbias_control = aqt_mbhc_request_micbias,
+	.mbhc_micb_ramp_control = aqt_mbhc_micb_ramp_control,
+	.get_hwdep_fw_cal = aqt_get_hwdep_fw_cal,
+	.mbhc_micb_ctrl_thr_mic = aqt_mbhc_micb_ctrl_threshold_mic,
+	.compute_impedance = aqt_wcd_mbhc_calc_impedance,
+	.mbhc_gnd_det_ctrl = aqt_mbhc_gnd_det_ctrl,
+	.hph_pull_down_ctrl = aqt_mbhc_hph_pull_down_ctrl,
+	.mbhc_moisture_config = aqt_mbhc_moisture_config,
+	.update_anc_state = aqt_update_anc_state,
+	.is_anc_on = aqt_is_anc_on,
+};
+
+static int aqt_get_hph_type(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	struct aqt1000_mbhc *aqt_mbhc = aqt->mbhc;
+	struct wcd_mbhc *mbhc;
+
+	if (!aqt_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mbhc = &aqt_mbhc->wcd_mbhc;
+
+	ucontrol->value.integer.value[0] = (u32) mbhc->hph_type;
+	dev_dbg(component->dev, "%s: hph_type = %u\n", __func__,
+		mbhc->hph_type);
+
+	return 0;
+}
+
+static int aqt_hph_impedance_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	uint32_t zl, zr;
+	bool hphr;
+	struct soc_multi_mixer_control *mc;
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	struct aqt1000_mbhc *aqt_mbhc = aqt->mbhc;
+
+	if (!aqt_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+	hphr = mc->shift;
+	wcd_mbhc_get_impedance(&aqt_mbhc->wcd_mbhc, &zl, &zr);
+	dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__,
+		zl, zr);
+	ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+	SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+		       aqt_get_hph_type, NULL),
+};
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+		       aqt_hph_impedance_get, NULL),
+	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+		       aqt_hph_impedance_get, NULL),
+};
+
+/*
+ * aqt_mbhc_get_impedance: get impedance of headphone left and right channels
+ * @aqt_mbhc: handle to struct aqt_mbhc *
+ * @zl: handle to left-ch impedance
+ * @zr: handle to right-ch impedance
+ * return 0 for success or error code in case of failure
+ */
+int aqt_mbhc_get_impedance(struct aqt1000_mbhc *aqt_mbhc,
+			     uint32_t *zl, uint32_t *zr)
+{
+	if (!aqt_mbhc) {
+		pr_err("%s: mbhc not initialized!\n", __func__);
+		return -EINVAL;
+	}
+	if (!zl || !zr) {
+		pr_err("%s: zl or zr null!\n", __func__);
+		return -EINVAL;
+	}
+
+	return wcd_mbhc_get_impedance(&aqt_mbhc->wcd_mbhc, zl, zr);
+}
+EXPORT_SYMBOL(aqt_mbhc_get_impedance);
+
+/*
+ * aqt_mbhc_hs_detect: starts mbhc insertion/removal functionality
+ * @component: handle to snd_soc_component *
+ * @mbhc_cfg: handle to mbhc configuration structure
+ * return 0 if mbhc_start is success or error code in case of failure
+ */
+int aqt_mbhc_hs_detect(struct snd_soc_component *component,
+			 struct wcd_mbhc_config *mbhc_cfg)
+{
+	struct aqt1000 *aqt;
+	struct aqt1000_mbhc *aqt_mbhc;
+
+	if (!component) {
+		pr_err("%s: codec is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	aqt = snd_soc_component_get_drvdata(component);
+	if (!aqt) {
+		pr_err("%s: aqt is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	aqt_mbhc = aqt->mbhc;
+	if (!aqt_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	return wcd_mbhc_start(&aqt_mbhc->wcd_mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL(aqt_mbhc_hs_detect);
+
+/*
+ * aqt_mbhc_hs_detect_exit: stop mbhc insertion/removal functionality
+ * @component: handle to snd_soc_component *
+ */
+void aqt_mbhc_hs_detect_exit(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt;
+	struct aqt1000_mbhc *aqt_mbhc;
+
+	if (!component) {
+		pr_err("%s: codec is NULL\n", __func__);
+		return;
+	}
+
+	aqt = snd_soc_component_get_drvdata(component);
+	if (!aqt) {
+		pr_err("%s: aqt is NULL\n", __func__);
+		return;
+	}
+
+	aqt_mbhc = aqt->mbhc;
+	if (!aqt_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return;
+	}
+	wcd_mbhc_stop(&aqt_mbhc->wcd_mbhc);
+}
+EXPORT_SYMBOL(aqt_mbhc_hs_detect_exit);
+
+/*
+ * aqt_mbhc_post_ssr_init: initialize mbhc for aqt post subsystem restart
+ * @mbhc: poniter to aqt_mbhc structure
+ * @component: handle to snd_soc_component *
+ *
+ * return 0 if mbhc_init is success or error code in case of failure
+ */
+int aqt_mbhc_post_ssr_init(struct aqt1000_mbhc *mbhc,
+			     struct snd_soc_component *component)
+{
+	int ret;
+	struct wcd_mbhc *wcd_mbhc;
+
+	if (!mbhc || !component)
+		return -EINVAL;
+
+	wcd_mbhc = &mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd_mbhc_deinit(wcd_mbhc);
+	ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb, &intr_ids,
+			    wcd_mbhc_registers, AQT_ZDET_SUPPORTED);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+		goto done;
+	}
+
+done:
+	return ret;
+}
+EXPORT_SYMBOL(aqt_mbhc_post_ssr_init);
+
+/*
+ * aqt_mbhc_init: initialize mbhc for aqt
+ * @mbhc: poniter to aqt_mbhc struct pointer to store the configs
+ * @component: handle to snd_soc_component *
+ * @fw_data: handle to firmware data
+ *
+ * return 0 if mbhc_init is success or error code in case of failure
+ */
+int aqt_mbhc_init(struct aqt1000_mbhc **mbhc,
+		  struct snd_soc_component *component,
+		  struct fw_info *fw_data)
+{
+	struct aqt1000_mbhc *aqt_mbhc;
+	struct wcd_mbhc *wcd_mbhc;
+	int ret;
+
+	if (!component) {
+		pr_err("%s: codec is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	aqt_mbhc = devm_kzalloc(component->dev, sizeof(struct aqt1000_mbhc),
+				    GFP_KERNEL);
+	if (!aqt_mbhc)
+		return -ENOMEM;
+
+	aqt_mbhc->aqt = dev_get_drvdata(component->dev);
+	aqt_mbhc->fw_data = fw_data;
+	BLOCKING_INIT_NOTIFIER_HEAD(&aqt_mbhc->notifier);
+	wcd_mbhc = &aqt_mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+
+	/* Setting default mbhc detection logic to ADC */
+	wcd_mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
+
+	ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb,
+				&intr_ids, wcd_mbhc_registers,
+				AQT_ZDET_SUPPORTED);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+		goto err;
+	}
+
+	(*mbhc) = aqt_mbhc;
+	snd_soc_add_component_controls(component, impedance_detect_controls,
+				   ARRAY_SIZE(impedance_detect_controls));
+	snd_soc_add_component_controls(component, hph_type_detect_controls,
+				   ARRAY_SIZE(hph_type_detect_controls));
+
+	return 0;
+err:
+	devm_kfree(component->dev, aqt_mbhc);
+	return ret;
+}
+EXPORT_SYMBOL(aqt_mbhc_init);
+
+/*
+ * aqt_mbhc_deinit: deinitialize mbhc for aqt
+ * @component: handle to snd_soc_component *
+ */
+void aqt_mbhc_deinit(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt;
+	struct aqt1000_mbhc *aqt_mbhc;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return;
+	}
+
+	aqt = snd_soc_component_get_drvdata(component);
+	if (!aqt) {
+		pr_err("%s: aqt is NULL\n", __func__);
+		return;
+	}
+
+	aqt_mbhc = aqt->mbhc;
+	if (aqt_mbhc) {
+		wcd_mbhc_deinit(&aqt_mbhc->wcd_mbhc);
+		devm_kfree(component->dev, aqt_mbhc);
+	}
+}
+EXPORT_SYMBOL(aqt_mbhc_deinit);

+ 63 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-mbhc.h

@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+#ifndef __AQT1000_MBHC_H__
+#define __AQT1000_MBHC_H__
+#include <asoc/wcd-mbhc-v2.h>
+
+struct aqt1000_mbhc {
+	struct wcd_mbhc wcd_mbhc;
+	struct blocking_notifier_head notifier;
+	struct aqt1000 *aqt;
+	struct fw_info *fw_data;
+	bool mbhc_started;
+};
+
+#if IS_ENABLED(CONFIG_SND_SOC_AQT1000)
+extern int aqt_mbhc_init(struct aqt1000_mbhc **mbhc,
+			   struct snd_soc_component *component,
+			   struct fw_info *fw_data);
+extern void aqt_mbhc_hs_detect_exit(struct snd_soc_component *component);
+extern int aqt_mbhc_hs_detect(struct snd_soc_component *component,
+				struct wcd_mbhc_config *mbhc_cfg);
+extern void aqt_mbhc_deinit(struct snd_soc_component *component);
+extern int aqt_mbhc_post_ssr_init(struct aqt1000_mbhc *mbhc,
+				    struct snd_soc_component *component);
+extern int aqt_mbhc_get_impedance(struct aqt1000_mbhc *aqt_mbhc,
+				    uint32_t *zl, uint32_t *zr);
+#else
+static inline int aqt_mbhc_init(struct aqt1000_mbhc **mbhc,
+				  struct snd_soc_component *component,
+				  struct fw_info *fw_data)
+{
+	return 0;
+}
+static inline void aqt_mbhc_hs_detect_exit(struct snd_soc_component *component)
+{
+}
+static inline int aqt_mbhc_hs_detect(struct snd_soc_component *component,
+				       struct wcd_mbhc_config *mbhc_cfg)
+{
+		return 0;
+}
+static inline void aqt_mbhc_deinit(struct snd_soc_component *component)
+{
+}
+static inline int aqt_mbhc_post_ssr_init(struct aqt1000_mbhc *mbhc,
+					   struct snd_soc_component *component)
+{
+	return 0;
+}
+
+static inline int aqt_mbhc_get_impedance(struct aqt1000_mbhc *aqt_mbhc,
+					   uint32_t *zl, uint32_t *zr)
+{
+	if (zl)
+		*zl = 0;
+	if (zr)
+		*zr = 0;
+	return -EINVAL;
+}
+#endif
+
+#endif /* __AQT1000_MBHC_H__ */

+ 1608 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-reg-defaults.h

@@ -0,0 +1,1608 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _AQT1000_REG_DEFAULTS_H
+#define _AQT1000_REG_DEFAULTS_H
+
+#include <linux/types.h>
+#include "aqt1000-registers.h"
+
+#define AQT1000_REG(reg)  ((reg) & 0xFF)
+#define AQT1000_PAGE_SIZE  256
+
+enum {
+	AQT1000_PAGE_0 = 0,
+	AQT1000_PAGE_1,
+	AQT1000_PAGE_2,
+	AQT1000_PAGE_5 = 5,
+	AQT1000_PAGE_6,
+	AQT1000_PAGE_7,
+	AQT1000_PAGE_10 = 0xA,
+	AQT1000_PAGE_11,
+	AQT1000_PAGE_12,
+	AQT1000_PAGE_13,
+	AQT1000_PAGE_15 = 0xF,
+	AQT1000_PAGE_128,
+	AQT1000_PAGE_MAX,
+};
+
+enum {
+	AQT1000_WO = 0,
+	AQT1000_RO,
+	AQT1000_RW,
+};
+
+static const struct reg_default aqt1000_defaults[] = {
+	{AQT1000_CHIP_CFG1_PWR_MEM_SD,                         0x07},
+	{AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_RAM,                 0x00},
+	{AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_ROM,                 0x00},
+	{AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_RAM,             0x00},
+	{AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_ROM,             0x00},
+	{AQT1000_CHIP_CFG1_CLK_CFG_FLL,                        0x20},
+	{AQT1000_CHIP_CFG1_CLK_CFG_SPI_M,                      0x01},
+	{AQT1000_CHIP_CFG1_CLK_CFG_I2C_M,                      0x01},
+	{AQT1000_CHIP_CFG1_CLK_CFG_UART,                       0x01},
+	{AQT1000_CHIP_CFG1_RST_USB_SS,                         0x0E},
+	{AQT1000_CHIP_CFG1_RST_BLSP,                           0x0F},
+	{AQT1000_CHIP_CFG1_RST_BUS_MTRX,                       0x00},
+	{AQT1000_CHIP_CFG1_RST_MISC,                           0x00},
+	{AQT1000_CHIP_CFG1_ANA_WAIT_STATE_CTL,                 0xCC},
+	{AQT1000_PAGE1_PAGE_REGISTER,                          0x00},
+	{AQT1000_FLL_USER_CTL_0,                               0x71},
+	{AQT1000_FLL_USER_CTL_1,                               0x34},
+	{AQT1000_FLL_USER_CTL_2,                               0x0B},
+	{AQT1000_FLL_USER_CTL_3,                               0x02},
+	{AQT1000_FLL_USER_CTL_4,                               0x04},
+	{AQT1000_FLL_USER_CTL_5,                               0x02},
+	{AQT1000_FLL_USER_CTL_6,                               0x6E},
+	{AQT1000_FLL_USER_CTL_7,                               0x00},
+	{AQT1000_FLL_USER_CTL_8,                               0x94},
+	{AQT1000_FLL_USER_CTL_9,                               0x70},
+	{AQT1000_FLL_L_VAL_CTL_0,                              0x34},
+	{AQT1000_FLL_L_VAL_CTL_1,                              0x00},
+	{AQT1000_FLL_DSM_FRAC_CTL_0,                           0x00},
+	{AQT1000_FLL_DSM_FRAC_CTL_1,                           0xFF},
+	{AQT1000_FLL_CONFIG_CTL_0,                             0x6B},
+	{AQT1000_FLL_CONFIG_CTL_1,                             0x05},
+	{AQT1000_FLL_CONFIG_CTL_2,                             0x08},
+	{AQT1000_FLL_CONFIG_CTL_3,                             0x00},
+	{AQT1000_FLL_CONFIG_CTL_4,                             0x10},
+	{AQT1000_FLL_TEST_CTL_0,                               0x80},
+	{AQT1000_FLL_TEST_CTL_1,                               0x00},
+	{AQT1000_FLL_TEST_CTL_2,                               0x00},
+	{AQT1000_FLL_TEST_CTL_3,                               0x00},
+	{AQT1000_FLL_TEST_CTL_4,                               0x00},
+	{AQT1000_FLL_TEST_CTL_5,                               0x00},
+	{AQT1000_FLL_TEST_CTL_6,                               0x04},
+	{AQT1000_FLL_TEST_CTL_7,                               0x33},
+	{AQT1000_FLL_FREQ_CTL_0,                               0x00},
+	{AQT1000_FLL_FREQ_CTL_1,                               0x00},
+	{AQT1000_FLL_FREQ_CTL_2,                               0x00},
+	{AQT1000_FLL_FREQ_CTL_3,                               0x00},
+	{AQT1000_FLL_SSC_CTL_0,                                0x00},
+	{AQT1000_FLL_SSC_CTL_1,                                0x00},
+	{AQT1000_FLL_SSC_CTL_2,                                0x00},
+	{AQT1000_FLL_SSC_CTL_3,                                0x00},
+	{AQT1000_FLL_FLL_MODE,                                 0xA0},
+	{AQT1000_FLL_STATUS_0,                                 0x00},
+	{AQT1000_FLL_STATUS_1,                                 0x00},
+	{AQT1000_FLL_STATUS_2,                                 0x00},
+	{AQT1000_FLL_STATUS_3,                                 0x00},
+	{AQT1000_PAGE2_PAGE_REGISTER,                          0x00},
+	{AQT1000_I2S_I2S_0_TX_CFG,                             0x00},
+	{AQT1000_I2S_I2S_0_RX_CFG,                             0x00},
+	{AQT1000_I2S_I2S_0_CTL,                                0x0C},
+	{AQT1000_I2S_I2S_CLKSRC_CTL,                           0x01},
+	{AQT1000_I2S_I2S_HS_CLK_CTL,                           0x00},
+	{AQT1000_I2S_I2S_0_RST,                                0x00},
+	{AQT1000_I2S_SHADOW_I2S_0_CTL,                         0x00},
+	{AQT1000_I2S_SHADOW_I2S_0_RX_CFG,                      0x09},
+	{AQT1000_PAGE5_PAGE_REGISTER,                          0x00},
+	{AQT1000_INTR_CTRL_MCU_INT_POLARITY,                   0x00},
+	{AQT1000_INTR_CTRL_INT_MASK_0,                         0xFE},
+	{AQT1000_INTR_CTRL_INT_MASK_1,                         0xFF},
+	{AQT1000_INTR_CTRL_INT_MASK_2,                         0xFF},
+	{AQT1000_INTR_CTRL_INT_MASK_3,                         0xEF},
+	{AQT1000_INTR_CTRL_INT_MASK_4,                         0x3B},
+	{AQT1000_INTR_CTRL_INT_MASK_5,                         0xFF},
+	{AQT1000_INTR_CTRL_INT_MASK_6,                         0x3F},
+	{AQT1000_INTR_CTRL_INT_STATUS_0,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_1,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_2,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_3,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_4,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_5,                       0x00},
+	{AQT1000_INTR_CTRL_INT_STATUS_6,                       0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_0,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_1,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_2,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_3,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_4,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_5,                        0x00},
+	{AQT1000_INTR_CTRL_INT_CLEAR_6,                        0x00},
+	{AQT1000_INTR_CTRL_INT_TYPE_0,                         0xEF},
+	{AQT1000_INTR_CTRL_INT_TYPE_1,                         0x03},
+	{AQT1000_INTR_CTRL_INT_TYPE_2,                         0x00},
+	{AQT1000_INTR_CTRL_INT_TYPE_3,                         0x20},
+	{AQT1000_INTR_CTRL_INT_TYPE_4,                         0x44},
+	{AQT1000_INTR_CTRL_INT_TYPE_5,                         0x00},
+	{AQT1000_INTR_CTRL_INT_TYPE_6,                         0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_0,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_1,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_2,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_3,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_4,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_5,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_EN_6,                      0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_0,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_1,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_2,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_3,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_4,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_5,                     0x00},
+	{AQT1000_INTR_CTRL_INT_TEST_VAL_6,                     0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_0,                         0x02},
+	{AQT1000_INTR_CTRL_INT_DEST_1,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_2,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_3,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_4,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_5,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_6,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_7,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_8,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_9,                         0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_10,                        0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_11,                        0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_12,                        0x00},
+	{AQT1000_INTR_CTRL_INT_DEST_13,                        0x00},
+	{AQT1000_INTR_CTRL_CLR_COMMIT,                         0x00},
+	{AQT1000_ANA_PAGE_REGISTER,                            0x00},
+	{AQT1000_ANA_BIAS,                                     0x00},
+	{AQT1000_ANA_RX_SUPPLIES,                              0x00},
+	{AQT1000_ANA_HPH,                                      0x0C},
+	{AQT1000_ANA_AMIC1,                                    0x20},
+	{AQT1000_ANA_AMIC2,                                    0x00},
+	{AQT1000_ANA_AMIC3,                                    0x20},
+	{AQT1000_ANA_AMIC3_HPF,                                0x00},
+	{AQT1000_ANA_MBHC_MECH,                                0x39},
+	{AQT1000_ANA_MBHC_ELECT,                               0x08},
+	{AQT1000_ANA_MBHC_ZDET,                                0x00},
+	{AQT1000_ANA_MBHC_RESULT_1,                            0x00},
+	{AQT1000_ANA_MBHC_RESULT_2,                            0x00},
+	{AQT1000_ANA_MBHC_RESULT_3,                            0x00},
+	{AQT1000_ANA_MBHC_BTN0,                                0x00},
+	{AQT1000_ANA_MBHC_BTN1,                                0x10},
+	{AQT1000_ANA_MBHC_BTN2,                                0x20},
+	{AQT1000_ANA_MBHC_BTN3,                                0x30},
+	{AQT1000_ANA_MBHC_BTN4,                                0x40},
+	{AQT1000_ANA_MBHC_BTN5,                                0x50},
+	{AQT1000_ANA_MBHC_BTN6,                                0x60},
+	{AQT1000_ANA_MBHC_BTN7,                                0x70},
+	{AQT1000_ANA_MICB1,                                    0x10},
+	{AQT1000_ANA_MICB1_RAMP,                               0x00},
+	{AQT1000_BIAS_CTL,                                     0x28},
+	{AQT1000_BIAS_CCOMP_FINE_ADJ,                          0x75},
+	{AQT1000_LED_LED_MODE_SEL_R,                           0x00},
+	{AQT1000_LED_LED_MISC_R,                               0x00},
+	{AQT1000_LED_LED_MODE_SEL_G,                           0x00},
+	{AQT1000_LED_LED_MISC_G,                               0x00},
+	{AQT1000_LED_LED_MODE_SEL_B,                           0x00},
+	{AQT1000_LED_LED_MISC_B,                               0x00},
+	{AQT1000_LDOH_MODE,                                    0x1D},
+	{AQT1000_LDOH_BIAS,                                    0x00},
+	{AQT1000_LDOH_STB_LOADS,                               0x00},
+	{AQT1000_LDOH_MISC1,                                   0x00},
+	{AQT1000_LDOL_VDDCX_ADJUST,                            0x01},
+	{AQT1000_LDOL_DISABLE_LDOL,                            0x00},
+	{AQT1000_BUCK_5V_EN_CTL,                               0x03},
+	{AQT1000_BUCK_5V_VOUT_SEL,                             0x03},
+	{AQT1000_BUCK_5V_CTRL_VCL_1,                           0x03},
+	{AQT1000_BUCK_5V_CTRL_VCL_2,                           0x21},
+	{AQT1000_BUCK_5V_CTRL_CCL_2,                           0x20},
+	{AQT1000_BUCK_5V_CTRL_CCL_1,                           0xA1},
+	{AQT1000_BUCK_5V_CTRL_CCL_3,                           0x02},
+	{AQT1000_BUCK_5V_CTRL_CCL_4,                           0x05},
+	{AQT1000_BUCK_5V_CTRL_CCL_5,                           0x00},
+	{AQT1000_BUCK_5V_IBIAS_CTL_1,                          0x37},
+	{AQT1000_BUCK_5V_IBIAS_CTL_2,                          0x00},
+	{AQT1000_BUCK_5V_IBIAS_CTL_3,                          0x33},
+	{AQT1000_BUCK_5V_IBIAS_CTL_4,                          0x33},
+	{AQT1000_BUCK_5V_IBIAS_CTL_5,                          0x00},
+	{AQT1000_BUCK_5V_ATEST_DTEST_CTL,                      0x00},
+	{AQT1000_PON_BG_CTRL,                                  0x80},
+	{AQT1000_PON_TEST_CTRL,                                0x00},
+	{AQT1000_MBHC_CTL_CLK,                                 0x30},
+	{AQT1000_MBHC_CTL_ANA,                                 0x00},
+	{AQT1000_MBHC_CTL_SPARE_1,                             0x00},
+	{AQT1000_MBHC_CTL_SPARE_2,                             0x00},
+	{AQT1000_MBHC_CTL_BCS,                                 0x00},
+	{AQT1000_MBHC_MOISTURE_DET_FSM_STATUS,                 0x00},
+	{AQT1000_MBHC_TEST_CTL,                                0x00},
+	{AQT1000_MICB1_TEST_CTL_1,                             0x1A},
+	{AQT1000_MICB1_TEST_CTL_2,                             0x18},
+	{AQT1000_MICB1_TEST_CTL_3,                             0xA4},
+	{AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS,                0x00},
+	{AQT1000_MICB1_MISC_MICB_MISC1,                        0x00},
+	{AQT1000_MICB1_MISC_MICB_MISC2,                        0x00},
+	{AQT1000_TX_COM_ADC_VCM,                               0x39},
+	{AQT1000_TX_COM_BIAS_ATEST,                            0xC0},
+	{AQT1000_TX_COM_ADC_INT1_IB,                           0x6F},
+	{AQT1000_TX_COM_ADC_INT2_IB,                           0x4F},
+	{AQT1000_TX_COM_TXFE_DIV_CTL,                          0x2E},
+	{AQT1000_TX_COM_TXFE_DIV_START,                        0x00},
+	{AQT1000_TX_COM_TXFE_DIV_STOP_9P6M,                    0xC7},
+	{AQT1000_TX_COM_TXFE_DIV_STOP_12P288M,                 0xFF},
+	{AQT1000_TX_1_2_TEST_EN,                               0xCC},
+	{AQT1000_TX_1_2_ADC_IB,                                0x09},
+	{AQT1000_TX_1_2_ATEST_REFCTL,                          0x0A},
+	{AQT1000_TX_1_2_TEST_CTL,                              0x38},
+	{AQT1000_TX_1_2_TEST_BLK_EN,                           0xFF},
+	{AQT1000_TX_1_2_TXFE_CLKDIV,                           0x00},
+	{AQT1000_TX_1_2_SAR1_ERR,                              0x00},
+	{AQT1000_TX_1_2_SAR2_ERR,                              0x00},
+	{AQT1000_TX_3_TEST_EN,                                 0xC0},
+	{AQT1000_TX_3_ADC_IB,                                  0x09},
+	{AQT1000_TX_3_ATEST_REFCTL,                            0x0A},
+	{AQT1000_TX_3_TEST_CTL,                                0x38},
+	{AQT1000_TX_3_TEST_BLK_EN,                             0xFE},
+	{AQT1000_TX_3_TXFE_CLKDIV,                             0x00},
+	{AQT1000_TX_3_SAR1_ERR,                                0x00},
+	{AQT1000_TX_3_SAR2_ERR,                                0x00},
+	{AQT1000_TX_ATEST1_2_SEL,                              0x60},
+	{AQT1000_CLASSH_MODE_1,                                0x40},
+	{AQT1000_CLASSH_MODE_2,                                0x3A},
+	{AQT1000_CLASSH_MODE_3,                                0x00},
+	{AQT1000_CLASSH_CTRL_VCL_1,                            0x70},
+	{AQT1000_CLASSH_CTRL_VCL_2,                            0x82},
+	{AQT1000_CLASSH_CTRL_CCL_1,                            0x31},
+	{AQT1000_CLASSH_CTRL_CCL_2,                            0x80},
+	{AQT1000_CLASSH_CTRL_CCL_3,                            0x80},
+	{AQT1000_CLASSH_CTRL_CCL_4,                            0x51},
+	{AQT1000_CLASSH_CTRL_CCL_5,                            0x00},
+	{AQT1000_CLASSH_BUCK_TMUX_A_D,                         0x00},
+	{AQT1000_CLASSH_BUCK_SW_DRV_CNTL,                      0x77},
+	{AQT1000_CLASSH_SPARE,                                 0x00},
+	{AQT1000_FLYBACK_EN,                                   0x4E},
+	{AQT1000_FLYBACK_VNEG_CTRL_1,                          0x0B},
+	{AQT1000_FLYBACK_VNEG_CTRL_2,                          0x45},
+	{AQT1000_FLYBACK_VNEG_CTRL_3,                          0x74},
+	{AQT1000_FLYBACK_VNEG_CTRL_4,                          0x7F},
+	{AQT1000_FLYBACK_VNEG_CTRL_5,                          0x83},
+	{AQT1000_FLYBACK_VNEG_CTRL_6,                          0x98},
+	{AQT1000_FLYBACK_VNEG_CTRL_7,                          0xA9},
+	{AQT1000_FLYBACK_VNEG_CTRL_8,                          0x68},
+	{AQT1000_FLYBACK_VNEG_CTRL_9,                          0x64},
+	{AQT1000_FLYBACK_VNEGDAC_CTRL_1,                       0xED},
+	{AQT1000_FLYBACK_VNEGDAC_CTRL_2,                       0xF0},
+	{AQT1000_FLYBACK_VNEGDAC_CTRL_3,                       0xA6},
+	{AQT1000_FLYBACK_CTRL_1,                               0x65},
+	{AQT1000_FLYBACK_TEST_CTL,                             0x00},
+	{AQT1000_RX_AUX_SW_CTL,                                0x00},
+	{AQT1000_RX_PA_AUX_IN_CONN,                            0x00},
+	{AQT1000_RX_TIMER_DIV,                                 0x32},
+	{AQT1000_RX_OCP_CTL,                                   0x1F},
+	{AQT1000_RX_OCP_COUNT,                                 0x77},
+	{AQT1000_RX_BIAS_ATEST,                                0x00},
+	{AQT1000_RX_BIAS_MISC1,                                0xAA},
+	{AQT1000_RX_BIAS_HPH_LDO,                              0xA9},
+	{AQT1000_RX_BIAS_HPH_PA,                               0xAA},
+	{AQT1000_RX_BIAS_HPH_RDACBUFF_CNP2,                    0x8A},
+	{AQT1000_RX_BIAS_HPH_RDAC_LDO,                         0x88},
+	{AQT1000_RX_BIAS_HPH_CNP1,                             0x82},
+	{AQT1000_RX_BIAS_HPH_LOWPOWER,                         0x82},
+	{AQT1000_RX_BIAS_MISC2,                                0x80},
+	{AQT1000_RX_BIAS_MISC3,                                0x88},
+	{AQT1000_RX_BIAS_MISC4,                                0x88},
+	{AQT1000_RX_BIAS_MISC5,                                0xA8},
+	{AQT1000_RX_BIAS_BUCK_RST,                             0x08},
+	{AQT1000_RX_BIAS_BUCK_VREF_ERRAMP,                     0x44},
+	{AQT1000_RX_BIAS_FLYB_ERRAMP,                          0x40},
+	{AQT1000_RX_BIAS_FLYB_BUFF,                            0xAA},
+	{AQT1000_RX_BIAS_FLYB_MID_RST,                         0x14},
+	{AQT1000_HPH_L_STATUS,                                 0x04},
+	{AQT1000_HPH_R_STATUS,                                 0x04},
+	{AQT1000_HPH_CNP_EN,                                   0x80},
+	{AQT1000_HPH_CNP_WG_CTL,                               0x9A},
+	{AQT1000_HPH_CNP_WG_TIME,                              0x14},
+	{AQT1000_HPH_OCP_CTL,                                  0x28},
+	{AQT1000_HPH_AUTO_CHOP,                                0x16},
+	{AQT1000_HPH_CHOP_CTL,                                 0x83},
+	{AQT1000_HPH_PA_CTL1,                                  0x46},
+	{AQT1000_HPH_PA_CTL2,                                  0x50},
+	{AQT1000_HPH_L_EN,                                     0x80},
+	{AQT1000_HPH_L_TEST,                                   0xE0},
+	{AQT1000_HPH_L_ATEST,                                  0x50},
+	{AQT1000_HPH_R_EN,                                     0x80},
+	{AQT1000_HPH_R_TEST,                                   0xE0},
+	{AQT1000_HPH_R_ATEST,                                  0x54},
+	{AQT1000_HPH_RDAC_CLK_CTL1,                            0x99},
+	{AQT1000_HPH_RDAC_CLK_CTL2,                            0x9B},
+	{AQT1000_HPH_RDAC_LDO_CTL,                             0x33},
+	{AQT1000_HPH_RDAC_CHOP_CLK_LP_CTL,                     0x00},
+	{AQT1000_HPH_REFBUFF_UHQA_CTL,                         0xA8},
+	{AQT1000_HPH_REFBUFF_LP_CTL,                           0x0E},
+	{AQT1000_HPH_L_DAC_CTL,                                0x00},
+	{AQT1000_HPH_R_DAC_CTL,                                0x00},
+	{AQT1000_HPHLR_SURGE_COMP_SEL,                         0x55},
+	{AQT1000_HPHLR_SURGE_EN,                               0x1D},
+	{AQT1000_HPHLR_SURGE_MISC1,                            0xA0},
+	{AQT1000_HPHLR_SURGE_STATUS,                           0x00},
+	{AQT1000_ANA_NEW_PAGE_REGISTER,                        0x00},
+	{AQT1000_HPH_NEW_ANA_HPH2,                             0x00},
+	{AQT1000_HPH_NEW_ANA_HPH3,                             0x00},
+	{AQT1000_CLK_SYS_MCLK1_PRG,                            0x09},
+	{AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG,                 0x20},
+	{AQT1000_CLK_SYS_XO_CAP_XTP,                           0x3F},
+	{AQT1000_CLK_SYS_XO_CAP_XTM,                           0x3F},
+	{AQT1000_CLK_SYS_PLL_ENABLES,                          0x00},
+	{AQT1000_CLK_SYS_PLL_PRESET,                           0x00},
+	{AQT1000_CLK_SYS_PLL_STATUS,                           0x00},
+	{AQT1000_MBHC_NEW_ELECT_REM_CLAMP_CTL,                 0x00},
+	{AQT1000_MBHC_NEW_CTL_1,                               0x02},
+	{AQT1000_MBHC_NEW_CTL_2,                               0x05},
+	{AQT1000_MBHC_NEW_PLUG_DETECT_CTL,                     0x29},
+	{AQT1000_MBHC_NEW_ZDET_ANA_CTL,                        0x0F},
+	{AQT1000_MBHC_NEW_ZDET_RAMP_CTL,                       0x00},
+	{AQT1000_MBHC_NEW_FSM_STATUS,                          0x00},
+	{AQT1000_MBHC_NEW_ADC_RESULT,                          0x00},
+	{AQT1000_HPH_NEW_INT_RDAC_GAIN_CTL,                    0x40},
+	{AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_L,                   0x81},
+	{AQT1000_HPH_NEW_INT_RDAC_VREF_CTL,                    0x10},
+	{AQT1000_HPH_NEW_INT_RDAC_OVERRIDE_CTL,                0x00},
+	{AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_R,                   0x81},
+	{AQT1000_HPH_NEW_INT_PA_MISC1,                         0x22},
+	{AQT1000_HPH_NEW_INT_PA_MISC2,                         0x00},
+	{AQT1000_HPH_NEW_INT_PA_RDAC_MISC,                     0x00},
+	{AQT1000_HPH_NEW_INT_HPH_TIMER1,                       0xFE},
+	{AQT1000_HPH_NEW_INT_HPH_TIMER2,                       0x02},
+	{AQT1000_HPH_NEW_INT_HPH_TIMER3,                       0x4E},
+	{AQT1000_HPH_NEW_INT_HPH_TIMER4,                       0x54},
+	{AQT1000_HPH_NEW_INT_PA_RDAC_MISC2,                    0x80},
+	{AQT1000_HPH_NEW_INT_PA_RDAC_MISC3,                    0x00},
+	{AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI,              0x62},
+	{AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_ULP,                 0x01},
+	{AQT1000_RX_NEW_INT_HPH_RDAC_LDO_LP,                   0x11},
+	{AQT1000_CLK_SYS_INT_CLK_TEST1,                        0x00},
+	{AQT1000_CLK_SYS_INT_XO_TEST1,                         0x98},
+	{AQT1000_CLK_SYS_INT_XO_TEST2,                         0x00},
+	{AQT1000_CLK_SYS_INT_POST_DIV_REG0,                    0x00},
+	{AQT1000_CLK_SYS_INT_POST_DIV_REG1,                    0x00},
+	{AQT1000_CLK_SYS_INT_REF_DIV_REG0,                     0x00},
+	{AQT1000_CLK_SYS_INT_REF_DIV_REG1,                     0x00},
+	{AQT1000_CLK_SYS_INT_FILTER_REG0,                      0x00},
+	{AQT1000_CLK_SYS_INT_FILTER_REG1,                      0x00},
+	{AQT1000_CLK_SYS_INT_PLL_L_VAL,                        0x00},
+	{AQT1000_CLK_SYS_INT_PLL_M_VAL,                        0x00},
+	{AQT1000_CLK_SYS_INT_PLL_N_VAL,                        0x00},
+	{AQT1000_CLK_SYS_INT_TEST_REG0,                        0x00},
+	{AQT1000_CLK_SYS_INT_PFD_CP_DSM_PROG,                  0x00},
+	{AQT1000_CLK_SYS_INT_VCO_PROG,                         0x00},
+	{AQT1000_CLK_SYS_INT_TEST_REG1,                        0x00},
+	{AQT1000_CLK_SYS_INT_LDO_LOCK_CFG,                     0x00},
+	{AQT1000_CLK_SYS_INT_DIG_LOCK_DET_CFG,                 0x00},
+	{AQT1000_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL,             0x57},
+	{AQT1000_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,             0x01},
+	{AQT1000_MBHC_NEW_INT_MECH_DET_CURRENT,                0x00},
+	{AQT1000_MBHC_NEW_INT_SPARE_2,                         0x00},
+	{AQT1000_PAGE10_PAGE_REGISTER,                         0x00},
+	{AQT1000_CDC_ANC0_CLK_RESET_CTL,                       0x00},
+	{AQT1000_CDC_ANC0_MODE_1_CTL,                          0x00},
+	{AQT1000_CDC_ANC0_MODE_2_CTL,                          0x00},
+	{AQT1000_CDC_ANC0_FF_SHIFT,                            0x00},
+	{AQT1000_CDC_ANC0_FB_SHIFT,                            0x00},
+	{AQT1000_CDC_ANC0_LPF_FF_A_CTL,                        0x00},
+	{AQT1000_CDC_ANC0_LPF_FF_B_CTL,                        0x00},
+	{AQT1000_CDC_ANC0_LPF_FB_CTL,                          0x00},
+	{AQT1000_CDC_ANC0_SMLPF_CTL,                           0x00},
+	{AQT1000_CDC_ANC0_DCFLT_SHIFT_CTL,                     0x00},
+	{AQT1000_CDC_ANC0_IIR_ADAPT_CTL,                       0x00},
+	{AQT1000_CDC_ANC0_IIR_COEFF_1_CTL,                     0x00},
+	{AQT1000_CDC_ANC0_IIR_COEFF_2_CTL,                     0x00},
+	{AQT1000_CDC_ANC0_FF_A_GAIN_CTL,                       0x00},
+	{AQT1000_CDC_ANC0_FF_B_GAIN_CTL,                       0x00},
+	{AQT1000_CDC_ANC0_FB_GAIN_CTL,                         0x00},
+	{AQT1000_CDC_ANC0_RC_COMMON_CTL,                       0x00},
+	{AQT1000_CDC_ANC0_FIFO_COMMON_CTL,                     0x88},
+	{AQT1000_CDC_ANC0_RC0_STATUS_FMIN_CNTR,                0x00},
+	{AQT1000_CDC_ANC0_RC1_STATUS_FMIN_CNTR,                0x00},
+	{AQT1000_CDC_ANC0_RC0_STATUS_FMAX_CNTR,                0x00},
+	{AQT1000_CDC_ANC0_RC1_STATUS_FMAX_CNTR,                0x00},
+	{AQT1000_CDC_ANC0_STATUS_FIFO,                         0x00},
+	{AQT1000_CDC_ANC1_CLK_RESET_CTL,                       0x00},
+	{AQT1000_CDC_ANC1_MODE_1_CTL,                          0x00},
+	{AQT1000_CDC_ANC1_MODE_2_CTL,                          0x00},
+	{AQT1000_CDC_ANC1_FF_SHIFT,                            0x00},
+	{AQT1000_CDC_ANC1_FB_SHIFT,                            0x00},
+	{AQT1000_CDC_ANC1_LPF_FF_A_CTL,                        0x00},
+	{AQT1000_CDC_ANC1_LPF_FF_B_CTL,                        0x00},
+	{AQT1000_CDC_ANC1_LPF_FB_CTL,                          0x00},
+	{AQT1000_CDC_ANC1_SMLPF_CTL,                           0x00},
+	{AQT1000_CDC_ANC1_DCFLT_SHIFT_CTL,                     0x00},
+	{AQT1000_CDC_ANC1_IIR_ADAPT_CTL,                       0x00},
+	{AQT1000_CDC_ANC1_IIR_COEFF_1_CTL,                     0x00},
+	{AQT1000_CDC_ANC1_IIR_COEFF_2_CTL,                     0x00},
+	{AQT1000_CDC_ANC1_FF_A_GAIN_CTL,                       0x00},
+	{AQT1000_CDC_ANC1_FF_B_GAIN_CTL,                       0x00},
+	{AQT1000_CDC_ANC1_FB_GAIN_CTL,                         0x00},
+	{AQT1000_CDC_ANC1_RC_COMMON_CTL,                       0x00},
+	{AQT1000_CDC_ANC1_FIFO_COMMON_CTL,                     0x88},
+	{AQT1000_CDC_ANC1_RC0_STATUS_FMIN_CNTR,                0x00},
+	{AQT1000_CDC_ANC1_RC1_STATUS_FMIN_CNTR,                0x00},
+	{AQT1000_CDC_ANC1_RC0_STATUS_FMAX_CNTR,                0x00},
+	{AQT1000_CDC_ANC1_RC1_STATUS_FMAX_CNTR,                0x00},
+	{AQT1000_CDC_ANC1_STATUS_FIFO,                         0x00},
+	{AQT1000_CDC_TX0_TX_PATH_CTL,                          0x04},
+	{AQT1000_CDC_TX0_TX_PATH_CFG0,                         0x10},
+	{AQT1000_CDC_TX0_TX_PATH_CFG1,                         0x03},
+	{AQT1000_CDC_TX0_TX_VOL_CTL,                           0x00},
+	{AQT1000_CDC_TX0_TX_PATH_SEC0,                         0x00},
+	{AQT1000_CDC_TX0_TX_PATH_SEC1,                         0x00},
+	{AQT1000_CDC_TX0_TX_PATH_SEC2,                         0x01},
+	{AQT1000_CDC_TX0_TX_PATH_SEC3,                         0x3C},
+	{AQT1000_CDC_TX0_TX_PATH_SEC4,                         0x20},
+	{AQT1000_CDC_TX0_TX_PATH_SEC5,                         0x00},
+	{AQT1000_CDC_TX0_TX_PATH_SEC6,                         0x00},
+	{AQT1000_CDC_TX1_TX_PATH_CTL,                          0x04},
+	{AQT1000_CDC_TX1_TX_PATH_CFG0,                         0x10},
+	{AQT1000_CDC_TX1_TX_PATH_CFG1,                         0x03},
+	{AQT1000_CDC_TX1_TX_VOL_CTL,                           0x00},
+	{AQT1000_CDC_TX1_TX_PATH_SEC0,                         0x00},
+	{AQT1000_CDC_TX1_TX_PATH_SEC1,                         0x00},
+	{AQT1000_CDC_TX1_TX_PATH_SEC2,                         0x01},
+	{AQT1000_CDC_TX1_TX_PATH_SEC3,                         0x3C},
+	{AQT1000_CDC_TX1_TX_PATH_SEC4,                         0x20},
+	{AQT1000_CDC_TX1_TX_PATH_SEC5,                         0x00},
+	{AQT1000_CDC_TX1_TX_PATH_SEC6,                         0x00},
+	{AQT1000_CDC_TX2_TX_PATH_CTL,                          0x04},
+	{AQT1000_CDC_TX2_TX_PATH_CFG0,                         0x10},
+	{AQT1000_CDC_TX2_TX_PATH_CFG1,                         0x03},
+	{AQT1000_CDC_TX2_TX_VOL_CTL,                           0x00},
+	{AQT1000_CDC_TX2_TX_PATH_SEC0,                         0x00},
+	{AQT1000_CDC_TX2_TX_PATH_SEC1,                         0x00},
+	{AQT1000_CDC_TX2_TX_PATH_SEC2,                         0x01},
+	{AQT1000_CDC_TX2_TX_PATH_SEC3,                         0x3C},
+	{AQT1000_CDC_TX2_TX_PATH_SEC4,                         0x20},
+	{AQT1000_CDC_TX2_TX_PATH_SEC5,                         0x00},
+	{AQT1000_CDC_TX2_TX_PATH_SEC6,                         0x00},
+	{AQT1000_CDC_TX2_TX_PATH_SEC7,                         0x25},
+	{AQT1000_PAGE11_PAGE_REGISTER,                         0x00},
+	{AQT1000_CDC_COMPANDER1_CTL0,                          0x60},
+	{AQT1000_CDC_COMPANDER1_CTL1,                          0xDB},
+	{AQT1000_CDC_COMPANDER1_CTL2,                          0xFF},
+	{AQT1000_CDC_COMPANDER1_CTL3,                          0x35},
+	{AQT1000_CDC_COMPANDER1_CTL4,                          0xFF},
+	{AQT1000_CDC_COMPANDER1_CTL5,                          0x00},
+	{AQT1000_CDC_COMPANDER1_CTL6,                          0x01},
+	{AQT1000_CDC_COMPANDER1_CTL7,                          0x26},
+	{AQT1000_CDC_COMPANDER2_CTL0,                          0x60},
+	{AQT1000_CDC_COMPANDER2_CTL1,                          0xDB},
+	{AQT1000_CDC_COMPANDER2_CTL2,                          0xFF},
+	{AQT1000_CDC_COMPANDER2_CTL3,                          0x35},
+	{AQT1000_CDC_COMPANDER2_CTL4,                          0xFF},
+	{AQT1000_CDC_COMPANDER2_CTL5,                          0x00},
+	{AQT1000_CDC_COMPANDER2_CTL6,                          0x01},
+	{AQT1000_CDC_COMPANDER2_CTL7,                          0x26},
+	{AQT1000_CDC_RX1_RX_PATH_CTL,                          0x04},
+	{AQT1000_CDC_RX1_RX_PATH_CFG0,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_CFG1,                         0x64},
+	{AQT1000_CDC_RX1_RX_PATH_CFG2,                         0x8F},
+	{AQT1000_CDC_RX1_RX_VOL_CTL,                           0x00},
+	{AQT1000_CDC_RX1_RX_PATH_MIX_CTL,                      0x04},
+	{AQT1000_CDC_RX1_RX_PATH_MIX_CFG,                      0x7E},
+	{AQT1000_CDC_RX1_RX_VOL_MIX_CTL,                       0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC0,                         0xFC},
+	{AQT1000_CDC_RX1_RX_PATH_SEC1,                         0x08},
+	{AQT1000_CDC_RX1_RX_PATH_SEC2,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC3,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC4,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC5,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC6,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_SEC7,                         0x00},
+	{AQT1000_CDC_RX1_RX_PATH_MIX_SEC0,                     0x08},
+	{AQT1000_CDC_RX1_RX_PATH_MIX_SEC1,                     0x00},
+	{AQT1000_CDC_RX1_RX_PATH_DSMDEM_CTL,                   0x00},
+	{AQT1000_CDC_RX2_RX_PATH_CTL,                          0x04},
+	{AQT1000_CDC_RX2_RX_PATH_CFG0,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_CFG1,                         0x64},
+	{AQT1000_CDC_RX2_RX_PATH_CFG2,                         0x8F},
+	{AQT1000_CDC_RX2_RX_VOL_CTL,                           0x00},
+	{AQT1000_CDC_RX2_RX_PATH_MIX_CTL,                      0x04},
+	{AQT1000_CDC_RX2_RX_PATH_MIX_CFG,                      0x7E},
+	{AQT1000_CDC_RX2_RX_VOL_MIX_CTL,                       0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC0,                         0xFC},
+	{AQT1000_CDC_RX2_RX_PATH_SEC1,                         0x08},
+	{AQT1000_CDC_RX2_RX_PATH_SEC2,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC3,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC4,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC5,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC6,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_SEC7,                         0x00},
+	{AQT1000_CDC_RX2_RX_PATH_MIX_SEC0,                     0x08},
+	{AQT1000_CDC_RX2_RX_PATH_MIX_SEC1,                     0x00},
+	{AQT1000_CDC_RX2_RX_PATH_DSMDEM_CTL,                   0x00},
+	{AQT1000_CDC_EQ_IIR0_PATH_CTL,                         0x00},
+	{AQT1000_CDC_EQ_IIR0_PATH_CFG0,                        0x1F},
+	{AQT1000_CDC_EQ_IIR0_PATH_CFG1,                        0x00},
+	{AQT1000_CDC_EQ_IIR0_PATH_CFG2,                        0x00},
+	{AQT1000_CDC_EQ_IIR0_PATH_CFG3,                        0x00},
+	{AQT1000_CDC_EQ_IIR0_COEF_CFG0,                        0x00},
+	{AQT1000_CDC_EQ_IIR0_COEF_CFG1,                        0x00},
+	{AQT1000_CDC_EQ_IIR1_PATH_CTL,                         0x00},
+	{AQT1000_CDC_EQ_IIR1_PATH_CFG0,                        0x1F},
+	{AQT1000_CDC_EQ_IIR1_PATH_CFG1,                        0x00},
+	{AQT1000_CDC_EQ_IIR1_PATH_CFG2,                        0x00},
+	{AQT1000_CDC_EQ_IIR1_PATH_CFG3,                        0x00},
+	{AQT1000_CDC_EQ_IIR1_COEF_CFG0,                        0x00},
+	{AQT1000_CDC_EQ_IIR1_COEF_CFG1,                        0x00},
+	{AQT1000_PAGE12_PAGE_REGISTER,                         0x00},
+	{AQT1000_CDC_CLSH_CRC,                                 0x00},
+	{AQT1000_CDC_CLSH_DLY_CTRL,                            0x03},
+	{AQT1000_CDC_CLSH_DECAY_CTRL,                          0x02},
+	{AQT1000_CDC_CLSH_HPH_V_PA,                            0x1C},
+	{AQT1000_CDC_CLSH_EAR_V_PA,                            0x39},
+	{AQT1000_CDC_CLSH_HPH_V_HD,                            0x0C},
+	{AQT1000_CDC_CLSH_EAR_V_HD,                            0x0C},
+	{AQT1000_CDC_CLSH_K1_MSB,                              0x01},
+	{AQT1000_CDC_CLSH_K1_LSB,                              0x00},
+	{AQT1000_CDC_CLSH_K2_MSB,                              0x00},
+	{AQT1000_CDC_CLSH_K2_LSB,                              0x80},
+	{AQT1000_CDC_CLSH_IDLE_CTRL,                           0x00},
+	{AQT1000_CDC_CLSH_IDLE_HPH,                            0x00},
+	{AQT1000_CDC_CLSH_IDLE_EAR,                            0x00},
+	{AQT1000_CDC_CLSH_TEST0,                               0x07},
+	{AQT1000_CDC_CLSH_TEST1,                               0x00},
+	{AQT1000_CDC_CLSH_OVR_VREF,                            0x00},
+	{AQT1000_MIXING_ASRC0_CLK_RST_CTL,                     0x00},
+	{AQT1000_MIXING_ASRC0_CTL0,                            0x00},
+	{AQT1000_MIXING_ASRC0_CTL1,                            0x00},
+	{AQT1000_MIXING_ASRC0_FIFO_CTL,                        0xA8},
+	{AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB,             0x00},
+	{AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB,             0x00},
+	{AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB,             0x00},
+	{AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB,             0x00},
+	{AQT1000_MIXING_ASRC0_STATUS_FIFO,                     0x00},
+	{AQT1000_MIXING_ASRC1_CLK_RST_CTL,                     0x00},
+	{AQT1000_MIXING_ASRC1_CTL0,                            0x00},
+	{AQT1000_MIXING_ASRC1_CTL1,                            0x00},
+	{AQT1000_MIXING_ASRC1_FIFO_CTL,                        0xA8},
+	{AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB,             0x00},
+	{AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB,             0x00},
+	{AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB,             0x00},
+	{AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB,             0x00},
+	{AQT1000_MIXING_ASRC1_STATUS_FIFO,                     0x00},
+	{AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,             0x04},
+	{AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1,             0x00},
+	{AQT1000_SIDETONE_ASRC0_CLK_RST_CTL,                   0x00},
+	{AQT1000_SIDETONE_ASRC0_CTL0,                          0x00},
+	{AQT1000_SIDETONE_ASRC0_CTL1,                          0x00},
+	{AQT1000_SIDETONE_ASRC0_FIFO_CTL,                      0xA8},
+	{AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB,             0x00},
+	{AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB,             0x00},
+	{AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB,             0x00},
+	{AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB,             0x00},
+	{AQT1000_SIDETONE_ASRC0_STATUS_FIFO,                   0x00},
+	{AQT1000_EC_REF_HQ0_EC_REF_HQ_PATH_CTL,                0x00},
+	{AQT1000_EC_REF_HQ0_EC_REF_HQ_CFG0,                    0x01},
+	{AQT1000_EC_REF_HQ1_EC_REF_HQ_PATH_CTL,                0x00},
+	{AQT1000_EC_REF_HQ1_EC_REF_HQ_CFG0,                    0x01},
+	{AQT1000_EC_ASRC0_CLK_RST_CTL,                         0x00},
+	{AQT1000_EC_ASRC0_CTL0,                                0x00},
+	{AQT1000_EC_ASRC0_CTL1,                                0x00},
+	{AQT1000_EC_ASRC0_FIFO_CTL,                            0xA8},
+	{AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_LSB,                0x00},
+	{AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_MSB,                0x00},
+	{AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_LSB,                0x00},
+	{AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_MSB,                0x00},
+	{AQT1000_EC_ASRC0_STATUS_FIFO,                         0x00},
+	{AQT1000_EC_ASRC1_CLK_RST_CTL,                         0x00},
+	{AQT1000_EC_ASRC1_CTL0,                                0x00},
+	{AQT1000_EC_ASRC1_CTL1,                                0x00},
+	{AQT1000_EC_ASRC1_FIFO_CTL,                            0xA8},
+	{AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_LSB,                0x00},
+	{AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_MSB,                0x00},
+	{AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_LSB,                0x00},
+	{AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_MSB,                0x00},
+	{AQT1000_EC_ASRC1_STATUS_FIFO,                         0x00},
+	{AQT1000_PAGE13_PAGE_REGISTER,                         0x00},
+	{AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG0,                  0x00},
+	{AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG1,                  0x00},
+	{AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG0,                  0x00},
+	{AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG1,                  0x00},
+	{AQT1000_CDC_RX_INP_MUX_EQ_IIR_CFG0,                   0x00},
+	{AQT1000_CDC_RX_INP_MUX_DSD_CFG0,                      0x00},
+	{AQT1000_CDC_RX_INP_MUX_RX_MIX_CFG0,                   0x00},
+	{AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0,             0x00},
+	{AQT1000_CDC_RX_INP_MUX_ANC_CFG0,                      0x00},
+	{AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0,              0x00},
+	{AQT1000_CDC_RX_INP_MUX_EC_REF_HQ_CFG0,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG0,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG1,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG0,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG1,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG0,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG1,                 0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG0,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG1,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG0,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG1,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG0,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG1,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG0,                0x00},
+	{AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG1,                0x00},
+	{AQT1000_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0,             0x00},
+	{AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0,                    0x00},
+	{AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,                0x00},
+	{AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,              0x00},
+	{AQT1000_CDC_CLK_RST_CTRL_DSD_CONTROL,                 0x00},
+	{AQT1000_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL,             0x0F},
+	{AQT1000_CDC_CLK_RST_CTRL_GFM_CONTROL,                 0x00},
+	{AQT1000_CDC_CLK_RST_CTRL_I2S_CONTROL,                 0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_PATH_CTL,               0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_CTL,                    0x40},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,             0x00},
+	{AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL,             0x00},
+	{AQT1000_CDC_TOP_TOP_CFG0,                             0x00},
+	{AQT1000_CDC_TOP_HPHL_COMP_WR_LSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHL_COMP_WR_MSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHL_COMP_LUT,                        0x00},
+	{AQT1000_CDC_TOP_HPHL_COMP_RD_LSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHL_COMP_RD_MSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHR_COMP_WR_LSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHR_COMP_WR_MSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHR_COMP_LUT,                        0x00},
+	{AQT1000_CDC_TOP_HPHR_COMP_RD_LSB,                     0x00},
+	{AQT1000_CDC_TOP_HPHR_COMP_RD_MSB,                     0x00},
+	{AQT1000_CDC_DSD0_PATH_CTL,                            0x00},
+	{AQT1000_CDC_DSD0_CFG0,                                0x00},
+	{AQT1000_CDC_DSD0_CFG1,                                0x00},
+	{AQT1000_CDC_DSD0_CFG2,                                0x42},
+	{AQT1000_CDC_DSD0_CFG3,                                0x00},
+	{AQT1000_CDC_DSD0_CFG4,                                0x02},
+	{AQT1000_CDC_DSD0_CFG5,                                0x00},
+	{AQT1000_CDC_DSD1_PATH_CTL,                            0x00},
+	{AQT1000_CDC_DSD1_CFG0,                                0x00},
+	{AQT1000_CDC_DSD1_CFG1,                                0x00},
+	{AQT1000_CDC_DSD1_CFG2,                                0x42},
+	{AQT1000_CDC_DSD1_CFG3,                                0x00},
+	{AQT1000_CDC_DSD1_CFG4,                                0x02},
+	{AQT1000_CDC_DSD1_CFG5,                                0x00},
+	{AQT1000_CDC_RX_IDLE_DET_PATH_CTL,                     0x00},
+	{AQT1000_CDC_RX_IDLE_DET_CFG0,                         0x07},
+	{AQT1000_CDC_RX_IDLE_DET_CFG1,                         0x3C},
+	{AQT1000_CDC_RX_IDLE_DET_CFG2,                         0x00},
+	{AQT1000_CDC_RX_IDLE_DET_CFG3,                         0x00},
+	{AQT1000_CDC_DOP_DET_CTL,                              0x00},
+	{AQT1000_CDC_DOP_DET_CFG0,                             0xFA},
+	{AQT1000_CDC_DOP_DET_CFG1,                             0x05},
+	{AQT1000_CDC_DOP_DET_CFG2,                             0x00},
+	{AQT1000_CDC_DOP_DET_CFG3,                             0x33},
+	{AQT1000_CDC_DOP_DET_CFG4,                             0x20},
+	{AQT1000_CDC_DOP_DET_STATUS0,                          0x00},
+	{AQT1000_PAGE15_PAGE_REGISTER,                         0x00},
+	{AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG0,                    0x1B},
+	{AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG1,                    0x24},
+	{AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG2,                    0x00},
+	{AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG3,                    0x08},
+	{AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG0,                    0x1B},
+	{AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG1,                    0x24},
+	{AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG2,                    0x00},
+	{AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG3,                    0x08},
+	{AQT1000_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0,              0x00},
+	{AQT1000_CDC_DEBUG_ANC0_RC0_FIFO_CTL,                  0x4C},
+	{AQT1000_CDC_DEBUG_ANC0_RC1_FIFO_CTL,                  0x4C},
+	{AQT1000_CDC_DEBUG_ANC1_RC0_FIFO_CTL,                  0x4C},
+	{AQT1000_CDC_DEBUG_ANC1_RC1_FIFO_CTL,                  0x4C},
+	{AQT1000_CDC_DEBUG_ANC_RC_RST_DBG_CNTR,                0x00},
+	{AQT1000_PAGE128_PAGE_REGISTER,                        0x00},
+	{AQT1000_TLMM_SPI_CLK_PINCFG,                          0x00},
+	{AQT1000_TLMM_SPI_MOSI_PINCFG,                         0x00},
+	{AQT1000_TLMM_SPI_MISO_PINCFG,                         0x00},
+	{AQT1000_TLMM_SPI_CS_N_PINCFG,                         0x00},
+	{AQT1000_TLMM_GPIO1_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO2_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO3_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO4_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO5_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO6_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO7_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO8_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO9_PINCFG,                            0x00},
+	{AQT1000_TLMM_GPIO10_PINCFG,                           0x00},
+	{AQT1000_PAD_CTRL_PAD_PDN_CTRL_0,                      0x00},
+	{AQT1000_PAD_CTRL_PAD_PDN_CTRL_1,                      0x00},
+	{AQT1000_PAD_CTRL_PAD_PU_CTRL_0,                       0x00},
+	{AQT1000_PAD_CTRL_PAD_PU_CTRL_1,                       0x00},
+	{AQT1000_PAD_CTRL_GPIO_CTL_0_OE,                       0x00},
+	{AQT1000_PAD_CTRL_GPIO_CTL_1_OE,                       0x00},
+	{AQT1000_PAD_CTRL_GPIO_CTL_0_DATA,                     0x00},
+	{AQT1000_PAD_CTRL_GPIO_CTL_1_DATA,                     0x00},
+	{AQT1000_PAD_CTRL_PAD_DRVCTL,                          0x00},
+	{AQT1000_PAD_CTRL_PIN_STATUS,                          0x00},
+	{AQT1000_PAD_CTRL_MEM_CTRL,                            0x00},
+	{AQT1000_PAD_CTRL_PAD_INP_DISABLE_0,                   0x00},
+	{AQT1000_PAD_CTRL_PAD_INP_DISABLE_1,                   0x00},
+	{AQT1000_PAD_CTRL_PIN_CTL_OE_0,                        0x00},
+	{AQT1000_PAD_CTRL_PIN_CTL_OE_1,                        0x00},
+	{AQT1000_PAD_CTRL_PIN_CTL_DATA_0,                      0x00},
+	{AQT1000_PAD_CTRL_PIN_CTL_DATA_1,                      0x00},
+	{AQT1000_PAD_CTRL_USB_PHY_CLK_DIV,                     0x0F},
+	{AQT1000_PAD_CTRL_DEBUG_BUS_CDC,                       0x00},
+	{AQT1000_PAD_CTRL_DEBUG_BUS_SEL,                       0x00},
+	{AQT1000_PAD_CTRL_DEBUG_EN_1,                          0x00},
+	{AQT1000_PAD_CTRL_DEBUG_EN_2,                          0x00},
+	{AQT1000_PAD_CTRL_DEBUG_EN_3,                          0x00},
+	{AQT1000_PAD_CTRL_DEBUG_EN_4,                          0x00},
+	{AQT1000_PAD_CTRL_DEBUG_EN_5,                          0x00},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_0,                     0x00},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_1,                     0x01},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_2,                     0x02},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_3,                     0x03},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_4,                     0x04},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_5,                     0x05},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_6,                     0x06},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_7,                     0x07},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_8,                     0x08},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_9,                     0x09},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_10,                    0x0A},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_11,                    0x0B},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_12,                    0x0C},
+	{AQT1000_PAD_CTRL_DEBUG_MUX_BIT_13,                    0x0D},
+	{AQT1000_PAD_CTRL_DEBUG_READ_0,                        0x0D},
+	{AQT1000_PAD_CTRL_DEBUG_READ_1,                        0x0D},
+	{AQT1000_PAD_CTRL_DEBUG_READ_2,                        0x0D},
+	{AQT1000_PAD_CTRL_DEBUG_READ_3,                        0x0D},
+	{AQT1000_PAD_CTRL_FPGA_CTL,                            0x00},
+};
+
+const u8 aqt1000_page0_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE0_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CHIP_ID_BYTE0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CHIP_ID_BYTE1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CHIP_ID_BYTE2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CHIP_ID_BYTE3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_TEST0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_TEST1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT4)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT5)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT6)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT7)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT8)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT9)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT10)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT11)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT12)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT13)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT14)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_VAL_OUT15)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_I2C_SLAVE_ID_NONNEGO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_I2C_SLAVE_ID_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_I2C_SLAVE_ID_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_I2C_SLAVE_ID_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_I2C_ACTIVE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CLK_CFG_MCLK)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CLK_CFG_MCLK2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_TEST0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_TEST1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT4)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT5)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT6)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT7)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT8)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT9)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT10)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT11)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT12)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT13)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT14)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT15)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG0_EFUSE2_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_BUS_MTRX_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_DMA_BUS_VOTE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_USB_BUS_VOTE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_BLSP_BUS_VOTE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_MEM_SD)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_RAM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_ROM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_RAM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_ROM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_CLK_CFG_FLL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_CLK_CFG_SPI_M)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_CLK_CFG_I2C_M)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_CLK_CFG_UART)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_RST_USB_SS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_RST_BLSP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_RST_BUS_MTRX)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_RST_MISC)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CHIP_CFG1_ANA_WAIT_STATE_CTL)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page1_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE1_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_8)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_USER_CTL_9)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_L_VAL_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_L_VAL_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_DSM_FRAC_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_DSM_FRAC_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_CONFIG_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_CONFIG_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_CONFIG_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_CONFIG_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_CONFIG_CTL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_TEST_CTL_7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_FREQ_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_FREQ_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_FREQ_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_FREQ_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_SSC_CTL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_SSC_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_SSC_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_SSC_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_FLL_MODE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLL_STATUS_0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_FLL_STATUS_1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_FLL_STATUS_2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_FLL_STATUS_3)] = AQT1000_RO,
+};
+
+const u8 aqt1000_page2_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE2_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_0_TX_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_0_RX_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_0_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_CLKSRC_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_HS_CLK_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_I2S_0_RST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_SHADOW_I2S_0_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_I2S_SHADOW_I2S_0_RX_CFG)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page5_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE5_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_MCU_INT_POLARITY)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_MASK_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_4)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_5)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_STATUS_6)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_0)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_1)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_2)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_3)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_4)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_5)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_CLEAR_6)] = AQT1000_WO,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TYPE_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_EN_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_TEST_VAL_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_8)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_9)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_10)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_11)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_12)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_INT_DEST_13)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_INTR_CTRL_CLR_COMMIT)] = AQT1000_WO,
+};
+
+const u8 aqt1000_page6_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_ANA_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_BIAS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_RX_SUPPLIES)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_HPH)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_AMIC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_AMIC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_AMIC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_AMIC3_HPF)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_MECH)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_ELECT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_ZDET)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_RESULT_1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_ANA_MBHC_RESULT_2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_ANA_MBHC_RESULT_3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MBHC_BTN7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MICB1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_ANA_MICB1_RAMP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BIAS_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BIAS_CCOMP_FINE_ADJ)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MODE_SEL_R)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MISC_R)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MODE_SEL_G)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MISC_G)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MODE_SEL_B)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LED_LED_MISC_B)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOH_MODE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOH_BIAS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOH_STB_LOADS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOH_MISC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOL_VDDCX_ADJUST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_LDOL_DISABLE_LDOL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_EN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_VOUT_SEL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_VCL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_VCL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_CCL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_CCL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_CCL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_CCL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_CTRL_CCL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_IBIAS_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_IBIAS_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_IBIAS_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_IBIAS_CTL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_IBIAS_CTL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_BUCK_5V_ATEST_DTEST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PON_BG_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PON_TEST_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_CTL_CLK)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_CTL_ANA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_CTL_SPARE_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_CTL_SPARE_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_CTL_BCS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_MOISTURE_DET_FSM_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MBHC_TEST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_TEST_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_TEST_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_TEST_CTL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_MISC_MICB_MISC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MICB1_MISC_MICB_MISC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_ADC_VCM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_BIAS_ATEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_ADC_INT1_IB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_ADC_INT2_IB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_TXFE_DIV_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_TXFE_DIV_START)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_TXFE_DIV_STOP_9P6M)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_COM_TXFE_DIV_STOP_12P288M)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_TEST_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_ADC_IB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_ATEST_REFCTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_TEST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_TEST_BLK_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_TXFE_CLKDIV)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_1_2_SAR1_ERR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_TX_1_2_SAR2_ERR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_TX_3_TEST_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_ADC_IB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_ATEST_REFCTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_TEST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_TEST_BLK_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_TXFE_CLKDIV)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TX_3_SAR1_ERR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_TX_3_SAR2_ERR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_TX_ATEST1_2_SEL)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CLASSH_MODE_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_MODE_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_MODE_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_VCL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_VCL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_CCL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_CCL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_CCL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_CCL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_CTRL_CCL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_BUCK_TMUX_A_D)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_BUCK_SW_DRV_CNTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLASSH_SPARE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_8)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEG_CTRL_9)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEGDAC_CTRL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEGDAC_CTRL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_VNEGDAC_CTRL_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_CTRL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_FLYBACK_TEST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_AUX_SW_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_PA_AUX_IN_CONN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_TIMER_DIV)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_OCP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_OCP_COUNT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_ATEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_MISC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_LDO)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_PA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_RDACBUFF_CNP2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_RDAC_LDO)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_CNP1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_HPH_LOWPOWER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_MISC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_MISC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_MISC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_MISC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_BUCK_RST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_BUCK_VREF_ERRAMP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_FLYB_ERRAMP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_FLYB_BUFF)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_BIAS_FLYB_MID_RST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_L_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_HPH_R_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_HPH_CNP_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_CNP_WG_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_CNP_WG_TIME)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_OCP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_AUTO_CHOP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_CHOP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_PA_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_PA_CTL2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_L_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_L_TEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_L_ATEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_R_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_R_TEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_R_ATEST)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_RDAC_CLK_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_RDAC_CLK_CTL2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_RDAC_LDO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_RDAC_CHOP_CLK_LP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_REFBUFF_UHQA_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_REFBUFF_LP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_L_DAC_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_R_DAC_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPHLR_SURGE_COMP_SEL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPHLR_SURGE_EN)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPHLR_SURGE_MISC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPHLR_SURGE_STATUS)] = AQT1000_RO,
+};
+
+const u8 aqt1000_page7_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_ANA_NEW_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_ANA_HPH2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_ANA_HPH3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_MCLK1_PRG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_XO_CAP_XTP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_XO_CAP_XTM)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_PLL_ENABLES)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_PLL_PRESET)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_PLL_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MBHC_NEW_ELECT_REM_CLAMP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_CTL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_CTL_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_PLUG_DETECT_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_ZDET_ANA_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_ZDET_RAMP_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_FSM_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MBHC_NEW_ADC_RESULT)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_RDAC_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_L)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_RDAC_VREF_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_RDAC_OVERRIDE_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_R)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_PA_MISC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_PA_MISC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_PA_RDAC_MISC)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_HPH_TIMER1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_HPH_TIMER2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_HPH_TIMER3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_HPH_TIMER4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_PA_RDAC_MISC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_HPH_NEW_INT_PA_RDAC_MISC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_ULP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_RX_NEW_INT_HPH_RDAC_LDO_LP)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_CLK_TEST1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_XO_TEST1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_XO_TEST2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_POST_DIV_REG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_POST_DIV_REG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_REF_DIV_REG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_REF_DIV_REG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_FILTER_REG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_FILTER_REG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_PLL_L_VAL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_PLL_M_VAL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_PLL_N_VAL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_TEST_REG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_PFD_CP_DSM_PROG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_VCO_PROG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_TEST_REG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_LDO_LOCK_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CLK_SYS_INT_DIG_LOCK_DET_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL)] =
+								   AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_INT_MECH_DET_CURRENT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MBHC_NEW_INT_SPARE_2)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page10_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE10_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_CLK_RESET_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_MODE_1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_MODE_2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FF_SHIFT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FB_SHIFT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_LPF_FF_A_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_LPF_FF_B_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_LPF_FB_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_SMLPF_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_DCFLT_SHIFT_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_IIR_ADAPT_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_IIR_COEFF_1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_IIR_COEFF_2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FF_A_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FF_B_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FB_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_RC_COMMON_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_FIFO_COMMON_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC0_RC0_STATUS_FMIN_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC0_RC1_STATUS_FMIN_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC0_RC0_STATUS_FMAX_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC0_RC1_STATUS_FMAX_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC0_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC1_CLK_RESET_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_MODE_1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_MODE_2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FF_SHIFT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FB_SHIFT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_LPF_FF_A_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_LPF_FF_B_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_LPF_FB_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_SMLPF_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_DCFLT_SHIFT_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_IIR_ADAPT_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_IIR_COEFF_1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_IIR_COEFF_2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FF_A_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FF_B_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FB_GAIN_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_RC_COMMON_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_FIFO_COMMON_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_ANC1_RC0_STATUS_FMIN_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC1_RC1_STATUS_FMIN_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC1_RC0_STATUS_FMAX_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC1_RC1_STATUS_FMAX_CNTR)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_ANC1_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_VOL_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX0_TX_PATH_SEC6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_VOL_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX1_TX_PATH_SEC6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_VOL_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX2_TX_PATH_SEC7)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page11_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE11_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL6)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER1_CTL7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL6)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_COMPANDER2_CTL7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_VOL_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_MIX_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_MIX_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_VOL_MIX_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_SEC7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_MIX_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_MIX_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX1_RX_PATH_DSMDEM_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_VOL_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_MIX_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_MIX_CFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_VOL_MIX_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_SEC7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_MIX_SEC0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_MIX_SEC1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX2_RX_PATH_DSMDEM_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_PATH_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_PATH_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_COEF_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR0_COEF_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_PATH_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_PATH_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_PATH_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_COEF_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_EQ_IIR1_COEF_CFG1)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page12_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE12_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_CRC)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_DLY_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_DECAY_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_HPH_V_PA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_EAR_V_PA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_HPH_V_HD)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_EAR_V_HD)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_K1_MSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_K1_LSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_K2_MSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_K2_LSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_IDLE_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_IDLE_HPH)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_IDLE_EAR)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_TEST0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_TEST1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLSH_OVR_VREF)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_CLK_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC0_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_CLK_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_MIXING_ASRC1_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_CLK_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_SIDETONE_ASRC0_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_REF_HQ0_EC_REF_HQ_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_REF_HQ0_EC_REF_HQ_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_REF_HQ1_EC_REF_HQ_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_REF_HQ1_EC_REF_HQ_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC0_CLK_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC0_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC0_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC0_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC0_STATUS_FIFO)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC1_CLK_RST_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC1_CTL0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC1_CTL1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC1_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_EC_ASRC1_STATUS_FIFO)] = AQT1000_RO,
+};
+
+const u8 aqt1000_page13_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE13_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_EQ_IIR_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_DSD_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_RX_MIX_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_ANC_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_INP_MUX_EC_REF_HQ_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0)] =
+								AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_DSD_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_GFM_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_CLK_RST_CTRL_I2S_CONTROL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] =
+								AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_TOP_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHL_COMP_WR_LSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHL_COMP_WR_MSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHL_COMP_LUT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHL_COMP_RD_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHL_COMP_RD_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHR_COMP_WR_LSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHR_COMP_WR_MSB)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHR_COMP_LUT)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHR_COMP_RD_LSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_TOP_HPHR_COMP_RD_MSB)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_DSD0_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD0_CFG5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DSD1_CFG5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_IDLE_DET_PATH_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_IDLE_DET_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_IDLE_DET_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_IDLE_DET_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_RX_IDLE_DET_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CFG2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_CFG4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DOP_DET_STATUS0)] = AQT1000_RO,
+};
+
+const u8 aqt1000_page15_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE15_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_ANC0_RC0_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_ANC0_RC1_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_ANC1_RC0_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_ANC1_RC1_FIFO_CTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_CDC_DEBUG_ANC_RC_RST_DBG_CNTR)] = AQT1000_RW,
+};
+
+const u8 aqt1000_page128_reg_access[AQT1000_PAGE_SIZE] = {
+	[AQT1000_REG(AQT1000_PAGE128_PAGE_REGISTER)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_SPI_CLK_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_SPI_MOSI_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_SPI_MISO_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_SPI_CS_N_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO1_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO2_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO3_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO4_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO5_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO6_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO7_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO8_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO9_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_TLMM_GPIO10_PINCFG)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_PDN_CTRL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_PDN_CTRL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_PU_CTRL_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_PU_CTRL_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_GPIO_CTL_0_OE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_GPIO_CTL_1_OE)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_GPIO_CTL_0_DATA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_GPIO_CTL_1_DATA)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_DRVCTL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PIN_STATUS)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_PAD_CTRL_MEM_CTRL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_INP_DISABLE_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PAD_INP_DISABLE_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PIN_CTL_OE_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PIN_CTL_OE_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PIN_CTL_DATA_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_PIN_CTL_DATA_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_USB_PHY_CLK_DIV)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_BUS_CDC)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_BUS_SEL)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_EN_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_EN_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_EN_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_EN_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_EN_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_0)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_1)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_2)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_3)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_4)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_5)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_6)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_7)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_8)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_9)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_10)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_11)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_12)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_MUX_BIT_13)] = AQT1000_RW,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_READ_0)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_READ_1)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_READ_2)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_PAD_CTRL_DEBUG_READ_3)] = AQT1000_RO,
+	[AQT1000_REG(AQT1000_PAD_CTRL_FPGA_CTL)] = AQT1000_RW,
+};
+
+const u8 * const aqt1000_reg[AQT1000_PAGE_MAX] = {
+	[AQT1000_PAGE_0] = aqt1000_page0_reg_access,
+	[AQT1000_PAGE_1] = aqt1000_page1_reg_access,
+	[AQT1000_PAGE_2] = aqt1000_page2_reg_access,
+	[AQT1000_PAGE_5] = aqt1000_page5_reg_access,
+	[AQT1000_PAGE_6] = aqt1000_page6_reg_access,
+	[AQT1000_PAGE_7] = aqt1000_page7_reg_access,
+	[AQT1000_PAGE_10] = aqt1000_page10_reg_access,
+	[AQT1000_PAGE_11] = aqt1000_page11_reg_access,
+	[AQT1000_PAGE_12] = aqt1000_page12_reg_access,
+	[AQT1000_PAGE_13] = aqt1000_page13_reg_access,
+	[AQT1000_PAGE_15] = aqt1000_page15_reg_access,
+	[AQT1000_PAGE_128] = aqt1000_page128_reg_access,
+};
+
+#endif /* _AQT1000_REG_DEFAULTS_H */

+ 873 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-registers.h

@@ -0,0 +1,873 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _AQT1000_REGISTERS_H
+#define _AQT1000_REGISTERS_H
+
+#define AQT1000_PAGE0_BASE                  (0x00000000)
+#define AQT1000_PAGE0_PAGE_REGISTER                       (0x00000000)
+#define AQT1000_CHIP_CFG0_BASE              (0x00000001)
+#define AQT1000_CHIP_CFG0_CHIP_ID_BYTE0                   (0x00000001)
+#define AQT1000_CHIP_CFG0_CHIP_ID_BYTE1                   (0x00000002)
+#define AQT1000_CHIP_CFG0_CHIP_ID_BYTE2                   (0x00000003)
+#define AQT1000_CHIP_CFG0_CHIP_ID_BYTE3                   (0x00000004)
+#define AQT1000_CHIP_CFG0_EFUSE_CTL                       (0x00000005)
+#define AQT1000_CHIP_CFG0_EFUSE_TEST0                     (0x00000006)
+#define AQT1000_CHIP_CFG0_EFUSE_TEST1                     (0x00000007)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT0                  (0x00000009)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT1                  (0x0000000A)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT2                  (0x0000000B)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT3                  (0x0000000C)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT4                  (0x0000000D)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT5                  (0x0000000E)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT6                  (0x0000000F)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT7                  (0x00000010)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT8                  (0x00000011)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT9                  (0x00000012)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT10                 (0x00000013)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT11                 (0x00000014)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT12                 (0x00000015)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT13                 (0x00000016)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT14                 (0x00000017)
+#define AQT1000_CHIP_CFG0_EFUSE_VAL_OUT15                 (0x00000018)
+#define AQT1000_CHIP_CFG0_EFUSE_STATUS                    (0x00000019)
+#define AQT1000_CHIP_CFG0_I2C_SLAVE_ID_NONNEGO            (0x0000001A)
+#define AQT1000_CHIP_CFG0_I2C_SLAVE_ID_1                  (0x0000001B)
+#define AQT1000_CHIP_CFG0_I2C_SLAVE_ID_2                  (0x0000001C)
+#define AQT1000_CHIP_CFG0_I2C_SLAVE_ID_3                  (0x0000001D)
+#define AQT1000_CHIP_CFG0_I2C_ACTIVE                      (0x00000020)
+#define AQT1000_CHIP_CFG0_CLK_CFG_MCLK                    (0x00000021)
+#define AQT1000_CHIP_CFG0_CLK_CFG_MCLK2                   (0x00000022)
+#define AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG                 (0x00000023)
+#define AQT1000_CHIP_CFG0_RST_CTL                         (0x00000032)
+#define AQT1000_CHIP_CFG0_EFUSE2_CTL                      (0x0000003D)
+#define AQT1000_CHIP_CFG0_EFUSE2_TEST0                    (0x0000003E)
+#define AQT1000_CHIP_CFG0_EFUSE2_TEST1                    (0x0000003F)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT0                 (0x00000040)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT1                 (0x00000041)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT2                 (0x00000042)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT3                 (0x00000043)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT4                 (0x00000044)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT5                 (0x00000045)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT6                 (0x00000046)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT7                 (0x00000047)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT8                 (0x00000048)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT9                 (0x00000049)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT10                (0x0000004A)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT11                (0x0000004B)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT12                (0x0000004C)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT13                (0x0000004D)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT14                (0x0000004E)
+#define AQT1000_CHIP_CFG0_EFUSE2_VAL_OUT15                (0x0000004F)
+#define AQT1000_CHIP_CFG0_EFUSE2_STATUS                   (0x00000050)
+#define AQT1000_CHIP_CFG1_BASE              (0x00000051)
+#define AQT1000_CHIP_CFG1_PWR_CTL                         (0x00000051)
+#define AQT1000_CHIP_CFG1_BUS_MTRX_CFG                    (0x00000052)
+#define AQT1000_CHIP_CFG1_DMA_BUS_VOTE                    (0x00000053)
+#define AQT1000_CHIP_CFG1_USB_BUS_VOTE                    (0x00000054)
+#define AQT1000_CHIP_CFG1_BLSP_BUS_VOTE                   (0x00000055)
+#define AQT1000_CHIP_CFG1_PWR_MEM_SD                      (0x00000059)
+#define AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_RAM              (0x0000005C)
+#define AQT1000_CHIP_CFG1_PWR_SYS_MEM_SD_ROM              (0x0000005D)
+#define AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_RAM        (0x0000005E)
+#define AQT1000_CHIP_CFG1_PWR_SYS_MEM_FORCE_DS_ROM        (0x0000005F)
+#define AQT1000_CHIP_CFG1_CLK_CFG_FLL                     (0x00000061)
+#define AQT1000_CHIP_CFG1_CLK_CFG_SPI_M                   (0x00000062)
+#define AQT1000_CHIP_CFG1_CLK_CFG_I2C_M                   (0x00000063)
+#define AQT1000_CHIP_CFG1_CLK_CFG_UART                    (0x00000064)
+#define AQT1000_CHIP_CFG1_RST_USB_SS                      (0x00000071)
+#define AQT1000_CHIP_CFG1_RST_BLSP                        (0x00000072)
+#define AQT1000_CHIP_CFG1_RST_BUS_MTRX                    (0x00000073)
+#define AQT1000_CHIP_CFG1_RST_MISC                        (0x00000074)
+#define AQT1000_CHIP_CFG1_ANA_WAIT_STATE_CTL              (0x00000081)
+#define AQT1000_PAGE1_BASE                  (0x00000100)
+#define AQT1000_PAGE1_PAGE_REGISTER                       (0x00000100)
+#define AQT1000_FLL_BASE                    (0x00000101)
+#define AQT1000_FLL_USER_CTL_0                            (0x00000101)
+#define AQT1000_FLL_USER_CTL_1                            (0x00000102)
+#define AQT1000_FLL_USER_CTL_2                            (0x00000103)
+#define AQT1000_FLL_USER_CTL_3                            (0x00000104)
+#define AQT1000_FLL_USER_CTL_4                            (0x00000105)
+#define AQT1000_FLL_USER_CTL_5                            (0x00000106)
+#define AQT1000_FLL_USER_CTL_6                            (0x00000107)
+#define AQT1000_FLL_USER_CTL_7                            (0x00000108)
+#define AQT1000_FLL_USER_CTL_8                            (0x00000109)
+#define AQT1000_FLL_USER_CTL_9                            (0x0000010A)
+#define AQT1000_FLL_L_VAL_CTL_0                           (0x0000010B)
+#define AQT1000_FLL_L_VAL_CTL_1                           (0x0000010C)
+#define AQT1000_FLL_DSM_FRAC_CTL_0                        (0x0000010D)
+#define AQT1000_FLL_DSM_FRAC_CTL_1                        (0x0000010E)
+#define AQT1000_FLL_CONFIG_CTL_0                          (0x0000010F)
+#define AQT1000_FLL_CONFIG_CTL_1                          (0x00000110)
+#define AQT1000_FLL_CONFIG_CTL_2                          (0x00000111)
+#define AQT1000_FLL_CONFIG_CTL_3                          (0x00000112)
+#define AQT1000_FLL_CONFIG_CTL_4                          (0x00000113)
+#define AQT1000_FLL_TEST_CTL_0                            (0x00000114)
+#define AQT1000_FLL_TEST_CTL_1                            (0x00000115)
+#define AQT1000_FLL_TEST_CTL_2                            (0x00000116)
+#define AQT1000_FLL_TEST_CTL_3                            (0x00000117)
+#define AQT1000_FLL_TEST_CTL_4                            (0x00000118)
+#define AQT1000_FLL_TEST_CTL_5                            (0x00000119)
+#define AQT1000_FLL_TEST_CTL_6                            (0x0000011A)
+#define AQT1000_FLL_TEST_CTL_7                            (0x0000011B)
+#define AQT1000_FLL_FREQ_CTL_0                            (0x0000011C)
+#define AQT1000_FLL_FREQ_CTL_1                            (0x0000011D)
+#define AQT1000_FLL_FREQ_CTL_2                            (0x0000011E)
+#define AQT1000_FLL_FREQ_CTL_3                            (0x0000011F)
+#define AQT1000_FLL_SSC_CTL_0                             (0x00000120)
+#define AQT1000_FLL_SSC_CTL_1                             (0x00000121)
+#define AQT1000_FLL_SSC_CTL_2                             (0x00000122)
+#define AQT1000_FLL_SSC_CTL_3                             (0x00000123)
+#define AQT1000_FLL_FLL_MODE                              (0x00000124)
+#define AQT1000_FLL_STATUS_0                              (0x00000125)
+#define AQT1000_FLL_STATUS_1                              (0x00000126)
+#define AQT1000_FLL_STATUS_2                              (0x00000127)
+#define AQT1000_FLL_STATUS_3                              (0x00000128)
+#define AQT1000_PAGE2_BASE                  (0x00000200)
+#define AQT1000_PAGE2_PAGE_REGISTER                       (0x00000200)
+#define AQT1000_I2S_BASE                    (0x00000201)
+#define AQT1000_I2S_I2S_0_TX_CFG                          (0x00000201)
+#define AQT1000_I2S_I2S_0_RX_CFG                          (0x00000202)
+#define AQT1000_I2S_I2S_0_CTL                             (0x00000203)
+#define AQT1000_I2S_I2S_CLKSRC_CTL                        (0x00000204)
+#define AQT1000_I2S_I2S_HS_CLK_CTL                        (0x00000205)
+#define AQT1000_I2S_I2S_0_RST                             (0x00000206)
+#define AQT1000_I2S_SHADOW_I2S_0_CTL                      (0x00000207)
+#define AQT1000_I2S_SHADOW_I2S_0_RX_CFG                   (0x00000208)
+#define AQT1000_PAGE5_BASE                  (0x00000500)
+#define AQT1000_PAGE5_PAGE_REGISTER                       (0x00000500)
+#define AQT1000_INTR_CTRL_INTR_CTRL_BASE    (0x00000501)
+#define AQT1000_INTR_CTRL_MCU_INT_POLARITY                (0x00000501)
+#define AQT1000_INTR_CTRL_INT_MASK_0                      (0x00000502)
+#define AQT1000_INTR_CTRL_INT_MASK_1                      (0x00000503)
+#define AQT1000_INTR_CTRL_INT_MASK_2                      (0x00000504)
+#define AQT1000_INTR_CTRL_INT_MASK_3                      (0x00000505)
+#define AQT1000_INTR_CTRL_INT_MASK_4                      (0x00000506)
+#define AQT1000_INTR_CTRL_INT_MASK_5                      (0x00000507)
+#define AQT1000_INTR_CTRL_INT_MASK_6                      (0x00000508)
+#define AQT1000_INTR_CTRL_INT_STATUS_0                    (0x00000509)
+#define AQT1000_INTR_CTRL_INT_STATUS_1                    (0x0000050A)
+#define AQT1000_INTR_CTRL_INT_STATUS_2                    (0x0000050B)
+#define AQT1000_INTR_CTRL_INT_STATUS_3                    (0x0000050C)
+#define AQT1000_INTR_CTRL_INT_STATUS_4                    (0x0000050D)
+#define AQT1000_INTR_CTRL_INT_STATUS_5                    (0x0000050E)
+#define AQT1000_INTR_CTRL_INT_STATUS_6                    (0x0000050F)
+#define AQT1000_INTR_CTRL_INT_CLEAR_0                     (0x00000510)
+#define AQT1000_INTR_CTRL_INT_CLEAR_1                     (0x00000511)
+#define AQT1000_INTR_CTRL_INT_CLEAR_2                     (0x00000512)
+#define AQT1000_INTR_CTRL_INT_CLEAR_3                     (0x00000513)
+#define AQT1000_INTR_CTRL_INT_CLEAR_4                     (0x00000514)
+#define AQT1000_INTR_CTRL_INT_CLEAR_5                     (0x00000515)
+#define AQT1000_INTR_CTRL_INT_CLEAR_6                     (0x00000516)
+#define AQT1000_INTR_CTRL_INT_TYPE_0                      (0x00000517)
+#define AQT1000_INTR_CTRL_INT_TYPE_1                      (0x00000518)
+#define AQT1000_INTR_CTRL_INT_TYPE_2                      (0x00000519)
+#define AQT1000_INTR_CTRL_INT_TYPE_3                      (0x0000051A)
+#define AQT1000_INTR_CTRL_INT_TYPE_4                      (0x0000051B)
+#define AQT1000_INTR_CTRL_INT_TYPE_5                      (0x0000051C)
+#define AQT1000_INTR_CTRL_INT_TYPE_6                      (0x0000051D)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_0                   (0x0000051E)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_1                   (0x0000051F)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_2                   (0x00000520)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_3                   (0x00000521)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_4                   (0x00000522)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_5                   (0x00000523)
+#define AQT1000_INTR_CTRL_INT_TEST_EN_6                   (0x00000524)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_0                  (0x00000525)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_1                  (0x00000526)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_2                  (0x00000527)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_3                  (0x00000528)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_4                  (0x00000529)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_5                  (0x0000052A)
+#define AQT1000_INTR_CTRL_INT_TEST_VAL_6                  (0x0000052B)
+#define AQT1000_INTR_CTRL_INT_DEST_0                      (0x0000052C)
+#define AQT1000_INTR_CTRL_INT_DEST_1                      (0x0000052D)
+#define AQT1000_INTR_CTRL_INT_DEST_2                      (0x0000052E)
+#define AQT1000_INTR_CTRL_INT_DEST_3                      (0x0000052F)
+#define AQT1000_INTR_CTRL_INT_DEST_4                      (0x00000530)
+#define AQT1000_INTR_CTRL_INT_DEST_5                      (0x00000531)
+#define AQT1000_INTR_CTRL_INT_DEST_6                      (0x00000532)
+#define AQT1000_INTR_CTRL_INT_DEST_7                      (0x00000533)
+#define AQT1000_INTR_CTRL_INT_DEST_8                      (0x00000534)
+#define AQT1000_INTR_CTRL_INT_DEST_9                      (0x00000535)
+#define AQT1000_INTR_CTRL_INT_DEST_10                     (0x00000536)
+#define AQT1000_INTR_CTRL_INT_DEST_11                     (0x00000537)
+#define AQT1000_INTR_CTRL_INT_DEST_12                     (0x00000538)
+#define AQT1000_INTR_CTRL_INT_DEST_13                     (0x00000539)
+#define AQT1000_INTR_CTRL_CLR_COMMIT                      (0x000005E1)
+#define AQT1000_ANA_BASE                    (0x00000600)
+#define AQT1000_ANA_PAGE_REGISTER                         (0x00000600)
+#define AQT1000_ANA_BIAS                                  (0x00000601)
+#define AQT1000_ANA_RX_SUPPLIES                           (0x00000608)
+#define AQT1000_ANA_HPH                                   (0x00000609)
+#define AQT1000_ANA_AMIC1                                 (0x0000060E)
+#define AQT1000_ANA_AMIC2                                 (0x0000060F)
+#define AQT1000_ANA_AMIC3                                 (0x00000610)
+#define AQT1000_ANA_AMIC3_HPF                             (0x00000611)
+#define AQT1000_ANA_MBHC_MECH                             (0x00000614)
+#define AQT1000_ANA_MBHC_ELECT                            (0x00000615)
+#define AQT1000_ANA_MBHC_ZDET                             (0x00000616)
+#define AQT1000_ANA_MBHC_RESULT_1                         (0x00000617)
+#define AQT1000_ANA_MBHC_RESULT_2                         (0x00000618)
+#define AQT1000_ANA_MBHC_RESULT_3                         (0x00000619)
+#define AQT1000_ANA_MBHC_BTN0                             (0x0000061A)
+#define AQT1000_ANA_MBHC_BTN1                             (0x0000061B)
+#define AQT1000_ANA_MBHC_BTN2                             (0x0000061C)
+#define AQT1000_ANA_MBHC_BTN3                             (0x0000061D)
+#define AQT1000_ANA_MBHC_BTN4                             (0x0000061E)
+#define AQT1000_ANA_MBHC_BTN5                             (0x0000061F)
+#define AQT1000_ANA_MBHC_BTN6                             (0x00000620)
+#define AQT1000_ANA_MBHC_BTN7                             (0x00000621)
+#define AQT1000_ANA_MICB1                                 (0x00000622)
+#define AQT1000_ANA_MICB1_RAMP                            (0x00000624)
+#define AQT1000_BIAS_BASE                   (0x00000628)
+#define AQT1000_BIAS_CTL                                  (0x00000628)
+#define AQT1000_BIAS_CCOMP_FINE_ADJ                       (0x00000629)
+#define AQT1000_LED_BASE                    (0x0000062E)
+#define AQT1000_LED_LED_MODE_SEL_R                        (0x0000062E)
+#define AQT1000_LED_LED_MISC_R                            (0x0000062F)
+#define AQT1000_LED_LED_MODE_SEL_G                        (0x00000630)
+#define AQT1000_LED_LED_MISC_G                            (0x00000631)
+#define AQT1000_LED_LED_MODE_SEL_B                        (0x00000632)
+#define AQT1000_LED_LED_MISC_B                            (0x00000633)
+#define AQT1000_LDOH_BASE                   (0x0000063A)
+#define AQT1000_LDOH_MODE                                 (0x0000063A)
+#define AQT1000_LDOH_BIAS                                 (0x0000063B)
+#define AQT1000_LDOH_STB_LOADS                            (0x0000063C)
+#define AQT1000_LDOH_MISC1                                (0x0000063D)
+#define AQT1000_LDOL_BASE                   (0x00000640)
+#define AQT1000_LDOL_VDDCX_ADJUST                         (0x00000640)
+#define AQT1000_LDOL_DISABLE_LDOL                         (0x00000641)
+#define AQT1000_BUCK_5V_BASE                (0x00000644)
+#define AQT1000_BUCK_5V_EN_CTL                            (0x00000644)
+#define AQT1000_BUCK_5V_VOUT_SEL                          (0x00000645)
+#define AQT1000_BUCK_5V_CTRL_VCL_1                        (0x00000646)
+#define AQT1000_BUCK_5V_CTRL_VCL_2                        (0x00000647)
+#define AQT1000_BUCK_5V_CTRL_CCL_2                        (0x00000648)
+#define AQT1000_BUCK_5V_CTRL_CCL_1                        (0x00000649)
+#define AQT1000_BUCK_5V_CTRL_CCL_3                        (0x0000064A)
+#define AQT1000_BUCK_5V_CTRL_CCL_4                        (0x0000064B)
+#define AQT1000_BUCK_5V_CTRL_CCL_5                        (0x0000064C)
+#define AQT1000_BUCK_5V_IBIAS_CTL_1                       (0x0000064D)
+#define AQT1000_BUCK_5V_IBIAS_CTL_2                       (0x0000064E)
+#define AQT1000_BUCK_5V_IBIAS_CTL_3                       (0x0000064F)
+#define AQT1000_BUCK_5V_IBIAS_CTL_4                       (0x00000650)
+#define AQT1000_BUCK_5V_IBIAS_CTL_5                       (0x00000651)
+#define AQT1000_BUCK_5V_ATEST_DTEST_CTL                   (0x00000652)
+#define AQT1000_PON_BASE                    (0x00000653)
+#define AQT1000_PON_BG_CTRL                               (0x00000653)
+#define AQT1000_PON_TEST_CTRL                             (0x00000654)
+#define AQT1000_MBHC_BASE                   (0x00000656)
+#define AQT1000_MBHC_CTL_CLK                              (0x00000656)
+#define AQT1000_MBHC_CTL_ANA                              (0x00000657)
+#define AQT1000_MBHC_CTL_SPARE_1                          (0x00000658)
+#define AQT1000_MBHC_CTL_SPARE_2                          (0x00000659)
+#define AQT1000_MBHC_CTL_BCS                              (0x0000065A)
+#define AQT1000_MBHC_MOISTURE_DET_FSM_STATUS              (0x0000065B)
+#define AQT1000_MBHC_TEST_CTL                             (0x0000065C)
+#define AQT1000_MICB1_BASE                  (0x0000066B)
+#define AQT1000_MICB1_TEST_CTL_1                          (0x0000066B)
+#define AQT1000_MICB1_TEST_CTL_2                          (0x0000066C)
+#define AQT1000_MICB1_TEST_CTL_3                          (0x0000066D)
+#define AQT1000_MICB1_MISC_BASE             (0x0000066E)
+#define AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS             (0x0000066E)
+#define AQT1000_MICB1_MISC_MICB_MISC1                     (0x0000066F)
+#define AQT1000_MICB1_MISC_MICB_MISC2                     (0x00000670)
+#define AQT1000_TX_COM_BASE                 (0x00000677)
+#define AQT1000_TX_COM_ADC_VCM                            (0x00000677)
+#define AQT1000_TX_COM_BIAS_ATEST                         (0x00000678)
+#define AQT1000_TX_COM_ADC_INT1_IB                        (0x00000679)
+#define AQT1000_TX_COM_ADC_INT2_IB                        (0x0000067A)
+#define AQT1000_TX_COM_TXFE_DIV_CTL                       (0x0000067B)
+#define AQT1000_TX_COM_TXFE_DIV_START                     (0x0000067C)
+#define AQT1000_TX_COM_TXFE_DIV_STOP_9P6M                 (0x0000067D)
+#define AQT1000_TX_COM_TXFE_DIV_STOP_12P288M              (0x0000067E)
+#define AQT1000_TX_1_2_BASE                 (0x0000067F)
+#define AQT1000_TX_1_2_TEST_EN                            (0x0000067F)
+#define AQT1000_TX_1_2_ADC_IB                             (0x00000680)
+#define AQT1000_TX_1_2_ATEST_REFCTL                       (0x00000681)
+#define AQT1000_TX_1_2_TEST_CTL                           (0x00000682)
+#define AQT1000_TX_1_2_TEST_BLK_EN                        (0x00000683)
+#define AQT1000_TX_1_2_TXFE_CLKDIV                        (0x00000684)
+#define AQT1000_TX_1_2_SAR1_ERR                           (0x00000685)
+#define AQT1000_TX_1_2_SAR2_ERR                           (0x00000686)
+#define AQT1000_TX_3_BASE                   (0x00000687)
+#define AQT1000_TX_3_TEST_EN                              (0x00000687)
+#define AQT1000_TX_3_ADC_IB                               (0x00000688)
+#define AQT1000_TX_3_ATEST_REFCTL                         (0x00000689)
+#define AQT1000_TX_3_TEST_CTL                             (0x0000068A)
+#define AQT1000_TX_3_TEST_BLK_EN                          (0x0000068B)
+#define AQT1000_TX_3_TXFE_CLKDIV                          (0x0000068C)
+#define AQT1000_TX_3_SAR1_ERR                             (0x0000068D)
+#define AQT1000_TX_3_SAR2_ERR                             (0x0000068E)
+#define AQT1000_TX_BASE                     (0x0000068F)
+#define AQT1000_TX_ATEST1_2_SEL                           (0x0000068F)
+#define AQT1000_CLASSH_BASE                 (0x00000697)
+#define AQT1000_CLASSH_MODE_1                             (0x00000697)
+#define AQT1000_CLASSH_MODE_2                             (0x00000698)
+#define AQT1000_CLASSH_MODE_3                             (0x00000699)
+#define AQT1000_CLASSH_CTRL_VCL_1                         (0x0000069A)
+#define AQT1000_CLASSH_CTRL_VCL_2                         (0x0000069B)
+#define AQT1000_CLASSH_CTRL_CCL_1                         (0x0000069C)
+#define AQT1000_CLASSH_CTRL_CCL_2                         (0x0000069D)
+#define AQT1000_CLASSH_CTRL_CCL_3                         (0x0000069E)
+#define AQT1000_CLASSH_CTRL_CCL_4                         (0x0000069F)
+#define AQT1000_CLASSH_CTRL_CCL_5                         (0x000006A0)
+#define AQT1000_CLASSH_BUCK_TMUX_A_D                      (0x000006A1)
+#define AQT1000_CLASSH_BUCK_SW_DRV_CNTL                   (0x000006A2)
+#define AQT1000_CLASSH_SPARE                              (0x000006A3)
+#define AQT1000_FLYBACK_BASE                (0x000006A4)
+#define AQT1000_FLYBACK_EN                                (0x000006A4)
+#define AQT1000_FLYBACK_VNEG_CTRL_1                       (0x000006A5)
+#define AQT1000_FLYBACK_VNEG_CTRL_2                       (0x000006A6)
+#define AQT1000_FLYBACK_VNEG_CTRL_3                       (0x000006A7)
+#define AQT1000_FLYBACK_VNEG_CTRL_4                       (0x000006A8)
+#define AQT1000_FLYBACK_VNEG_CTRL_5                       (0x000006A9)
+#define AQT1000_FLYBACK_VNEG_CTRL_6                       (0x000006AA)
+#define AQT1000_FLYBACK_VNEG_CTRL_7                       (0x000006AB)
+#define AQT1000_FLYBACK_VNEG_CTRL_8                       (0x000006AC)
+#define AQT1000_FLYBACK_VNEG_CTRL_9                       (0x000006AD)
+#define AQT1000_FLYBACK_VNEGDAC_CTRL_1                    (0x000006AE)
+#define AQT1000_FLYBACK_VNEGDAC_CTRL_2                    (0x000006AF)
+#define AQT1000_FLYBACK_VNEGDAC_CTRL_3                    (0x000006B0)
+#define AQT1000_FLYBACK_CTRL_1                            (0x000006B1)
+#define AQT1000_FLYBACK_TEST_CTL                          (0x000006B2)
+#define AQT1000_RX_BASE                     (0x000006B3)
+#define AQT1000_RX_AUX_SW_CTL                             (0x000006B3)
+#define AQT1000_RX_PA_AUX_IN_CONN                         (0x000006B4)
+#define AQT1000_RX_TIMER_DIV                              (0x000006B5)
+#define AQT1000_RX_OCP_CTL                                (0x000006B6)
+#define AQT1000_RX_OCP_COUNT                              (0x000006B7)
+#define AQT1000_RX_BIAS_ATEST                             (0x000006B8)
+#define AQT1000_RX_BIAS_MISC1                             (0x000006B9)
+#define AQT1000_RX_BIAS_HPH_LDO                           (0x000006BA)
+#define AQT1000_RX_BIAS_HPH_PA                            (0x000006BB)
+#define AQT1000_RX_BIAS_HPH_RDACBUFF_CNP2                 (0x000006BC)
+#define AQT1000_RX_BIAS_HPH_RDAC_LDO                      (0x000006BD)
+#define AQT1000_RX_BIAS_HPH_CNP1                          (0x000006BE)
+#define AQT1000_RX_BIAS_HPH_LOWPOWER                      (0x000006BF)
+#define AQT1000_RX_BIAS_MISC2                             (0x000006C0)
+#define AQT1000_RX_BIAS_MISC3                             (0x000006C1)
+#define AQT1000_RX_BIAS_MISC4                             (0x000006C2)
+#define AQT1000_RX_BIAS_MISC5                             (0x000006C3)
+#define AQT1000_RX_BIAS_BUCK_RST                          (0x000006C4)
+#define AQT1000_RX_BIAS_BUCK_VREF_ERRAMP                  (0x000006C5)
+#define AQT1000_RX_BIAS_FLYB_ERRAMP                       (0x000006C6)
+#define AQT1000_RX_BIAS_FLYB_BUFF                         (0x000006C7)
+#define AQT1000_RX_BIAS_FLYB_MID_RST                      (0x000006C8)
+#define AQT1000_HPH_BASE                    (0x000006C9)
+#define AQT1000_HPH_L_STATUS                              (0x000006C9)
+#define AQT1000_HPH_R_STATUS                              (0x000006CA)
+#define AQT1000_HPH_CNP_EN                                (0x000006CB)
+#define AQT1000_HPH_CNP_WG_CTL                            (0x000006CC)
+#define AQT1000_HPH_CNP_WG_TIME                           (0x000006CD)
+#define AQT1000_HPH_OCP_CTL                               (0x000006CE)
+#define AQT1000_HPH_AUTO_CHOP                             (0x000006CF)
+#define AQT1000_HPH_CHOP_CTL                              (0x000006D0)
+#define AQT1000_HPH_PA_CTL1                               (0x000006D1)
+#define AQT1000_HPH_PA_CTL2                               (0x000006D2)
+#define AQT1000_HPH_L_EN                                  (0x000006D3)
+#define AQT1000_HPH_L_TEST                                (0x000006D4)
+#define AQT1000_HPH_L_ATEST                               (0x000006D5)
+#define AQT1000_HPH_R_EN                                  (0x000006D6)
+#define AQT1000_HPH_R_TEST                                (0x000006D7)
+#define AQT1000_HPH_R_ATEST                               (0x000006D8)
+#define AQT1000_HPH_RDAC_CLK_CTL1                         (0x000006D9)
+#define AQT1000_HPH_RDAC_CLK_CTL2                         (0x000006DA)
+#define AQT1000_HPH_RDAC_LDO_CTL                          (0x000006DB)
+#define AQT1000_HPH_RDAC_CHOP_CLK_LP_CTL                  (0x000006DC)
+#define AQT1000_HPH_REFBUFF_UHQA_CTL                      (0x000006DD)
+#define AQT1000_HPH_REFBUFF_LP_CTL                        (0x000006DE)
+#define AQT1000_HPH_L_DAC_CTL                             (0x000006DF)
+#define AQT1000_HPH_R_DAC_CTL                             (0x000006E0)
+#define AQT1000_HPHLR_BASE                  (0x000006E1)
+#define AQT1000_HPHLR_SURGE_COMP_SEL                      (0x000006E1)
+#define AQT1000_HPHLR_SURGE_EN                            (0x000006E2)
+#define AQT1000_HPHLR_SURGE_MISC1                         (0x000006E3)
+#define AQT1000_HPHLR_SURGE_STATUS                        (0x000006E4)
+#define AQT1000_ANA_NEW_BASE                (0x00000700)
+#define AQT1000_ANA_NEW_PAGE_REGISTER                     (0x00000700)
+#define AQT1000_HPH_NEW_BASE                (0x00000701)
+#define AQT1000_HPH_NEW_ANA_HPH2                          (0x00000701)
+#define AQT1000_HPH_NEW_ANA_HPH3                          (0x00000702)
+#define AQT1000_CLK_SYS_BASE                (0x0000070E)
+#define AQT1000_CLK_SYS_MCLK1_PRG                         (0x0000070E)
+#define AQT1000_CLK_SYS_MCLK2_I2S_HS_CLK_PRG              (0x0000070F)
+#define AQT1000_CLK_SYS_XO_CAP_XTP                        (0x00000710)
+#define AQT1000_CLK_SYS_XO_CAP_XTM                        (0x00000711)
+#define AQT1000_CLK_SYS_PLL_ENABLES                       (0x00000712)
+#define AQT1000_CLK_SYS_PLL_PRESET                        (0x00000713)
+#define AQT1000_CLK_SYS_PLL_STATUS                        (0x00000714)
+#define AQT1000_MBHC_NEW_BASE               (0x0000071F)
+#define AQT1000_MBHC_NEW_ELECT_REM_CLAMP_CTL              (0x0000071F)
+#define AQT1000_MBHC_NEW_CTL_1                            (0x00000720)
+#define AQT1000_MBHC_NEW_CTL_2                            (0x00000721)
+#define AQT1000_MBHC_NEW_PLUG_DETECT_CTL                  (0x00000722)
+#define AQT1000_MBHC_NEW_ZDET_ANA_CTL                     (0x00000723)
+#define AQT1000_MBHC_NEW_ZDET_RAMP_CTL                    (0x00000724)
+#define AQT1000_MBHC_NEW_FSM_STATUS                       (0x00000725)
+#define AQT1000_MBHC_NEW_ADC_RESULT                       (0x00000726)
+#define AQT1000_HPH_NEW_INT_BASE            (0x00000732)
+#define AQT1000_HPH_NEW_INT_RDAC_GAIN_CTL                 (0x00000732)
+#define AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_L                (0x00000733)
+#define AQT1000_HPH_NEW_INT_RDAC_VREF_CTL                 (0x00000734)
+#define AQT1000_HPH_NEW_INT_RDAC_OVERRIDE_CTL             (0x00000735)
+#define AQT1000_HPH_NEW_INT_RDAC_HD2_CTL_R                (0x00000736)
+#define AQT1000_HPH_NEW_INT_PA_MISC1                      (0x00000737)
+#define AQT1000_HPH_NEW_INT_PA_MISC2                      (0x00000738)
+#define AQT1000_HPH_NEW_INT_PA_RDAC_MISC                  (0x00000739)
+#define AQT1000_HPH_NEW_INT_HPH_TIMER1                    (0x0000073A)
+#define AQT1000_HPH_NEW_INT_HPH_TIMER2                    (0x0000073B)
+#define AQT1000_HPH_NEW_INT_HPH_TIMER3                    (0x0000073C)
+#define AQT1000_HPH_NEW_INT_HPH_TIMER4                    (0x0000073D)
+#define AQT1000_HPH_NEW_INT_PA_RDAC_MISC2                 (0x0000073E)
+#define AQT1000_HPH_NEW_INT_PA_RDAC_MISC3                 (0x0000073F)
+#define AQT1000_RX_NEW_INT_BASE             (0x00000745)
+#define AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI           (0x00000745)
+#define AQT1000_RX_NEW_INT_HPH_RDAC_BIAS_ULP              (0x00000746)
+#define AQT1000_RX_NEW_INT_HPH_RDAC_LDO_LP                (0x00000747)
+#define AQT1000_CLK_SYS_INT_BASE            (0x0000076C)
+#define AQT1000_CLK_SYS_INT_CLK_TEST1                     (0x0000076C)
+#define AQT1000_CLK_SYS_INT_XO_TEST1                      (0x0000076D)
+#define AQT1000_CLK_SYS_INT_XO_TEST2                      (0x0000076E)
+#define AQT1000_CLK_SYS_INT_POST_DIV_REG0                 (0x0000076F)
+#define AQT1000_CLK_SYS_INT_POST_DIV_REG1                 (0x00000770)
+#define AQT1000_CLK_SYS_INT_REF_DIV_REG0                  (0x00000771)
+#define AQT1000_CLK_SYS_INT_REF_DIV_REG1                  (0x00000772)
+#define AQT1000_CLK_SYS_INT_FILTER_REG0                   (0x00000773)
+#define AQT1000_CLK_SYS_INT_FILTER_REG1                   (0x00000774)
+#define AQT1000_CLK_SYS_INT_PLL_L_VAL                     (0x00000775)
+#define AQT1000_CLK_SYS_INT_PLL_M_VAL                     (0x00000776)
+#define AQT1000_CLK_SYS_INT_PLL_N_VAL                     (0x00000777)
+#define AQT1000_CLK_SYS_INT_TEST_REG0                     (0x00000778)
+#define AQT1000_CLK_SYS_INT_PFD_CP_DSM_PROG               (0x00000779)
+#define AQT1000_CLK_SYS_INT_VCO_PROG                      (0x0000077A)
+#define AQT1000_CLK_SYS_INT_TEST_REG1                     (0x0000077B)
+#define AQT1000_CLK_SYS_INT_LDO_LOCK_CFG                  (0x0000077C)
+#define AQT1000_CLK_SYS_INT_DIG_LOCK_DET_CFG              (0x0000077D)
+#define AQT1000_MBHC_NEW_INT_BASE           (0x000007AF)
+#define AQT1000_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL         (0x000007AF)
+#define AQT1000_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL    (0x000007B0)
+#define AQT1000_MBHC_NEW_INT_MECH_DET_CURRENT             (0x000007B1)
+#define AQT1000_MBHC_NEW_INT_SPARE_2                      (0x000007B2)
+#define AQT1000_PAGE10_BASE                 (0x00000A00)
+#define AQT1000_PAGE10_PAGE_REGISTER                      (0x00000A00)
+#define AQT1000_CDC_ANC0_BASE               (0x00000A01)
+#define AQT1000_CDC_ANC0_CLK_RESET_CTL                    (0x00000A01)
+#define AQT1000_CDC_ANC0_MODE_1_CTL                       (0x00000A02)
+#define AQT1000_CDC_ANC0_MODE_2_CTL                       (0x00000A03)
+#define AQT1000_CDC_ANC0_FF_SHIFT                         (0x00000A04)
+#define AQT1000_CDC_ANC0_FB_SHIFT                         (0x00000A05)
+#define AQT1000_CDC_ANC0_LPF_FF_A_CTL                     (0x00000A06)
+#define AQT1000_CDC_ANC0_LPF_FF_B_CTL                     (0x00000A07)
+#define AQT1000_CDC_ANC0_LPF_FB_CTL                       (0x00000A08)
+#define AQT1000_CDC_ANC0_SMLPF_CTL                        (0x00000A09)
+#define AQT1000_CDC_ANC0_DCFLT_SHIFT_CTL                  (0x00000A0A)
+#define AQT1000_CDC_ANC0_IIR_ADAPT_CTL                    (0x00000A0B)
+#define AQT1000_CDC_ANC0_IIR_COEFF_1_CTL                  (0x00000A0C)
+#define AQT1000_CDC_ANC0_IIR_COEFF_2_CTL                  (0x00000A0D)
+#define AQT1000_CDC_ANC0_FF_A_GAIN_CTL                    (0x00000A0E)
+#define AQT1000_CDC_ANC0_FF_B_GAIN_CTL                    (0x00000A0F)
+#define AQT1000_CDC_ANC0_FB_GAIN_CTL                      (0x00000A10)
+#define AQT1000_CDC_ANC0_RC_COMMON_CTL                    (0x00000A11)
+#define AQT1000_CDC_ANC0_FIFO_COMMON_CTL                  (0x00000A13)
+#define AQT1000_CDC_ANC0_RC0_STATUS_FMIN_CNTR             (0x00000A14)
+#define AQT1000_CDC_ANC0_RC1_STATUS_FMIN_CNTR             (0x00000A15)
+#define AQT1000_CDC_ANC0_RC0_STATUS_FMAX_CNTR             (0x00000A16)
+#define AQT1000_CDC_ANC0_RC1_STATUS_FMAX_CNTR             (0x00000A17)
+#define AQT1000_CDC_ANC0_STATUS_FIFO                      (0x00000A18)
+#define AQT1000_CDC_ANC1_BASE               (0x00000A19)
+#define AQT1000_CDC_ANC1_CLK_RESET_CTL                    (0x00000A19)
+#define AQT1000_CDC_ANC1_MODE_1_CTL                       (0x00000A1A)
+#define AQT1000_CDC_ANC1_MODE_2_CTL                       (0x00000A1B)
+#define AQT1000_CDC_ANC1_FF_SHIFT                         (0x00000A1C)
+#define AQT1000_CDC_ANC1_FB_SHIFT                         (0x00000A1D)
+#define AQT1000_CDC_ANC1_LPF_FF_A_CTL                     (0x00000A1E)
+#define AQT1000_CDC_ANC1_LPF_FF_B_CTL                     (0x00000A1F)
+#define AQT1000_CDC_ANC1_LPF_FB_CTL                       (0x00000A20)
+#define AQT1000_CDC_ANC1_SMLPF_CTL                        (0x00000A21)
+#define AQT1000_CDC_ANC1_DCFLT_SHIFT_CTL                  (0x00000A22)
+#define AQT1000_CDC_ANC1_IIR_ADAPT_CTL                    (0x00000A23)
+#define AQT1000_CDC_ANC1_IIR_COEFF_1_CTL                  (0x00000A24)
+#define AQT1000_CDC_ANC1_IIR_COEFF_2_CTL                  (0x00000A25)
+#define AQT1000_CDC_ANC1_FF_A_GAIN_CTL                    (0x00000A26)
+#define AQT1000_CDC_ANC1_FF_B_GAIN_CTL                    (0x00000A27)
+#define AQT1000_CDC_ANC1_FB_GAIN_CTL                      (0x00000A28)
+#define AQT1000_CDC_ANC1_RC_COMMON_CTL                    (0x00000A29)
+#define AQT1000_CDC_ANC1_FIFO_COMMON_CTL                  (0x00000A2B)
+#define AQT1000_CDC_ANC1_RC0_STATUS_FMIN_CNTR             (0x00000A2C)
+#define AQT1000_CDC_ANC1_RC1_STATUS_FMIN_CNTR             (0x00000A2D)
+#define AQT1000_CDC_ANC1_RC0_STATUS_FMAX_CNTR             (0x00000A2E)
+#define AQT1000_CDC_ANC1_RC1_STATUS_FMAX_CNTR             (0x00000A2F)
+#define AQT1000_CDC_ANC1_STATUS_FIFO                      (0x00000A30)
+#define AQT1000_CDC_TX0_BASE                (0x00000A31)
+#define AQT1000_CDC_TX0_TX_PATH_CTL                       (0x00000A31)
+#define AQT1000_CDC_TX0_TX_PATH_CFG0                      (0x00000A32)
+#define AQT1000_CDC_TX0_TX_PATH_CFG1                      (0x00000A33)
+#define AQT1000_CDC_TX0_TX_VOL_CTL                        (0x00000A34)
+#define AQT1000_CDC_TX0_TX_PATH_SEC0                      (0x00000A37)
+#define AQT1000_CDC_TX0_TX_PATH_SEC1                      (0x00000A38)
+#define AQT1000_CDC_TX0_TX_PATH_SEC2                      (0x00000A39)
+#define AQT1000_CDC_TX0_TX_PATH_SEC3                      (0x00000A3A)
+#define AQT1000_CDC_TX0_TX_PATH_SEC4                      (0x00000A3B)
+#define AQT1000_CDC_TX0_TX_PATH_SEC5                      (0x00000A3C)
+#define AQT1000_CDC_TX0_TX_PATH_SEC6                      (0x00000A3D)
+#define AQT1000_CDC_TX1_BASE                (0x00000A41)
+#define AQT1000_CDC_TX1_TX_PATH_CTL                       (0x00000A41)
+#define AQT1000_CDC_TX1_TX_PATH_CFG0                      (0x00000A42)
+#define AQT1000_CDC_TX1_TX_PATH_CFG1                      (0x00000A43)
+#define AQT1000_CDC_TX1_TX_VOL_CTL                        (0x00000A44)
+#define AQT1000_CDC_TX1_TX_PATH_SEC0                      (0x00000A47)
+#define AQT1000_CDC_TX1_TX_PATH_SEC1                      (0x00000A48)
+#define AQT1000_CDC_TX1_TX_PATH_SEC2                      (0x00000A49)
+#define AQT1000_CDC_TX1_TX_PATH_SEC3                      (0x00000A4A)
+#define AQT1000_CDC_TX1_TX_PATH_SEC4                      (0x00000A4B)
+#define AQT1000_CDC_TX1_TX_PATH_SEC5                      (0x00000A4C)
+#define AQT1000_CDC_TX1_TX_PATH_SEC6                      (0x00000A4D)
+#define AQT1000_CDC_TX2_BASE                (0x00000A51)
+#define AQT1000_CDC_TX2_TX_PATH_CTL                       (0x00000A51)
+#define AQT1000_CDC_TX2_TX_PATH_CFG0                      (0x00000A52)
+#define AQT1000_CDC_TX2_TX_PATH_CFG1                      (0x00000A53)
+#define AQT1000_CDC_TX2_TX_VOL_CTL                        (0x00000A54)
+#define AQT1000_CDC_TX2_TX_PATH_SEC0                      (0x00000A57)
+#define AQT1000_CDC_TX2_TX_PATH_SEC1                      (0x00000A58)
+#define AQT1000_CDC_TX2_TX_PATH_SEC2                      (0x00000A59)
+#define AQT1000_CDC_TX2_TX_PATH_SEC3                      (0x00000A5A)
+#define AQT1000_CDC_TX2_TX_PATH_SEC4                      (0x00000A5B)
+#define AQT1000_CDC_TX2_TX_PATH_SEC5                      (0x00000A5C)
+#define AQT1000_CDC_TX2_TX_PATH_SEC6                      (0x00000A5D)
+#define AQT1000_CDC_TX2_TX_PATH_SEC7                      (0x00000A5E)
+#define AQT1000_PAGE11_BASE                 (0x00000B00)
+#define AQT1000_PAGE11_PAGE_REGISTER                      (0x00000B00)
+#define AQT1000_CDC_COMPANDER1_BASE         (0x00000B01)
+#define AQT1000_CDC_COMPANDER1_CTL0                       (0x00000B01)
+#define AQT1000_CDC_COMPANDER1_CTL1                       (0x00000B02)
+#define AQT1000_CDC_COMPANDER1_CTL2                       (0x00000B03)
+#define AQT1000_CDC_COMPANDER1_CTL3                       (0x00000B04)
+#define AQT1000_CDC_COMPANDER1_CTL4                       (0x00000B05)
+#define AQT1000_CDC_COMPANDER1_CTL5                       (0x00000B06)
+#define AQT1000_CDC_COMPANDER1_CTL6                       (0x00000B07)
+#define AQT1000_CDC_COMPANDER1_CTL7                       (0x00000B08)
+#define AQT1000_CDC_COMPANDER2_BASE         (0x00000B09)
+#define AQT1000_CDC_COMPANDER2_CTL0                       (0x00000B09)
+#define AQT1000_CDC_COMPANDER2_CTL1                       (0x00000B0A)
+#define AQT1000_CDC_COMPANDER2_CTL2                       (0x00000B0B)
+#define AQT1000_CDC_COMPANDER2_CTL3                       (0x00000B0C)
+#define AQT1000_CDC_COMPANDER2_CTL4                       (0x00000B0D)
+#define AQT1000_CDC_COMPANDER2_CTL5                       (0x00000B0E)
+#define AQT1000_CDC_COMPANDER2_CTL6                       (0x00000B0F)
+#define AQT1000_CDC_COMPANDER2_CTL7                       (0x00000B10)
+#define AQT1000_CDC_RX1_BASE                (0x00000B55)
+#define AQT1000_CDC_RX1_RX_PATH_CTL                       (0x00000B55)
+#define AQT1000_CDC_RX1_RX_PATH_CFG0                      (0x00000B56)
+#define AQT1000_CDC_RX1_RX_PATH_CFG1                      (0x00000B57)
+#define AQT1000_CDC_RX1_RX_PATH_CFG2                      (0x00000B58)
+#define AQT1000_CDC_RX1_RX_VOL_CTL                        (0x00000B59)
+#define AQT1000_CDC_RX1_RX_PATH_MIX_CTL                   (0x00000B5A)
+#define AQT1000_CDC_RX1_RX_PATH_MIX_CFG                   (0x00000B5B)
+#define AQT1000_CDC_RX1_RX_VOL_MIX_CTL                    (0x00000B5C)
+#define AQT1000_CDC_RX1_RX_PATH_SEC0                      (0x00000B5D)
+#define AQT1000_CDC_RX1_RX_PATH_SEC1                      (0x00000B5E)
+#define AQT1000_CDC_RX1_RX_PATH_SEC2                      (0x00000B5F)
+#define AQT1000_CDC_RX1_RX_PATH_SEC3                      (0x00000B60)
+#define AQT1000_CDC_RX1_RX_PATH_SEC4                      (0x00000B61)
+#define AQT1000_CDC_RX1_RX_PATH_SEC5                      (0x00000B62)
+#define AQT1000_CDC_RX1_RX_PATH_SEC6                      (0x00000B63)
+#define AQT1000_CDC_RX1_RX_PATH_SEC7                      (0x00000B64)
+#define AQT1000_CDC_RX1_RX_PATH_MIX_SEC0                  (0x00000B65)
+#define AQT1000_CDC_RX1_RX_PATH_MIX_SEC1                  (0x00000B66)
+#define AQT1000_CDC_RX1_RX_PATH_DSMDEM_CTL                (0x00000B67)
+#define AQT1000_CDC_RX2_BASE                (0x00000B69)
+#define AQT1000_CDC_RX2_RX_PATH_CTL                       (0x00000B69)
+#define AQT1000_CDC_RX2_RX_PATH_CFG0                      (0x00000B6A)
+#define AQT1000_CDC_RX2_RX_PATH_CFG1                      (0x00000B6B)
+#define AQT1000_CDC_RX2_RX_PATH_CFG2                      (0x00000B6C)
+#define AQT1000_CDC_RX2_RX_VOL_CTL                        (0x00000B6D)
+#define AQT1000_CDC_RX2_RX_PATH_MIX_CTL                   (0x00000B6E)
+#define AQT1000_CDC_RX2_RX_PATH_MIX_CFG                   (0x00000B6F)
+#define AQT1000_CDC_RX2_RX_VOL_MIX_CTL                    (0x00000B70)
+#define AQT1000_CDC_RX2_RX_PATH_SEC0                      (0x00000B71)
+#define AQT1000_CDC_RX2_RX_PATH_SEC1                      (0x00000B72)
+#define AQT1000_CDC_RX2_RX_PATH_SEC2                      (0x00000B73)
+#define AQT1000_CDC_RX2_RX_PATH_SEC3                      (0x00000B74)
+#define AQT1000_CDC_RX2_RX_PATH_SEC4                      (0x00000B75)
+#define AQT1000_CDC_RX2_RX_PATH_SEC5                      (0x00000B76)
+#define AQT1000_CDC_RX2_RX_PATH_SEC6                      (0x00000B77)
+#define AQT1000_CDC_RX2_RX_PATH_SEC7                      (0x00000B78)
+#define AQT1000_CDC_RX2_RX_PATH_MIX_SEC0                  (0x00000B79)
+#define AQT1000_CDC_RX2_RX_PATH_MIX_SEC1                  (0x00000B7A)
+#define AQT1000_CDC_RX2_RX_PATH_DSMDEM_CTL                (0x00000B7B)
+#define AQT1000_CDC_EQ_IIR0_BASE            (0x00000BD1)
+#define AQT1000_CDC_EQ_IIR0_PATH_CTL                      (0x00000BD1)
+#define AQT1000_CDC_EQ_IIR0_PATH_CFG0                     (0x00000BD2)
+#define AQT1000_CDC_EQ_IIR0_PATH_CFG1                     (0x00000BD3)
+#define AQT1000_CDC_EQ_IIR0_PATH_CFG2                     (0x00000BD4)
+#define AQT1000_CDC_EQ_IIR0_PATH_CFG3                     (0x00000BD5)
+#define AQT1000_CDC_EQ_IIR0_COEF_CFG0                     (0x00000BD6)
+#define AQT1000_CDC_EQ_IIR0_COEF_CFG1                     (0x00000BD7)
+#define AQT1000_CDC_EQ_IIR1_BASE            (0x00000BE1)
+#define AQT1000_CDC_EQ_IIR1_PATH_CTL                      (0x00000BE1)
+#define AQT1000_CDC_EQ_IIR1_PATH_CFG0                     (0x00000BE2)
+#define AQT1000_CDC_EQ_IIR1_PATH_CFG1                     (0x00000BE3)
+#define AQT1000_CDC_EQ_IIR1_PATH_CFG2                     (0x00000BE4)
+#define AQT1000_CDC_EQ_IIR1_PATH_CFG3                     (0x00000BE5)
+#define AQT1000_CDC_EQ_IIR1_COEF_CFG0                     (0x00000BE6)
+#define AQT1000_CDC_EQ_IIR1_COEF_CFG1                     (0x00000BE7)
+#define AQT1000_PAGE12_BASE                 (0x00000C00)
+#define AQT1000_PAGE12_PAGE_REGISTER                      (0x00000C00)
+#define AQT1000_CDC_CLSH_CDC_CLSH_BASE      (0x00000C01)
+#define AQT1000_CDC_CLSH_CRC                              (0x00000C01)
+#define AQT1000_CDC_CLSH_DLY_CTRL                         (0x00000C02)
+#define AQT1000_CDC_CLSH_DECAY_CTRL                       (0x00000C03)
+#define AQT1000_CDC_CLSH_HPH_V_PA                         (0x00000C04)
+#define AQT1000_CDC_CLSH_EAR_V_PA                         (0x00000C05)
+#define AQT1000_CDC_CLSH_HPH_V_HD                         (0x00000C06)
+#define AQT1000_CDC_CLSH_EAR_V_HD                         (0x00000C07)
+#define AQT1000_CDC_CLSH_K1_MSB                           (0x00000C08)
+#define AQT1000_CDC_CLSH_K1_LSB                           (0x00000C09)
+#define AQT1000_CDC_CLSH_K2_MSB                           (0x00000C0A)
+#define AQT1000_CDC_CLSH_K2_LSB                           (0x00000C0B)
+#define AQT1000_CDC_CLSH_IDLE_CTRL                        (0x00000C0C)
+#define AQT1000_CDC_CLSH_IDLE_HPH                         (0x00000C0D)
+#define AQT1000_CDC_CLSH_IDLE_EAR                         (0x00000C0E)
+#define AQT1000_CDC_CLSH_TEST0                            (0x00000C0F)
+#define AQT1000_CDC_CLSH_TEST1                            (0x00000C10)
+#define AQT1000_CDC_CLSH_OVR_VREF                         (0x00000C11)
+#define AQT1000_MIXING_ASRC0_BASE           (0x00000C55)
+#define AQT1000_MIXING_ASRC0_CLK_RST_CTL                  (0x00000C55)
+#define AQT1000_MIXING_ASRC0_CTL0                         (0x00000C56)
+#define AQT1000_MIXING_ASRC0_CTL1                         (0x00000C57)
+#define AQT1000_MIXING_ASRC0_FIFO_CTL                     (0x00000C58)
+#define AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB         (0x00000C59)
+#define AQT1000_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB         (0x00000C5A)
+#define AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB         (0x00000C5B)
+#define AQT1000_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB         (0x00000C5C)
+#define AQT1000_MIXING_ASRC0_STATUS_FIFO                  (0x00000C5D)
+#define AQT1000_MIXING_ASRC1_BASE           (0x00000C61)
+#define AQT1000_MIXING_ASRC1_CLK_RST_CTL                  (0x00000C61)
+#define AQT1000_MIXING_ASRC1_CTL0                         (0x00000C62)
+#define AQT1000_MIXING_ASRC1_CTL1                         (0x00000C63)
+#define AQT1000_MIXING_ASRC1_FIFO_CTL                     (0x00000C64)
+#define AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB         (0x00000C65)
+#define AQT1000_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB         (0x00000C66)
+#define AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB         (0x00000C67)
+#define AQT1000_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB         (0x00000C68)
+#define AQT1000_MIXING_ASRC1_STATUS_FIFO                  (0x00000C69)
+#define AQT1000_CDC_SIDETONE_SRC0_BASE      (0x00000CB5)
+#define AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL         (0x00000CB5)
+#define AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1        (0x00000CB6)
+#define AQT1000_SIDETONE_ASRC0_BASE         (0x00000CBD)
+#define AQT1000_SIDETONE_ASRC0_CLK_RST_CTL                (0x00000CBD)
+#define AQT1000_SIDETONE_ASRC0_CTL0                       (0x00000CBE)
+#define AQT1000_SIDETONE_ASRC0_CTL1                       (0x00000CBF)
+#define AQT1000_SIDETONE_ASRC0_FIFO_CTL                   (0x00000CC0)
+#define AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB       (0x00000CC1)
+#define AQT1000_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB       (0x00000CC2)
+#define AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB       (0x00000CC3)
+#define AQT1000_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB       (0x00000CC4)
+#define AQT1000_SIDETONE_ASRC0_STATUS_FIFO                (0x00000CC5)
+#define AQT1000_EC_REF_HQ0_BASE             (0x00000CD5)
+#define AQT1000_EC_REF_HQ0_EC_REF_HQ_PATH_CTL             (0x00000CD5)
+#define AQT1000_EC_REF_HQ0_EC_REF_HQ_CFG0                 (0x00000CD6)
+#define AQT1000_EC_REF_HQ1_BASE             (0x00000CDD)
+#define AQT1000_EC_REF_HQ1_EC_REF_HQ_PATH_CTL             (0x00000CDD)
+#define AQT1000_EC_REF_HQ1_EC_REF_HQ_CFG0                 (0x00000CDE)
+#define AQT1000_EC_ASRC0_BASE               (0x00000CE5)
+#define AQT1000_EC_ASRC0_CLK_RST_CTL                      (0x00000CE5)
+#define AQT1000_EC_ASRC0_CTL0                             (0x00000CE6)
+#define AQT1000_EC_ASRC0_CTL1                             (0x00000CE7)
+#define AQT1000_EC_ASRC0_FIFO_CTL                         (0x00000CE8)
+#define AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_LSB             (0x00000CE9)
+#define AQT1000_EC_ASRC0_STATUS_FMIN_CNTR_MSB             (0x00000CEA)
+#define AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_LSB             (0x00000CEB)
+#define AQT1000_EC_ASRC0_STATUS_FMAX_CNTR_MSB             (0x00000CEC)
+#define AQT1000_EC_ASRC0_STATUS_FIFO                      (0x00000CED)
+#define AQT1000_EC_ASRC1_BASE               (0x00000CF1)
+#define AQT1000_EC_ASRC1_CLK_RST_CTL                      (0x00000CF1)
+#define AQT1000_EC_ASRC1_CTL0                             (0x00000CF2)
+#define AQT1000_EC_ASRC1_CTL1                             (0x00000CF3)
+#define AQT1000_EC_ASRC1_FIFO_CTL                         (0x00000CF4)
+#define AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_LSB             (0x00000CF5)
+#define AQT1000_EC_ASRC1_STATUS_FMIN_CNTR_MSB             (0x00000CF6)
+#define AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_LSB             (0x00000CF7)
+#define AQT1000_EC_ASRC1_STATUS_FMAX_CNTR_MSB             (0x00000CF8)
+#define AQT1000_EC_ASRC1_STATUS_FIFO                      (0x00000CF9)
+#define AQT1000_PAGE13_BASE                 (0x00000D00)
+#define AQT1000_PAGE13_PAGE_REGISTER                      (0x00000D00)
+#define AQT1000_CDC_RX_INP_MUX_CDC_RX_INP_MUX_BASE (0x00000D01)
+#define AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG0               (0x00000D03)
+#define AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG1               (0x00000D04)
+#define AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG0               (0x00000D05)
+#define AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG1               (0x00000D06)
+#define AQT1000_CDC_RX_INP_MUX_EQ_IIR_CFG0                (0x00000D11)
+#define AQT1000_CDC_RX_INP_MUX_DSD_CFG0                   (0x00000D12)
+#define AQT1000_CDC_RX_INP_MUX_RX_MIX_CFG0                (0x00000D13)
+#define AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0          (0x00000D18)
+#define AQT1000_CDC_RX_INP_MUX_ANC_CFG0                   (0x00000D1A)
+#define AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0           (0x00000D1B)
+#define AQT1000_CDC_RX_INP_MUX_EC_REF_HQ_CFG0             (0x00000D1C)
+#define AQT1000_CDC_TX_INP_MUX_CDC_TX_INP_MUX_BASE (0x00000D1D)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG0              (0x00000D1D)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG1              (0x00000D1E)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG0              (0x00000D1F)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG1              (0x00000D20)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG0              (0x00000D21)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG1              (0x00000D22)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG0             (0x00000D29)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG1             (0x00000D2A)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG0             (0x00000D2B)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG1             (0x00000D2C)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG0             (0x00000D2D)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG1             (0x00000D2E)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG0             (0x00000D2F)
+#define AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG1             (0x00000D30)
+#define AQT1000_CDC_SIDETONE_IIR_INP_MUX_CDC_SIDETONE_IIR_INP_MUX_BASE (0xD31)
+#define AQT1000_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0    (0x00000D31)
+#define AQT1000_CDC_IF_ROUTER_CDC_IF_ROUTER_BASE (0x00000D3D)
+#define AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0                 (0x00000D3D)
+#define AQT1000_CDC_CLK_RST_CTRL_CDC_CLK_RST_CTRL_BASE (0x00000D41)
+#define AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL             (0x00000D41)
+#define AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL           (0x00000D42)
+#define AQT1000_CDC_CLK_RST_CTRL_DSD_CONTROL              (0x00000D44)
+#define AQT1000_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL       (0x00000D45)
+#define AQT1000_CDC_CLK_RST_CTRL_GFM_CONTROL              (0x00000D46)
+#define AQT1000_CDC_CLK_RST_CTRL_I2S_CONTROL              (0x00000D47)
+#define AQT1000_CDC_SIDETONE_IIR0_BASE      (0x00000D55)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_PATH_CTL            (0x00000D55)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL         (0x00000D56)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL         (0x00000D57)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL         (0x00000D58)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL         (0x00000D59)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL         (0x00000D5A)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL         (0x00000D5B)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL         (0x00000D5C)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL         (0x00000D5D)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_CTL                 (0x00000D5E)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL      (0x00000D5F)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL         (0x00000D60)
+#define AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL         (0x00000D61)
+#define AQT1000_CDC_TOP_CDC_TOP_BASE        (0x00000D81)
+#define AQT1000_CDC_TOP_TOP_CFG0                          (0x00000D81)
+#define AQT1000_CDC_TOP_HPHL_COMP_WR_LSB                  (0x00000D89)
+#define AQT1000_CDC_TOP_HPHL_COMP_WR_MSB                  (0x00000D8A)
+#define AQT1000_CDC_TOP_HPHL_COMP_LUT                     (0x00000D8B)
+#define AQT1000_CDC_TOP_HPHL_COMP_RD_LSB                  (0x00000D8C)
+#define AQT1000_CDC_TOP_HPHL_COMP_RD_MSB                  (0x00000D8D)
+#define AQT1000_CDC_TOP_HPHR_COMP_WR_LSB                  (0x00000D8E)
+#define AQT1000_CDC_TOP_HPHR_COMP_WR_MSB                  (0x00000D8F)
+#define AQT1000_CDC_TOP_HPHR_COMP_LUT                     (0x00000D90)
+#define AQT1000_CDC_TOP_HPHR_COMP_RD_LSB                  (0x00000D91)
+#define AQT1000_CDC_TOP_HPHR_COMP_RD_MSB                  (0x00000D92)
+#define AQT1000_CDC_DSD0_BASE               (0x00000DB1)
+#define AQT1000_CDC_DSD0_PATH_CTL                         (0x00000DB1)
+#define AQT1000_CDC_DSD0_CFG0                             (0x00000DB2)
+#define AQT1000_CDC_DSD0_CFG1                             (0x00000DB3)
+#define AQT1000_CDC_DSD0_CFG2                             (0x00000DB4)
+#define AQT1000_CDC_DSD0_CFG3                             (0x00000DB5)
+#define AQT1000_CDC_DSD0_CFG4                             (0x00000DB6)
+#define AQT1000_CDC_DSD0_CFG5                             (0x00000DB7)
+#define AQT1000_CDC_DSD1_BASE               (0x00000DC1)
+#define AQT1000_CDC_DSD1_PATH_CTL                         (0x00000DC1)
+#define AQT1000_CDC_DSD1_CFG0                             (0x00000DC2)
+#define AQT1000_CDC_DSD1_CFG1                             (0x00000DC3)
+#define AQT1000_CDC_DSD1_CFG2                             (0x00000DC4)
+#define AQT1000_CDC_DSD1_CFG3                             (0x00000DC5)
+#define AQT1000_CDC_DSD1_CFG4                             (0x00000DC6)
+#define AQT1000_CDC_DSD1_CFG5                             (0x00000DC7)
+#define AQT1000_CDC_RX_IDLE_DET_CDC_RX_IDLE_DET_BASE (0x00000DD1)
+#define AQT1000_CDC_RX_IDLE_DET_PATH_CTL                  (0x00000DD1)
+#define AQT1000_CDC_RX_IDLE_DET_CFG0                      (0x00000DD2)
+#define AQT1000_CDC_RX_IDLE_DET_CFG1                      (0x00000DD3)
+#define AQT1000_CDC_RX_IDLE_DET_CFG2                      (0x00000DD4)
+#define AQT1000_CDC_RX_IDLE_DET_CFG3                      (0x00000DD5)
+#define AQT1000_CDC_DOP_DET_CDC_DOP_DET_BASE (0x00000DD9)
+#define AQT1000_CDC_DOP_DET_CTL                           (0x00000DD9)
+#define AQT1000_CDC_DOP_DET_CFG0                          (0x00000DDA)
+#define AQT1000_CDC_DOP_DET_CFG1                          (0x00000DDB)
+#define AQT1000_CDC_DOP_DET_CFG2                          (0x00000DDC)
+#define AQT1000_CDC_DOP_DET_CFG3                          (0x00000DDD)
+#define AQT1000_CDC_DOP_DET_CFG4                          (0x00000DDE)
+#define AQT1000_CDC_DOP_DET_STATUS0                       (0x00000DE1)
+#define AQT1000_PAGE15_BASE                 (0x00000F00)
+#define AQT1000_PAGE15_PAGE_REGISTER                      (0x00000F00)
+#define AQT1000_CDC_DEBUG_CDC_DEBUG_BASE    (0x00000FA1)
+#define AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG0                 (0x00000FA1)
+#define AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG1                 (0x00000FA2)
+#define AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG2                 (0x00000FA3)
+#define AQT1000_CDC_DEBUG_DSD0_DEBUG_CFG3                 (0x00000FA4)
+#define AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG0                 (0x00000FA5)
+#define AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG1                 (0x00000FA6)
+#define AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG2                 (0x00000FA7)
+#define AQT1000_CDC_DEBUG_DSD1_DEBUG_CFG3                 (0x00000FA8)
+#define AQT1000_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0           (0x00000FAB)
+#define AQT1000_CDC_DEBUG_ANC0_RC0_FIFO_CTL               (0x00000FAC)
+#define AQT1000_CDC_DEBUG_ANC0_RC1_FIFO_CTL               (0x00000FAD)
+#define AQT1000_CDC_DEBUG_ANC1_RC0_FIFO_CTL               (0x00000FAE)
+#define AQT1000_CDC_DEBUG_ANC1_RC1_FIFO_CTL               (0x00000FAF)
+#define AQT1000_CDC_DEBUG_ANC_RC_RST_DBG_CNTR             (0x00000FB0)
+#define AQT1000_PAGE128_BASE                (0x00008000)
+#define AQT1000_PAGE128_PAGE_REGISTER                     (0x00008000)
+#define AQT1000_TLMM_TLMM_BASE              (0x00008001)
+#define AQT1000_TLMM_SPI_CLK_PINCFG                       (0x00008001)
+#define AQT1000_TLMM_SPI_MOSI_PINCFG                      (0x00008002)
+#define AQT1000_TLMM_SPI_MISO_PINCFG                      (0x00008003)
+#define AQT1000_TLMM_SPI_CS_N_PINCFG                      (0x00008004)
+#define AQT1000_TLMM_GPIO1_PINCFG                         (0x00008005)
+#define AQT1000_TLMM_GPIO2_PINCFG                         (0x00008006)
+#define AQT1000_TLMM_GPIO3_PINCFG                         (0x00008007)
+#define AQT1000_TLMM_GPIO4_PINCFG                         (0x00008008)
+#define AQT1000_TLMM_GPIO5_PINCFG                         (0x00008009)
+#define AQT1000_TLMM_GPIO6_PINCFG                         (0x0000800A)
+#define AQT1000_TLMM_GPIO7_PINCFG                         (0x0000800B)
+#define AQT1000_TLMM_GPIO8_PINCFG                         (0x0000800C)
+#define AQT1000_TLMM_GPIO9_PINCFG                         (0x0000800D)
+#define AQT1000_TLMM_GPIO10_PINCFG                        (0x0000800E)
+#define AQT1000_PAD_CTRL_PAD_CTRL_BASE      (0x00008031)
+#define AQT1000_PAD_CTRL_PAD_PDN_CTRL_0                   (0x00008031)
+#define AQT1000_PAD_CTRL_PAD_PDN_CTRL_1                   (0x00008032)
+#define AQT1000_PAD_CTRL_PAD_PU_CTRL_0                    (0x00008033)
+#define AQT1000_PAD_CTRL_PAD_PU_CTRL_1                    (0x00008034)
+#define AQT1000_PAD_CTRL_GPIO_CTL_0_OE                    (0x00008036)
+#define AQT1000_PAD_CTRL_GPIO_CTL_1_OE                    (0x00008037)
+#define AQT1000_PAD_CTRL_GPIO_CTL_0_DATA                  (0x00008038)
+#define AQT1000_PAD_CTRL_GPIO_CTL_1_DATA                  (0x00008039)
+#define AQT1000_PAD_CTRL_PAD_DRVCTL                       (0x0000803A)
+#define AQT1000_PAD_CTRL_PIN_STATUS                       (0x0000803B)
+#define AQT1000_PAD_CTRL_MEM_CTRL                         (0x0000803C)
+#define AQT1000_PAD_CTRL_PAD_INP_DISABLE_0                (0x0000803E)
+#define AQT1000_PAD_CTRL_PAD_INP_DISABLE_1                (0x0000803F)
+#define AQT1000_PAD_CTRL_PIN_CTL_OE_0                     (0x00008040)
+#define AQT1000_PAD_CTRL_PIN_CTL_OE_1                     (0x00008041)
+#define AQT1000_PAD_CTRL_PIN_CTL_DATA_0                   (0x00008042)
+#define AQT1000_PAD_CTRL_PIN_CTL_DATA_1                   (0x00008043)
+#define AQT1000_PAD_CTRL_USB_PHY_CLK_DIV                  (0x00008044)
+#define AQT1000_PAD_CTRL_DEBUG_BUS_CDC                    (0x00008045)
+#define AQT1000_PAD_CTRL_DEBUG_BUS_SEL                    (0x00008046)
+#define AQT1000_PAD_CTRL_DEBUG_EN_1                       (0x00008047)
+#define AQT1000_PAD_CTRL_DEBUG_EN_2                       (0x00008048)
+#define AQT1000_PAD_CTRL_DEBUG_EN_3                       (0x00008049)
+#define AQT1000_PAD_CTRL_DEBUG_EN_4                       (0x0000804A)
+#define AQT1000_PAD_CTRL_DEBUG_EN_5                       (0x0000804B)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_0                  (0x0000804C)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_1                  (0x0000804D)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_2                  (0x0000804E)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_3                  (0x0000804F)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_4                  (0x00008050)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_5                  (0x00008051)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_6                  (0x00008052)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_7                  (0x00008053)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_8                  (0x00008054)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_9                  (0x00008055)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_10                 (0x00008056)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_11                 (0x00008057)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_12                 (0x00008058)
+#define AQT1000_PAD_CTRL_DEBUG_MUX_BIT_13                 (0x00008059)
+#define AQT1000_PAD_CTRL_DEBUG_READ_0                     (0x0000805A)
+#define AQT1000_PAD_CTRL_DEBUG_READ_1                     (0x0000805B)
+#define AQT1000_PAD_CTRL_DEBUG_READ_2                     (0x0000805C)
+#define AQT1000_PAD_CTRL_DEBUG_READ_3                     (0x0000805D)
+#define AQT1000_PAD_CTRL_FPGA_CTL                         (0x00008061)
+#define AQT1000_MAX_REGISTER                              (0x000080FF)
+
+#endif /*_AQT_REGISTERS_H*/

+ 102 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-regmap.c

@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "aqt1000-registers.h"
+#include "aqt1000-reg-defaults.h"
+#include "aqt1000-internal.h"
+
+static bool aqt1000_is_readable_register(struct device *dev, unsigned int reg)
+{
+	u8 pg_num, reg_offset;
+	const u8 *reg_tbl = NULL;
+
+	/*
+	 * Get the page number from MSB of codec register. If its 0x80, assign
+	 * the corresponding page index PAGE_0x80.
+	 */
+	pg_num = reg >> 0x8;
+	if (pg_num == 0x80)
+		pg_num = AQT1000_PAGE_128;
+	else if (pg_num > 15)
+		return false;
+
+	reg_tbl = aqt1000_reg[pg_num];
+	reg_offset = reg & 0xFF;
+
+	if (reg_tbl && reg_tbl[reg_offset])
+		return true;
+	else
+		return false;
+}
+
+static bool aqt1000_is_volatile_register(struct device *dev, unsigned int reg)
+{
+	u8 pg_num, reg_offset;
+	const u8 *reg_tbl = NULL;
+
+	pg_num = reg >> 0x8;
+	if (pg_num == 0x80)
+		pg_num = AQT1000_PAGE_128;
+	else if (pg_num > 15)
+		return false;
+
+	reg_tbl = aqt1000_reg[pg_num];
+	reg_offset = reg & 0xFF;
+
+	if (reg_tbl && reg_tbl[reg_offset] == AQT1000_RO)
+		return true;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL) &&
+	    (reg <= AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL))
+		return true;
+
+	if ((reg >= AQT1000_CDC_ANC0_IIR_COEFF_1_CTL) &&
+	    (reg <= AQT1000_CDC_ANC0_FB_GAIN_CTL))
+		return true;
+
+	if ((reg >= AQT1000_CDC_ANC1_IIR_COEFF_1_CTL) &&
+	    (reg <= AQT1000_CDC_ANC1_FB_GAIN_CTL))
+		return true;
+
+	/*
+	 * Need to mark volatile for registers that are writable but
+	 * only few bits are read-only
+	 */
+	switch (reg) {
+	case AQT1000_BUCK_5V_CTRL_CCL_1:
+	case AQT1000_BIAS_CCOMP_FINE_ADJ:
+	case AQT1000_ANA_BIAS:
+	case AQT1000_BUCK_5V_IBIAS_CTL_4:
+	case AQT1000_BUCK_5V_CTRL_CCL_2:
+	case AQT1000_CHIP_CFG0_RST_CTL:
+	case AQT1000_CHIP_CFG0_CLK_CTL_CDC_DIG:
+	case AQT1000_CHIP_CFG0_CLK_CFG_MCLK:
+	case AQT1000_CHIP_CFG0_EFUSE_CTL:
+	case AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL:
+	case AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL:
+	case AQT1000_ANA_RX_SUPPLIES:
+	case AQT1000_ANA_MBHC_MECH:
+	case AQT1000_ANA_MBHC_ELECT:
+	case AQT1000_ANA_MBHC_ZDET:
+	case AQT1000_ANA_MICB1:
+	case AQT1000_BUCK_5V_EN_CTL:
+		return true;
+	}
+
+	return false;
+}
+
+struct regmap_config aqt1000_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = aqt1000_defaults,
+	.num_reg_defaults = ARRAY_SIZE(aqt1000_defaults),
+	.max_register = AQT1000_MAX_REGISTER,
+	.volatile_reg = aqt1000_is_volatile_register,
+	.readable_reg = aqt1000_is_readable_register,
+};

+ 166 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-routing.h

@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+#ifndef AQT1000_ROUTING_H
+#define AQT1000_ROUTING_H
+
+#include <sound/soc-dapm.h>
+
+const struct snd_soc_dapm_route aqt_audio_map[] = {
+
+	/* CDC Tx interface */
+
+	{"AQT AIF1 CAP", NULL, "AQT AIF1 CAP Mixer"},
+	{"AQT AIF1 CAP Mixer", "TX0", "AQT TX0_MUX"},
+	{"AQT AIF1 CAP Mixer", "TX1", "AQT TX1_MUX"},
+
+	{"AQT TX0_MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT TX0_MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT TX0_MUX", "DEC_V", "AQT ADC2 MUX"},
+
+	{"AQT TX1_MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT TX1_MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT TX1_MUX", "DEC_V", "AQT ADC2 MUX"},
+
+	{"AQT ADC0 MUX", "AMIC", "AQT AMIC0_MUX"},
+	{"AQT ADC0 MUX", "ANC_FB0", "AQT ANC_FB_TUNE0"},
+	{"AQT ADC0 MUX", "ANC_FB1", "AQT ANC_FB_TUNE1"},
+
+	{"AQT ADC1 MUX", "AMIC", "AQT AMIC1_MUX"},
+	{"AQT ADC1 MUX", "ANC_FB0", "AQT ANC_FB_TUNE0"},
+	{"AQT ADC1 MUX", "ANC_FB1", "AQT ANC_FB_TUNE1"},
+
+	{"AQT ADC2 MUX", "AMIC", "AQT AMIC2_MUX"},
+	{"AQT ADC2 MUX", "ANC_FB0", "AQT ANC_FB_TUNE0"},
+	{"AQT ADC2 MUX", "ANC_FB1", "AQT ANC_FB_TUNE1"},
+
+	{"AQT AMIC0_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC0_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC0_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT AMIC1_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC1_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC1_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT AMIC2_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC2_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC2_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT ADC_L", NULL, "AQT AMIC1"},
+	{"AQT ADC_R", NULL, "AQT AMIC2"},
+	{"AQT ADC_V", NULL, "AQT AMIC3"},
+
+	{"AQT AMIC10_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC10_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC10_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT AMIC11_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC11_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC11_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT AMIC12_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC12_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC12_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT AMIC13_MUX", "ADC_L", "AQT ADC_L"},
+	{"AQT AMIC13_MUX", "ADC_R", "AQT ADC_R"},
+	{"AQT AMIC13_MUX", "ADC_V", "AQT ADC_V"},
+
+	{"AQT ANC OUT HPHL Enable", "Switch", "AQT AMIC10_MUX"},
+	{"AQT ANC OUT HPHL Enable", "Switch", "AQT AMIC11_MUX"},
+	{"AQT ANC OUT HPHR Enable", "Switch", "AQT AMIC12_MUX"},
+	{"AQT ANC OUT HPHR Enable", "Switch", "AQT AMIC13_MUX"},
+
+	{"AQT RX INT1 MIX2", NULL, "AQT ANC OUT HPHL Enable"},
+	{"AQT RX INT2 MIX2", NULL, "AQT ANC OUT HPHR Enable"},
+
+	{"AQT ANC0 FB MUX", "ANC_IN_HPHL", "AQT RX INT1 MIX2"},
+	{"AQT ANC1 FB MUX", "ANC_IN_HPHR", "AQT RX INT2 MIX2"},
+
+	{"AQT I2S_L RX", NULL, "AQT AIF1 PB"},
+	{"AQT I2S_R RX", NULL, "AQT AIF1 PB"},
+
+	{"AQT RX INT1_1 MUX", "I2S0_L", "AQT I2S_L RX"},
+	{"AQT RX INT1_1 MUX", "I2S0_R", "AQT I2S_R RX"},
+	{"AQT RX INT1_1 MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT RX INT1_1 MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT RX INT1_1 MUX", "DEC_V", "AQT ADC2 MUX"},
+
+	{"AQT RX INT2_1 MUX", "I2S0_L", "AQT I2S_L RX"},
+	{"AQT RX INT2_1 MUX", "I2S0_R", "AQT I2S_R RX"},
+	{"AQT RX INT2_1 MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT RX INT2_1 MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT RX INT2_1 MUX", "DEC_V", "AQT ADC2 MUX"},
+
+	{"AQT RX INT1_2 MUX", "I2S0_L", "AQT I2S_L RX"},
+	{"AQT RX INT1_2 MUX", "I2S0_R", "AQT I2S_R RX"},
+	{"AQT RX INT1_2 MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT RX INT1_2 MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT RX INT1_2 MUX", "DEC_V", "AQT ADC2 MUX"},
+	{"AQT RX INT1_2 MUX", "IIR0", "AQT IIR0"},
+
+	{"AQT RX INT2_2 MUX", "I2S0_L", "AQT I2S_L RX"},
+	{"AQT RX INT2_2 MUX", "I2S0_R", "AQT I2S_R RX"},
+	{"AQT RX INT2_2 MUX", "DEC_L", "AQT ADC0 MUX"},
+	{"AQT RX INT2_2 MUX", "DEC_R", "AQT ADC1 MUX"},
+	{"AQT RX INT2_2 MUX", "DEC_V", "AQT ADC2 MUX"},
+	{"AQT RX INT2_2 MUX", "IIR0", "AQT IIR0"},
+
+	{"AQT RX INT1_1 INTERP", NULL, "AQT RX INT1_1 MUX"},
+	{"AQT RX INT1 MIX1", NULL, "AQT RX INT1_1 INTERP"},
+	{"AQT RX INT1 MIX2", NULL, "AQT RX INT1 MIX1"},
+
+	{"AQT RX INT1_2 INTERP", NULL, "AQT RX INT1_2 MUX"},
+	{"AQT RX INT1 MIX1", NULL, "AQT RX INT1_2 INTERP"},
+
+	{"AQT ASRC0 MUX", "ASRC_IN_HPHL", "AQT RX INT1_2 INTERP"},
+	{"AQT RX INT1 MIX1", "HPHL Switch", "AQT ASRC0 MUX"},
+
+	{"AQT RX INT2_1 INTERP", NULL, "AQT RX INT2_1 MUX"},
+	{"AQT RX INT2 MIX1", NULL, "AQT RX INT2_1 INTERP"},
+	{"AQT RX INT2 MIX2", NULL, "AQT RX INT2 MIX1"},
+
+	{"AQT RX INT2_2 INTERP", NULL, "AQT RX INT2_2 MUX"},
+	{"AQT RX INT2 MIX1", NULL, "AQT RX INT2_2 INTERP"},
+
+	{"AQT ASRC1 MUX", "ASRC_IN_HPHR", "AQT RX INT2_2 INTERP"},
+	{"AQT RX INT2 MIX1", "HPHR Switch", "AQT ASRC1 MUX"},
+
+	{"AQT RX INT1 DEM MUX", "CLSH_DSM_OUT", "AQT RX INT1 MIX2"},
+	{"AQT RX INT1 DAC", NULL, "AQT RX INT1 DEM MUX"},
+	{"AQT RX INT1 DAC", NULL, "AQT RX_BIAS"},
+	{"AQT RX_BIAS", NULL, "AQT MCLK"},
+	{"AQT MIC BIAS1", NULL, "AQT MCLK"},
+	{"AQT HPHL PA", NULL, "AQT RX INT1 DAC"},
+	{"AQT HPHL", NULL, "AQT HPHL PA"},
+
+	{"AQT RX INT2 DEM MUX", "CLSH_DSM_OUT", "AQT RX INT2 MIX2"},
+	{"AQT RX INT2 DAC", NULL, "AQT RX INT2 DEM MUX"},
+	{"AQT RX INT2 DAC", NULL, "AQT RX_BIAS"},
+	{"AQT HPHR PA", NULL, "AQT RX INT2 DAC"},
+	{"AQT HPHR", NULL, "AQT HPHR PA"},
+
+	{"AQT ANC HPHL PA", NULL, "AQT RX INT1 DAC"},
+	{"AQT ANC HPHL", NULL, "AQT ANC HPHL PA"},
+
+	{"AQT ANC HPHR PA", NULL, "AQT RX INT2 DAC"},
+	{"AQT ANC HPHR", NULL, "AQT ANC HPHR PA"},
+
+	{"AQT IIR0", NULL, "AQT ADC2 MUX"},
+	{"AQT SRC0", NULL, "AQT IIR0"},
+	{"AQT RX ST MUX", "SRC0", "AQT SRC0"},
+
+	{"AQT RX INT1 MIX2", NULL, "AQT RX ST MUX"},
+	{"AQT RX INT2 MIX2", NULL, "AQT RX ST MUX"},
+
+	/* Native clk main path routing */
+	{"AQT RX INT1_1 NATIVE MUX", "ON", "AQT RX INT1_1 MUX"},
+	{"AQT RX INT1_1 INTERP", NULL, "AQT RX INT1_1 NATIVE MUX"},
+	{"AQT RX INT1_1 NATIVE MUX", NULL, "AQT RX INT1 NATIVE SUPPLY"},
+
+	{"AQT RX INT2_1 NATIVE MUX", "ON", "AQT RX INT2_1 MUX"},
+	{"AQT RX INT2_1 INTERP", NULL, "AQT RX INT2_1 NATIVE MUX"},
+	{"AQT RX INT2_1 NATIVE MUX", NULL, "AQT RX INT2 NATIVE SUPPLY"},
+};
+
+#endif

+ 191 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-utils.c

@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include "aqt1000.h"
+#include "aqt1000-utils.h"
+
+#define REG_BYTES 2
+#define VAL_BYTES 1
+/*
+ * Page Register Address that APP Proc uses to
+ * access codec registers is identified as 0x00
+ */
+#define PAGE_REG_ADDR 0x00
+
+static int aqt_page_write(struct aqt1000 *aqt, unsigned short *reg)
+{
+	int ret = 0;
+	unsigned short c_reg, reg_addr;
+	u8 pg_num, prev_pg_num;
+
+	c_reg = *reg;
+	pg_num = c_reg >> 8;
+	reg_addr = c_reg & 0xff;
+	if (aqt->prev_pg_valid) {
+		prev_pg_num = aqt->prev_pg;
+		if (prev_pg_num != pg_num) {
+			ret = aqt->write_dev(
+					aqt, PAGE_REG_ADDR,
+					(void *) &pg_num, 1);
+			if (ret < 0)
+				dev_err(aqt->dev,
+					"%s: page write error, pg_num: 0x%x\n",
+					__func__, pg_num);
+			else {
+				aqt->prev_pg = pg_num;
+				dev_dbg(aqt->dev, "%s: Page 0x%x Write to 0x00\n",
+					__func__, pg_num);
+			}
+		}
+	} else {
+		ret = aqt->write_dev(
+				aqt, PAGE_REG_ADDR, (void *) &pg_num, 1);
+		if (ret < 0)
+			dev_err(aqt->dev,
+				"%s: page write error, pg_num: 0x%x\n",
+				__func__, pg_num);
+		else {
+			aqt->prev_pg = pg_num;
+			aqt->prev_pg_valid = true;
+			dev_dbg(aqt->dev, "%s: Page 0x%x Write to 0x00\n",
+				__func__, pg_num);
+		}
+	}
+	*reg = reg_addr;
+	return ret;
+}
+
+static int regmap_bus_read(void *context, const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct aqt1000 *aqt = dev_get_drvdata(dev);
+	unsigned short c_reg, rreg;
+	int ret, i;
+
+	if (!aqt) {
+		dev_err(dev, "%s: aqt is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+
+	mutex_lock(&aqt->io_lock);
+	c_reg = *(u16 *)reg;
+	rreg = c_reg;
+
+	ret = aqt_page_write(aqt, &c_reg);
+	if (ret)
+		goto err;
+	ret = aqt->read_dev(aqt, c_reg, val, val_size);
+	if (ret < 0)
+		dev_err(dev, "%s: Codec read failed (%d), reg: 0x%x, size:%zd\n",
+			__func__, ret, rreg, val_size);
+	else {
+		for (i = 0; i < val_size; i++)
+			dev_dbg(dev, "%s: Read 0x%02x from 0x%x\n",
+				__func__, ((u8 *)val)[i], rreg + i);
+	}
+err:
+	mutex_unlock(&aqt->io_lock);
+	return ret;
+}
+
+static int regmap_bus_gather_write(void *context,
+				   const void *reg, size_t reg_size,
+				   const void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct aqt1000 *aqt = dev_get_drvdata(dev);
+	unsigned short c_reg, rreg;
+	int ret, i;
+
+	if (!aqt) {
+		dev_err(dev, "%s: aqt is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+	mutex_lock(&aqt->io_lock);
+	c_reg = *(u16 *)reg;
+	rreg = c_reg;
+
+	ret = aqt_page_write(aqt, &c_reg);
+	if (ret)
+		goto err;
+
+	for (i = 0; i < val_size; i++)
+		dev_dbg(dev, "Write %02x to 0x%x\n", ((u8 *)val)[i],
+			rreg + i);
+
+	ret = aqt->write_dev(aqt, c_reg, (void *) val, val_size);
+	if (ret < 0)
+		dev_err(dev, "%s: Codec write failed (%d), reg:0x%x, size:%zd\n",
+			__func__, ret, rreg, val_size);
+
+err:
+	mutex_unlock(&aqt->io_lock);
+	return ret;
+}
+
+static int regmap_bus_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct aqt1000 *aqt = dev_get_drvdata(dev);
+
+	if (!aqt)
+		return -EINVAL;
+
+	WARN_ON(count < REG_BYTES);
+
+	return regmap_bus_gather_write(context, data, REG_BYTES,
+					       data + REG_BYTES,
+					       count - REG_BYTES);
+}
+
+static struct regmap_bus regmap_bus_config = {
+	.write = regmap_bus_write,
+	.gather_write = regmap_bus_gather_write,
+	.read = regmap_bus_read,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/*
+ * aqt1000_regmap_init:
+ *	Initialize aqt1000 register map
+ *
+ * @dev: pointer to wcd device
+ * @config: pointer to register map config
+ *
+ * Returns pointer to regmap structure for success
+ * or NULL in case of failure.
+ */
+struct regmap *aqt1000_regmap_init(struct device *dev,
+				   const struct regmap_config *config)
+{
+	return devm_regmap_init(dev, &regmap_bus_config, dev, config);
+}
+EXPORT_SYMBOL(aqt1000_regmap_init);

+ 14 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000-utils.h

@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __WCD9XXX_UTILS_H__
+#define __WCD9XXX_UTILS_H__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct regmap *aqt1000_regmap_init(struct device *dev,
+				   const struct regmap_config *config);
+#endif

+ 3611 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000.c

@@ -0,0 +1,3611 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/info.h>
+#include <asoc/wcdcal-hwdep.h>
+#include "aqt1000-registers.h"
+#include "aqt1000.h"
+#include "aqt1000-api.h"
+#include "aqt1000-mbhc.h"
+#include "aqt1000-routing.h"
+#include "aqt1000-internal.h"
+
+#define DRV_NAME "aqt_codec"
+
+#define AQT1000_TX_UNMUTE_DELAY_MS 40
+#define  TX_HPF_CUT_OFF_FREQ_MASK 0x60
+#define  CF_MIN_3DB_4HZ     0x0
+#define  CF_MIN_3DB_75HZ    0x1
+#define  CF_MIN_3DB_150HZ   0x2
+
+#define AQT_VERSION_ENTRY_SIZE 17
+#define AQT_VOUT_CTL_TO_MICB(x) (1000 + x *50)
+
+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},
+};
+
+static int tx_unmute_delay = AQT1000_TX_UNMUTE_DELAY_MS;
+module_param(tx_unmute_delay, int, 0664);
+MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path");
+
+static void aqt_codec_set_tx_hold(struct snd_soc_component *, u16, bool);
+
+/* Cutoff frequency for high pass filter */
+static const char * const cf_text[] = {
+	"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
+};
+
+static const char * const rx_cf_text[] = {
+	"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
+	"CF_NEG_3DB_0P48HZ"
+};
+
+struct aqt1000_anc_header {
+	u32 reserved[3];
+	u32 num_anc_slots;
+};
+
+static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, AQT1000_CDC_TX0_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, AQT1000_CDC_TX1_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, AQT1000_CDC_TX2_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_int1_1_enum, AQT1000_CDC_RX1_RX_PATH_CFG2, 0,
+							rx_cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, AQT1000_CDC_RX1_RX_PATH_MIX_CFG, 2,
+							rx_cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_int2_1_enum, AQT1000_CDC_RX2_RX_PATH_CFG2, 0,
+							rx_cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, AQT1000_CDC_RX2_RX_PATH_MIX_CFG, 2,
+							rx_cf_text);
+
+static const DECLARE_TLV_DB_SCALE(hph_gain, -3000, 150, 0);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+static int aqt_get_anc_slot(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = aqt->anc_slot;
+	return 0;
+}
+
+static int aqt_put_anc_slot(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	aqt->anc_slot = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int aqt_get_anc_func(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = (aqt->anc_func == true ? 1 : 0);
+	return 0;
+}
+
+static int aqt_put_anc_func(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm =
+			snd_soc_component_get_dapm(component);
+
+	mutex_lock(&aqt->codec_mutex);
+	aqt->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+	dev_dbg(component->dev, "%s: anc_func %x", __func__, aqt->anc_func);
+
+	if (aqt->anc_func == true) {
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHL PA");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHR PA");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_disable_pin(dapm, "HPHL PA");
+		snd_soc_dapm_disable_pin(dapm, "HPHR PA");
+		snd_soc_dapm_disable_pin(dapm, "HPHL");
+		snd_soc_dapm_disable_pin(dapm, "HPHR");
+	} else {
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_enable_pin(dapm, "HPHL");
+		snd_soc_dapm_enable_pin(dapm, "HPHR");
+		snd_soc_dapm_enable_pin(dapm, "HPHL PA");
+		snd_soc_dapm_enable_pin(dapm, "HPHR PA");
+	}
+	mutex_unlock(&aqt->codec_mutex);
+
+	snd_soc_dapm_sync(dapm);
+	return 0;
+}
+
+static const char *const aqt_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum aqt_anc_func_enum =
+	SOC_ENUM_SINGLE_EXT(2, aqt_anc_func_text);
+
+static int aqt_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = aqt->hph_mode;
+	return 0;
+}
+
+static int aqt_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	u32 mode_val;
+
+	mode_val = ucontrol->value.enumerated.item[0];
+
+	dev_dbg(component->dev, "%s: mode: %d\n", __func__, mode_val);
+
+	if (mode_val == 0) {
+		dev_warn(component->dev, "%s:Invalid HPH Mode, default to Cls-H LOHiFi\n",
+			__func__);
+		mode_val = CLS_H_LOHIFI;
+	}
+	aqt->hph_mode = mode_val;
+	return 0;
+}
+
+static const char * const rx_hph_mode_mux_text[] = {
+	"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
+	"CLS_H_ULP", "CLS_AB_HIFI",
+};
+
+static const struct soc_enum rx_hph_mode_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
+			    rx_hph_mode_mux_text);
+
+static int aqt_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] = (snd_soc_component_read32(component,
+					    AQT1000_CDC_SIDETONE_IIR0_IIR_CTL) &
+					    (1 << band_idx)) != 0;
+
+	dev_dbg(component->dev, "%s: IIR0 band #%d enable %d\n", __func__,
+		band_idx, (uint32_t)ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int aqt_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	bool iir_band_en_status;
+	int value = ucontrol->value.integer.value[0];
+
+	/* Mask first 5 bits, 6-8 are reserved */
+	snd_soc_component_update_bits(component,
+			AQT1000_CDC_SIDETONE_IIR0_IIR_CTL,
+			(1 << band_idx), (value << band_idx));
+
+	iir_band_en_status = ((snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_CTL) &
+			      (1 << band_idx)) != 0);
+	dev_dbg(component->dev, "%s: IIR0 band #%d enable %d\n", __func__,
+		band_idx, iir_band_en_status);
+
+	return 0;
+}
+
+static uint32_t aqt_get_iir_band_coeff(struct snd_soc_component *component,
+					int band_idx, int coeff_idx)
+{
+	uint32_t value = 0;
+
+	/* Address does not automatically update if reading */
+	snd_soc_component_write(component,
+		AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t)) & 0x7F);
+
+	value |= snd_soc_component_read32(component,
+			AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL);
+
+	snd_soc_component_write(component,
+		AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_component_read32(component,
+			AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL) << 8);
+
+	snd_soc_component_write(component,
+		AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_component_read32(component,
+			AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL) << 16);
+
+	snd_soc_component_write(component,
+		AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 3) & 0x7F);
+
+	/* Mask bits top 2 bits since they are reserved */
+	value |= ((snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL)
+				& 0x3F) << 24);
+
+	return value;
+}
+
+static int aqt_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		aqt_get_iir_band_coeff(component, band_idx, 0);
+	ucontrol->value.integer.value[1] =
+		aqt_get_iir_band_coeff(component, band_idx, 1);
+	ucontrol->value.integer.value[2] =
+		aqt_get_iir_band_coeff(component, band_idx, 2);
+	ucontrol->value.integer.value[3] =
+		aqt_get_iir_band_coeff(component, band_idx, 3);
+	ucontrol->value.integer.value[4] =
+		aqt_get_iir_band_coeff(component, band_idx, 4);
+
+	dev_dbg(component->dev, "%s: IIR band #%d b0 = 0x%x\n"
+		"%s: IIR band #%d b1 = 0x%x\n"
+		"%s: IIR band #%d b2 = 0x%x\n"
+		"%s: IIR band #%d a1 = 0x%x\n"
+		"%s: IIR band #%d a2 = 0x%x\n",
+		__func__, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0],
+		__func__, band_idx,
+		(uint32_t)ucontrol->value.integer.value[1],
+		__func__, band_idx,
+		(uint32_t)ucontrol->value.integer.value[2],
+		__func__, band_idx,
+		(uint32_t)ucontrol->value.integer.value[3],
+		__func__, band_idx,
+		(uint32_t)ucontrol->value.integer.value[4]);
+
+	return 0;
+}
+
+static void aqt_set_iir_band_coeff(struct snd_soc_component *component,
+				   int band_idx, uint32_t value)
+{
+	snd_soc_component_write(component,
+		(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL),
+		(value & 0xFF));
+
+	snd_soc_component_write(component,
+		(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL),
+		(value >> 8) & 0xFF);
+
+	snd_soc_component_write(component,
+		(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL),
+		(value >> 16) & 0xFF);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_component_write(component,
+		(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL),
+		(value >> 24) & 0x3F);
+}
+
+static int aqt_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int coeff_idx;
+
+	/*
+	 * Mask top bit it is reserved
+	 * Updates addr automatically for each B2 write
+	 */
+	snd_soc_component_write(component,
+		(AQT1000_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	for (coeff_idx = 0; coeff_idx < AQT1000_CDC_SIDETONE_IIR_COEFF_MAX;
+		coeff_idx++) {
+		aqt_set_iir_band_coeff(component, band_idx,
+				   ucontrol->value.integer.value[coeff_idx]);
+	}
+
+	dev_dbg(component->dev, "%s: IIR band #%d b0 = 0x%x\n"
+		"%s: IIR band #%d b1 = 0x%x\n"
+		"%s: IIR band #%d b2 = 0x%x\n"
+		"%s: IIR band #%d a1 = 0x%x\n"
+		"%s: IIR band #%d a2 = 0x%x\n",
+		__func__, band_idx,
+		aqt_get_iir_band_coeff(component, band_idx, 0),
+		__func__, band_idx,
+		aqt_get_iir_band_coeff(component, band_idx, 1),
+		__func__, band_idx,
+		aqt_get_iir_band_coeff(component, band_idx, 2),
+		__func__, band_idx,
+		aqt_get_iir_band_coeff(component, band_idx, 3),
+		__func__, band_idx,
+		aqt_get_iir_band_coeff(component, band_idx, 4));
+
+	return 0;
+}
+
+static int aqt_compander_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int comp = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = aqt->comp_enabled[comp];
+	return 0;
+}
+
+static int aqt_compander_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int comp = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		 __func__, comp + 1, aqt->comp_enabled[comp], value);
+	aqt->comp_enabled[comp] = value;
+
+	/* Any specific register configuration for compander */
+	switch (comp) {
+	case COMPANDER_1:
+		/* Set Gain Source Select based on compander enable/disable */
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_L_EN, 0x20,
+				(value ? 0x00 : 0x20));
+		break;
+	case COMPANDER_2:
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_R_EN, 0x20,
+				(value ? 0x00 : 0x20));
+		break;
+	default:
+		/*
+		 * if compander is not enabled for any interpolator,
+		 * it does not cause any audio failure, so do not
+		 * return error in this case, but just print a log
+		 */
+		dev_warn(component->dev, "%s: unknown compander: %d\n",
+			__func__, comp);
+	};
+	return 0;
+}
+
+static int aqt_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			 snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int index = -EINVAL;
+
+	if (!strcmp(kcontrol->id.name, "AQT ASRC0 Output Mode"))
+		index = ASRC0;
+	if (!strcmp(kcontrol->id.name, "AQT ASRC1 Output Mode"))
+		index = ASRC1;
+
+	if (aqt && (index >= 0) && (index < ASRC_MAX))
+		aqt->asrc_output_mode[index] =
+			ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int aqt_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int val = 0;
+	int index = -EINVAL;
+
+	if (!strcmp(kcontrol->id.name, "AQT ASRC0 Output Mode"))
+		index = ASRC0;
+	if (!strcmp(kcontrol->id.name, "AQT ASRC1 Output Mode"))
+		index = ASRC1;
+
+	if (aqt && (index >= 0) && (index < ASRC_MAX))
+		val = aqt->asrc_output_mode[index];
+
+	ucontrol->value.integer.value[0] = val;
+
+	return 0;
+}
+
+static const char * const asrc_mode_text[] = {
+	"INT", "FRAC"
+};
+static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
+
+static int aqt_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int val = 0;
+
+	if (aqt)
+		val = aqt->idle_det_cfg.hph_idle_detect_en;
+
+	ucontrol->value.integer.value[0] = val;
+
+	return 0;
+}
+
+static int aqt_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	if (aqt)
+		aqt->idle_det_cfg.hph_idle_detect_en =
+			ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static const char * const hph_idle_detect_text[] = {
+	"OFF", "ON"
+};
+
+static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
+
+static int aqt_amic_pwr_lvl_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	u16 amic_reg = 0;
+
+	if (!strcmp(kcontrol->id.name, "AQT AMIC_1_2 PWR MODE"))
+		amic_reg = AQT1000_ANA_AMIC1;
+	if (!strcmp(kcontrol->id.name, "AQT AMIC_3 PWR MODE"))
+		amic_reg = AQT1000_ANA_AMIC3;
+
+	if (amic_reg)
+		ucontrol->value.integer.value[0] =
+			(snd_soc_component_read32(component, amic_reg) &
+			 AQT1000_AMIC_PWR_LVL_MASK) >>
+			  AQT1000_AMIC_PWR_LVL_SHIFT;
+	return 0;
+}
+
+static int aqt_amic_pwr_lvl_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	u32 mode_val;
+	u16 amic_reg = 0;
+
+	mode_val = ucontrol->value.enumerated.item[0];
+
+	dev_dbg(component->dev, "%s: mode: %d\n", __func__, mode_val);
+
+	if (!strcmp(kcontrol->id.name, "AQT AMIC_1_2 PWR MODE"))
+		amic_reg = AQT1000_ANA_AMIC1;
+	if (!strcmp(kcontrol->id.name, "AQT AMIC_3 PWR MODE"))
+		amic_reg = AQT1000_ANA_AMIC3;
+
+	if (amic_reg)
+		snd_soc_component_update_bits(component, amic_reg,
+				AQT1000_AMIC_PWR_LVL_MASK,
+				mode_val << AQT1000_AMIC_PWR_LVL_SHIFT);
+	return 0;
+}
+
+static const char * const amic_pwr_lvl_text[] = {
+	"LOW_PWR", "DEFAULT", "HIGH_PERF", "HYBRID"
+};
+
+static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
+
+static const struct snd_kcontrol_new aqt_snd_controls[] = {
+	SOC_SINGLE_TLV("AQT HPHL Volume", AQT1000_HPH_L_EN, 0, 24, 1, hph_gain),
+	SOC_SINGLE_TLV("AQT HPHR Volume", AQT1000_HPH_R_EN, 0, 24, 1, hph_gain),
+	SOC_SINGLE_TLV("AQT ADC1 Volume", AQT1000_ANA_AMIC1, 0, 20, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("AQT ADC2 Volume", AQT1000_ANA_AMIC2, 0, 20, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("AQT ADC3 Volume", AQT1000_ANA_AMIC3, 0, 20, 0,
+			analog_gain),
+
+	SOC_SINGLE_SX_TLV("AQT RX1 Digital Volume", AQT1000_CDC_RX1_RX_VOL_CTL,
+		0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("AQT RX2 Digital Volume", AQT1000_CDC_RX2_RX_VOL_CTL,
+		0, -84, 40, digital_gain),
+
+	SOC_SINGLE_SX_TLV("AQT DEC0 Volume", AQT1000_CDC_TX0_TX_VOL_CTL, 0,
+		-84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("AQT DEC1 Volume", AQT1000_CDC_TX1_TX_VOL_CTL, 0,
+		-84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("AQT DEC2 Volume", AQT1000_CDC_TX2_TX_VOL_CTL, 0,
+		-84, 40, digital_gain),
+
+	SOC_SINGLE_SX_TLV("AQT IIR0 INP0 Volume",
+		AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
+		digital_gain),
+	SOC_SINGLE_SX_TLV("AQT IIR0 INP1 Volume",
+		AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40,
+		digital_gain),
+	SOC_SINGLE_SX_TLV("AQT IIR0 INP2 Volume",
+		AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40,
+		digital_gain),
+	SOC_SINGLE_SX_TLV("AQT IIR0 INP3 Volume",
+		AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40,
+		digital_gain),
+	SOC_SINGLE_EXT("AQT ANC Slot", SND_SOC_NOPM, 0, 100, 0,
+			aqt_get_anc_slot, aqt_put_anc_slot),
+	SOC_ENUM_EXT("AQT ANC Function", aqt_anc_func_enum, aqt_get_anc_func,
+		aqt_put_anc_func),
+
+	SOC_ENUM("AQT TX0 HPF cut off", cf_dec0_enum),
+	SOC_ENUM("AQT TX1 HPF cut off", cf_dec1_enum),
+	SOC_ENUM("AQT TX2 HPF cut off", cf_dec2_enum),
+
+	SOC_ENUM("AQT RX INT1_1 HPF cut off", cf_int1_1_enum),
+	SOC_ENUM("AQT RX INT1_2 HPF cut off", cf_int1_2_enum),
+	SOC_ENUM("AQT RX INT2_1 HPF cut off", cf_int2_1_enum),
+	SOC_ENUM("AQT RX INT2_2 HPF cut off", cf_int2_2_enum),
+
+	SOC_ENUM_EXT("AQT RX HPH Mode", rx_hph_mode_mux_enum,
+		aqt_rx_hph_mode_get, aqt_rx_hph_mode_put),
+
+	SOC_SINGLE_EXT("AQT IIR0 Enable Band1", IIR0, BAND1, 1, 0,
+		aqt_iir_enable_audio_mixer_get,
+		aqt_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("AQT IIR0 Enable Band2", IIR0, BAND2, 1, 0,
+		aqt_iir_enable_audio_mixer_get,
+		aqt_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("AQT IIR0 Enable Band3", IIR0, BAND3, 1, 0,
+		aqt_iir_enable_audio_mixer_get,
+		aqt_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("AQT IIR0 Enable Band4", IIR0, BAND4, 1, 0,
+		aqt_iir_enable_audio_mixer_get,
+		aqt_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("AQT IIR0 Enable Band5", IIR0, BAND5, 1, 0,
+		aqt_iir_enable_audio_mixer_get,
+		aqt_iir_enable_audio_mixer_put),
+
+	SOC_SINGLE_MULTI_EXT("AQT IIR0 Band1", IIR0, BAND1, 255, 0, 5,
+		aqt_iir_band_audio_mixer_get, aqt_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("AQT IIR0 Band2", IIR0, BAND2, 255, 0, 5,
+		aqt_iir_band_audio_mixer_get, aqt_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("AQT IIR0 Band3", IIR0, BAND3, 255, 0, 5,
+		aqt_iir_band_audio_mixer_get, aqt_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("AQT IIR0 Band4", IIR0, BAND4, 255, 0, 5,
+		aqt_iir_band_audio_mixer_get, aqt_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("AQT IIR0 Band5", IIR0, BAND5, 255, 0, 5,
+		aqt_iir_band_audio_mixer_get, aqt_iir_band_audio_mixer_put),
+
+	SOC_SINGLE_EXT("AQT COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
+		aqt_compander_get, aqt_compander_put),
+	SOC_SINGLE_EXT("AQT COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
+		aqt_compander_get, aqt_compander_put),
+
+	SOC_ENUM_EXT("AQT ASRC0 Output Mode", asrc_mode_enum,
+		aqt_hph_asrc_mode_get, aqt_hph_asrc_mode_put),
+	SOC_ENUM_EXT("AQT ASRC1 Output Mode", asrc_mode_enum,
+		aqt_hph_asrc_mode_get, aqt_hph_asrc_mode_put),
+
+	SOC_ENUM_EXT("AQT HPH Idle Detect", hph_idle_detect_enum,
+		aqt_hph_idle_detect_get, aqt_hph_idle_detect_put),
+
+	SOC_ENUM_EXT("AQT AMIC_1_2 PWR MODE", amic_pwr_lvl_enum,
+		aqt_amic_pwr_lvl_get, aqt_amic_pwr_lvl_put),
+	SOC_ENUM_EXT("AQT AMIC_3 PWR MODE", amic_pwr_lvl_enum,
+		aqt_amic_pwr_lvl_get, aqt_amic_pwr_lvl_put),
+};
+
+static int aqt_codec_enable_rx_bias(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		aqt->rx_bias_count++;
+		if (aqt->rx_bias_count == 1) {
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_RX_SUPPLIES,
+					0x01, 0x01);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		aqt->rx_bias_count--;
+		if (!aqt->rx_bias_count)
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_RX_SUPPLIES,
+					0x01, 0x00);
+		break;
+	};
+	dev_dbg(component->dev, "%s: Current RX BIAS user count: %d\n",
+		__func__, aqt->rx_bias_count);
+
+	return 0;
+}
+
+/*
+ * aqt_mbhc_micb_adjust_voltage: adjust specific micbias voltage
+ * @component: handle to snd_soc_component *
+ * @req_volt: micbias voltage to be set
+ * @micb_num: micbias to be set, e.g. micbias1 or micbias2
+ *
+ * return 0 if adjustment is success or error code in case of failure
+ */
+int aqt_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+				   int req_volt, int micb_num)
+{
+	struct aqt1000 *aqt;
+	int cur_vout_ctl, req_vout_ctl;
+	int micb_reg, micb_val, micb_en;
+	int ret = 0;
+
+	if (!component) {
+		pr_err("%s: Invalid component pointer\n", __func__);
+		return -EINVAL;
+	}
+
+	if (micb_num != MIC_BIAS_1)
+		return -EINVAL;
+	else
+		micb_reg = AQT1000_ANA_MICB1;
+
+	aqt = snd_soc_component_get_drvdata(component);
+	mutex_lock(&aqt->micb_lock);
+
+	/*
+	 * If requested micbias voltage is same as current micbias
+	 * voltage, then just return. Otherwise, adjust voltage as
+	 * per requested value. If micbias is already enabled, then
+	 * to avoid slow micbias ramp-up or down enable pull-up
+	 * momentarily, change the micbias value and then re-enable
+	 * micbias.
+	 */
+	micb_val = snd_soc_component_read32(component, micb_reg);
+	micb_en = (micb_val & 0xC0) >> 6;
+	cur_vout_ctl = micb_val & 0x3F;
+
+	req_vout_ctl = aqt_get_micb_vout_ctl_val(req_volt);
+	if (req_vout_ctl < 0) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	if (cur_vout_ctl == req_vout_ctl) {
+		ret = 0;
+		goto exit;
+	}
+
+	dev_dbg(component->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
+		 __func__, micb_num, AQT_VOUT_CTL_TO_MICB(cur_vout_ctl),
+		 req_volt, micb_en);
+
+	if (micb_en == 0x1)
+		snd_soc_component_update_bits(component, micb_reg, 0xC0, 0x80);
+
+	snd_soc_component_update_bits(component, micb_reg, 0x3F, req_vout_ctl);
+
+	if (micb_en == 0x1) {
+		snd_soc_component_update_bits(component, micb_reg, 0xC0, 0x40);
+		/*
+		 * Add 2ms delay as per HW requirement after enabling
+		 * micbias
+		 */
+		usleep_range(2000, 2100);
+	}
+exit:
+	mutex_unlock(&aqt->micb_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(aqt_mbhc_micb_adjust_voltage);
+
+/*
+ * aqt_micbias_control: enable/disable micbias
+ * @component: handle to snd_soc_component *
+ * @micb_num: micbias to be enabled/disabled, e.g. micbias1 or micbias2
+ * @req: control requested, enable/disable or pullup enable/disable
+ * @is_dapm: triggered by dapm or not
+ *
+ * return 0 if control is success or error code in case of failure
+ */
+int aqt_micbias_control(struct snd_soc_component *component,
+			  int micb_num, int req, bool is_dapm)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	u16 micb_reg;
+	int pre_off_event = 0, post_off_event = 0;
+	int post_on_event = 0, post_dapm_off = 0;
+	int post_dapm_on = 0;
+	int ret = 0;
+
+	switch (micb_num) {
+	case MIC_BIAS_1:
+		micb_reg = AQT1000_ANA_MICB1;
+		pre_off_event = AQT_EVENT_PRE_MICBIAS_1_OFF;
+		post_off_event = AQT_EVENT_POST_MICBIAS_1_OFF;
+		post_on_event = AQT_EVENT_POST_MICBIAS_1_ON;
+		post_dapm_on = AQT_EVENT_POST_DAPM_MICBIAS_1_ON;
+		post_dapm_off = AQT_EVENT_POST_DAPM_MICBIAS_1_OFF;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
+			__func__, micb_num);
+		return -EINVAL;
+	}
+	mutex_lock(&aqt->micb_lock);
+
+	switch (req) {
+	case MICB_PULLUP_ENABLE:
+		aqt->pullup_ref++;
+		if ((aqt->pullup_ref == 1) &&
+		    (aqt->micb_ref == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+						      0xC0, 0x80);
+		break;
+	case MICB_PULLUP_DISABLE:
+		if (aqt->pullup_ref > 0)
+			aqt->pullup_ref--;
+		if ((aqt->pullup_ref == 0) &&
+		    (aqt->micb_ref == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+						      0xC0, 0x00);
+		break;
+	case MICB_ENABLE:
+		aqt->micb_ref++;
+		if (aqt->micb_ref == 1) {
+			snd_soc_component_update_bits(component, micb_reg,
+						      0xC0, 0x40);
+			if (post_on_event && aqt->mbhc)
+				blocking_notifier_call_chain(
+						&aqt->mbhc->notifier,
+						post_on_event,
+						&aqt->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_on && aqt->mbhc)
+			blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					post_dapm_on, &aqt->mbhc->wcd_mbhc);
+		break;
+	case MICB_DISABLE:
+		if (aqt->micb_ref > 0)
+			aqt->micb_ref--;
+		if ((aqt->micb_ref == 0) &&
+		    (aqt->pullup_ref > 0))
+			snd_soc_component_update_bits(component, micb_reg,
+						      0xC0, 0x80);
+		else if ((aqt->micb_ref == 0) &&
+			 (aqt->pullup_ref == 0)) {
+			if (pre_off_event && aqt->mbhc)
+				blocking_notifier_call_chain(
+						&aqt->mbhc->notifier,
+						pre_off_event,
+						&aqt->mbhc->wcd_mbhc);
+			snd_soc_component_update_bits(component, micb_reg,
+						      0xC0, 0x00);
+			if (post_off_event && aqt->mbhc)
+				blocking_notifier_call_chain(
+						&aqt->mbhc->notifier,
+						post_off_event,
+						&aqt->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_off && aqt->mbhc)
+			blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					post_dapm_off, &aqt->mbhc->wcd_mbhc);
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid micbias request: %d\n",
+			__func__, req);
+		ret = -EINVAL;
+		break;
+	};
+
+	if (!ret)
+		dev_dbg(component->dev,
+			"%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
+			__func__, micb_num, aqt->micb_ref, aqt->pullup_ref);
+
+	mutex_unlock(&aqt->micb_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(aqt_micbias_control);
+
+static int __aqt_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+					int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "AQT MIC BIAS1", sizeof("AQT MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/*
+		 * MIC BIAS can also be requested by MBHC,
+		 * so use ref count to handle micbias pullup
+		 * and enable requests
+		 */
+		aqt_micbias_control(component, micb_num, MICB_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* wait for cnp time */
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		aqt_micbias_control(component, micb_num, MICB_DISABLE, true);
+		break;
+	};
+
+	return 0;
+}
+
+static int aqt_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+				      struct snd_kcontrol *kcontrol, int event)
+{
+	return __aqt_codec_enable_micbias(w, event);
+}
+
+static int aqt_codec_enable_i2s_block(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&aqt->i2s_lock);
+	if (++aqt->i2s_users == 1)
+		snd_soc_component_update_bits(component, AQT1000_I2S_I2S_0_CTL,
+					      0x01, 0x01);
+	mutex_unlock(&aqt->i2s_lock);
+
+	return 0;
+}
+
+static int aqt_codec_disable_i2s_block(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&aqt->i2s_lock);
+	if (--aqt->i2s_users == 0)
+		snd_soc_component_update_bits(component, AQT1000_I2S_I2S_0_CTL,
+					      0x01, 0x00);
+
+	if (aqt->i2s_users < 0)
+		dev_warn(component->dev, "%s: i2s_users count (%d) < 0\n",
+			 __func__, aqt->i2s_users);
+	mutex_unlock(&aqt->i2s_lock);
+
+	return 0;
+}
+
+static int aqt_codec_enable_i2s_tx(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:
+		aqt_codec_enable_i2s_block(component);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		aqt_codec_disable_i2s_block(component);
+		break;
+	}
+	dev_dbg(component->dev, "%s: event: %d\n", __func__, event);
+
+	return 0;
+}
+
+static int aqt_codec_enable_i2s_rx(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:
+		aqt_codec_enable_i2s_block(component);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		aqt_codec_disable_i2s_block(component);
+		break;
+	}
+	dev_dbg(component->dev, "%s: event: %d\n", __func__, event);
+
+	return 0;
+}
+
+static const char * const tx_mux_text[] = {
+	"ZERO", "DEC_L", "DEC_R", "DEC_V",
+};
+AQT_DAPM_ENUM(tx0, AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0, 0, tx_mux_text);
+AQT_DAPM_ENUM(tx1, AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0, 2, tx_mux_text);
+
+static const char * const tx_adc_mux_text[] = {
+	"AMIC", "ANC_FB0", "ANC_FB1",
+};
+AQT_DAPM_ENUM(tx_adc0, AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
+	      tx_adc_mux_text);
+AQT_DAPM_ENUM(tx_adc1, AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
+	      tx_adc_mux_text);
+AQT_DAPM_ENUM(tx_adc2, AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
+	      tx_adc_mux_text);
+
+static int aqt_find_amic_input(struct snd_soc_component *component,
+			       int adc_mux_n)
+{
+	u8 mask;
+	u16 adc_mux_in_reg = 0, amic_mux_sel_reg = 0;
+	bool is_amic;
+
+	if (adc_mux_n > 2)
+		return 0;
+
+	if (adc_mux_n < 3) {
+		adc_mux_in_reg = AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+				 adc_mux_n;
+		mask = 0x03;
+		amic_mux_sel_reg = AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+				   2 * adc_mux_n;
+	}
+	is_amic = (
+		((snd_soc_component_read32(component, adc_mux_in_reg)
+		  & mask)) == 0);
+	if (!is_amic)
+		return 0;
+
+	return snd_soc_component_read32(component, amic_mux_sel_reg) & 0x07;
+}
+
+static u16 aqt_codec_get_amic_pwlvl_reg(
+		struct snd_soc_component *component, int amic)
+{
+	u16 pwr_level_reg = 0;
+
+	switch (amic) {
+	case 1:
+	case 2:
+		pwr_level_reg = AQT1000_ANA_AMIC1;
+		break;
+	case 3:
+		pwr_level_reg = AQT1000_ANA_AMIC3;
+		break;
+	default:
+		dev_dbg(component->dev, "%s: invalid amic: %d\n",
+			__func__, amic);
+		break;
+	}
+
+	return pwr_level_reg;
+}
+
+static void aqt_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct aqt1000 *aqt;
+	struct snd_soc_component *component;
+	u16 dec_cfg_reg, amic_reg, go_bit_reg;
+	u8 hpf_cut_off_freq;
+	int amic_n;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	aqt = hpf_work->aqt;
+	component = aqt->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = AQT1000_CDC_TX0_TX_PATH_CFG0 + 16 * hpf_work->decimator;
+	go_bit_reg = dec_cfg_reg + 7;
+
+	dev_dbg(component->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
+		__func__, hpf_work->decimator, hpf_cut_off_freq);
+
+	amic_n = aqt_find_amic_input(component, hpf_work->decimator);
+	if (amic_n) {
+		amic_reg = AQT1000_ANA_AMIC1 + amic_n - 1;
+		aqt_codec_set_tx_hold(component, amic_reg, false);
+	}
+	snd_soc_component_update_bits(component, dec_cfg_reg,
+			TX_HPF_CUT_OFF_FREQ_MASK,
+			hpf_cut_off_freq << 5);
+	snd_soc_component_update_bits(component, go_bit_reg, 0x02, 0x02);
+	/* Minimum 1 clk cycle delay is required as per HW spec */
+	usleep_range(1000, 1010);
+	snd_soc_component_update_bits(component, go_bit_reg, 0x02, 0x00);
+}
+
+static void aqt_tx_mute_update_callback(struct work_struct *work)
+{
+	struct tx_mute_work *tx_mute_dwork;
+	struct aqt1000 *aqt;
+	struct delayed_work *delayed_work;
+	struct snd_soc_component *component;
+	u16 tx_vol_ctl_reg, hpf_gate_reg;
+
+	delayed_work = to_delayed_work(work);
+	tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
+	aqt = tx_mute_dwork->aqt;
+	component = aqt->component;
+
+	tx_vol_ctl_reg = AQT1000_CDC_TX0_TX_PATH_CTL +
+			 16 * tx_mute_dwork->decimator;
+	hpf_gate_reg = AQT1000_CDC_TX0_TX_PATH_SEC2 +
+		       16 * tx_mute_dwork->decimator;
+	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
+}
+
+static int aqt_codec_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);
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	char *widget_name = NULL;
+	char *dec = NULL;
+	unsigned int decimator = 0;
+	u8 amic_n = 0;
+	u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
+	u16 tx_gain_ctl_reg;
+	int ret = 0;
+	u8 hpf_cut_off_freq;
+
+	dev_dbg(component->dev, "%s: event: %d\n", __func__, event);
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+
+	dec = strpbrk(widget_name, "012");
+	if (!dec) {
+		dev_err(component->dev, "%s: decimator index not found\n",
+			__func__);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(dec, 10, &decimator);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid decimator = %s\n",
+			__func__, widget_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+	dev_dbg(component->dev, "%s(): widget = %s decimator = %u\n", __func__,
+			w->name, decimator);
+
+	tx_vol_ctl_reg = AQT1000_CDC_TX0_TX_PATH_CTL + 16 * decimator;
+	hpf_gate_reg = AQT1000_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
+	dec_cfg_reg = AQT1000_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
+	tx_gain_ctl_reg = AQT1000_CDC_TX0_TX_VOL_CTL + 16 * decimator;
+
+	amic_n = aqt_find_amic_input(component, decimator);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (amic_n)
+			pwr_level_reg = aqt_codec_get_amic_pwlvl_reg(component,
+								     amic_n);
+		if (pwr_level_reg) {
+			switch ((snd_soc_component_read32(
+					component, pwr_level_reg) &
+					AQT1000_AMIC_PWR_LVL_MASK) >>
+					AQT1000_AMIC_PWR_LVL_SHIFT) {
+			case AQT1000_AMIC_PWR_LEVEL_LP:
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						AQT1000_DEC_PWR_LVL_MASK,
+						AQT1000_DEC_PWR_LVL_LP);
+				break;
+
+			case AQT1000_AMIC_PWR_LEVEL_HP:
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						AQT1000_DEC_PWR_LVL_MASK,
+						AQT1000_DEC_PWR_LVL_HP);
+				break;
+			case AQT1000_AMIC_PWR_LEVEL_DEFAULT:
+			default:
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						AQT1000_DEC_PWR_LVL_MASK,
+						AQT1000_DEC_PWR_LVL_DF);
+				break;
+			}
+		}
+		/* Enable TX PGA Mute */
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					      0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		hpf_cut_off_freq = (snd_soc_component_read32(
+				    component, dec_cfg_reg) &
+				    TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+
+		aqt->tx_hpf_work[decimator].hpf_cut_off_freq =
+							hpf_cut_off_freq;
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					    TX_HPF_CUT_OFF_FREQ_MASK,
+					    CF_MIN_3DB_150HZ << 5);
+			snd_soc_component_update_bits(component, hpf_gate_reg,
+						      0x02, 0x02);
+			/*
+			 * Minimum 1 clk cycle delay is required as per
+			 * HW spec.
+			 */
+			usleep_range(1000, 1010);
+			snd_soc_component_update_bits(component, hpf_gate_reg,
+						      0x02, 0x00);
+		}
+		/* schedule work queue to Remove Mute */
+		schedule_delayed_work(&aqt->tx_mute_dwork[decimator].dwork,
+				      msecs_to_jiffies(tx_unmute_delay));
+		if (aqt->tx_hpf_work[decimator].hpf_cut_off_freq !=
+							CF_MIN_3DB_150HZ)
+			schedule_delayed_work(
+					&aqt->tx_hpf_work[decimator].dwork,
+					msecs_to_jiffies(300));
+		/* apply gain after decimator is enabled */
+		snd_soc_component_write(component, tx_gain_ctl_reg,
+			      snd_soc_component_read32(
+					component, tx_gain_ctl_reg));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			aqt->tx_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					      0x10, 0x10);
+		if (cancel_delayed_work_sync(
+		    &aqt->tx_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						hpf_cut_off_freq << 5);
+				snd_soc_component_update_bits(
+						component, hpf_gate_reg,
+						0x02, 0x02);
+				/*
+				 * Minimum 1 clk cycle delay is required as per
+				 * HW spec.
+				 */
+				usleep_range(1000, 1010);
+				snd_soc_component_update_bits(
+						component, hpf_gate_reg,
+						0x02, 0x00);
+			}
+		}
+		cancel_delayed_work_sync(
+				&aqt->tx_mute_dwork[decimator].dwork);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					      0x10, 0x00);
+		snd_soc_component_update_bits(component, dec_cfg_reg,
+				    AQT1000_DEC_PWR_LVL_MASK,
+				    AQT1000_DEC_PWR_LVL_DF);
+		break;
+	}
+
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+static const char * const tx_amic_text[] = {
+	"ZERO", "ADC_L", "ADC_R", "ADC_V",
+};
+AQT_DAPM_ENUM(tx_amic0, AQT1000_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0, tx_amic_text);
+AQT_DAPM_ENUM(tx_amic1, AQT1000_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0, tx_amic_text);
+AQT_DAPM_ENUM(tx_amic2, AQT1000_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0, tx_amic_text);
+
+AQT_DAPM_ENUM(tx_amic10, AQT1000_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 0,
+	      tx_amic_text);
+AQT_DAPM_ENUM(tx_amic11, AQT1000_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 0,
+	      tx_amic_text);
+AQT_DAPM_ENUM(tx_amic12, AQT1000_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 0,
+	      tx_amic_text);
+AQT_DAPM_ENUM(tx_amic13, AQT1000_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 0,
+	      tx_amic_text);
+
+static int aqt_codec_enable_adc(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:
+		aqt_codec_set_tx_hold(component, w->reg, true);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new anc_hphl_pa_switch =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
+
+static const struct snd_kcontrol_new anc_hphr_pa_switch =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
+
+static int aqt_config_compander(struct snd_soc_component *component,
+				int interp_n, int event)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int comp;
+	u16 comp_ctl0_reg, rx_path_cfg0_reg;
+
+	comp = interp_n;
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp, aqt->comp_enabled[comp]);
+
+	if (!aqt->comp_enabled[comp])
+		return 0;
+
+	comp_ctl0_reg = AQT1000_CDC_COMPANDER1_CTL0 + (comp * 8);
+	rx_path_cfg0_reg = AQT1000_CDC_RX1_RX_PATH_CFG0 + (comp * 20);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x01, 0x01);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x02, 0x02);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x02, 0x00);
+		snd_soc_component_update_bits(
+				component, rx_path_cfg0_reg, 0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(
+				component, rx_path_cfg0_reg, 0x02, 0x00);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x04, 0x04);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x02, 0x02);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x02, 0x00);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x01, 0x00);
+		snd_soc_component_update_bits(
+				component, comp_ctl0_reg, 0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static void aqt_codec_idle_detect_control(struct snd_soc_component *component,
+					    int interp, int event)
+{
+	int reg = 0, mask, val;
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	if (!aqt->idle_det_cfg.hph_idle_detect_en)
+		return;
+
+	if (interp == INTERP_HPHL) {
+		reg = AQT1000_CDC_RX_IDLE_DET_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == INTERP_HPHR) {
+		reg = AQT1000_CDC_RX_IDLE_DET_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event))
+		snd_soc_component_update_bits(component, reg, mask, val);
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		aqt->idle_det_cfg.hph_idle_thr = 0;
+		snd_soc_component_write(component,
+				AQT1000_CDC_RX_IDLE_DET_CFG3, 0x0);
+	}
+}
+
+static void aqt_codec_hphdelay_lutbypass(struct snd_soc_component *component,
+				    u16 interp_idx, int event)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	u8 hph_dly_mask;
+	u16 hph_lut_bypass_reg = 0;
+	u16 hph_comp_ctrl7 = 0;
+
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hph_dly_mask = 1;
+		hph_lut_bypass_reg = AQT1000_CDC_TOP_HPHL_COMP_LUT;
+		hph_comp_ctrl7 = AQT1000_CDC_COMPANDER1_CTL7;
+		break;
+	case INTERP_HPHR:
+		hph_dly_mask = 2;
+		hph_lut_bypass_reg = AQT1000_CDC_TOP_HPHR_COMP_LUT;
+		hph_comp_ctrl7 = AQT1000_CDC_COMPANDER2_CTL7;
+		break;
+	default:
+		break;
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, AQT1000_CDC_CLSH_TEST0,
+				hph_dly_mask, 0x0);
+		snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+				0x80, 0x80);
+		if (aqt->hph_mode == CLS_H_ULP)
+			snd_soc_component_update_bits(component, hph_comp_ctrl7,
+				0x20, 0x20);
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, AQT1000_CDC_CLSH_TEST0,
+				hph_dly_mask, hph_dly_mask);
+		snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component, hph_comp_ctrl7,
+				0x20, 0x0);
+	}
+}
+
+static int aqt_codec_enable_interp_clk(struct snd_soc_component *component,
+				       int event, int interp_idx)
+{
+	struct aqt1000 *aqt;
+	u16 main_reg, dsm_reg;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	aqt = snd_soc_component_get_drvdata(component);
+	main_reg = AQT1000_CDC_RX1_RX_PATH_CTL + (interp_idx * 20);
+	dsm_reg = AQT1000_CDC_RX1_RX_PATH_DSMDEM_CTL + (interp_idx * 20);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (aqt->main_clk_users[interp_idx] == 0) {
+			/* Main path PGA mute enable */
+			snd_soc_component_update_bits(component, main_reg,
+						0x10, 0x10);
+			/* Clk enable */
+			snd_soc_component_update_bits(component, dsm_reg,
+						0x01, 0x01);
+			snd_soc_component_update_bits(component, main_reg,
+						0x20, 0x20);
+			aqt_codec_idle_detect_control(component, interp_idx,
+							event);
+			aqt_codec_hphdelay_lutbypass(component, interp_idx,
+						       event);
+			aqt_config_compander(component, interp_idx, event);
+		}
+		aqt->main_clk_users[interp_idx]++;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		aqt->main_clk_users[interp_idx]--;
+		if (aqt->main_clk_users[interp_idx] <= 0) {
+			aqt->main_clk_users[interp_idx] = 0;
+			aqt_config_compander(component, interp_idx, event);
+			aqt_codec_hphdelay_lutbypass(component, interp_idx,
+						       event);
+			aqt_codec_idle_detect_control(component, interp_idx,
+							event);
+			/* Clk Disable */
+			snd_soc_component_update_bits(component, main_reg,
+						0x20, 0x00);
+			snd_soc_component_update_bits(component, dsm_reg,
+						0x01, 0x00);
+			/* Reset enable and disable */
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x40);
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x00);
+			/* Reset rate to 48K*/
+			snd_soc_component_update_bits(component, main_reg,
+						0x0F, 0x04);
+		}
+	}
+
+	dev_dbg(component->dev, "%s event %d main_clk_users %d\n",
+		__func__,  event, aqt->main_clk_users[interp_idx]);
+
+	return aqt->main_clk_users[interp_idx];
+}
+
+static int aqt_anc_out_switch_cb(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	aqt_codec_enable_interp_clk(component, event, w->shift);
+
+	return 0;
+}
+
+static const char * const anc0_fb_mux_text[] = {
+	"ZERO", "ANC_IN_HPHL",
+};
+
+static const char * const anc1_fb_mux_text[] = {
+	"ZERO", "ANC_IN_HPHR",
+};
+
+AQT_DAPM_ENUM(anc0_fb, AQT1000_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
+AQT_DAPM_ENUM(anc1_fb, AQT1000_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
+
+static const char *const rx_int1_1_mux_text[] = {
+	"ZERO", "MAIN_DMA_L", "I2S0_L", "I2S0_R", "DEC_L", "DEC_R", "DEC_V",
+	"SHADOW_I2S0_L", "MAIN_DMA_R"
+};
+
+static const char *const rx_int1_2_mux_text[] = {
+	"ZERO", "MIX_DMA_L", "I2S0_L", "I2S0_R", "DEC_L", "DEC_R", "DEC_V",
+	"IIR0", "MIX_DMA_R"
+};
+
+static const char *const rx_int2_1_mux_text[] = {
+	"ZERO", "MAIN_DMA_R", "I2S0_L", "I2S0_R", "DEC_L", "DEC_R", "DEC_V",
+	"SHADOW_I2S0_R", "MAIN_DMA_L"
+};
+
+static const char *const rx_int2_2_mux_text[] = {
+	"ZERO", "MIX_DMA_R", "I2S0_L", "I2S0_R", "DEC_L", "DEC_R", "DEC_V",
+	"IIR0", "MIX_DMA_L"
+};
+
+AQT_DAPM_ENUM(rx_int1_1, AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
+		rx_int1_1_mux_text);
+AQT_DAPM_ENUM(rx_int1_2, AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
+		rx_int1_2_mux_text);
+AQT_DAPM_ENUM(rx_int2_1, AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
+		rx_int2_1_mux_text);
+AQT_DAPM_ENUM(rx_int2_2, AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
+		rx_int2_2_mux_text);
+
+static int aqt_codec_set_idle_detect_thr(struct snd_soc_component *component,
+					   int interp, int path_type)
+{
+	int port_id[4] = { 0, 0, 0, 0 };
+	int *port_ptr, num_ports;
+	int bit_width = 0;
+	int mux_reg = 0, mux_reg_val = 0;
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int idle_thr;
+
+	if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
+		return 0;
+
+	if (!aqt->idle_det_cfg.hph_idle_detect_en)
+		return 0;
+
+	port_ptr = &port_id[0];
+	num_ports = 0;
+
+	if (path_type == INTERP_MIX_PATH) {
+		if (interp == INTERP_HPHL)
+			mux_reg =  AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG1;
+		else
+			mux_reg = AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG1;
+	}
+
+	if (path_type == INTERP_MAIN_PATH) {
+		if (interp == INTERP_HPHL)
+			mux_reg = AQT1000_CDC_RX_INP_MUX_RX_INT1_CFG0;
+		else
+			mux_reg = AQT1000_CDC_RX_INP_MUX_RX_INT2_CFG0;
+	}
+	mux_reg_val = snd_soc_component_read32(component, mux_reg);
+
+	/* Read bit width from I2S reg if mux is set to I2S0_L or I2S0_R */
+	if (mux_reg_val == 0x02 || mux_reg_val == 0x03)
+		bit_width = ((snd_soc_component_read32(
+				component, AQT1000_I2S_I2S_0_CTL) &
+				0x40) >> 6);
+
+	switch (bit_width) {
+	case 1: /* 16 bit */
+		idle_thr = 0xff; /* F16 */
+		break;
+	case 0: /* 32 bit */
+	default:
+		idle_thr = 0x03; /* F22 */
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
+		__func__, idle_thr, aqt->idle_det_cfg.hph_idle_thr);
+
+	if ((aqt->idle_det_cfg.hph_idle_thr == 0) ||
+	    (idle_thr < aqt->idle_det_cfg.hph_idle_thr)) {
+		snd_soc_component_write(component, AQT1000_CDC_RX_IDLE_DET_CFG3,
+					idle_thr);
+		aqt->idle_det_cfg.hph_idle_thr = idle_thr;
+	}
+
+	return 0;
+}
+
+static int aqt_codec_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 = 0;
+	int val = 0;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (w->shift >= AQT1000_NUM_INTERPOLATORS) {
+		dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	};
+
+	gain_reg = AQT1000_CDC_RX1_RX_VOL_CTL + (w->shift *
+						 AQT1000_RX_PATH_CTL_OFFSET);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		aqt_codec_enable_interp_clk(component, event, w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		aqt_codec_set_idle_detect_thr(component, w->shift,
+						INTERP_MAIN_PATH);
+		/* apply gain after int clk is enabled */
+		val = snd_soc_component_read32(component, gain_reg);
+		snd_soc_component_write(component, gain_reg, val);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		aqt_codec_enable_interp_clk(component, event, w->shift);
+		break;
+	};
+
+	return 0;
+}
+
+static int aqt_codec_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 = 0;
+	u16 mix_reg = 0;
+
+	if (w->shift >= AQT1000_NUM_INTERPOLATORS) {
+		dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	};
+	gain_reg = AQT1000_CDC_RX1_RX_VOL_MIX_CTL +
+					(w->shift * AQT1000_RX_PATH_CTL_OFFSET);
+	mix_reg = AQT1000_CDC_RX1_RX_PATH_MIX_CTL +
+					(w->shift * AQT1000_RX_PATH_CTL_OFFSET);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		aqt_codec_enable_interp_clk(component, event, w->shift);
+		/* Clk enable */
+		snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		aqt_codec_set_idle_detect_thr(component, w->shift,
+						INTERP_MIX_PATH);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Clk Disable */
+		snd_soc_component_update_bits(component, mix_reg, 0x20, 0x00);
+		aqt_codec_enable_interp_clk(component, event, w->shift);
+		/* Reset enable and disable */
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00);
+
+		break;
+	};
+	dev_dbg(component->dev, "%s event %d name %s\n", __func__,
+		event, w->name);
+
+	return 0;
+}
+
+static const char * const rx_int1_1_interp_mux_text[] = {
+	"ZERO", "RX INT1_1 MUX",
+};
+
+static const char * const rx_int2_1_interp_mux_text[] = {
+	"ZERO", "RX INT2_1 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",
+};
+
+AQT_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0, rx_int1_1_interp_mux_text);
+AQT_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0, rx_int2_1_interp_mux_text);
+
+AQT_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0, rx_int1_2_interp_mux_text);
+AQT_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0, rx_int2_2_interp_mux_text);
+
+static const char * const asrc0_mux_text[] = {
+	"ZERO", "ASRC_IN_HPHL",
+};
+
+static const char * const asrc1_mux_text[] = {
+	"ZERO", "ASRC_IN_HPHR",
+};
+
+AQT_DAPM_ENUM(asrc0, AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 0,
+	asrc0_mux_text);
+AQT_DAPM_ENUM(asrc1, AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 2,
+	asrc1_mux_text);
+
+static int aqt_get_asrc_mode(struct aqt1000 *aqt, int asrc,
+			       u8 main_sr, u8 mix_sr)
+{
+	u8 asrc_output_mode;
+	int asrc_mode = CONV_88P2K_TO_384K;
+
+	if ((asrc < 0) || (asrc >= ASRC_MAX))
+		return 0;
+
+	asrc_output_mode = aqt->asrc_output_mode[asrc];
+
+	if (asrc_output_mode) {
+		/*
+		 * If Mix sample rate is < 96KHz, use 96K to 352.8K
+		 * conversion, or else use 384K to 352.8K conversion
+		 */
+		if (mix_sr < 5)
+			asrc_mode = CONV_96K_TO_352P8K;
+		else
+			asrc_mode = CONV_384K_TO_352P8K;
+	} else {
+		/* Integer main and Fractional mix path */
+		if (main_sr < 8 && mix_sr > 9) {
+			asrc_mode = CONV_352P8K_TO_384K;
+		} else if (main_sr > 8 && mix_sr < 8) {
+			/* Fractional main and Integer mix path */
+			if (mix_sr < 5)
+				asrc_mode = CONV_96K_TO_352P8K;
+			else
+				asrc_mode = CONV_384K_TO_352P8K;
+		} else if (main_sr < 8 && mix_sr < 8) {
+			/* Integer main and Integer mix path */
+			asrc_mode = CONV_96K_TO_384K;
+		}
+	}
+
+	return asrc_mode;
+}
+
+static int aqt_codec_enable_asrc_resampler(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int asrc = 0, ret = 0;
+	u8 cfg;
+	u16 cfg_reg = 0;
+	u16 ctl_reg = 0;
+	u16 clk_reg = 0;
+	u16 asrc_ctl = 0;
+	u16 mix_ctl_reg = 0;
+	u16 paired_reg = 0;
+	u8 main_sr, mix_sr, asrc_mode = 0;
+
+	cfg = snd_soc_component_read32(component,
+			AQT1000_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0);
+	if (!(cfg & 0xFF)) {
+		dev_err(component->dev, "%s: ASRC%u input not selected\n",
+			__func__, w->shift);
+		return -EINVAL;
+	}
+
+	switch (w->shift) {
+	case ASRC0:
+		if ((cfg & 0x03) == 0x01) {
+			cfg_reg = AQT1000_CDC_RX1_RX_PATH_CFG0;
+			ctl_reg = AQT1000_CDC_RX1_RX_PATH_CTL;
+			clk_reg = AQT1000_MIXING_ASRC0_CLK_RST_CTL;
+			paired_reg = AQT1000_MIXING_ASRC1_CLK_RST_CTL;
+			asrc_ctl = AQT1000_MIXING_ASRC0_CTL1;
+		}
+		break;
+	case ASRC1:
+		if ((cfg & 0x0C) == 0x4) {
+			cfg_reg = AQT1000_CDC_RX2_RX_PATH_CFG0;
+			ctl_reg = AQT1000_CDC_RX2_RX_PATH_CTL;
+			clk_reg = AQT1000_MIXING_ASRC1_CLK_RST_CTL;
+			paired_reg = AQT1000_MIXING_ASRC0_CLK_RST_CTL;
+			asrc_ctl = AQT1000_MIXING_ASRC1_CTL1;
+		}
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid asrc:%u\n", __func__,
+			w->shift);
+		ret = -EINVAL;
+		break;
+	};
+
+	if ((cfg_reg == 0) || (ctl_reg == 0) || (clk_reg == 0) ||
+		 (asrc_ctl == 0) || ret)
+		goto done;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if ((snd_soc_component_read32(component, clk_reg) & 0x02) ||
+		    (snd_soc_component_read32(component, paired_reg) & 0x02)) {
+			snd_soc_component_update_bits(component, clk_reg,
+					0x02, 0x00);
+			snd_soc_component_update_bits(component, paired_reg,
+					0x02, 0x00);
+		}
+		snd_soc_component_update_bits(component, cfg_reg, 0x80, 0x80);
+		snd_soc_component_update_bits(component, clk_reg, 0x01, 0x01);
+		main_sr = snd_soc_component_read32(component, ctl_reg) & 0x0F;
+		mix_ctl_reg = ctl_reg + 5;
+		mix_sr = snd_soc_component_read32(
+				component, mix_ctl_reg) & 0x0F;
+		asrc_mode = aqt_get_asrc_mode(aqt, asrc,
+						main_sr, mix_sr);
+		dev_dbg(component->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
+			__func__, main_sr, mix_sr, asrc_mode);
+		snd_soc_component_update_bits(
+				component, asrc_ctl, 0x07, asrc_mode);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, asrc_ctl, 0x07, 0x00);
+		snd_soc_component_update_bits(component, cfg_reg, 0x80, 0x00);
+		snd_soc_component_update_bits(component, clk_reg, 0x03, 0x02);
+		break;
+	};
+
+done:
+	return ret;
+}
+
+static int aqt_codec_enable_anc(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	const char *filename;
+	const struct firmware *fw;
+	int i;
+	int ret = 0;
+	int num_anc_slots;
+	struct aqt1000_anc_header *anc_head;
+	struct firmware_cal *hwdep_cal = NULL;
+	u32 anc_writes_size = 0;
+	u32 anc_cal_size = 0;
+	int anc_size_remaining;
+	u32 *anc_ptr;
+	u16 reg;
+	u8 mask, val;
+	size_t cal_size;
+	const void *data;
+
+	if (!aqt->anc_func)
+		return 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		hwdep_cal = wcdcal_get_fw_cal(aqt->fw_data, WCD9XXX_ANC_CAL);
+		if (hwdep_cal) {
+			data = hwdep_cal->data;
+			cal_size = hwdep_cal->size;
+			dev_dbg(component->dev, "%s: using hwdep calibration, cal_size %zd",
+				__func__, cal_size);
+		} else {
+			filename = "AQT1000/AQT1000_anc.bin";
+			ret = request_firmware(&fw, filename, component->dev);
+			if (ret < 0) {
+				dev_err(component->dev, "%s: Failed to acquire ANC data: %d\n",
+					__func__, ret);
+				return ret;
+			}
+			if (!fw) {
+				dev_err(component->dev, "%s: Failed to get anc fw\n",
+					__func__);
+				return -ENODEV;
+			}
+			data = fw->data;
+			cal_size = fw->size;
+			dev_dbg(component->dev, "%s: using request_firmware calibration\n",
+				__func__);
+		}
+		if (cal_size < sizeof(struct aqt1000_anc_header)) {
+			dev_err(component->dev, "%s: Invalid cal_size %zd\n",
+				__func__, cal_size);
+			ret = -EINVAL;
+			goto err;
+		}
+		/* First number is the number of register writes */
+		anc_head = (struct aqt1000_anc_header *)(data);
+		anc_ptr = (u32 *)(data + sizeof(struct aqt1000_anc_header));
+		anc_size_remaining = cal_size -
+				     sizeof(struct aqt1000_anc_header);
+		num_anc_slots = anc_head->num_anc_slots;
+
+		if (aqt->anc_slot >= num_anc_slots) {
+			dev_err(component->dev, "%s: Invalid ANC slot selected\n",
+				__func__);
+			ret = -EINVAL;
+			goto err;
+		}
+		for (i = 0; i < num_anc_slots; i++) {
+			if (anc_size_remaining < AQT1000_PACKED_REG_SIZE) {
+				dev_err(component->dev, "%s: Invalid register format\n",
+					__func__);
+				ret = -EINVAL;
+				goto err;
+			}
+			anc_writes_size = (u32)(*anc_ptr);
+			anc_size_remaining -= sizeof(u32);
+			anc_ptr += 1;
+
+			if ((anc_writes_size * AQT1000_PACKED_REG_SIZE) >
+			    anc_size_remaining) {
+				dev_err(component->dev, "%s: Invalid register format\n",
+					__func__);
+				ret = -EINVAL;
+				goto err;
+			}
+
+			if (aqt->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				AQT1000_PACKED_REG_SIZE);
+			anc_ptr += anc_writes_size;
+		}
+		if (i == num_anc_slots) {
+			dev_err(component->dev, "%s: Selected ANC slot not present\n",
+				__func__);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		i = 0;
+		anc_cal_size = anc_writes_size;
+		/* Rate converter clk enable and set bypass mode */
+		if (!strcmp(w->name, "AQT RX INT1 DAC")) {
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_ANC0_RC_COMMON_CTL,
+					    0x05, 0x05);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_FIFO_COMMON_CTL,
+					0x66, 0x66);
+			anc_writes_size = anc_cal_size / 2;
+			snd_soc_component_update_bits(component,
+				AQT1000_CDC_ANC0_CLK_RESET_CTL, 0x39, 0x39);
+		} else if (!strcmp(w->name, "AQT RX INT2 DAC")) {
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_ANC1_RC_COMMON_CTL,
+					    0x05, 0x05);
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_ANC1_FIFO_COMMON_CTL,
+					    0x66, 0x66);
+			i = anc_cal_size / 2;
+			snd_soc_component_update_bits(component,
+				AQT1000_CDC_ANC1_CLK_RESET_CTL, 0x39, 0x39);
+		}
+
+		for (; i < anc_writes_size; i++) {
+			AQT1000_CODEC_UNPACK_ENTRY(anc_ptr[i], reg, mask, val);
+			snd_soc_component_write(component, reg, (val & mask));
+		}
+		if (!strcmp(w->name, "AQT RX INT1 DAC"))
+			snd_soc_component_update_bits(component,
+				AQT1000_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08);
+		else if (!strcmp(w->name, "AQT RX INT2 DAC"))
+			snd_soc_component_update_bits(component,
+				AQT1000_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08);
+
+		if (!hwdep_cal)
+			release_firmware(fw);
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		/* Remove ANC Rx from reset */
+		snd_soc_component_update_bits(component,
+				    AQT1000_CDC_ANC0_CLK_RESET_CTL,
+				    0x08, 0x00);
+		snd_soc_component_update_bits(component,
+				    AQT1000_CDC_ANC1_CLK_RESET_CTL,
+				    0x08, 0x00);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_ANC0_RC_COMMON_CTL,
+				0x05, 0x00);
+		if (!strcmp(w->name, "AQT ANC HPHL PA")) {
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_MODE_1_CTL,
+					0x30, 0x00);
+			/* 50 msec sleep is needed to avoid click and pop as
+			 * per HW requirement
+			 */
+			msleep(50);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_MODE_1_CTL,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_CLK_RESET_CTL,
+					0x38, 0x38);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_CLK_RESET_CTL,
+					0x07, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC0_CLK_RESET_CTL,
+					0x38, 0x00);
+		} else if (!strcmp(w->name, "AQT ANC HPHR PA")) {
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC1_MODE_1_CTL,
+					0x30, 0x00);
+			/* 50 msec sleep is needed to avoid click and pop as
+			 * per HW requirement
+			 */
+			msleep(50);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC1_MODE_1_CTL,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC1_CLK_RESET_CTL,
+					0x38, 0x38);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC1_CLK_RESET_CTL,
+					0x07, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_ANC1_CLK_RESET_CTL,
+					0x38, 0x00);
+		}
+		break;
+	}
+
+	return 0;
+err:
+	if (!hwdep_cal)
+		release_firmware(fw);
+	return ret;
+}
+
+static void aqt_codec_override(struct snd_soc_component *component, int mode,
+				 int event)
+{
+	if (mode == CLS_AB || mode == CLS_AB_HIFI) {
+		switch (event) {
+		case SND_SOC_DAPM_PRE_PMU:
+		case SND_SOC_DAPM_POST_PMU:
+			snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES, 0x02, 0x02);
+		break;
+		case SND_SOC_DAPM_POST_PMD:
+			snd_soc_component_update_bits(component,
+				AQT1000_ANA_RX_SUPPLIES, 0x02, 0x00);
+		break;
+		}
+	}
+}
+
+static void aqt_codec_set_tx_hold(struct snd_soc_component *component,
+				    u16 amic_reg, bool set)
+{
+	u8 mask = 0x20;
+	u8 val;
+
+	if (amic_reg == AQT1000_ANA_AMIC1 ||
+	    amic_reg == AQT1000_ANA_AMIC3)
+		mask = 0x40;
+
+	val = set ? mask : 0x00;
+
+	switch (amic_reg) {
+	case AQT1000_ANA_AMIC1:
+	case AQT1000_ANA_AMIC2:
+		snd_soc_component_update_bits(component, AQT1000_ANA_AMIC2,
+					mask, val);
+		break;
+	case AQT1000_ANA_AMIC3:
+		snd_soc_component_update_bits(component, AQT1000_ANA_AMIC3_HPF,
+					mask, val);
+		break;
+	default:
+		dev_dbg(component->dev, "%s: invalid amic: %d\n",
+			__func__, amic_reg);
+		break;
+	}
+}
+
+static void aqt_codec_clear_anc_tx_hold(struct aqt1000 *aqt)
+{
+	if (test_and_clear_bit(ANC_MIC_AMIC1, &aqt->status_mask))
+		aqt_codec_set_tx_hold(aqt->component, AQT1000_ANA_AMIC1, false);
+	if (test_and_clear_bit(ANC_MIC_AMIC2, &aqt->status_mask))
+		aqt_codec_set_tx_hold(aqt->component, AQT1000_ANA_AMIC2, false);
+	if (test_and_clear_bit(ANC_MIC_AMIC3, &aqt->status_mask))
+		aqt_codec_set_tx_hold(aqt->component, AQT1000_ANA_AMIC3, false);
+}
+
+static const char * const rx_int_dem_inp_mux_text[] = {
+	"NORMAL_DSM_OUT", "CLSH_DSM_OUT",
+};
+
+static int aqt_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 int val;
+	unsigned short look_ahead_dly_reg = AQT1000_CDC_RX1_RX_PATH_CFG0;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val >= e->items)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	if (e->reg == AQT1000_CDC_RX1_RX_PATH_SEC0)
+		look_ahead_dly_reg = AQT1000_CDC_RX1_RX_PATH_CFG0;
+	else if (e->reg == AQT1000_CDC_RX2_RX_PATH_SEC0)
+		look_ahead_dly_reg = AQT1000_CDC_RX2_RX_PATH_CFG0;
+
+	/* Set Look Ahead Delay */
+	snd_soc_component_update_bits(component, look_ahead_dly_reg,
+			    0x08, (val ? 0x08 : 0x00));
+	/* Set DEM INP Select */
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+AQT_DAPM_ENUM_EXT(rx_int1_dem, AQT1000_CDC_RX1_RX_PATH_SEC0, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	aqt_int_dem_inp_mux_put);
+AQT_DAPM_ENUM_EXT(rx_int2_dem, AQT1000_CDC_RX2_RX_PATH_SEC0, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	aqt_int_dem_inp_mux_put);
+
+static int aqt_codec_hphl_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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int hph_mode = aqt->hph_mode;
+	u8 dem_inp;
+	int ret = 0;
+	uint32_t impedl = 0;
+	uint32_t impedr = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d hph_mode: %d\n",
+		__func__, w->name, event, hph_mode);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (aqt->anc_func) {
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+			/* 40 msec delay is needed to avoid click and pop */
+			msleep(40);
+		}
+		/* Read DEM INP Select */
+		dem_inp = snd_soc_component_read32(
+				component, AQT1000_CDC_RX1_RX_PATH_SEC0) &
+				0x03;
+		if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+		     (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+			dev_err(component->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
+					__func__, hph_mode);
+			return -EINVAL;
+		}
+		/* Disable AutoChop timer during power up */
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_NEW_INT_HPH_TIMER1,
+					0x02, 0x00);
+
+		aqt_clsh_fsm(component, &aqt->clsh_d,
+			     AQT_CLSH_EVENT_PRE_DAC,
+			     AQT_CLSH_STATE_HPHL,
+			     hph_mode);
+
+		if (aqt->anc_func)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX1_RX_PATH_CFG0,
+					    0x10, 0x10);
+
+		ret = aqt_mbhc_get_impedance(aqt->mbhc,
+					       &impedl, &impedr);
+		if (!ret) {
+			aqt_clsh_imped_config(component, impedl, false);
+			set_bit(CLSH_Z_CONFIG, &aqt->status_mask);
+		} else {
+			dev_dbg(component->dev, "%s: Failed to get mbhc impedance %d\n",
+				__func__, ret);
+			ret = 0;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 1000us required as per HW requirement */
+		usleep_range(1000, 1100);
+		aqt_clsh_fsm(component, &aqt->clsh_d,
+			     AQT_CLSH_EVENT_POST_PA,
+			     AQT_CLSH_STATE_HPHL,
+			     hph_mode);
+		if (test_bit(CLSH_Z_CONFIG, &aqt->status_mask)) {
+			aqt_clsh_imped_config(component, impedl, true);
+			clear_bit(CLSH_Z_CONFIG, &aqt->status_mask);
+		}
+		break;
+	default:
+		break;
+	};
+
+	return ret;
+}
+
+static int aqt_codec_hphr_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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int hph_mode = aqt->hph_mode;
+	u8 dem_inp;
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d hph_mode: %d\n",
+		__func__, w->name, event, hph_mode);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (aqt->anc_func) {
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+			/* 40 msec delay is needed to avoid click and pop */
+			msleep(40);
+		}
+		/* Read DEM INP Select */
+		dem_inp = snd_soc_component_read32(
+				component, AQT1000_CDC_RX2_RX_PATH_SEC0) &
+				0x03;
+		if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+		     (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+			dev_err(component->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
+					__func__, hph_mode);
+			return -EINVAL;
+		}
+		/* Disable AutoChop timer during power up */
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_NEW_INT_HPH_TIMER1,
+					0x02, 0x00);
+		aqt_clsh_fsm(component, &aqt->clsh_d,
+			     AQT_CLSH_EVENT_PRE_DAC,
+			     AQT_CLSH_STATE_HPHR,
+			     hph_mode);
+		if (aqt->anc_func)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 1000us required as per HW requirement */
+		usleep_range(1000, 1100);
+		aqt_clsh_fsm(component, &aqt->clsh_d,
+			     AQT_CLSH_EVENT_POST_PA,
+			     AQT_CLSH_STATE_HPHR,
+			     hph_mode);
+		break;
+	default:
+		break;
+	};
+
+	return 0;
+}
+
+static int aqt_codec_enable_hphr_pa(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if ((!(strcmp(w->name, "AQT ANC HPHR PA"))) &&
+		    (test_bit(HPH_PA_DELAY, &aqt->status_mask)))
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_HPH, 0xC0, 0xC0);
+
+		set_bit(HPH_PA_DELAY, &aqt->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if ((!(strcmp(w->name, "AQT ANC HPHR PA")))) {
+			if ((snd_soc_component_read32(
+					component, AQT1000_ANA_HPH) & 0xC0)
+					!= 0xC0)
+				/*
+				 * If PA_EN is not set (potentially in ANC case)
+				 * then do nothing for POST_PMU and let left
+				 * channel handle everything.
+				 */
+				break;
+		}
+		/*
+		 * 7ms sleep is required after PA is enabled as per
+		 * HW requirement. If compander is disabled, then
+		 * 20ms delay is needed.
+		 */
+		if (test_bit(HPH_PA_DELAY, &aqt->status_mask)) {
+			if (!aqt->comp_enabled[COMPANDER_2])
+				usleep_range(20000, 20100);
+			else
+				usleep_range(7000, 7100);
+			clear_bit(HPH_PA_DELAY, &aqt->status_mask);
+		}
+		if (aqt->anc_func) {
+			/* Clear Tx FE HOLD if both PAs are enabled */
+			if ((snd_soc_component_read32(
+					aqt->component, AQT1000_ANA_HPH) &
+					0xC0) == 0xC0)
+				aqt_codec_clear_anc_tx_hold(aqt);
+		}
+
+		snd_soc_component_update_bits(
+				component, AQT1000_HPH_R_TEST, 0x01, 0x01);
+
+		/* Remove mute */
+		snd_soc_component_update_bits(
+					component, AQT1000_CDC_RX2_RX_PATH_CTL,
+					0x10, 0x00);
+		/* Enable GM3 boost */
+		snd_soc_component_update_bits(
+					component, AQT1000_HPH_CNP_WG_CTL,
+					0x80, 0x80);
+		/* Enable AutoChop timer at the end of power up */
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_NEW_INT_HPH_TIMER1,
+					0x02, 0x02);
+		/* Remove mix path mute if it is enabled */
+		if ((snd_soc_component_read32(
+				component, AQT1000_CDC_RX2_RX_PATH_MIX_CTL)) &
+				0x10)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_MIX_CTL,
+					    0x10, 0x00);
+		if (!(strcmp(w->name, "AQT ANC HPHR PA"))) {
+			dev_dbg(component->dev,
+				"%s:Do everything needed for left channel\n",
+				__func__);
+			/* Do everything needed for left channel */
+			snd_soc_component_update_bits(
+						component, AQT1000_HPH_L_TEST,
+						0x01, 0x01);
+
+			/* Remove mute */
+			snd_soc_component_update_bits(component,
+						AQT1000_CDC_RX1_RX_PATH_CTL,
+						0x10, 0x00);
+
+			/* Remove mix path mute if it is enabled */
+			if ((snd_soc_component_read32(component,
+					AQT1000_CDC_RX1_RX_PATH_MIX_CTL)) &
+					0x10)
+				snd_soc_component_update_bits(component,
+					AQT1000_CDC_RX1_RX_PATH_MIX_CTL,
+					0x10, 0x00);
+
+			/* Remove ANC Rx from reset */
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+		}
+		aqt_codec_override(component, aqt->hph_mode, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					     AQT_EVENT_PRE_HPHR_PA_OFF,
+					     &aqt->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_R_TEST, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+					AQT1000_CDC_RX2_RX_PATH_CTL,
+					0x10, 0x10);
+		snd_soc_component_update_bits(component,
+					AQT1000_CDC_RX2_RX_PATH_MIX_CTL,
+					0x10, 0x10);
+		if (!(strcmp(w->name, "AQT ANC HPHR PA")))
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_HPH, 0x40, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/*
+		 * 5ms sleep is required after PA disable. If compander is
+		 * disabled, then 20ms delay is needed after PA disable.
+		 */
+		if (!aqt->comp_enabled[COMPANDER_2])
+			usleep_range(20000, 20100);
+		else
+			usleep_range(5000, 5100);
+		aqt_codec_override(component, aqt->hph_mode, event);
+		blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					     AQT_EVENT_POST_HPHR_PA_OFF,
+					     &aqt->mbhc->wcd_mbhc);
+		if (!(strcmp(w->name, "AQT ANC HPHR PA"))) {
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX2_RX_PATH_CFG0,
+					    0x10, 0x00);
+		}
+		break;
+	};
+
+	return ret;
+}
+
+static int aqt_codec_enable_hphl_pa(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if ((!(strcmp(w->name, "AQT ANC HPHL PA"))) &&
+		    (test_bit(HPH_PA_DELAY, &aqt->status_mask)))
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_HPH,
+					0xC0, 0xC0);
+		set_bit(HPH_PA_DELAY, &aqt->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (!(strcmp(w->name, "AQT ANC HPHL PA"))) {
+			if ((snd_soc_component_read32(
+					component, AQT1000_ANA_HPH) & 0xC0)
+								!= 0xC0)
+				/*
+				 * If PA_EN is not set (potentially in ANC
+				 * case) then do nothing for POST_PMU and
+				 * let right channel handle everything.
+				 */
+				break;
+		}
+		/*
+		 * 7ms sleep is required after PA is enabled as per
+		 * HW requirement. If compander is disabled, then
+		 * 20ms delay is needed.
+		 */
+		if (test_bit(HPH_PA_DELAY, &aqt->status_mask)) {
+			if (!aqt->comp_enabled[COMPANDER_1])
+				usleep_range(20000, 20100);
+			else
+				usleep_range(7000, 7100);
+			clear_bit(HPH_PA_DELAY, &aqt->status_mask);
+		}
+		if (aqt->anc_func) {
+			/* Clear Tx FE HOLD if both PAs are enabled */
+			if ((snd_soc_component_read32(
+					aqt->component, AQT1000_ANA_HPH) &
+					0xC0) == 0xC0)
+				aqt_codec_clear_anc_tx_hold(aqt);
+		}
+
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_L_TEST, 0x01, 0x01);
+		/* Remove Mute on primary path */
+		snd_soc_component_update_bits(component,
+					AQT1000_CDC_RX1_RX_PATH_CTL,
+					0x10, 0x00);
+		/* Enable GM3 boost */
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_CNP_WG_CTL,
+					0x80, 0x80);
+		/* Enable AutoChop timer at the end of power up */
+		snd_soc_component_update_bits(component,
+					AQT1000_HPH_NEW_INT_HPH_TIMER1,
+					0x02, 0x02);
+		/* Remove mix path mute if it is enabled */
+		if ((snd_soc_component_read32(component,
+				AQT1000_CDC_RX1_RX_PATH_MIX_CTL)) &
+				0x10)
+			snd_soc_component_update_bits(component,
+					    AQT1000_CDC_RX1_RX_PATH_MIX_CTL,
+					    0x10, 0x00);
+		if (!(strcmp(w->name, "AQT ANC HPHL PA"))) {
+			dev_dbg(component->dev,
+				"%s:Do everything needed for right channel\n",
+				__func__);
+
+			/* Do everything needed for right channel */
+			snd_soc_component_update_bits(component,
+						AQT1000_HPH_R_TEST,
+						0x01, 0x01);
+
+			/* Remove mute */
+			snd_soc_component_update_bits(component,
+						AQT1000_CDC_RX2_RX_PATH_CTL,
+						0x10, 0x00);
+
+			/* Remove mix path mute if it is enabled */
+			if ((snd_soc_component_read32(component,
+					AQT1000_CDC_RX2_RX_PATH_MIX_CTL)) &
+					0x10)
+				snd_soc_component_update_bits(component,
+						AQT1000_CDC_RX2_RX_PATH_MIX_CTL,
+						0x10, 0x00);
+			/* Remove ANC Rx from reset */
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+		}
+		aqt_codec_override(component, aqt->hph_mode, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					     AQT_EVENT_PRE_HPHL_PA_OFF,
+					     &aqt->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component,
+				AQT1000_HPH_L_TEST, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_RX1_RX_PATH_CTL, 0x10, 0x10);
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_RX1_RX_PATH_MIX_CTL, 0x10, 0x10);
+		if (!(strcmp(w->name, "AQT ANC HPHL PA")))
+			snd_soc_component_update_bits(component,
+					AQT1000_ANA_HPH, 0x80, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/*
+		 * 5ms sleep is required after PA disable. If compander is
+		 * disabled, then 20ms delay is needed after PA disable.
+		 */
+		if (!aqt->comp_enabled[COMPANDER_1])
+			usleep_range(20000, 20100);
+		else
+			usleep_range(5000, 5100);
+		aqt_codec_override(component, aqt->hph_mode, event);
+		blocking_notifier_call_chain(&aqt->mbhc->notifier,
+					     AQT_EVENT_POST_HPHL_PA_OFF,
+					     &aqt->mbhc->wcd_mbhc);
+		if (!(strcmp(w->name, "AQT ANC HPHL PA"))) {
+			ret = aqt_codec_enable_anc(w, kcontrol, event);
+			snd_soc_component_update_bits(component,
+				AQT1000_CDC_RX1_RX_PATH_CFG0, 0x10, 0x00);
+		}
+		break;
+	};
+
+	return ret;
+}
+
+static int aqt_codec_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);
+
+	dev_dbg(component->dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU: /* fall through */
+	case SND_SOC_DAPM_PRE_PMD:
+		if (strnstr(w->name, "AQT IIR0", sizeof("AQT IIR0"))) {
+			snd_soc_component_write(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+			snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
+			snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
+			snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
+			snd_soc_component_read32(component,
+				AQT1000_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
+		}
+		break;
+	}
+	return 0;
+}
+
+static int aqt_enable_native_supply(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 aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (++aqt->native_clk_users == 1) {
+			snd_soc_component_update_bits(component,
+					AQT1000_CLK_SYS_PLL_ENABLES,
+					0x01, 0x01);
+			/* 100usec is needed as per HW requirement */
+			usleep_range(100, 120);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
+					0x02, 0x02);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
+					0x10, 0x10);
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (aqt->native_clk_users &&
+		    (--aqt->native_clk_users == 0)) {
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
+					0x10, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
+					0x02, 0x00);
+			snd_soc_component_update_bits(component,
+					AQT1000_CLK_SYS_PLL_ENABLES,
+					0x01, 0x00);
+		}
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: native_clk_users: %d, event: %d\n",
+		__func__, aqt->native_clk_users, event);
+
+	return 0;
+}
+
+static const char * const native_mux_text[] = {
+	"OFF", "ON",
+};
+
+AQT_DAPM_ENUM(int1_1_native, SND_SOC_NOPM, 0, native_mux_text);
+AQT_DAPM_ENUM(int2_1_native, SND_SOC_NOPM, 0, native_mux_text);
+
+static int aqt_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);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = aqt_cdc_mclk_enable(component, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = aqt_cdc_mclk_enable(component, false);
+		break;
+	}
+
+	return ret;
+}
+
+static int aif_cap_mixer_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	return 0;
+}
+
+static int aif_cap_mixer_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif1_cap_mixer[] = {
+	SOC_SINGLE_EXT("TX0", SND_SOC_NOPM, AQT_TX0, 1, 0,
+			aif_cap_mixer_get, aif_cap_mixer_put),
+	SOC_SINGLE_EXT("TX1", SND_SOC_NOPM, AQT_TX1, 1, 0,
+			aif_cap_mixer_get, aif_cap_mixer_put),
+};
+
+static const char * const rx_inp_st_mux_text[] = {
+	"ZERO", "SRC0",
+};
+AQT_DAPM_ENUM(rx_inp_st, AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
+	      rx_inp_st_mux_text);
+
+static const struct snd_soc_dapm_widget aqt_dapm_widgets[] = {
+
+	SND_SOC_DAPM_SUPPLY("AQT MCLK", SND_SOC_NOPM, 0, 0, aqt_mclk_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("AQT AIF1 CAP", "AQT AIF1 Capture", 0,
+		SND_SOC_NOPM, AIF1_CAP, 0, aqt_codec_enable_i2s_tx,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("AQT AIF1 CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+			   aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
+
+	AQT_DAPM_MUX("AQT TX0_MUX", 0, tx0),
+	AQT_DAPM_MUX("AQT TX1_MUX", 0, tx1),
+
+	SND_SOC_DAPM_MUX_E("AQT ADC0 MUX", AQT1000_CDC_TX0_TX_PATH_CTL, 5, 0,
+		&tx_adc0_mux, aqt_codec_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("AQT ADC1 MUX", AQT1000_CDC_TX1_TX_PATH_CTL, 5, 0,
+		&tx_adc1_mux, aqt_codec_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("AQT ADC2 MUX", AQT1000_CDC_TX2_TX_PATH_CTL, 5, 0,
+		&tx_adc2_mux, aqt_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	AQT_DAPM_MUX("AQT AMIC0_MUX", 0, tx_amic0),
+	AQT_DAPM_MUX("AQT AMIC1_MUX", 0, tx_amic1),
+	AQT_DAPM_MUX("AQT AMIC2_MUX", 0, tx_amic2),
+
+	SND_SOC_DAPM_ADC_E("AQT ADC_L", NULL, AQT1000_ANA_AMIC1, 7, 0,
+		aqt_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_ADC_E("AQT ADC_R", NULL, AQT1000_ANA_AMIC2, 7, 0,
+		aqt_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_ADC_E("AQT ADC_V", NULL, AQT1000_ANA_AMIC3, 7, 0,
+		aqt_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+
+	AQT_DAPM_MUX("AQT AMIC10_MUX", 0, tx_amic10),
+	AQT_DAPM_MUX("AQT AMIC11_MUX", 0, tx_amic11),
+	AQT_DAPM_MUX("AQT AMIC12_MUX", 0, tx_amic12),
+	AQT_DAPM_MUX("AQT AMIC13_MUX", 0, tx_amic13),
+
+	SND_SOC_DAPM_SWITCH_E("AQT ANC OUT HPHL Enable", SND_SOC_NOPM,
+		INTERP_HPHL, 0, &anc_hphl_pa_switch, aqt_anc_out_switch_cb,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+	 SND_SOC_DAPM_SWITCH_E("AQT ANC OUT HPHR Enable", SND_SOC_NOPM,
+		INTERP_HPHR, 0, &anc_hphr_pa_switch, aqt_anc_out_switch_cb,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_MIXER("AQT RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("AQT RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	AQT_DAPM_MUX("AQT ANC0 FB MUX", 0, anc0_fb),
+	AQT_DAPM_MUX("AQT ANC1 FB MUX", 0, anc1_fb),
+
+	SND_SOC_DAPM_INPUT("AQT AMIC1"),
+	SND_SOC_DAPM_INPUT("AQT AMIC2"),
+	SND_SOC_DAPM_INPUT("AQT AMIC3"),
+
+	SND_SOC_DAPM_MIXER("AQT I2S_L RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("AQT I2S_R RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_AIF_IN_E("AQT AIF1 PB", "AQT AIF1 Playback", 0,
+		SND_SOC_NOPM, AIF1_PB, 0, aqt_codec_enable_i2s_rx,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("AQT RX INT1_1 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int1_1_mux, aqt_codec_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("AQT RX INT2_1 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+		&rx_int2_1_mux, aqt_codec_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("AQT RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int1_2_mux, aqt_codec_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("AQT RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+		&rx_int2_2_mux, aqt_codec_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	AQT_DAPM_MUX("AQT RX INT1_1 INTERP", 0, rx_int1_1_interp),
+	AQT_DAPM_MUX("AQT RX INT1_2 INTERP", 0, rx_int1_2_interp),
+	AQT_DAPM_MUX("AQT RX INT2_1 INTERP", 0, rx_int2_1_interp),
+	AQT_DAPM_MUX("AQT RX INT2_2 INTERP", 0, rx_int2_2_interp),
+
+	SND_SOC_DAPM_MIXER("AQT RX INT1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("AQT RX INT2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("AQT ASRC0 MUX", SND_SOC_NOPM, ASRC0, 0,
+		&asrc0_mux, aqt_codec_enable_asrc_resampler,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("AQT ASRC1 MUX", SND_SOC_NOPM, ASRC1, 0,
+		&asrc1_mux, aqt_codec_enable_asrc_resampler,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	AQT_DAPM_MUX("AQT RX INT1 DEM MUX", 0, rx_int1_dem),
+	AQT_DAPM_MUX("AQT RX INT2 DEM MUX", 0, rx_int2_dem),
+
+	SND_SOC_DAPM_DAC_E("AQT RX INT1 DAC", NULL, AQT1000_ANA_HPH,
+		5, 0, aqt_codec_hphl_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("AQT RX INT2 DAC", NULL, AQT1000_ANA_HPH,
+		4, 0, aqt_codec_hphr_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_PGA_E("AQT HPHL PA", AQT1000_ANA_HPH, 7, 0, NULL, 0,
+		aqt_codec_enable_hphl_pa,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("AQT HPHR PA", AQT1000_ANA_HPH, 6, 0, NULL, 0,
+		aqt_codec_enable_hphr_pa,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("AQT ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		aqt_codec_enable_hphl_pa,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("AQT ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		aqt_codec_enable_hphr_pa,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_OUTPUT("AQT HPHL"),
+	SND_SOC_DAPM_OUTPUT("AQT HPHR"),
+	SND_SOC_DAPM_OUTPUT("AQT ANC HPHL"),
+	SND_SOC_DAPM_OUTPUT("AQT ANC HPHR"),
+
+	SND_SOC_DAPM_MIXER_E("AQT IIR0", AQT1000_CDC_SIDETONE_IIR0_IIR_PATH_CTL,
+		4, 0, NULL, 0, aqt_codec_set_iir_gain,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_MIXER("AQT SRC0",
+			AQT1000_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+			4, 0, NULL, 0),
+
+	SND_SOC_DAPM_MICBIAS_E("AQT MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		aqt_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("AQT RX_BIAS", SND_SOC_NOPM, 0, 0,
+		aqt_codec_enable_rx_bias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("AQT RX INT1 NATIVE SUPPLY", SND_SOC_NOPM,
+		INTERP_HPHL, 0, aqt_enable_native_supply,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_SUPPLY("AQT RX INT2 NATIVE SUPPLY", SND_SOC_NOPM,
+		INTERP_HPHR, 0, aqt_enable_native_supply,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	AQT_DAPM_MUX("AQT RX INT1_1 NATIVE MUX", 0, int1_1_native),
+	AQT_DAPM_MUX("AQT RX INT2_1 NATIVE MUX", 0, int2_1_native),
+
+	SND_SOC_DAPM_MUX("AQT RX ST MUX",
+			 AQT1000_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, 0,
+			 &rx_inp_st_mux),
+};
+
+static int aqt_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+
+	return 0;
+}
+
+static void aqt_shutdown(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *dai)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static int aqt_set_decimator_rate(struct snd_soc_dai *dai,
+				    u32 sample_rate)
+{
+	struct snd_soc_component *component = dai->component;
+	u8 tx_fs_rate = 0;
+	u8 tx_mux_sel = 0, tx0_mux_sel = 0, tx1_mux_sel = 0;
+	u16 tx_path_ctl_reg = 0;
+
+	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;
+	default:
+		dev_err(component->dev, "%s: Invalid TX sample rate: %d\n",
+			__func__, sample_rate);
+		return -EINVAL;
+
+	};
+
+	/* Find which decimator path is enabled */
+	tx_mux_sel = snd_soc_component_read32(component,
+					AQT1000_CDC_IF_ROUTER_TX_MUX_CFG0);
+	tx0_mux_sel = (tx_mux_sel & 0x03);
+	tx1_mux_sel = (tx_mux_sel & 0xC0);
+
+	if (tx0_mux_sel) {
+		tx_path_ctl_reg = AQT1000_CDC_TX0_TX_PATH_CTL +
+					((tx0_mux_sel - 1) * 16);
+		snd_soc_component_update_bits(component, tx_path_ctl_reg,
+					0x0F, tx_fs_rate);
+	}
+
+	if (tx1_mux_sel) {
+		tx_path_ctl_reg = AQT1000_CDC_TX0_TX_PATH_CTL +
+					((tx1_mux_sel - 1) * 16);
+		snd_soc_component_update_bits(component, tx_path_ctl_reg,
+					0x0F, tx_fs_rate);
+	}
+
+	return 0;
+}
+
+static int aqt_set_interpolator_rate(struct snd_soc_dai *dai,
+				       u32 sample_rate)
+{
+	struct snd_soc_component *component = dai->component;
+	int rate_val = 0;
+	int i;
+
+	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;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
+		dev_err(component->dev, "%s: Unsupported sample rate: %d\n",
+			__func__, sample_rate);
+		return -EINVAL;
+	}
+
+	/* TODO - Set the rate only to enabled path */
+	/* Set Primary interpolator rate */
+	snd_soc_component_update_bits(component, AQT1000_CDC_RX1_RX_PATH_CTL,
+			    0x0F, (u8)rate_val);
+	snd_soc_component_update_bits(component, AQT1000_CDC_RX2_RX_PATH_CTL,
+			    0x0F, (u8)rate_val);
+
+	/* Set mixing path interpolator rate */
+	snd_soc_component_update_bits(component,
+			AQT1000_CDC_RX1_RX_PATH_MIX_CTL,
+			0x0F, (u8)rate_val);
+	snd_soc_component_update_bits(component,
+			AQT1000_CDC_RX2_RX_PATH_MIX_CTL,
+			0x0F, (u8)rate_val);
+
+	return 0;
+}
+
+static int aqt_prepare(struct snd_pcm_substream *substream,
+			 struct snd_soc_dai *dai)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+static int aqt_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(dai->component);
+	int ret = 0;
+
+	dev_dbg(aqt->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
+		 __func__, dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = aqt_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			dev_err(aqt->dev, "%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		switch (params_width(params)) {
+		case 16:
+			aqt->dai[dai->id].bit_width = 16;
+			break;
+		case 24:
+			aqt->dai[dai->id].bit_width = 24;
+			break;
+		case 32:
+			aqt->dai[dai->id].bit_width = 32;
+			break;
+		default:
+			return -EINVAL;
+		}
+		aqt->dai[dai->id].rate = params_rate(params);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		ret = aqt_set_decimator_rate(dai, params_rate(params));
+		if (ret) {
+			dev_err(aqt->dev,
+				"%s: cannot set TX Decimator rate: %d\n",
+				__func__, ret);
+			return ret;
+		}
+		switch (params_width(params)) {
+		case 16:
+			aqt->dai[dai->id].bit_width = 16;
+			break;
+		case 24:
+			aqt->dai[dai->id].bit_width = 24;
+			break;
+		default:
+			dev_err(aqt->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+		};
+		aqt->dai[dai->id].rate = params_rate(params);
+		break;
+	default:
+		dev_err(aqt->dev, "%s: Invalid stream type %d\n", __func__,
+			substream->stream);
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops aqt_dai_ops = {
+	.startup = aqt_startup,
+	.shutdown = aqt_shutdown,
+	.hw_params = aqt_hw_params,
+	.prepare = aqt_prepare,
+};
+
+struct snd_soc_dai_driver aqt_dai[] = {
+	{
+		.name = "aqt_rx1",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AQT AIF1 Playback",
+			.rates = AQT1000_RATES_MASK | AQT1000_FRAC_RATES_MASK,
+			.formats = AQT1000_FORMATS_S16_S24_S32_LE,
+			.rate_min = 8000,
+			.rate_max = 384000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &aqt_dai_ops,
+	},
+	{
+		.name = "aqt_tx1",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AQT AIF1 Capture",
+			.rates = AQT1000_RATES_MASK,
+			.formats = AQT1000_FORMATS_S16_S24_LE,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &aqt_dai_ops,
+	},
+};
+
+static int aqt_enable_mclk(struct aqt1000 *aqt)
+{
+	struct snd_soc_component *component = aqt->component;
+
+	/* Enable mclk requires master bias to be enabled first */
+	if (aqt->master_bias_users <= 0) {
+		dev_err(aqt->dev,
+			"%s: Cannot turn on MCLK, BG is not enabled\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (++aqt->mclk_users == 1) {
+		/* Set clock div 2 */
+		snd_soc_component_update_bits(component,
+				AQT1000_CLK_SYS_MCLK1_PRG, 0x0C, 0x04);
+		snd_soc_component_update_bits(component,
+				AQT1000_CLK_SYS_MCLK1_PRG, 0x10, 0x10);
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+		/*
+		 * 10us sleep is required after clock is enabled
+		 * as per HW requirement
+		 */
+		usleep_range(10, 15);
+	}
+
+	dev_dbg(aqt->dev, "%s: mclk_users: %d\n", __func__, aqt->mclk_users);
+
+	return 0;
+}
+
+static int aqt_disable_mclk(struct aqt1000 *aqt)
+{
+	struct snd_soc_component *component = aqt->component;
+
+	if (aqt->mclk_users <= 0) {
+		dev_err(aqt->dev, "%s: No mclk users, cannot disable mclk\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (--aqt->mclk_users == 0) {
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				AQT1000_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				AQT1000_CLK_SYS_MCLK1_PRG, 0x10, 0x00);
+	}
+
+	dev_dbg(component->dev, "%s: mclk_users: %d\n", __func__,
+		aqt->mclk_users);
+
+	return 0;
+}
+
+static int aqt_enable_master_bias(struct aqt1000 *aqt)
+{
+	struct snd_soc_component *component = aqt->component;
+
+	mutex_lock(&aqt->master_bias_lock);
+
+	aqt->master_bias_users++;
+	if (aqt->master_bias_users == 1) {
+		snd_soc_component_update_bits(component, AQT1000_ANA_BIAS,
+					      0x80, 0x80);
+		snd_soc_component_update_bits(component, AQT1000_ANA_BIAS,
+					      0x40, 0x40);
+		/*
+		 * 1ms delay is required after pre-charge is enabled
+		 * as per HW requirement
+		 */
+		usleep_range(1000, 1100);
+		snd_soc_component_update_bits(component, AQT1000_ANA_BIAS,
+					      0x40, 0x00);
+	}
+
+	mutex_unlock(&aqt->master_bias_lock);
+
+	return 0;
+}
+
+static int aqt_disable_master_bias(struct aqt1000 *aqt)
+{
+	struct snd_soc_component *component = aqt->component;
+
+	mutex_lock(&aqt->master_bias_lock);
+	if (aqt->master_bias_users <= 0) {
+		mutex_unlock(&aqt->master_bias_lock);
+		return -EINVAL;
+	}
+
+	aqt->master_bias_users--;
+	if (aqt->master_bias_users == 0)
+		snd_soc_component_update_bits(component, AQT1000_ANA_BIAS,
+					      0x80, 0x00);
+	mutex_unlock(&aqt->master_bias_lock);
+
+	return 0;
+}
+
+static int aqt_cdc_req_mclk_enable(struct aqt1000 *aqt,
+				     bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		ret = clk_prepare_enable(aqt->ext_clk);
+		if (ret) {
+			dev_err(aqt->dev, "%s: ext clk enable failed\n",
+				__func__);
+			goto done;
+		}
+		/* Get BG */
+		aqt_enable_master_bias(aqt);
+		/* Get MCLK */
+		aqt_enable_mclk(aqt);
+	} else {
+		/* put MCLK */
+		aqt_disable_mclk(aqt);
+		/* put BG */
+		if (aqt_disable_master_bias(aqt))
+			dev_err(aqt->dev, "%s: master bias disable failed\n",
+				__func__);
+		clk_disable_unprepare(aqt->ext_clk);
+	}
+
+done:
+	return ret;
+}
+
+static int __aqt_cdc_mclk_enable_locked(struct aqt1000 *aqt,
+					  bool enable)
+{
+	int ret = 0;
+
+	dev_dbg(aqt->dev, "%s: mclk_enable = %u\n", __func__, enable);
+
+	if (enable)
+		ret = aqt_cdc_req_mclk_enable(aqt, true);
+	else
+		aqt_cdc_req_mclk_enable(aqt, false);
+
+	return ret;
+}
+
+static int __aqt_cdc_mclk_enable(struct aqt1000 *aqt,
+				   bool enable)
+{
+	int ret;
+
+	mutex_lock(&aqt->cdc_bg_clk_lock);
+	ret = __aqt_cdc_mclk_enable_locked(aqt, enable);
+	mutex_unlock(&aqt->cdc_bg_clk_lock);
+
+	return ret;
+}
+
+/**
+ * aqt_cdc_mclk_enable - Enable/disable codec mclk
+ *
+ * @component: codec component instance
+ * @enable: Indicates clk enable or disable
+ *
+ * Returns 0 on Success and error on failure
+ */
+int aqt_cdc_mclk_enable(struct snd_soc_component *component, bool enable)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	return __aqt_cdc_mclk_enable(aqt, enable);
+}
+EXPORT_SYMBOL(aqt_cdc_mclk_enable);
+
+/*
+ * aqt_get_micb_vout_ctl_val: converts micbias from volts to register value
+ * @micb_mv: micbias in mv
+ *
+ * return register value converted
+ */
+int aqt_get_micb_vout_ctl_val(u32 micb_mv)
+{
+	/* min micbias voltage is 1V and maximum is 2.85V */
+	if (micb_mv < 1000 || micb_mv > 2850) {
+		pr_err("%s: unsupported micbias voltage\n", __func__);
+		return -EINVAL;
+	}
+
+	return (micb_mv - 1000) / 50;
+}
+EXPORT_SYMBOL(aqt_get_micb_vout_ctl_val);
+
+static int aqt_set_micbias(struct aqt1000 *aqt,
+			   struct aqt1000_pdata *pdata)
+{
+	struct snd_soc_component *component = aqt->component;
+	int vout_ctl_1;
+
+	if (!pdata) {
+		dev_err(component->dev, "%s: NULL pdata\n", __func__);
+		return -ENODEV;
+	}
+
+	/* set micbias voltage */
+	vout_ctl_1 = aqt_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
+	if (vout_ctl_1 < 0)
+		return -EINVAL;
+
+	snd_soc_component_update_bits(component, AQT1000_ANA_MICB1,
+				      0x3F, vout_ctl_1);
+
+	return 0;
+}
+
+static ssize_t aqt_codec_version_read(struct snd_info_entry *entry,
+					void *file_private_data,
+					struct file *file,
+					char __user *buf, size_t count,
+					loff_t pos)
+{
+	char buffer[AQT_VERSION_ENTRY_SIZE];
+	int len = 0;
+
+	len = snprintf(buffer, sizeof(buffer), "AQT1000_1_0\n");
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static struct snd_info_entry_ops aqt_codec_info_ops = {
+	.read = aqt_codec_version_read,
+};
+
+/*
+ * aqt_codec_info_create_codec_entry - creates aqt1000 module
+ * @codec_root: The parent directory
+ * @component: Codec component instance
+ *
+ * Creates aqt1000 module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int aqt_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
+				struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct aqt1000 *aqt;
+	struct snd_soc_card *card;
+
+	if (!codec_root || !component)
+		return -EINVAL;
+
+	aqt = snd_soc_component_get_drvdata(component);
+	if (!aqt) {
+		dev_dbg(component->dev, "%s: aqt is NULL\n", __func__);
+		return -EINVAL;
+	}
+	card = component->card;
+	aqt->entry = snd_info_create_subdir(codec_root->module,
+					   "aqt1000", codec_root);
+	if (!aqt->entry) {
+		dev_dbg(component->dev, "%s: failed to create aqt1000 entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	version_entry = snd_info_create_card_entry(card->snd_card,
+						  "version",
+						   aqt->entry);
+	if (!version_entry) {
+		dev_dbg(component->dev, "%s: failed to create aqt1000 version entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = aqt;
+	version_entry->size = AQT_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &aqt_codec_info_ops;
+
+	if (snd_info_register(version_entry) < 0) {
+		snd_info_free_entry(version_entry);
+		return -ENOMEM;
+	}
+	aqt->version_entry = version_entry;
+
+	return 0;
+}
+EXPORT_SYMBOL(aqt_codec_info_create_codec_entry);
+
+static const struct aqt_reg_mask_val aqt_codec_reg_init[] = {
+	{AQT1000_CHIP_CFG0_EFUSE_CTL, 0x01, 0x01},
+};
+
+static const struct aqt_reg_mask_val aqt_codec_reg_update[] = {
+	{AQT1000_LDOH_MODE, 0x1F, 0x0B},
+	{AQT1000_MICB1_TEST_CTL_2, 0x07, 0x01},
+	{AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS, 0x03, 0x02},
+	{AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS, 0x0C, 0x08},
+	{AQT1000_MICB1_MISC_MICB1_INM_RES_BIAS, 0x30, 0x20},
+	{AQT1000_CDC_TX0_TX_PATH_CFG1, 0x01, 0x00},
+	{AQT1000_CDC_TX1_TX_PATH_CFG1, 0x01, 0x00},
+	{AQT1000_CDC_TX2_TX_PATH_CFG1, 0x01, 0x00},
+};
+
+static void aqt_codec_init_reg(struct aqt1000 *priv)
+{
+	struct snd_soc_component *component = priv->component;
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(aqt_codec_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				    aqt_codec_reg_init[i].reg,
+				    aqt_codec_reg_init[i].mask,
+				    aqt_codec_reg_init[i].val);
+}
+
+static void aqt_codec_update_reg(struct aqt1000 *priv)
+{
+	struct snd_soc_component *component = priv->component;
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(aqt_codec_reg_update); i++)
+		snd_soc_component_update_bits(component,
+				    aqt_codec_reg_update[i].reg,
+				    aqt_codec_reg_update[i].mask,
+				    aqt_codec_reg_update[i].val);
+
+}
+
+static int aqt_soc_codec_probe(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt;
+	struct aqt1000_pdata *pdata;
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int i, ret = 0;
+
+	dev_dbg(component->dev, "%s()\n", __func__);
+	aqt = snd_soc_component_get_drvdata(component);
+
+	snd_soc_component_init_regmap(component, aqt->regmap);
+
+	mutex_init(&aqt->codec_mutex);
+	mutex_init(&aqt->i2s_lock);
+	/* Class-H Init */
+	aqt_clsh_init(&aqt->clsh_d);
+	/* Default HPH Mode to Class-H Low HiFi */
+	aqt->hph_mode = CLS_H_LOHIFI;
+
+	aqt->fw_data = devm_kzalloc(component->dev, sizeof(*(aqt->fw_data)),
+				      GFP_KERNEL);
+	if (!aqt->fw_data)
+		goto err;
+
+	set_bit(WCD9XXX_ANC_CAL, aqt->fw_data->cal_bit);
+	set_bit(WCD9XXX_MBHC_CAL, aqt->fw_data->cal_bit);
+
+	/* Register for Clock */
+	aqt->ext_clk = clk_get(aqt->dev, "aqt_clk");
+	if (IS_ERR(aqt->ext_clk)) {
+		dev_err(aqt->dev, "%s: clk get %s failed\n",
+			__func__, "aqt_ext_clk");
+		goto err_clk;
+	}
+
+	ret = wcd_cal_create_hwdep(aqt->fw_data,
+				   AQT1000_CODEC_HWDEP_NODE, component);
+	if (ret < 0) {
+		dev_err(component->dev, "%s hwdep failed %d\n", __func__, ret);
+		goto err_hwdep;
+	}
+
+	/* Initialize MBHC module */
+	ret = aqt_mbhc_init(&aqt->mbhc, component, aqt->fw_data);
+	if (ret) {
+		pr_err("%s: mbhc initialization failed\n", __func__);
+		goto err_hwdep;
+	}
+	aqt->component = component;
+	for (i = 0; i < COMPANDER_MAX; i++)
+		aqt->comp_enabled[i] = 0;
+
+	aqt_cdc_mclk_enable(component, true);
+	aqt_codec_init_reg(aqt);
+	aqt_cdc_mclk_enable(component, false);
+
+	/* Add 100usec delay as per HW requirement */
+	usleep_range(100, 110);
+
+	aqt_codec_update_reg(aqt);
+
+	pdata = dev_get_platdata(component->dev);
+
+	/* If 1.8v is supplied externally, then disable internal 1.8v supply */
+	for (i = 0; i < pdata->num_supplies; i++) {
+		if (!strcmp(pdata->regulator->name, "aqt_vdd1p8")) {
+			snd_soc_component_update_bits(component,
+					AQT1000_BUCK_5V_EN_CTL,
+					0x03, 0x00);
+			dev_dbg(component->dev, "%s: Disabled internal supply\n",
+				__func__);
+			break;
+		}
+	}
+
+	aqt_set_micbias(aqt, pdata);
+
+	snd_soc_dapm_add_routes(dapm, aqt_audio_map,
+			ARRAY_SIZE(aqt_audio_map));
+
+	for (i = 0; i < NUM_CODEC_DAIS; i++) {
+		INIT_LIST_HEAD(&aqt->dai[i].ch_list);
+		init_waitqueue_head(&aqt->dai[i].dai_wait);
+	}
+
+	for (i = 0; i < AQT1000_NUM_DECIMATORS; i++) {
+		aqt->tx_hpf_work[i].aqt = aqt;
+		aqt->tx_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&aqt->tx_hpf_work[i].dwork,
+				  aqt_tx_hpf_corner_freq_callback);
+
+		aqt->tx_mute_dwork[i].aqt = aqt;
+		aqt->tx_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&aqt->tx_mute_dwork[i].dwork,
+				  aqt_tx_mute_update_callback);
+	}
+
+	mutex_lock(&aqt->codec_mutex);
+	snd_soc_dapm_disable_pin(dapm, "AQT ANC HPHL PA");
+	snd_soc_dapm_disable_pin(dapm, "AQT ANC HPHR PA");
+	snd_soc_dapm_disable_pin(dapm, "AQT ANC HPHL");
+	snd_soc_dapm_disable_pin(dapm, "AQT ANC HPHR");
+	mutex_unlock(&aqt->codec_mutex);
+
+	snd_soc_dapm_ignore_suspend(dapm, "AQT AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "AQT AIF1 Capture");
+
+	snd_soc_dapm_sync(dapm);
+
+	return ret;
+
+err_hwdep:
+	clk_put(aqt->ext_clk);
+err_clk:
+	devm_kfree(component->dev, aqt->fw_data);
+	aqt->fw_data = NULL;
+err:
+	mutex_destroy(&aqt->i2s_lock);
+	mutex_destroy(&aqt->codec_mutex);
+	return ret;
+}
+
+static void aqt_soc_codec_remove(struct snd_soc_component *component)
+{
+	struct aqt1000 *aqt = snd_soc_component_get_drvdata(component);
+
+	/* Deinitialize MBHC module */
+	aqt_mbhc_deinit(component);
+	aqt->mbhc = NULL;
+	mutex_destroy(&aqt->i2s_lock);
+	mutex_destroy(&aqt->codec_mutex);
+	clk_put(aqt->ext_clk);
+
+	return;
+}
+
+static const struct snd_soc_component_driver snd_cdc_dev_aqt = {
+	.name = DRV_NAME,
+	.probe = aqt_soc_codec_probe,
+	.remove = aqt_soc_codec_remove,
+	.controls = aqt_snd_controls,
+	.num_controls = ARRAY_SIZE(aqt_snd_controls),
+	.dapm_widgets = aqt_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aqt_dapm_widgets),
+	.dapm_routes = aqt_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(aqt_audio_map),
+};
+
+/*
+ * aqt_register_codec: Register the device to ASoC
+ * @dev: device
+ *
+ * return 0 success or error code in case of failure
+ */
+int aqt_register_codec(struct device *dev)
+{
+	return snd_soc_register_component(dev, &snd_cdc_dev_aqt, aqt_dai,
+					ARRAY_SIZE(aqt_dai));
+}
+EXPORT_SYMBOL(aqt_register_codec);

+ 221 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/aqt1000.h

@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef AQT1000_H
+#define AQT1000_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include "pdata.h"
+#include "aqt1000-clsh.h"
+
+#define AQT1000_MAX_MICBIAS 1
+#define AQT1000_NUM_INTERPOLATORS 2
+#define AQT1000_NUM_DECIMATORS 3
+#define  AQT1000_VOUT_CTL_TO_MICB(v)  (1000 + v * 50)
+#define AQT1000_RX_PATH_CTL_OFFSET 20
+
+#define AQT1000_CLK_24P576MHZ 24576000
+#define AQT1000_CLK_19P2MHZ 19200000
+#define AQT1000_CLK_12P288MHZ 12288000
+#define AQT1000_CLK_9P6MHZ 9600000
+
+#define AQT1000_ST_IIR_COEFF_MAX 5
+
+enum {
+	AQT1000_RX0 = 0,
+	AQT1000_RX1,
+	AQT1000_RX_MAX,
+};
+
+enum {
+	AQT_NONE,
+	AQT_MCLK,
+	AQT_RCO,
+};
+
+enum {
+	AQT_TX0 = 0,
+	AQT_TX1,
+};
+
+enum {
+	ASRC0,
+	ASRC1,
+	ASRC_MAX,
+};
+
+/* Each IIR has 5 Filter Stages */
+enum {
+	BAND1 = 0,
+	BAND2,
+	BAND3,
+	BAND4,
+	BAND5,
+	BAND_MAX,
+};
+
+enum {
+	AQT1000_TX0 = 0,
+	AQT1000_TX1,
+	AQT1000_TX2,
+	AQT1000_TX_MAX,
+};
+
+enum {
+	INTERP_HPHL,
+	INTERP_HPHR,
+	INTERP_MAX,
+};
+
+enum {
+	INTERP_MAIN_PATH,
+	INTERP_MIX_PATH,
+};
+
+enum {
+	COMPANDER_1, /* HPH_L */
+	COMPANDER_2, /* HPH_R */
+	COMPANDER_MAX,
+};
+
+enum {
+	AIF1_PB = 0,
+	AIF1_CAP,
+	NUM_CODEC_DAIS,
+};
+
+struct aqt_codec_dai_data {
+	u32 rate;
+	u32 *ch_num;
+	u32 ch_act;
+	u32 ch_tot;
+};
+
+struct aqt_idle_detect_config {
+	u8 hph_idle_thr;
+	u8 hph_idle_detect_en;
+};
+
+struct aqt1000_i2c {
+	struct i2c_client *client;
+	struct i2c_msg xfer_msg[2];
+	struct mutex xfer_lock;
+	int mod_id;
+};
+
+struct aqt1000_cdc_dai_data {
+	u32 rate;		/* sample rate */
+	u32 bit_width;		/* sit width 16,24,32 */
+	struct list_head ch_list;
+	wait_queue_head_t dai_wait;
+};
+
+struct tx_mute_work {
+	struct aqt1000 *aqt;
+	u8 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct aqt1000 *aqt;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+struct aqt1000 {
+	struct device *dev;
+	struct mutex io_lock;
+	struct mutex xfer_lock;
+	struct mutex reset_lock;
+
+	struct device_node *aqt_rst_np;
+
+	int (*read_dev)(struct aqt1000 *aqt, unsigned short reg,
+			void *dest, int bytes);
+	int (*write_dev)(struct aqt1000 *aqt, unsigned short reg,
+			 void *src, int bytes);
+
+	u32 num_of_supplies;
+	struct regulator_bulk_data *supplies;
+
+	u32 mclk_rate;
+	struct regmap *regmap;
+	struct snd_soc_component *component;
+	bool dev_up;
+	bool prev_pg_valid;
+	u8 prev_pg;
+
+	struct aqt1000_i2c i2c_dev;
+
+	/* Codec params */
+
+	/* ANC related */
+	u32 anc_slot;
+	bool anc_func;
+
+	/* compander */
+	int comp_enabled[COMPANDER_MAX];
+
+	/* class h specific data */
+	struct aqt_clsh_cdc_data clsh_d;
+
+	/* Interpolator Mode Select for HPH_L and HPH_R */
+	u32 hph_mode;
+
+	unsigned long status_mask;
+
+	struct aqt1000_cdc_dai_data dai[NUM_CODEC_DAIS];
+
+	struct mutex micb_lock;
+
+	struct clk *ext_clk;
+
+	/* mbhc module */
+	struct aqt1000_mbhc *mbhc;
+
+	struct mutex codec_mutex;
+
+	/* cal info for codec */
+	struct fw_info *fw_data;
+
+	int native_clk_users;
+	/* ASRC users count */
+	int asrc_users[ASRC_MAX];
+	int asrc_output_mode[ASRC_MAX];
+	/* Main path clock users count */
+	int main_clk_users[AQT1000_NUM_INTERPOLATORS];
+
+	struct aqt_idle_detect_config idle_det_cfg;
+	u32 rx_bias_count;
+
+	s32 micb_ref;
+	s32 pullup_ref;
+	int master_bias_users;
+	int mclk_users;
+	int i2s_users;
+
+	struct hpf_work tx_hpf_work[AQT1000_NUM_DECIMATORS];
+	struct tx_mute_work tx_mute_dwork[AQT1000_NUM_DECIMATORS];
+
+	struct mutex master_bias_lock;
+	struct mutex cdc_bg_clk_lock;
+	struct mutex i2s_lock;
+
+	/* Interrupt */
+	struct regmap_irq_chip_data *irq_chip;
+	int num_irq_regs;
+	struct irq_domain *virq;
+	int irq;
+	int irq_base;
+
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+};
+
+#endif /* AQT1000_H */

+ 32 - 0
qcom/opensource/audio-kernel/asoc/codecs/aqt1000/pdata.h

@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _AQT1000_PDATA_H_
+#define _AQT1000_PDATA_H_
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <asoc/msm-cdc-supply.h>
+
+struct aqt1000_micbias_setting {
+	u8 ldoh_v;
+	u32 cfilt1_mv;
+	u32 micb1_mv;
+	u8 bias1_cfilt_sel;
+};
+
+struct aqt1000_pdata {
+	unsigned int irq_gpio;
+	unsigned int irq_flags;
+	struct cdc_regulator *regulator;
+	int num_supplies;
+	struct aqt1000_micbias_setting micbias;
+	struct device_node *aqt_rst_np;
+	u32 mclk_rate;
+	u32 ext_clk_rate;
+	u32 ext_1p8v_supply;
+};
+
+#endif /* _AQT1000_PDATA_H_ */

+ 773 - 0
qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk-up.c

@@ -0,0 +1,773 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <bindings/qcom,audio-ext-clk.h>
+#include <linux/ratelimit.h>
+#ifdef CONFIG_AUDIO_PRM
+#include <dsp/audio_prm.h>
+#else
+#include "audio-ext-clk-up.h"
+#endif
+enum {
+	AUDIO_EXT_CLK_PMI,
+	AUDIO_EXT_CLK_LNBB2,
+	AUDIO_EXT_CLK_LPASS,
+	AUDIO_EXT_CLK_LPASS2,
+	AUDIO_EXT_CLK_LPASS3,
+	AUDIO_EXT_CLK_LPASS4,
+	AUDIO_EXT_CLK_LPASS5,
+	AUDIO_EXT_CLK_LPASS6,
+	AUDIO_EXT_CLK_LPASS7,
+	AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE,
+	AUDIO_EXT_CLK_LPASS8,
+	AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE,
+	AUDIO_EXT_CLK_LPASS9,
+	AUDIO_EXT_CLK_LPASS10,
+	AUDIO_EXT_CLK_LPASS11,
+	AUDIO_EXT_CLK_LPASS12,
+	AUDIO_EXT_CLK_LPASS13,
+	AUDIO_EXT_CLK_LPASS14,
+	AUDIO_EXT_CLK_LPASS15,
+	AUDIO_EXT_CLK_LPASS16,
+	AUDIO_EXT_CLK_LPASS_MAX,
+	AUDIO_EXT_CLK_EXTERNAL_PLL = AUDIO_EXT_CLK_LPASS_MAX,
+	AUDIO_EXT_CLK_MAX,
+};
+
+struct pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *sleep;
+	struct pinctrl_state *active;
+	char __iomem *base;
+};
+
+struct audio_ext_clk {
+	struct pinctrl_info pnctrl_info;
+	struct clk_fixed_factor fact;
+};
+
+struct audio_ext_clk_priv {
+	struct device *dev;
+	int clk_src;
+	uint32_t enable;
+#ifdef CONFIG_AUDIO_PRM
+	struct clk_cfg prm_clk_cfg;
+#endif
+	struct audio_ext_clk audio_clk;
+	const char *clk_name;
+	uint32_t lpass_core_hwvote_client_handle;
+	uint32_t lpass_audio_hwvote_client_handle;
+};
+
+static inline struct audio_ext_clk_priv *to_audio_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct audio_ext_clk_priv, audio_clk.fact.hw);
+}
+
+static int audio_ext_clk_prepare(struct clk_hw *hw)
+{
+	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
+	struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
+	int ret;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
+		(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX) && !clk_priv->enable)  {
+#ifdef CONFIG_AUDIO_PRM
+	    pr_debug("%s: clk_id %x ", __func__, clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_clk_cfg(&clk_priv->prm_clk_cfg,1);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			if (__ratelimit(&rtl))
+				pr_err_ratelimited("%s prm set lpass clk failed\n",
+				__func__);
+			return ret;
+		}
+		clk_priv->enable = 1;
+	}
+
+	if (pnctrl_info->pinctrl) {
+		ret = pinctrl_select_state(pnctrl_info->pinctrl,
+				pnctrl_info->active);
+		if (ret) {
+			pr_err("%s: active state select failed with %d\n",
+				__func__, ret);
+			return -EIO;
+		}
+	}
+
+	if (pnctrl_info->base)
+		iowrite32(1, pnctrl_info->base);
+	return 0;
+}
+
+static void audio_ext_clk_unprepare(struct clk_hw *hw)
+{
+	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
+	struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
+	int ret;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	if (pnctrl_info->pinctrl) {
+		ret = pinctrl_select_state(pnctrl_info->pinctrl,
+					   pnctrl_info->sleep);
+		if (ret) {
+			pr_err("%s: active state select failed with %d\n",
+				__func__, ret);
+			return;
+		}
+	}
+
+	if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
+		(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX))  {
+		clk_priv->enable = 0;
+#ifdef CONFIG_AUDIO_PRM
+		pr_debug("%s: clk_id %x", __func__,
+				clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_clk_cfg(&clk_priv->prm_clk_cfg, 0);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			if (__ratelimit(&rtl))
+				pr_err_ratelimited("%s: unset lpass clk cfg failed, ret = %d\n",
+				__func__, ret);
+		}
+	}
+
+	if (pnctrl_info->base)
+		iowrite32(0, pnctrl_info->base);
+}
+
+static u8 audio_ext_clk_get_parent(struct clk_hw *hw)
+{
+	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	const char * const *parent_names = hw->init->parent_names;
+	u8 i = 0, ret = hw->init->num_parents + 1;
+
+	if ((clk_priv->clk_src == AUDIO_EXT_CLK_PMI) && clk_priv->clk_name) {
+		for (i = 0; i < num_parents; i++) {
+			if (!strcmp(parent_names[i], clk_priv->clk_name))
+				ret = i;
+		}
+		pr_debug("%s: parent index = %u\n", __func__, ret);
+		return ret;
+	} else
+		return 0;
+}
+
+static int lpass_hw_vote_prepare(struct clk_hw *hw)
+{
+	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
+	int ret;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE)  {
+#ifdef CONFIG_AUDIO_PRM
+		pr_debug("%s: core vote clk_id %x \n", __func__, clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg,
+			HW_CORE_ID_LPASS, 1);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			if (__ratelimit(&rtl))
+				pr_err("%s lpass core hw vote failed %d\n",
+					__func__, ret);
+			return ret;
+		}
+	}
+
+	if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE)  {
+#ifdef CONFIG_AUDIO_PRM
+		pr_debug("%s: audio vote clk_id %x \n", __func__, clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg,
+			HW_CORE_ID_DCODEC, 1);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			if (__ratelimit(&rtl))
+				pr_err("%s lpass audio hw vote failed %d\n",
+				__func__, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void lpass_hw_vote_unprepare(struct clk_hw *hw)
+{
+	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
+	int ret = 0;
+
+	if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) {
+#ifdef CONFIG_AUDIO_PRM
+		pr_debug("%s: core vote clk_id %x \n", __func__, clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg,
+				HW_CORE_ID_LPASS, 0);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			pr_err("%s lpass core hw vote failed %d\n",
+				__func__, ret);
+		}
+	}
+
+	if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) {
+
+#ifdef CONFIG_AUDIO_PRM
+		pr_debug("%s: audio vote clk_id %x \n", __func__, clk_priv->prm_clk_cfg.clk_id);
+		ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg,
+				HW_CORE_ID_DCODEC, 0);
+#else
+		pr_debug("%s: audio prm not enabled", __func__);
+		ret = -EPERM;
+#endif
+		if (ret < 0) {
+			pr_err("%s lpass audio hw unvote failed %d\n",
+				__func__, ret);
+		}
+	}
+}
+
+static const struct clk_ops audio_ext_clk_ops = {
+	.prepare = audio_ext_clk_prepare,
+	.unprepare = audio_ext_clk_unprepare,
+	.get_parent = audio_ext_clk_get_parent,
+};
+
+static const struct clk_ops lpass_hw_vote_ops = {
+	.prepare = lpass_hw_vote_prepare,
+	.unprepare = lpass_hw_vote_unprepare,
+};
+
+static const char * const audio_ext_pmi_div_clk[] = {
+	"qpnp_clkdiv_1",
+	"pms405_div_clk1",
+	"pm6150_div_clk1",
+	"pm6125_div_clk1",
+};
+
+static int audio_ext_clk_dummy_prepare(struct clk_hw *hw)
+{
+	return 0;
+}
+
+static void audio_ext_clk_dummy_unprepare(struct clk_hw *hw)
+{
+
+}
+
+static const struct clk_ops audio_ext_clk_dummy_ops = {
+	.prepare = audio_ext_clk_dummy_prepare,
+	.unprepare = audio_ext_clk_dummy_unprepare,
+};
+
+static struct audio_ext_clk audio_clk_array[] = {
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_ext_pmi_clk",
+				.parent_names = audio_ext_pmi_div_clk,
+				.num_parents =
+					 ARRAY_SIZE(audio_ext_pmi_div_clk),
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_ext_pmi_lnbb_clk",
+				.parent_names = (const char *[])
+							{ "ln_bb_clk2" },
+				.num_parents = 1,
+				.ops = &audio_ext_clk_dummy_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk2",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk3",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk4",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk5",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk6",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk7",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.hw.init = &(struct clk_init_data){
+				.name = "lpass_hw_vote_clk",
+				.ops = &lpass_hw_vote_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk8",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.hw.init = &(struct clk_init_data){
+				.name = "lpass_audio_hw_vote_clk",
+				.ops = &lpass_hw_vote_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk9",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk10",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk11",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk12",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk13",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk14",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk15",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_lpass_mclk16",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+	{
+		.pnctrl_info = {NULL},
+		.fact = {
+			.mult = 1,
+			.div = 1,
+			.hw.init = &(struct clk_init_data){
+				.name = "audio_external_pll_clk",
+				.ops = &audio_ext_clk_ops,
+			},
+		},
+	},
+};
+
+static int audio_get_pinctrl(struct platform_device *pdev)
+{
+	struct device *dev =  &pdev->dev;
+	struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
+	struct pinctrl_info *pnctrl_info;
+	struct pinctrl *pinctrl;
+	int ret;
+	u32 reg;
+
+	pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
+	if (pnctrl_info->pinctrl) {
+		dev_err(dev, "%s: already requested before\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR_OR_NULL(pinctrl)) {
+		dev_err(dev, "%s: Unable to get pinctrl handle\n",
+			__func__);
+		return -EINVAL;
+	}
+	pnctrl_info->pinctrl = pinctrl;
+	/* get all state handles from Device Tree */
+	pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
+	if (IS_ERR(pnctrl_info->sleep)) {
+		dev_err(dev, "%s: could not get sleep pinstate\n",
+			__func__);
+		goto err;
+	}
+	pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
+	if (IS_ERR(pnctrl_info->active)) {
+		dev_err(dev, "%s: could not get active pinstate\n",
+			__func__);
+		goto err;
+	}
+	/* Reset the TLMM pins to a default state */
+	ret = pinctrl_select_state(pnctrl_info->pinctrl,
+				   pnctrl_info->sleep);
+	if (ret) {
+		dev_err(dev, "%s: Disable TLMM pins failed with %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "qcom,mclk-clk-reg", &reg);
+	if (ret < 0) {
+		dev_dbg(dev, "%s: miss mclk reg\n", __func__);
+	} else {
+		pnctrl_info->base = ioremap(reg, sizeof(u32));
+		if (pnctrl_info->base ==  NULL) {
+			dev_err(dev, "%s ioremap failed\n", __func__);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	devm_pinctrl_put(pnctrl_info->pinctrl);
+	return -EINVAL;
+}
+
+static int audio_put_pinctrl(struct platform_device *pdev)
+{
+	struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
+	struct pinctrl_info *pnctrl_info = NULL;
+
+	pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
+	if (pnctrl_info && pnctrl_info->pinctrl) {
+		devm_pinctrl_put(pnctrl_info->pinctrl);
+		pnctrl_info->pinctrl = NULL;
+	}
+
+	return 0;
+}
+
+static int audio_get_clk_data(struct platform_device *pdev)
+{
+	int ret;
+	struct clk *audio_clk;
+	struct clk_hw *clkhw;
+	struct clk_onecell_data *clk_data;
+	struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
+
+	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->clk_num = 1;
+	clk_data->clks = devm_kzalloc(&pdev->dev,
+				sizeof(struct clk *),
+				GFP_KERNEL);
+	if (!clk_data->clks)
+		return -ENOMEM;
+
+	clkhw = &clk_priv->audio_clk.fact.hw;
+	audio_clk = devm_clk_register(&pdev->dev, clkhw);
+	if (IS_ERR(audio_clk)) {
+		dev_err(&pdev->dev,
+			"%s: clock register failed for clk_src = %d\\n",
+			__func__, clk_priv->clk_src);
+		ret = PTR_ERR(audio_clk);
+		return ret;
+	}
+	clk_data->clks[0] = audio_clk;
+
+	ret = of_clk_add_provider(pdev->dev.of_node,
+			 of_clk_src_onecell_get, clk_data);
+	if (ret)
+		dev_err(&pdev->dev, "%s: clock add failed for clk_src = %d\n",
+			__func__, clk_priv->clk_src);
+
+	return ret;
+}
+
+static int audio_ref_clk_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct audio_ext_clk_priv *clk_priv;
+	u32 clk_freq = 0, clk_id = 0, clk_src = 0, use_pinctrl = 0;
+
+	clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
+	if (!clk_priv)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,codec-ext-clk-src",
+			&clk_src);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not get clk source, ret = %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	if (clk_src >= AUDIO_EXT_CLK_MAX) {
+		dev_err(&pdev->dev, "%s: Invalid clk source = %d\n",
+				__func__, clk_src);
+		return -EINVAL;
+	}
+	clk_priv->clk_name = NULL;
+	clk_priv->clk_src = clk_src;
+	memcpy(&clk_priv->audio_clk, &audio_clk_array[clk_src],
+		   sizeof(struct audio_ext_clk));
+
+#ifdef CONFIG_AUDIO_PRM
+	/* Init prm clk cfg default values */
+	clk_priv->prm_clk_cfg.clk_id = CLOCK_ID_QUI_MI2S_OSR;
+	clk_priv->prm_clk_cfg.clk_freq_in_hz = OSR_CLOCK_9_P600_MHZ;
+	clk_priv->prm_clk_cfg.clk_attri = CLOCK_ATTRIBUTE_COUPLE_NO;
+	clk_priv->prm_clk_cfg.clk_root = 0;
+#endif
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,codec-lpass-ext-clk-freq",
+			&clk_freq);
+	if (!ret) {
+#ifdef CONFIG_AUDIO_PRM
+		clk_priv->prm_clk_cfg.clk_freq_in_hz = clk_freq;
+#endif
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,codec-lpass-clk-id",
+			&clk_id);
+	if (!ret) {
+#ifdef CONFIG_AUDIO_PRM
+		clk_priv->prm_clk_cfg.clk_id = clk_id;
+		dev_dbg(&pdev->dev, "%s: PRM ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
+			__func__, clk_priv->prm_clk_cfg.clk_freq_in_hz,
+			clk_priv->prm_clk_cfg.clk_id, clk_priv->clk_src);
+#endif
+	}
+
+        dev_dbg(&pdev->dev, "%s: PRM2 ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
+                        __func__, clk_priv->prm_clk_cfg.clk_freq_in_hz,
+                        clk_priv->prm_clk_cfg.clk_id, clk_priv->clk_src);
+
+	platform_set_drvdata(pdev, clk_priv);
+
+	ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names",
+				      &clk_priv->clk_name);
+	if (ret)
+		dev_dbg(&pdev->dev, "%s: could not find pmic clock names\n",
+			__func__);
+	/*
+	 * property qcom,use-pinctrl to be defined in DTSI to val 1
+	 * for clock nodes using pinctrl
+	 */
+	of_property_read_u32(pdev->dev.of_node, "qcom,use-pinctrl",
+			     &use_pinctrl);
+	dev_dbg(&pdev->dev, "%s: use-pinctrl : %d\n",
+		__func__, use_pinctrl);
+
+	if (use_pinctrl) {
+		ret = audio_get_pinctrl(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Parsing PMI pinctrl failed\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	ret = audio_get_clk_data(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: clk_init is failed\n",
+			__func__);
+		audio_put_pinctrl(pdev);
+		return ret;
+	}
+	return 0;
+}
+
+static int audio_ref_clk_remove(struct platform_device *pdev)
+{
+	audio_put_pinctrl(pdev);
+
+	return 0;
+}
+
+static const struct of_device_id audio_ref_clk_match[] = {
+	{.compatible = "qcom,audio-ref-clk"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
+
+static struct platform_driver audio_ref_clk_driver = {
+	.driver = {
+		.name = "audio-ref-clk",
+		.owner = THIS_MODULE,
+		.of_match_table = audio_ref_clk_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = audio_ref_clk_probe,
+	.remove = audio_ref_clk_remove,
+};
+
+int audio_ref_clk_platform_init(void)
+{
+	return platform_driver_register(&audio_ref_clk_driver);
+}
+
+void audio_ref_clk_platform_exit(void)
+{
+	platform_driver_unregister(&audio_ref_clk_driver);
+}
+
+MODULE_DESCRIPTION("Audio Ref Up Clock module platform driver");
+MODULE_LICENSE("GPL v2");

+ 12 - 0
qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk-up.h

@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __AUDIO_EXT_CLK_UP_H_
+#define __AUDIO_EXT_CLK_UP_H_
+
+int audio_ref_clk_platform_init(void);
+void audio_ref_clk_platform_exit(void);
+
+#endif

+ 341 - 0
qcom/opensource/audio-kernel/asoc/codecs/audio-ext-clk.c

@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/clk/msm-clk-provider.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <dt-bindings/clock/audio-ext-clk.h>
+#include <sound/q6afe-v2.h>
+#include "audio-ext-clk-up.h"
+
+struct pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *sleep;
+	struct pinctrl_state *active;
+};
+
+struct audio_ext_ap_clk {
+	bool enabled;
+	int gpio;
+	struct clk c;
+};
+
+struct audio_ext_pmi_clk {
+	int gpio;
+	struct clk c;
+};
+
+struct audio_ext_ap_clk2 {
+	bool enabled;
+	struct pinctrl_info pnctrl_info;
+	struct clk c;
+};
+
+static struct afe_clk_set clk2_config = {
+	Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
+	Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR,
+	Q6AFE_LPASS_IBIT_CLK_11_P2896_MHZ,
+	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+	0,
+};
+
+static inline struct audio_ext_ap_clk *to_audio_ap_clk(struct clk *clk)
+{
+	return container_of(clk, struct audio_ext_ap_clk, c);
+}
+
+static int audio_ext_clk_prepare(struct clk *clk)
+{
+	struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(clk);
+
+	pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
+	if (gpio_is_valid(audio_clk->gpio))
+		return gpio_direction_output(audio_clk->gpio, 1);
+	return 0;
+}
+
+static void audio_ext_clk_unprepare(struct clk *clk)
+{
+	struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(clk);
+
+	pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
+	if (gpio_is_valid(audio_clk->gpio))
+		gpio_direction_output(audio_clk->gpio, 0);
+}
+
+static inline struct audio_ext_ap_clk2 *to_audio_ap_clk2(struct clk *clk)
+{
+	return container_of(clk, struct audio_ext_ap_clk2, c);
+}
+
+static int audio_ext_clk2_prepare(struct clk *clk)
+{
+	struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(clk);
+	struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
+	int ret;
+
+
+	if (!pnctrl_info->pinctrl || !pnctrl_info->active)
+		return 0;
+
+	ret = pinctrl_select_state(pnctrl_info->pinctrl,
+				   pnctrl_info->active);
+	if (ret) {
+		pr_err("%s: active state select failed with %d\n",
+			__func__, ret);
+		return -EIO;
+	}
+
+	clk2_config.enable = 1;
+	ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
+	if (ret < 0) {
+		pr_err("%s: failed to set clock, ret = %d\n", __func__, ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void audio_ext_clk2_unprepare(struct clk *clk)
+{
+	struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(clk);
+	struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
+	int ret;
+
+	if (!pnctrl_info->pinctrl || !pnctrl_info->sleep)
+		return;
+
+	ret = pinctrl_select_state(pnctrl_info->pinctrl,
+				   pnctrl_info->sleep);
+	if (ret)
+		pr_err("%s: sleep state select failed with %d\n",
+			__func__, ret);
+
+	clk2_config.enable = 0;
+	ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
+	if (ret < 0)
+		pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret);
+}
+
+static const struct clk_ops audio_ext_ap_clk_ops = {
+	.prepare = audio_ext_clk_prepare,
+	.unprepare = audio_ext_clk_unprepare,
+};
+
+static const struct clk_ops audio_ext_ap_clk2_ops = {
+	.prepare = audio_ext_clk2_prepare,
+	.unprepare = audio_ext_clk2_unprepare,
+};
+
+static struct audio_ext_pmi_clk audio_pmi_clk = {
+	.gpio = -EINVAL,
+	.c = {
+		.dbg_name = "audio_ext_pmi_clk",
+		.ops = &clk_ops_dummy,
+		CLK_INIT(audio_pmi_clk.c),
+	},
+};
+
+static struct audio_ext_pmi_clk audio_pmi_lnbb_clk = {
+	.gpio = -EINVAL,
+	.c = {
+		.dbg_name = "audio_ext_pmi_lnbb_clk",
+		.ops = &clk_ops_dummy,
+		CLK_INIT(audio_pmi_lnbb_clk.c),
+	},
+};
+
+static struct audio_ext_ap_clk audio_ap_clk = {
+	.gpio = -EINVAL,
+	.c = {
+		.dbg_name = "audio_ext_ap_clk",
+		.ops = &audio_ext_ap_clk_ops,
+		CLK_INIT(audio_ap_clk.c),
+	},
+};
+
+static struct audio_ext_ap_clk2 audio_ap_clk2 = {
+	.c = {
+		.dbg_name = "audio_ext_ap_clk2",
+		.ops = &audio_ext_ap_clk2_ops,
+		CLK_INIT(audio_ap_clk2.c),
+	},
+};
+
+static struct clk_lookup audio_ref_clock[] = {
+	CLK_LIST(audio_ap_clk),
+	CLK_LIST(audio_pmi_clk),
+	CLK_LIST(audio_pmi_lnbb_clk),
+	CLK_LIST(audio_ap_clk2),
+};
+
+static int audio_get_pinctrl(struct platform_device *pdev)
+{
+	struct pinctrl_info *pnctrl_info;
+	struct pinctrl *pinctrl;
+	int ret;
+
+	pnctrl_info = &audio_ap_clk2.pnctrl_info;
+
+	if (pnctrl_info->pinctrl) {
+		dev_dbg(&pdev->dev, "%s: already requested before\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR_OR_NULL(pinctrl)) {
+		dev_dbg(&pdev->dev, "%s: Unable to get pinctrl handle\n",
+			__func__);
+		return -EINVAL;
+	}
+	pnctrl_info->pinctrl = pinctrl;
+	/* get all state handles from Device Tree */
+	pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
+	if (IS_ERR(pnctrl_info->sleep)) {
+		dev_err(&pdev->dev, "%s: could not get sleep pinstate\n",
+			__func__);
+		goto err;
+	}
+	pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
+	if (IS_ERR(pnctrl_info->active)) {
+		dev_err(&pdev->dev, "%s: could not get active pinstate\n",
+			__func__);
+		goto err;
+	}
+	/* Reset the TLMM pins to a default state */
+	ret = pinctrl_select_state(pnctrl_info->pinctrl,
+				   pnctrl_info->sleep);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Disable TLMM pins failed with %d\n",
+			__func__, ret);
+		goto err;
+	}
+	return 0;
+
+err:
+	devm_pinctrl_put(pnctrl_info->pinctrl);
+	return -EINVAL;
+}
+
+static int audio_ref_clk_probe(struct platform_device *pdev)
+{
+	int clk_gpio;
+	int ret;
+	struct clk *audio_clk;
+
+	clk_gpio = of_get_named_gpio(pdev->dev.of_node,
+				     "qcom,audio-ref-clk-gpio", 0);
+	if (clk_gpio > 0) {
+		ret = gpio_request(clk_gpio, "EXT_CLK");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Request ext clk gpio failed %d, err:%d\n",
+				clk_gpio, ret);
+			goto err;
+		}
+		if (of_property_read_bool(pdev->dev.of_node,
+					"qcom,node_has_rpm_clock")) {
+			audio_clk = clk_get(&pdev->dev, NULL);
+			if (IS_ERR(audio_clk)) {
+				dev_err(&pdev->dev, "Failed to get RPM div clk\n");
+				ret = PTR_ERR(audio_clk);
+				goto err_gpio;
+			}
+			audio_pmi_clk.c.parent = audio_clk;
+			audio_pmi_clk.gpio = clk_gpio;
+		} else
+			audio_ap_clk.gpio = clk_gpio;
+
+	} else {
+		if (of_property_read_bool(pdev->dev.of_node,
+					"qcom,node_has_rpm_clock")) {
+			audio_clk = clk_get(&pdev->dev, NULL);
+			if (IS_ERR(audio_clk)) {
+				dev_err(&pdev->dev, "Failed to get lnbbclk2\n");
+				ret = PTR_ERR(audio_clk);
+				goto err;
+			}
+			audio_pmi_lnbb_clk.c.parent = audio_clk;
+			audio_pmi_lnbb_clk.gpio = -EINVAL;
+		}
+	}
+
+	ret = audio_get_pinctrl(pdev);
+	if (ret)
+		dev_dbg(&pdev->dev, "%s: Parsing pinctrl failed\n",
+			__func__);
+
+	ret = of_msm_clock_register(pdev->dev.of_node, audio_ref_clock,
+			      ARRAY_SIZE(audio_ref_clock));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: audio ref clock register failed\n",
+			__func__);
+		goto err_gpio;
+	}
+
+	return 0;
+
+err_gpio:
+	gpio_free(clk_gpio);
+
+err:
+	return ret;
+}
+
+static int audio_ref_clk_remove(struct platform_device *pdev)
+{
+	struct pinctrl_info *pnctrl_info = &audio_ap_clk2.pnctrl_info;
+
+	if (audio_pmi_clk.gpio > 0)
+		gpio_free(audio_pmi_clk.gpio);
+	else if (audio_ap_clk.gpio > 0)
+		gpio_free(audio_ap_clk.gpio);
+
+	if (pnctrl_info->pinctrl) {
+		devm_pinctrl_put(pnctrl_info->pinctrl);
+		pnctrl_info->pinctrl = NULL;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id audio_ref_clk_match[] = {
+	{.compatible = "qcom,audio-ref-clk"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
+
+static struct platform_driver audio_ref_clk_driver = {
+	.driver = {
+		.name = "audio-ref-clk",
+		.owner = THIS_MODULE,
+		.of_match_table = audio_ref_clk_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = audio_ref_clk_probe,
+	.remove = audio_ref_clk_remove,
+};
+
+int audio_ref_clk_platform_init(void)
+{
+	return platform_driver_register(&audio_ref_clk_driver);
+}
+
+void audio_ref_clk_platform_exit(void)
+{
+	platform_driver_unregister(&audio_ref_clk_driver);
+}
+
+MODULE_DESCRIPTION("Audio Ref Clock module platform driver");
+MODULE_LICENSE("GPL v2");

+ 163 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/Kbuild

@@ -0,0 +1,163 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_TRINKET), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KONA), y)
+		include $(AUDIO_ROOT)/config/konaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/konaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_WAIPIO), y)
+		include $(AUDIO_ROOT)/config/waipioauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/waipioautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_HOLI), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_BLAIR), y)
+		include $(AUDIO_ROOT)/config/holiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/holiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_LITO), y)
+		include $(AUDIO_ROOT)/config/litoauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KHAJE), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ BOLERO ############
+
+# for BOLERO Codec
+ifdef CONFIG_SND_SOC_BOLERO
+	BOLERO_OBJS += bolero-cdc.o
+	BOLERO_OBJS += bolero-cdc-utils.o
+	BOLERO_OBJS += bolero-cdc-regmap.o
+	BOLERO_OBJS += bolero-cdc-tables.o
+	BOLERO_OBJS += bolero-clk-rsc.o
+endif
+
+ifdef CONFIG_WSA_MACRO
+	WSA_OBJS += wsa-macro.o
+endif
+
+ifdef CONFIG_VA_MACRO
+	VA_OBJS += va-macro.o
+endif
+
+ifdef CONFIG_TX_MACRO
+	TX_OBJS += tx-macro.o
+endif
+
+ifdef CONFIG_RX_MACRO
+	RX_OBJS += rx-macro.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_BOLERO) += bolero_cdc_dlkm.o
+bolero_cdc_dlkm-y := $(BOLERO_OBJS)
+
+obj-$(CONFIG_WSA_MACRO) += wsa_macro_dlkm.o
+wsa_macro_dlkm-y := $(WSA_OBJS)
+
+obj-$(CONFIG_VA_MACRO) += va_macro_dlkm.o
+va_macro_dlkm-y := $(VA_OBJS)
+
+obj-$(CONFIG_TX_MACRO) += tx_macro_dlkm.o
+tx_macro_dlkm-y := $(TX_OBJS)
+
+obj-$(CONFIG_RX_MACRO) += rx_macro_dlkm.o
+rx_macro_dlkm-y := $(RX_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 6 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/Makefile

@@ -0,0 +1,6 @@
+modules:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) VERBOSE=1
+modules_install:
+	$(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean

+ 844 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-registers.h

@@ -0,0 +1,844 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _BOLERO_CDC_REGISTERS_H
+#define _BOLERO_CDC_REGISTERS_H
+
+#define TX_START_OFFSET 0x0000
+
+#define BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (TX_START_OFFSET + 0x0000)
+#define BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (TX_START_OFFSET + 0x0004)
+#define BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL	(TX_START_OFFSET + 0x0008)
+#define BOLERO_CDC_TX_TOP_CSR_TOP_CFG0		(TX_START_OFFSET + 0x0080)
+#define BOLERO_CDC_TX_TOP_CSR_ANC_CFG		(TX_START_OFFSET + 0x0084)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_CTRL		(TX_START_OFFSET + 0x0088)
+#define BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK		(TX_START_OFFSET + 0x0090)
+#define BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS		(TX_START_OFFSET + 0x0094)
+#define BOLERO_CDC_TX_TOP_CSR_DEBUG_EN		(TX_START_OFFSET + 0x0098)
+#define BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL	(TX_START_OFFSET + 0x00A4)
+#define BOLERO_CDC_TX_TOP_CSR_I2S_CLK		(TX_START_OFFSET + 0x00A8)
+#define BOLERO_CDC_TX_TOP_CSR_I2S_RESET		(TX_START_OFFSET + 0x00AC)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL	(TX_START_OFFSET + 0x00C0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL	(TX_START_OFFSET + 0x00C4)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL	(TX_START_OFFSET + 0x00C8)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL	(TX_START_OFFSET + 0x00CC)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL	(TX_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL	(TX_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL	(TX_START_OFFSET + 0x00C0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL	(TX_START_OFFSET + 0x00C4)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL	(TX_START_OFFSET + 0x00C8)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL	(TX_START_OFFSET + 0x00CC)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL	(TX_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL	(TX_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0	(TX_START_OFFSET + 0x0100)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1	(TX_START_OFFSET + 0x0104)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0	(TX_START_OFFSET + 0x0108)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1	(TX_START_OFFSET + 0x010C)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0	(TX_START_OFFSET + 0x0110)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1	(TX_START_OFFSET + 0x0114)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0	(TX_START_OFFSET + 0x0118)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1	(TX_START_OFFSET + 0x011C)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0	(TX_START_OFFSET + 0x0120)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG1	(TX_START_OFFSET + 0x0124)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0	(TX_START_OFFSET + 0x0128)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG1	(TX_START_OFFSET + 0x012C)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0	(TX_START_OFFSET + 0x0130)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG1	(TX_START_OFFSET + 0x0134)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0	(TX_START_OFFSET + 0x0138)
+#define BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG1	(TX_START_OFFSET + 0x013C)
+#define BOLERO_CDC_TX_ANC0_CLK_RESET_CTL	(TX_START_OFFSET + 0x0200)
+#define BOLERO_CDC_TX_ANC0_MODE_1_CTL		(TX_START_OFFSET + 0x0204)
+#define BOLERO_CDC_TX_ANC0_MODE_2_CTL		(TX_START_OFFSET + 0x0208)
+#define BOLERO_CDC_TX_ANC0_FF_SHIFT		(TX_START_OFFSET + 0x020C)
+#define BOLERO_CDC_TX_ANC0_FB_SHIFT		(TX_START_OFFSET + 0x0210)
+#define BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL	(TX_START_OFFSET + 0x0214)
+#define BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL	(TX_START_OFFSET + 0x0218)
+#define BOLERO_CDC_TX_ANC0_LPF_FB_CTL	(TX_START_OFFSET + 0x021C)
+#define BOLERO_CDC_TX_ANC0_SMLPF_CTL	(TX_START_OFFSET + 0x0220)
+#define BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL	(TX_START_OFFSET + 0x0224)
+#define BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL	(TX_START_OFFSET + 0x0228)
+#define BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL	(TX_START_OFFSET + 0x022C)
+#define BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL	(TX_START_OFFSET + 0x0230)
+#define BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL	(TX_START_OFFSET + 0x0234)
+#define BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL	(TX_START_OFFSET + 0x0238)
+#define BOLERO_CDC_TX_ANC0_FB_GAIN_CTL	(TX_START_OFFSET + 0x023C)
+#define BOLERO_CDC_TX0_TX_PATH_CTL	(TX_START_OFFSET + 0x0400)
+#define BOLERO_CDC_TX0_TX_PATH_CFG0	(TX_START_OFFSET + 0x0404)
+#define BOLERO_CDC_TX0_TX_PATH_CFG1	(TX_START_OFFSET + 0x0408)
+#define BOLERO_CDC_TX0_TX_VOL_CTL	(TX_START_OFFSET + 0x040C)
+#define BOLERO_CDC_TX0_TX_PATH_SEC0	(TX_START_OFFSET + 0x0410)
+#define BOLERO_CDC_TX0_TX_PATH_SEC1	(TX_START_OFFSET + 0x0414)
+#define BOLERO_CDC_TX0_TX_PATH_SEC2	(TX_START_OFFSET + 0x0418)
+#define BOLERO_CDC_TX0_TX_PATH_SEC3	(TX_START_OFFSET + 0x041C)
+#define BOLERO_CDC_TX0_TX_PATH_SEC4	(TX_START_OFFSET + 0x0420)
+#define BOLERO_CDC_TX0_TX_PATH_SEC5	(TX_START_OFFSET + 0x0424)
+#define BOLERO_CDC_TX0_TX_PATH_SEC6	(TX_START_OFFSET + 0x0428)
+#define BOLERO_CDC_TX0_TX_PATH_SEC7	(TX_START_OFFSET + 0x042C)
+#define BOLERO_CDC_TX1_TX_PATH_CTL	(TX_START_OFFSET + 0x0480)
+#define BOLERO_CDC_TX1_TX_PATH_CFG0	(TX_START_OFFSET + 0x0484)
+#define BOLERO_CDC_TX1_TX_PATH_CFG1	(TX_START_OFFSET + 0x0488)
+#define BOLERO_CDC_TX1_TX_VOL_CTL	(TX_START_OFFSET + 0x048C)
+#define BOLERO_CDC_TX1_TX_PATH_SEC0	(TX_START_OFFSET + 0x0490)
+#define BOLERO_CDC_TX1_TX_PATH_SEC1	(TX_START_OFFSET + 0x0494)
+#define BOLERO_CDC_TX1_TX_PATH_SEC2	(TX_START_OFFSET + 0x0498)
+#define BOLERO_CDC_TX1_TX_PATH_SEC3	(TX_START_OFFSET + 0x049C)
+#define BOLERO_CDC_TX1_TX_PATH_SEC4	(TX_START_OFFSET + 0x04A0)
+#define BOLERO_CDC_TX1_TX_PATH_SEC5	(TX_START_OFFSET + 0x04A4)
+#define BOLERO_CDC_TX1_TX_PATH_SEC6	(TX_START_OFFSET + 0x04A8)
+#define BOLERO_CDC_TX2_TX_PATH_CTL	(TX_START_OFFSET + 0x0500)
+#define BOLERO_CDC_TX2_TX_PATH_CFG0	(TX_START_OFFSET + 0x0504)
+#define BOLERO_CDC_TX2_TX_PATH_CFG1	(TX_START_OFFSET + 0x0508)
+#define BOLERO_CDC_TX2_TX_VOL_CTL	(TX_START_OFFSET + 0x050C)
+#define BOLERO_CDC_TX2_TX_PATH_SEC0	(TX_START_OFFSET + 0x0510)
+#define BOLERO_CDC_TX2_TX_PATH_SEC1	(TX_START_OFFSET + 0x0514)
+#define BOLERO_CDC_TX2_TX_PATH_SEC2	(TX_START_OFFSET + 0x0518)
+#define BOLERO_CDC_TX2_TX_PATH_SEC3	(TX_START_OFFSET + 0x051C)
+#define BOLERO_CDC_TX2_TX_PATH_SEC4	(TX_START_OFFSET + 0x0520)
+#define BOLERO_CDC_TX2_TX_PATH_SEC5	(TX_START_OFFSET + 0x0524)
+#define BOLERO_CDC_TX2_TX_PATH_SEC6	(TX_START_OFFSET + 0x0528)
+#define BOLERO_CDC_TX3_TX_PATH_CTL	(TX_START_OFFSET + 0x0580)
+#define BOLERO_CDC_TX3_TX_PATH_CFG0	(TX_START_OFFSET + 0x0584)
+#define BOLERO_CDC_TX3_TX_PATH_CFG1	(TX_START_OFFSET + 0x0588)
+#define BOLERO_CDC_TX3_TX_VOL_CTL	(TX_START_OFFSET + 0x058C)
+#define BOLERO_CDC_TX3_TX_PATH_SEC0	(TX_START_OFFSET + 0x0590)
+#define BOLERO_CDC_TX3_TX_PATH_SEC1	(TX_START_OFFSET + 0x0594)
+#define BOLERO_CDC_TX3_TX_PATH_SEC2	(TX_START_OFFSET + 0x0598)
+#define BOLERO_CDC_TX3_TX_PATH_SEC3	(TX_START_OFFSET + 0x059C)
+#define BOLERO_CDC_TX3_TX_PATH_SEC4	(TX_START_OFFSET + 0x05A0)
+#define BOLERO_CDC_TX3_TX_PATH_SEC5	(TX_START_OFFSET + 0x05A4)
+#define BOLERO_CDC_TX3_TX_PATH_SEC6	(TX_START_OFFSET + 0x05A8)
+#define BOLERO_CDC_TX4_TX_PATH_CTL	(TX_START_OFFSET + 0x0600)
+#define BOLERO_CDC_TX4_TX_PATH_CFG0	(TX_START_OFFSET + 0x0604)
+#define BOLERO_CDC_TX4_TX_PATH_CFG1	(TX_START_OFFSET + 0x0608)
+#define BOLERO_CDC_TX4_TX_VOL_CTL	(TX_START_OFFSET + 0x060C)
+#define BOLERO_CDC_TX4_TX_PATH_SEC0	(TX_START_OFFSET + 0x0610)
+#define BOLERO_CDC_TX4_TX_PATH_SEC1	(TX_START_OFFSET + 0x0614)
+#define BOLERO_CDC_TX4_TX_PATH_SEC2	(TX_START_OFFSET + 0x0618)
+#define BOLERO_CDC_TX4_TX_PATH_SEC3	(TX_START_OFFSET + 0x061C)
+#define BOLERO_CDC_TX4_TX_PATH_SEC4	(TX_START_OFFSET + 0x0620)
+#define BOLERO_CDC_TX4_TX_PATH_SEC5	(TX_START_OFFSET + 0x0624)
+#define BOLERO_CDC_TX4_TX_PATH_SEC6	(TX_START_OFFSET + 0x0628)
+#define BOLERO_CDC_TX5_TX_PATH_CTL	(TX_START_OFFSET + 0x0680)
+#define BOLERO_CDC_TX5_TX_PATH_CFG0	(TX_START_OFFSET + 0x0684)
+#define BOLERO_CDC_TX5_TX_PATH_CFG1	(TX_START_OFFSET + 0x0688)
+#define BOLERO_CDC_TX5_TX_VOL_CTL	(TX_START_OFFSET + 0x068C)
+#define BOLERO_CDC_TX5_TX_PATH_SEC0	(TX_START_OFFSET + 0x0690)
+#define BOLERO_CDC_TX5_TX_PATH_SEC1	(TX_START_OFFSET + 0x0694)
+#define BOLERO_CDC_TX5_TX_PATH_SEC2	(TX_START_OFFSET + 0x0698)
+#define BOLERO_CDC_TX5_TX_PATH_SEC3	(TX_START_OFFSET + 0x069C)
+#define BOLERO_CDC_TX5_TX_PATH_SEC4	(TX_START_OFFSET + 0x06A0)
+#define BOLERO_CDC_TX5_TX_PATH_SEC5	(TX_START_OFFSET + 0x06A4)
+#define BOLERO_CDC_TX5_TX_PATH_SEC6	(TX_START_OFFSET + 0x06A8)
+#define BOLERO_CDC_TX6_TX_PATH_CTL	(TX_START_OFFSET + 0x0700)
+#define BOLERO_CDC_TX6_TX_PATH_CFG0	(TX_START_OFFSET + 0x0704)
+#define BOLERO_CDC_TX6_TX_PATH_CFG1	(TX_START_OFFSET + 0x0708)
+#define BOLERO_CDC_TX6_TX_VOL_CTL	(TX_START_OFFSET + 0x070C)
+#define BOLERO_CDC_TX6_TX_PATH_SEC0	(TX_START_OFFSET + 0x0710)
+#define BOLERO_CDC_TX6_TX_PATH_SEC1	(TX_START_OFFSET + 0x0714)
+#define BOLERO_CDC_TX6_TX_PATH_SEC2	(TX_START_OFFSET + 0x0718)
+#define BOLERO_CDC_TX6_TX_PATH_SEC3	(TX_START_OFFSET + 0x071C)
+#define BOLERO_CDC_TX6_TX_PATH_SEC4	(TX_START_OFFSET + 0x0720)
+#define BOLERO_CDC_TX6_TX_PATH_SEC5	(TX_START_OFFSET + 0x0724)
+#define BOLERO_CDC_TX6_TX_PATH_SEC6	(TX_START_OFFSET + 0x0728)
+#define BOLERO_CDC_TX7_TX_PATH_CTL	(TX_START_OFFSET + 0x0780)
+#define BOLERO_CDC_TX7_TX_PATH_CFG0	(TX_START_OFFSET + 0x0784)
+#define BOLERO_CDC_TX7_TX_PATH_CFG1	(TX_START_OFFSET + 0x0788)
+#define BOLERO_CDC_TX7_TX_VOL_CTL	(TX_START_OFFSET + 0x078C)
+#define BOLERO_CDC_TX7_TX_PATH_SEC0	(TX_START_OFFSET + 0x0790)
+#define BOLERO_CDC_TX7_TX_PATH_SEC1	(TX_START_OFFSET + 0x0794)
+#define BOLERO_CDC_TX7_TX_PATH_SEC2	(TX_START_OFFSET + 0x0798)
+#define BOLERO_CDC_TX7_TX_PATH_SEC3	(TX_START_OFFSET + 0x079C)
+#define BOLERO_CDC_TX7_TX_PATH_SEC4	(TX_START_OFFSET + 0x07A0)
+#define BOLERO_CDC_TX7_TX_PATH_SEC5	(TX_START_OFFSET + 0x07A4)
+#define BOLERO_CDC_TX7_TX_PATH_SEC6	(TX_START_OFFSET + 0x07A8)
+#define TX_MAX_OFFSET			(TX_START_OFFSET + 0x07A8)
+
+#define BOLERO_CDC_TX_MACRO_MAX 0x1EB /* 7A8/4 = 1EA + 1 */
+
+#define RX_START_OFFSET				0x1000
+#define BOLERO_CDC_RX_TOP_TOP_CFG0		(RX_START_OFFSET + 0x0000)
+#define BOLERO_CDC_RX_TOP_SWR_CTRL		(RX_START_OFFSET + 0x0008)
+#define BOLERO_CDC_RX_TOP_DEBUG			(RX_START_OFFSET + 0x000C)
+#define BOLERO_CDC_RX_TOP_DEBUG_BUS		(RX_START_OFFSET + 0x0010)
+#define BOLERO_CDC_RX_TOP_DEBUG_EN0		(RX_START_OFFSET + 0x0014)
+#define BOLERO_CDC_RX_TOP_DEBUG_EN1		(RX_START_OFFSET + 0x0018)
+#define BOLERO_CDC_RX_TOP_DEBUG_EN2		(RX_START_OFFSET + 0x001C)
+#define BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB	(RX_START_OFFSET + 0x0020)
+#define BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB	(RX_START_OFFSET + 0x0024)
+#define BOLERO_CDC_RX_TOP_HPHL_COMP_LUT		(RX_START_OFFSET + 0x0028)
+#define BOLERO_CDC_RX_TOP_HPHL_COMP_RD_LSB	(RX_START_OFFSET + 0x002C)
+#define BOLERO_CDC_RX_TOP_HPHL_COMP_RD_MSB	(RX_START_OFFSET + 0x0030)
+#define BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB	(RX_START_OFFSET + 0x0034)
+#define BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB	(RX_START_OFFSET + 0x0038)
+#define BOLERO_CDC_RX_TOP_HPHR_COMP_LUT		(RX_START_OFFSET + 0x003C)
+#define BOLERO_CDC_RX_TOP_HPHR_COMP_RD_LSB	(RX_START_OFFSET + 0x0040)
+#define BOLERO_CDC_RX_TOP_HPHR_COMP_RD_MSB	(RX_START_OFFSET + 0x0044)
+#define BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG0	(RX_START_OFFSET + 0x0070)
+#define BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG1	(RX_START_OFFSET + 0x0074)
+#define BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG2	(RX_START_OFFSET + 0x0078)
+#define BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG3	(RX_START_OFFSET + 0x007C)
+#define BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG0	(RX_START_OFFSET + 0x0080)
+#define BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG1	(RX_START_OFFSET + 0x0084)
+#define BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG2	(RX_START_OFFSET + 0x0088)
+#define BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG3	(RX_START_OFFSET + 0x008C)
+#define BOLERO_CDC_RX_TOP_RX_I2S_CTL		(RX_START_OFFSET + 0x0090)
+#define BOLERO_CDC_RX_TOP_TX_I2S2_CTL		(RX_START_OFFSET + 0x0094)
+#define BOLERO_CDC_RX_TOP_I2S_CLK		(RX_START_OFFSET + 0x0098)
+#define BOLERO_CDC_RX_TOP_I2S_RESET		(RX_START_OFFSET + 0x009C)
+#define BOLERO_CDC_RX_TOP_I2S_MUX		(RX_START_OFFSET + 0x00A0)
+#define BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL	(RX_START_OFFSET + 0x0100)
+#define BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(RX_START_OFFSET + 0x0104)
+#define BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL	(RX_START_OFFSET + 0x0108)
+#define BOLERO_CDC_RX_CLK_RST_CTRL_DSD_CONTROL	(RX_START_OFFSET + 0x010C)
+#define BOLERO_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL \
+						(RX_START_OFFSET + 0x0110)
+#define BOLERO_CDC_RX_SOFTCLIP_CRC		(RX_START_OFFSET + 0x0140)
+#define BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL	(RX_START_OFFSET + 0x0144)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG0	(RX_START_OFFSET + 0x0180)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1	(RX_START_OFFSET + 0x0184)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0	(RX_START_OFFSET + 0x0188)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1	(RX_START_OFFSET + 0x018C)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG0	(RX_START_OFFSET + 0x0190)
+#define BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG1	(RX_START_OFFSET + 0x0194)
+#define BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG4	(RX_START_OFFSET + 0x0198)
+#define BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG5	(RX_START_OFFSET + 0x019C)
+#define BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0	(RX_START_OFFSET + 0x01A0)
+#define BOLERO_CDC_RX_CLSH_CRC			(RX_START_OFFSET + 0x0200)
+#define BOLERO_CDC_RX_CLSH_DLY_CTRL		(RX_START_OFFSET + 0x0204)
+#define BOLERO_CDC_RX_CLSH_DECAY_CTRL		(RX_START_OFFSET + 0x0208)
+#define BOLERO_CDC_RX_CLSH_HPH_V_PA		(RX_START_OFFSET + 0x020C)
+#define BOLERO_CDC_RX_CLSH_EAR_V_PA		(RX_START_OFFSET + 0x0210)
+#define BOLERO_CDC_RX_CLSH_HPH_V_HD		(RX_START_OFFSET + 0x0214)
+#define BOLERO_CDC_RX_CLSH_EAR_V_HD		(RX_START_OFFSET + 0x0218)
+#define BOLERO_CDC_RX_CLSH_K1_MSB		(RX_START_OFFSET + 0x021C)
+#define BOLERO_CDC_RX_CLSH_K1_LSB		(RX_START_OFFSET + 0x0220)
+#define BOLERO_CDC_RX_CLSH_K2_MSB		(RX_START_OFFSET + 0x0224)
+#define BOLERO_CDC_RX_CLSH_K2_LSB		(RX_START_OFFSET + 0x0228)
+#define BOLERO_CDC_RX_CLSH_IDLE_CTRL		(RX_START_OFFSET + 0x022C)
+#define BOLERO_CDC_RX_CLSH_IDLE_HPH		(RX_START_OFFSET + 0x0230)
+#define BOLERO_CDC_RX_CLSH_IDLE_EAR		(RX_START_OFFSET + 0x0234)
+#define BOLERO_CDC_RX_CLSH_TEST0		(RX_START_OFFSET + 0x0238)
+#define BOLERO_CDC_RX_CLSH_TEST1		(RX_START_OFFSET + 0x023C)
+#define BOLERO_CDC_RX_CLSH_OVR_VREF		(RX_START_OFFSET + 0x0240)
+#define BOLERO_CDC_RX_CLSH_CLSG_CTL		(RX_START_OFFSET + 0x0244)
+#define BOLERO_CDC_RX_CLSH_CLSG_CFG1		(RX_START_OFFSET + 0x0248)
+#define BOLERO_CDC_RX_CLSH_CLSG_CFG2		(RX_START_OFFSET + 0x024C)
+#define BOLERO_CDC_RX_BCL_VBAT_PATH_CTL		(RX_START_OFFSET + 0x0280)
+#define BOLERO_CDC_RX_BCL_VBAT_CFG		(RX_START_OFFSET + 0x0284)
+#define BOLERO_CDC_RX_BCL_VBAT_ADC_CAL1		(RX_START_OFFSET + 0x0288)
+#define BOLERO_CDC_RX_BCL_VBAT_ADC_CAL2		(RX_START_OFFSET + 0x028C)
+#define BOLERO_CDC_RX_BCL_VBAT_ADC_CAL3		(RX_START_OFFSET + 0x0290)
+#define BOLERO_CDC_RX_BCL_VBAT_PK_EST1		(RX_START_OFFSET + 0x0294)
+#define BOLERO_CDC_RX_BCL_VBAT_PK_EST2		(RX_START_OFFSET + 0x0298)
+#define BOLERO_CDC_RX_BCL_VBAT_PK_EST3		(RX_START_OFFSET + 0x029C)
+#define BOLERO_CDC_RX_BCL_VBAT_RF_PROC1		(RX_START_OFFSET + 0x02A0)
+#define BOLERO_CDC_RX_BCL_VBAT_RF_PROC2		(RX_START_OFFSET + 0x02A4)
+#define BOLERO_CDC_RX_BCL_VBAT_TAC1		(RX_START_OFFSET + 0x02A8)
+#define BOLERO_CDC_RX_BCL_VBAT_TAC2		(RX_START_OFFSET + 0x02AC)
+#define BOLERO_CDC_RX_BCL_VBAT_TAC3		(RX_START_OFFSET + 0x02B0)
+#define BOLERO_CDC_RX_BCL_VBAT_TAC4		(RX_START_OFFSET + 0x02B4)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD1	(RX_START_OFFSET + 0x02B8)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD2	(RX_START_OFFSET + 0x02BC)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD3	(RX_START_OFFSET + 0x02C0)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD4	(RX_START_OFFSET + 0x02C4)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD5	(RX_START_OFFSET + 0x02C8)
+#define BOLERO_CDC_RX_BCL_VBAT_DEBUG1		(RX_START_OFFSET + 0x02CC)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD_MON	(RX_START_OFFSET + 0x02D0)
+#define BOLERO_CDC_RX_BCL_VBAT_GAIN_MON_VAL	(RX_START_OFFSET + 0x02D4)
+#define BOLERO_CDC_RX_BCL_VBAT_BAN		(RX_START_OFFSET + 0x02D8)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1	(RX_START_OFFSET + 0x02DC)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2	(RX_START_OFFSET + 0x02E0)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3	(RX_START_OFFSET + 0x02E4)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4	(RX_START_OFFSET + 0x02E8)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5	(RX_START_OFFSET + 0x02EC)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6	(RX_START_OFFSET + 0x02F0)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7	(RX_START_OFFSET + 0x02F4)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8	(RX_START_OFFSET + 0x02F8)
+#define BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9	(RX_START_OFFSET + 0x02FC)
+#define BOLERO_CDC_RX_BCL_VBAT_ATTN1		(RX_START_OFFSET + 0x0300)
+#define BOLERO_CDC_RX_BCL_VBAT_ATTN2		(RX_START_OFFSET + 0x0304)
+#define BOLERO_CDC_RX_BCL_VBAT_ATTN3		(RX_START_OFFSET + 0x0308)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1	(RX_START_OFFSET + 0x030C)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL2	(RX_START_OFFSET + 0x0310)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1	(RX_START_OFFSET + 0x0314)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2	(RX_START_OFFSET + 0x0318)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3	(RX_START_OFFSET + 0x031C)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG4	(RX_START_OFFSET + 0x0320)
+#define BOLERO_CDC_RX_BCL_VBAT_DECODE_ST	(RX_START_OFFSET + 0x0324)
+#define BOLERO_CDC_RX_INTR_CTRL_CFG		(RX_START_OFFSET + 0x0340)
+#define BOLERO_CDC_RX_INTR_CTRL_CLR_COMMIT	(RX_START_OFFSET + 0x0344)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN1_MASK0	(RX_START_OFFSET + 0x0360)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN1_STATUS0	(RX_START_OFFSET + 0x0368)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN1_CLEAR0	(RX_START_OFFSET + 0x0370)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN2_MASK0	(RX_START_OFFSET + 0x0380)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN2_STATUS0	(RX_START_OFFSET + 0x0388)
+#define BOLERO_CDC_RX_INTR_CTRL_PIN2_CLEAR0	(RX_START_OFFSET + 0x0390)
+#define BOLERO_CDC_RX_INTR_CTRL_LEVEL0		(RX_START_OFFSET + 0x03C0)
+#define BOLERO_CDC_RX_INTR_CTRL_BYPASS0		(RX_START_OFFSET + 0x03C8)
+#define BOLERO_CDC_RX_INTR_CTRL_SET0		(RX_START_OFFSET + 0x03D0)
+#define BOLERO_CDC_RX_RX0_RX_PATH_CTL		(RX_START_OFFSET + 0x0400)
+#define BOLERO_CDC_RX_RX0_RX_PATH_CFG0		(RX_START_OFFSET + 0x0404)
+#define BOLERO_CDC_RX_RX0_RX_PATH_CFG1		(RX_START_OFFSET + 0x0408)
+#define BOLERO_CDC_RX_RX0_RX_PATH_CFG2		(RX_START_OFFSET + 0x040C)
+#define BOLERO_CDC_RX_RX0_RX_PATH_CFG3		(RX_START_OFFSET + 0x0410)
+#define BOLERO_CDC_RX_RX0_RX_VOL_CTL		(RX_START_OFFSET + 0x0414)
+#define BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0418)
+#define BOLERO_CDC_RX_RX0_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x041C)
+#define BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x0420)
+#define BOLERO_CDC_RX_RX0_RX_PATH_SEC1		(RX_START_OFFSET + 0x0424)
+#define BOLERO_CDC_RX_RX0_RX_PATH_SEC2		(RX_START_OFFSET + 0x0428)
+#define BOLERO_CDC_RX_RX0_RX_PATH_SEC3		(RX_START_OFFSET + 0x042C)
+#define BOLERO_CDC_RX_RX0_RX_PATH_SEC4		(RX_START_OFFSET + 0x0430)
+#define BOLERO_CDC_RX_RX0_RX_PATH_SEC7		(RX_START_OFFSET + 0x0434)
+#define BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x0438)
+#define BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x043C)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x0440)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA1	(RX_START_OFFSET + 0x0444)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA2	(RX_START_OFFSET + 0x0448)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA3	(RX_START_OFFSET + 0x044C)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA4	(RX_START_OFFSET + 0x0450)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA5	(RX_START_OFFSET + 0x0454)
+#define BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA6	(RX_START_OFFSET + 0x0458)
+#define BOLERO_CDC_RX_RX1_RX_PATH_CTL		(RX_START_OFFSET + 0x0480)
+#define BOLERO_CDC_RX_RX1_RX_PATH_CFG0		(RX_START_OFFSET + 0x0484)
+#define BOLERO_CDC_RX_RX1_RX_PATH_CFG1		(RX_START_OFFSET + 0x0488)
+#define BOLERO_CDC_RX_RX1_RX_PATH_CFG2		(RX_START_OFFSET + 0x048C)
+#define BOLERO_CDC_RX_RX1_RX_PATH_CFG3		(RX_START_OFFSET + 0x0490)
+#define BOLERO_CDC_RX_RX1_RX_VOL_CTL		(RX_START_OFFSET + 0x0494)
+#define BOLERO_CDC_RX_RX1_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0498)
+#define BOLERO_CDC_RX_RX1_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x049C)
+#define BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x04A0)
+#define BOLERO_CDC_RX_RX1_RX_PATH_SEC1		(RX_START_OFFSET + 0x04A4)
+#define BOLERO_CDC_RX_RX1_RX_PATH_SEC2		(RX_START_OFFSET + 0x04A8)
+#define BOLERO_CDC_RX_RX1_RX_PATH_SEC3		(RX_START_OFFSET + 0x04AC)
+#define BOLERO_CDC_RX_RX1_RX_PATH_SEC4		(RX_START_OFFSET + 0x04B0)
+#define BOLERO_CDC_RX_RX1_RX_PATH_SEC7		(RX_START_OFFSET + 0x04B4)
+#define BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x04B8)
+#define BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x04BC)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x04C0)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA1	(RX_START_OFFSET + 0x04C4)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA2	(RX_START_OFFSET + 0x04C8)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA3	(RX_START_OFFSET + 0x04CC)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA4	(RX_START_OFFSET + 0x04D0)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA5	(RX_START_OFFSET + 0x04D4)
+#define BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA6	(RX_START_OFFSET + 0x04D8)
+#define BOLERO_CDC_RX_RX2_RX_PATH_CTL		(RX_START_OFFSET + 0x0500)
+#define BOLERO_CDC_RX_RX2_RX_PATH_CFG0		(RX_START_OFFSET + 0x0504)
+#define BOLERO_CDC_RX_RX2_RX_PATH_CFG1		(RX_START_OFFSET + 0x0508)
+#define BOLERO_CDC_RX_RX2_RX_PATH_CFG2		(RX_START_OFFSET + 0x050C)
+#define BOLERO_CDC_RX_RX2_RX_PATH_CFG3		(RX_START_OFFSET + 0x0510)
+#define BOLERO_CDC_RX_RX2_RX_VOL_CTL		(RX_START_OFFSET + 0x0514)
+#define BOLERO_CDC_RX_RX2_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0518)
+#define BOLERO_CDC_RX_RX2_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x051C)
+#define BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x0520)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC0		(RX_START_OFFSET + 0x0524)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC1		(RX_START_OFFSET + 0x0528)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC2		(RX_START_OFFSET + 0x052C)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC3		(RX_START_OFFSET + 0x0530)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC4		(RX_START_OFFSET + 0x0534)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC5		(RX_START_OFFSET + 0x0538)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC6		(RX_START_OFFSET + 0x053C)
+#define BOLERO_CDC_RX_RX2_RX_PATH_SEC7		(RX_START_OFFSET + 0x0540)
+#define BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x0544)
+#define BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x0548)
+#define BOLERO_CDC_RX_RX2_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x054C)
+#define BOLERO_CDC_RX_IDLE_DETECT_PATH_CTL	(RX_START_OFFSET + 0x0780)
+#define BOLERO_CDC_RX_IDLE_DETECT_CFG0		(RX_START_OFFSET + 0x0784)
+#define BOLERO_CDC_RX_IDLE_DETECT_CFG1		(RX_START_OFFSET + 0x0788)
+#define BOLERO_CDC_RX_IDLE_DETECT_CFG2		(RX_START_OFFSET + 0x078C)
+#define BOLERO_CDC_RX_IDLE_DETECT_CFG3		(RX_START_OFFSET + 0x0790)
+#define BOLERO_CDC_RX_COMPANDER0_CTL0		(RX_START_OFFSET + 0x0800)
+#define BOLERO_CDC_RX_COMPANDER0_CTL1		(RX_START_OFFSET + 0x0804)
+#define BOLERO_CDC_RX_COMPANDER0_CTL2		(RX_START_OFFSET + 0x0808)
+#define BOLERO_CDC_RX_COMPANDER0_CTL3		(RX_START_OFFSET + 0x080C)
+#define BOLERO_CDC_RX_COMPANDER0_CTL4		(RX_START_OFFSET + 0x0810)
+#define BOLERO_CDC_RX_COMPANDER0_CTL5		(RX_START_OFFSET + 0x0814)
+#define BOLERO_CDC_RX_COMPANDER0_CTL6		(RX_START_OFFSET + 0x0818)
+#define BOLERO_CDC_RX_COMPANDER0_CTL7		(RX_START_OFFSET + 0x081C)
+#define BOLERO_CDC_RX_COMPANDER1_CTL0		(RX_START_OFFSET + 0x0840)
+#define BOLERO_CDC_RX_COMPANDER1_CTL1		(RX_START_OFFSET + 0x0844)
+#define BOLERO_CDC_RX_COMPANDER1_CTL2		(RX_START_OFFSET + 0x0848)
+#define BOLERO_CDC_RX_COMPANDER1_CTL3		(RX_START_OFFSET + 0x084C)
+#define BOLERO_CDC_RX_COMPANDER1_CTL4		(RX_START_OFFSET + 0x0850)
+#define BOLERO_CDC_RX_COMPANDER1_CTL5		(RX_START_OFFSET + 0x0854)
+#define BOLERO_CDC_RX_COMPANDER1_CTL6		(RX_START_OFFSET + 0x0858)
+#define BOLERO_CDC_RX_COMPANDER1_CTL7		(RX_START_OFFSET + 0x085C)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL \
+						(RX_START_OFFSET + 0x0A00)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL \
+						(RX_START_OFFSET + 0x0A04)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL \
+						(RX_START_OFFSET + 0x0A08)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL \
+						(RX_START_OFFSET + 0x0A0C)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL \
+						(RX_START_OFFSET + 0x0A10)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL \
+						(RX_START_OFFSET + 0x0A14)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL \
+						(RX_START_OFFSET + 0x0A18)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL \
+						(RX_START_OFFSET + 0x0A1C)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL \
+						(RX_START_OFFSET + 0x0A20)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_CTL	(RX_START_OFFSET + 0x0A24)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL \
+						(RX_START_OFFSET + 0x0A28)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL \
+						(RX_START_OFFSET + 0x0A2C)
+#define BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL \
+						(RX_START_OFFSET + 0x0A30)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL \
+						(RX_START_OFFSET + 0x0A80)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL \
+						(RX_START_OFFSET + 0x0A84)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL \
+						(RX_START_OFFSET + 0x0A88)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL \
+						(RX_START_OFFSET + 0x0A8C)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL \
+						(RX_START_OFFSET + 0x0A90)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL \
+						(RX_START_OFFSET + 0x0A94)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL \
+						(RX_START_OFFSET + 0x0A98)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL \
+						(RX_START_OFFSET + 0x0A9C)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL \
+						(RX_START_OFFSET + 0x0AA0)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_CTL	(RX_START_OFFSET + 0x0AA4)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL \
+						(RX_START_OFFSET + 0x0AA8)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL \
+						(RX_START_OFFSET + 0x0AAC)
+#define BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL \
+						(RX_START_OFFSET + 0x0AB0)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0	(RX_START_OFFSET + 0x0B00)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1	(RX_START_OFFSET + 0x0B04)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2	(RX_START_OFFSET + 0x0B08)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3	(RX_START_OFFSET + 0x0B0C)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0	(RX_START_OFFSET + 0x0B10)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1	(RX_START_OFFSET + 0x0B14)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2	(RX_START_OFFSET + 0x0B18)
+#define BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3	(RX_START_OFFSET + 0x0B1C)
+#define BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL \
+						(RX_START_OFFSET + 0x0B40)
+#define BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1 \
+						(RX_START_OFFSET + 0x0B44)
+#define BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL \
+						(RX_START_OFFSET + 0x0B50)
+#define BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1 \
+						(RX_START_OFFSET + 0x0B54)
+#define BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C00)
+#define BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C04)
+#define BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C40)
+#define BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C44)
+#define BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C80)
+#define BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C84)
+#define BOLERO_CDC_RX_EC_ASRC0_CLK_RST_CTL	(RX_START_OFFSET + 0x0D00)
+#define BOLERO_CDC_RX_EC_ASRC0_CTL0		(RX_START_OFFSET + 0x0D04)
+#define BOLERO_CDC_RX_EC_ASRC0_CTL1		(RX_START_OFFSET + 0x0D08)
+#define BOLERO_CDC_RX_EC_ASRC0_FIFO_CTL		(RX_START_OFFSET + 0x0D0C)
+#define BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D10)
+#define BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D14)
+#define BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D18)
+#define BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D1C)
+#define BOLERO_CDC_RX_EC_ASRC0_STATUS_FIFO	(RX_START_OFFSET + 0x0D20)
+#define BOLERO_CDC_RX_EC_ASRC1_CLK_RST_CTL	(RX_START_OFFSET + 0x0D40)
+#define BOLERO_CDC_RX_EC_ASRC1_CTL0		(RX_START_OFFSET + 0x0D44)
+#define BOLERO_CDC_RX_EC_ASRC1_CTL1		(RX_START_OFFSET + 0x0D48)
+#define BOLERO_CDC_RX_EC_ASRC1_FIFO_CTL		(RX_START_OFFSET + 0x0D4C)
+#define BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D50)
+#define BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D54)
+#define BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D58)
+#define BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D5C)
+#define BOLERO_CDC_RX_EC_ASRC1_STATUS_FIFO	(RX_START_OFFSET + 0x0D60)
+#define BOLERO_CDC_RX_EC_ASRC2_CLK_RST_CTL	(RX_START_OFFSET + 0x0D80)
+#define BOLERO_CDC_RX_EC_ASRC2_CTL0		(RX_START_OFFSET + 0x0D84)
+#define BOLERO_CDC_RX_EC_ASRC2_CTL1		(RX_START_OFFSET + 0x0D88)
+#define BOLERO_CDC_RX_EC_ASRC2_FIFO_CTL		(RX_START_OFFSET + 0x0D8C)
+#define BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D90)
+#define BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D94)
+#define BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D98)
+#define BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D9C)
+#define BOLERO_CDC_RX_EC_ASRC2_STATUS_FIFO	(RX_START_OFFSET + 0x0DA0)
+#define BOLERO_CDC_RX_DSD0_PATH_CTL		(RX_START_OFFSET + 0x0F00)
+#define BOLERO_CDC_RX_DSD0_CFG0			(RX_START_OFFSET + 0x0F04)
+#define BOLERO_CDC_RX_DSD0_CFG1			(RX_START_OFFSET + 0x0F08)
+#define BOLERO_CDC_RX_DSD0_CFG2			(RX_START_OFFSET + 0x0F0C)
+#define BOLERO_CDC_RX_DSD1_PATH_CTL		(RX_START_OFFSET + 0x0F80)
+#define BOLERO_CDC_RX_DSD1_CFG0			(RX_START_OFFSET + 0x0F84)
+#define BOLERO_CDC_RX_DSD1_CFG1			(RX_START_OFFSET + 0x0F88)
+#define BOLERO_CDC_RX_DSD1_CFG2			(RX_START_OFFSET + 0x0F8C)
+#define RX_MAX_OFFSET				(RX_START_OFFSET + 0x0F8C)
+
+#define BOLERO_CDC_RX_MACRO_MAX 0x3E4 /* F8C/4 = 3E3 + 1 */
+
+/* WSA - macro#2 */
+#define WSA_START_OFFSET			0x2000
+#define BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL \
+						(WSA_START_OFFSET + 0x0000)
+#define BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(WSA_START_OFFSET + 0x0004)
+#define BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL	(WSA_START_OFFSET + 0x0008)
+#define BOLERO_CDC_WSA_TOP_TOP_CFG0		(WSA_START_OFFSET + 0x0080)
+#define BOLERO_CDC_WSA_TOP_TOP_CFG1		(WSA_START_OFFSET + 0x0084)
+#define BOLERO_CDC_WSA_TOP_FREQ_MCLK		(WSA_START_OFFSET + 0x0088)
+#define BOLERO_CDC_WSA_TOP_DEBUG_BUS_SEL	(WSA_START_OFFSET + 0x008C)
+#define BOLERO_CDC_WSA_TOP_DEBUG_EN0		(WSA_START_OFFSET + 0x0090)
+#define BOLERO_CDC_WSA_TOP_DEBUG_EN1		(WSA_START_OFFSET + 0x0094)
+#define BOLERO_CDC_WSA_TOP_DEBUG_DSM_LB		(WSA_START_OFFSET + 0x0098)
+#define BOLERO_CDC_WSA_TOP_RX_I2S_CTL		(WSA_START_OFFSET + 0x009C)
+#define BOLERO_CDC_WSA_TOP_TX_I2S_CTL		(WSA_START_OFFSET + 0x00A0)
+#define BOLERO_CDC_WSA_TOP_I2S_CLK		(WSA_START_OFFSET + 0x00A4)
+#define BOLERO_CDC_WSA_TOP_I2S_RESET		(WSA_START_OFFSET + 0x00A8)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0	(WSA_START_OFFSET + 0x0100)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1	(WSA_START_OFFSET + 0x0104)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0	(WSA_START_OFFSET + 0x0108)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1	(WSA_START_OFFSET + 0x010C)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0	(WSA_START_OFFSET + 0x0110)
+#define BOLERO_CDC_WSA_RX_INP_MUX_RX_EC_CFG0	(WSA_START_OFFSET + 0x0114)
+#define BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0	(WSA_START_OFFSET + 0x0118)
+/* VBAT registers  */
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL	(WSA_START_OFFSET + 0x0180)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG	(WSA_START_OFFSET + 0x0184)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1	(WSA_START_OFFSET + 0x0188)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2	(WSA_START_OFFSET + 0x018C)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3	(WSA_START_OFFSET + 0x0190)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST1	(WSA_START_OFFSET + 0x0194)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST2	(WSA_START_OFFSET + 0x0198)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST3	(WSA_START_OFFSET + 0x019C)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1	(WSA_START_OFFSET + 0x01A0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2	(WSA_START_OFFSET + 0x01A4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC1	(WSA_START_OFFSET + 0x01A8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC2	(WSA_START_OFFSET + 0x01AC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC3	(WSA_START_OFFSET + 0x01B0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC4	(WSA_START_OFFSET + 0x01B4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1	(WSA_START_OFFSET + 0x01B8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2	(WSA_START_OFFSET + 0x01BC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3	(WSA_START_OFFSET + 0x01C0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4	(WSA_START_OFFSET + 0x01C4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5	(WSA_START_OFFSET + 0x01C8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DEBUG1	(WSA_START_OFFSET + 0x01CC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON \
+						(WSA_START_OFFSET + 0x01D0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL \
+						(WSA_START_OFFSET + 0x01D4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BAN	(WSA_START_OFFSET + 0x01D8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1 \
+						(WSA_START_OFFSET + 0x01DC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2 \
+						(WSA_START_OFFSET + 0x01E0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3 \
+						(WSA_START_OFFSET + 0x01E4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4 \
+						(WSA_START_OFFSET + 0x01E8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5 \
+						(WSA_START_OFFSET + 0x01EC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6 \
+						(WSA_START_OFFSET + 0x01F0)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7 \
+						(WSA_START_OFFSET + 0x01F4)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8 \
+						(WSA_START_OFFSET + 0x01F8)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9 \
+						(WSA_START_OFFSET + 0x01FC)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1	(WSA_START_OFFSET + 0x0200)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2	(WSA_START_OFFSET + 0x0204)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3	(WSA_START_OFFSET + 0x0208)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1 \
+						(WSA_START_OFFSET + 0x020C)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2 \
+						(WSA_START_OFFSET + 0x0210)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1 \
+						(WSA_START_OFFSET + 0x0214)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2 \
+						(WSA_START_OFFSET + 0x0218)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3 \
+						(WSA_START_OFFSET + 0x021C)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4 \
+						(WSA_START_OFFSET + 0x0220)
+#define BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST	(WSA_START_OFFSET + 0x0224)
+#define BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0244)
+#define BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0248)
+#define BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0264)
+#define BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0268)
+#define BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0284)
+#define BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0288)
+#define BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x02A4)
+#define BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x02A8)
+#define BOLERO_CDC_WSA_INTR_CTRL_CFG		(WSA_START_OFFSET + 0x0340)
+#define BOLERO_CDC_WSA_INTR_CTRL_CLR_COMMIT	(WSA_START_OFFSET + 0x0344)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN1_MASK0	(WSA_START_OFFSET + 0x0360)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0	(WSA_START_OFFSET + 0x0368)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN1_CLEAR0	(WSA_START_OFFSET + 0x0370)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN2_MASK0	(WSA_START_OFFSET + 0x0380)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN2_STATUS0	(WSA_START_OFFSET + 0x0388)
+#define BOLERO_CDC_WSA_INTR_CTRL_PIN2_CLEAR0	(WSA_START_OFFSET + 0x0390)
+#define BOLERO_CDC_WSA_INTR_CTRL_LEVEL0		(WSA_START_OFFSET + 0x03C0)
+#define BOLERO_CDC_WSA_INTR_CTRL_BYPASS0	(WSA_START_OFFSET + 0x03C8)
+#define BOLERO_CDC_WSA_INTR_CTRL_SET0		(WSA_START_OFFSET + 0x03D0)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_CTL		(WSA_START_OFFSET + 0x0400)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_CFG0		(WSA_START_OFFSET + 0x0404)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_CFG1		(WSA_START_OFFSET + 0x0408)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_CFG2		(WSA_START_OFFSET + 0x040C)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_CFG3		(WSA_START_OFFSET + 0x0410)
+#define BOLERO_CDC_WSA_RX0_RX_VOL_CTL		(WSA_START_OFFSET + 0x0414)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL	(WSA_START_OFFSET + 0x0418)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG	(WSA_START_OFFSET + 0x041C)
+#define BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL	(WSA_START_OFFSET + 0x0420)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC0		(WSA_START_OFFSET + 0x0424)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC1		(WSA_START_OFFSET + 0x0428)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC2		(WSA_START_OFFSET + 0x042C)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC3		(WSA_START_OFFSET + 0x0430)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC5		(WSA_START_OFFSET + 0x0438)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC6		(WSA_START_OFFSET + 0x043C)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_SEC7		(WSA_START_OFFSET + 0x0440)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0	(WSA_START_OFFSET + 0x0444)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC1	(WSA_START_OFFSET + 0x0448)
+#define BOLERO_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL	(WSA_START_OFFSET + 0x044C)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_CTL		(WSA_START_OFFSET + 0x0480)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_CFG0		(WSA_START_OFFSET + 0x0484)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_CFG1		(WSA_START_OFFSET + 0x0488)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_CFG2		(WSA_START_OFFSET + 0x048C)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_CFG3		(WSA_START_OFFSET + 0x0490)
+#define BOLERO_CDC_WSA_RX1_RX_VOL_CTL		(WSA_START_OFFSET + 0x0494)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL	(WSA_START_OFFSET + 0x0498)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG	(WSA_START_OFFSET + 0x049C)
+#define BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL	(WSA_START_OFFSET + 0x04A0)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC0		(WSA_START_OFFSET + 0x04A4)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC1		(WSA_START_OFFSET + 0x04A8)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC2		(WSA_START_OFFSET + 0x04AC)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC3		(WSA_START_OFFSET + 0x04B0)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC5		(WSA_START_OFFSET + 0x04B8)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC6		(WSA_START_OFFSET + 0x04BC)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_SEC7		(WSA_START_OFFSET + 0x04C0)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0	(WSA_START_OFFSET + 0x04C4)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC1	(WSA_START_OFFSET + 0x04C8)
+#define BOLERO_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL	(WSA_START_OFFSET + 0x04CC)
+#define BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL	(WSA_START_OFFSET + 0x0500)
+#define BOLERO_CDC_WSA_BOOST0_BOOST_CTL		(WSA_START_OFFSET + 0x0504)
+#define BOLERO_CDC_WSA_BOOST0_BOOST_CFG1	(WSA_START_OFFSET + 0x0508)
+#define BOLERO_CDC_WSA_BOOST0_BOOST_CFG2	(WSA_START_OFFSET + 0x050C)
+#define BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL	(WSA_START_OFFSET + 0x0540)
+#define BOLERO_CDC_WSA_BOOST1_BOOST_CTL		(WSA_START_OFFSET + 0x0544)
+#define BOLERO_CDC_WSA_BOOST1_BOOST_CFG1	(WSA_START_OFFSET + 0x0548)
+#define BOLERO_CDC_WSA_BOOST1_BOOST_CFG2	(WSA_START_OFFSET + 0x054C)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL0		(WSA_START_OFFSET + 0x0580)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL1		(WSA_START_OFFSET + 0x0584)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL2		(WSA_START_OFFSET + 0x0588)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL3		(WSA_START_OFFSET + 0x058C)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL4		(WSA_START_OFFSET + 0x0590)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL5		(WSA_START_OFFSET + 0x0594)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL6		(WSA_START_OFFSET + 0x0598)
+#define BOLERO_CDC_WSA_COMPANDER0_CTL7		(WSA_START_OFFSET + 0x059C)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL0		(WSA_START_OFFSET + 0x05C0)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL1		(WSA_START_OFFSET + 0x05C4)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL2		(WSA_START_OFFSET + 0x05C8)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL3		(WSA_START_OFFSET + 0x05CC)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL4		(WSA_START_OFFSET + 0x05D0)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL5		(WSA_START_OFFSET + 0x05D4)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL6		(WSA_START_OFFSET + 0x05D8)
+#define BOLERO_CDC_WSA_COMPANDER1_CTL7		(WSA_START_OFFSET + 0x05DC)
+#define BOLERO_CDC_WSA_SOFTCLIP0_CRC		(WSA_START_OFFSET + 0x0600)
+#define BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL	(WSA_START_OFFSET + 0x0604)
+#define BOLERO_CDC_WSA_SOFTCLIP1_CRC		(WSA_START_OFFSET + 0x0640)
+#define BOLERO_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL	(WSA_START_OFFSET + 0x0644)
+#define BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL \
+						(WSA_START_OFFSET + 0x0680)
+#define BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0	(WSA_START_OFFSET + 0x0684)
+#define BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL \
+						(WSA_START_OFFSET + 0x06C0)
+#define BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0	(WSA_START_OFFSET + 0x06C4)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL	(WSA_START_OFFSET + 0x0700)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_CTL0	(WSA_START_OFFSET + 0x0704)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_CTL1	(WSA_START_OFFSET + 0x0708)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_FIFO_CTL	(WSA_START_OFFSET + 0x070C)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB \
+						(WSA_START_OFFSET + 0x0710)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB \
+						(WSA_START_OFFSET + 0x0714)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB \
+						(WSA_START_OFFSET + 0x0718)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB \
+						(WSA_START_OFFSET + 0x071C)
+#define BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO	(WSA_START_OFFSET + 0x0720)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL	(WSA_START_OFFSET + 0x0740)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_CTL0	(WSA_START_OFFSET + 0x0744)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_CTL1	(WSA_START_OFFSET + 0x0748)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_FIFO_CTL	(WSA_START_OFFSET + 0x074C)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB \
+						(WSA_START_OFFSET + 0x0750)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB \
+						(WSA_START_OFFSET + 0x0754)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB \
+						(WSA_START_OFFSET + 0x0758)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB \
+						(WSA_START_OFFSET + 0x075C)
+#define BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO	(WSA_START_OFFSET + 0x0760)
+#define WSA_MAX_OFFSET				(WSA_START_OFFSET + 0x0760)
+
+#define BOLERO_CDC_WSA_MACRO_MAX 0x1D9 /* 0x760/4 = 0x1D8 + 1 registers */
+
+/* VA macro registers */
+#define VA_START_OFFSET				0x3000
+#define BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL	(VA_START_OFFSET + 0x0000)
+#define BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(VA_START_OFFSET + 0x0004)
+#define BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL	(VA_START_OFFSET + 0x0008)
+#define BOLERO_CDC_VA_TOP_CSR_TOP_CFG0		(VA_START_OFFSET + 0x0080)
+#define BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL		(VA_START_OFFSET + 0x0084)
+#define BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL		(VA_START_OFFSET + 0x0088)
+#define BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL		(VA_START_OFFSET + 0x008C)
+#define BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL		(VA_START_OFFSET + 0x0090)
+#define BOLERO_CDC_VA_TOP_CSR_DMIC_CFG		(VA_START_OFFSET + 0x0094)
+#define BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS		(VA_START_OFFSET + 0x009C)
+#define BOLERO_CDC_VA_TOP_CSR_DEBUG_EN		(VA_START_OFFSET + 0x00A0)
+#define BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL	(VA_START_OFFSET + 0x00A4)
+#define BOLERO_CDC_VA_TOP_CSR_I2S_CLK		(VA_START_OFFSET + 0x00A8)
+#define BOLERO_CDC_VA_TOP_CSR_I2S_RESET		(VA_START_OFFSET + 0x00AC)
+#define BOLERO_CDC_VA_TOP_CSR_CORE_ID_0		(VA_START_OFFSET + 0x00C0)
+#define BOLERO_CDC_VA_TOP_CSR_CORE_ID_1		(VA_START_OFFSET + 0x00C4)
+#define BOLERO_CDC_VA_TOP_CSR_CORE_ID_2		(VA_START_OFFSET + 0x00C8)
+#define BOLERO_CDC_VA_TOP_CSR_CORE_ID_3		(VA_START_OFFSET + 0x00CC)
+#define VA_TOP_MAX_OFFSET			(VA_START_OFFSET + 0x00CC)
+
+#define BOLERO_CDC_VA_MACRO_TOP_MAX 0x34 /* 0x0CC/4 = 0x33 + 1 = 0x34 */
+
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0	(VA_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1	(VA_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2	(VA_START_OFFSET + 0x00D8)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_CTRL		(VA_START_OFFSET + 0x00DC)
+
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0	(VA_START_OFFSET + 0x0100)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1	(VA_START_OFFSET + 0x0104)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0	(VA_START_OFFSET + 0x0108)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1	(VA_START_OFFSET + 0x010C)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0	(VA_START_OFFSET + 0x0110)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG1	(VA_START_OFFSET + 0x0114)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0	(VA_START_OFFSET + 0x0118)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG1	(VA_START_OFFSET + 0x011C)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0	(VA_START_OFFSET + 0x0120)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG1	(VA_START_OFFSET + 0x0124)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0	(VA_START_OFFSET + 0x0128)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG1	(VA_START_OFFSET + 0x012C)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0	(VA_START_OFFSET + 0x0130)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG1	(VA_START_OFFSET + 0x0134)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0	(VA_START_OFFSET + 0x0138)
+#define BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG1	(VA_START_OFFSET + 0x013C)
+
+#define BOLERO_CDC_VA_TX0_TX_PATH_CTL	(VA_START_OFFSET + 0x0400)
+#define BOLERO_CDC_VA_TX0_TX_PATH_CFG0	(VA_START_OFFSET + 0x0404)
+#define BOLERO_CDC_VA_TX0_TX_PATH_CFG1	(VA_START_OFFSET + 0x0408)
+#define BOLERO_CDC_VA_TX0_TX_VOL_CTL	(VA_START_OFFSET + 0x040C)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC0	(VA_START_OFFSET + 0x0410)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC1	(VA_START_OFFSET + 0x0414)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC2	(VA_START_OFFSET + 0x0418)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC3	(VA_START_OFFSET + 0x041C)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC4	(VA_START_OFFSET + 0x0420)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC5	(VA_START_OFFSET + 0x0424)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC6	(VA_START_OFFSET + 0x0428)
+#define BOLERO_CDC_VA_TX0_TX_PATH_SEC7	(VA_START_OFFSET + 0x042C)
+#define BOLERO_CDC_VA_TX1_TX_PATH_CTL	(VA_START_OFFSET + 0x0480)
+#define BOLERO_CDC_VA_TX1_TX_PATH_CFG0	(VA_START_OFFSET + 0x0484)
+#define BOLERO_CDC_VA_TX1_TX_PATH_CFG1	(VA_START_OFFSET + 0x0488)
+#define BOLERO_CDC_VA_TX1_TX_VOL_CTL	(VA_START_OFFSET + 0x048C)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC0	(VA_START_OFFSET + 0x0490)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC1	(VA_START_OFFSET + 0x0494)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC2	(VA_START_OFFSET + 0x0498)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC3	(VA_START_OFFSET + 0x049C)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC4	(VA_START_OFFSET + 0x04A0)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC5	(VA_START_OFFSET + 0x04A4)
+#define BOLERO_CDC_VA_TX1_TX_PATH_SEC6	(VA_START_OFFSET + 0x04A8)
+#define BOLERO_CDC_VA_TX2_TX_PATH_CTL	(VA_START_OFFSET + 0x0500)
+#define BOLERO_CDC_VA_TX2_TX_PATH_CFG0	(VA_START_OFFSET + 0x0504)
+#define BOLERO_CDC_VA_TX2_TX_PATH_CFG1	(VA_START_OFFSET + 0x0508)
+#define BOLERO_CDC_VA_TX2_TX_VOL_CTL	(VA_START_OFFSET + 0x050C)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC0	(VA_START_OFFSET + 0x0510)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC1	(VA_START_OFFSET + 0x0514)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC2	(VA_START_OFFSET + 0x0518)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC3	(VA_START_OFFSET + 0x051C)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC4	(VA_START_OFFSET + 0x0520)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC5	(VA_START_OFFSET + 0x0524)
+#define BOLERO_CDC_VA_TX2_TX_PATH_SEC6	(VA_START_OFFSET + 0x0528)
+#define BOLERO_CDC_VA_TX3_TX_PATH_CTL	(VA_START_OFFSET + 0x0580)
+#define BOLERO_CDC_VA_TX3_TX_PATH_CFG0	(VA_START_OFFSET + 0x0584)
+#define BOLERO_CDC_VA_TX3_TX_PATH_CFG1	(VA_START_OFFSET + 0x0588)
+#define BOLERO_CDC_VA_TX3_TX_VOL_CTL	(VA_START_OFFSET + 0x058C)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC0	(VA_START_OFFSET + 0x0590)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC1	(VA_START_OFFSET + 0x0594)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC2	(VA_START_OFFSET + 0x0598)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC3	(VA_START_OFFSET + 0x059C)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC4	(VA_START_OFFSET + 0x05A0)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC5	(VA_START_OFFSET + 0x05A4)
+#define BOLERO_CDC_VA_TX3_TX_PATH_SEC6	(VA_START_OFFSET + 0x05A8)
+#define BOLERO_CDC_VA_TX4_TX_PATH_CTL	(VA_START_OFFSET + 0x0600)
+#define BOLERO_CDC_VA_TX4_TX_PATH_CFG0	(VA_START_OFFSET + 0x0604)
+#define BOLERO_CDC_VA_TX4_TX_PATH_CFG1	(VA_START_OFFSET + 0x0608)
+#define BOLERO_CDC_VA_TX4_TX_VOL_CTL	(VA_START_OFFSET + 0x060C)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC0	(VA_START_OFFSET + 0x0610)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC1	(VA_START_OFFSET + 0x0614)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC2	(VA_START_OFFSET + 0x0618)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC3	(VA_START_OFFSET + 0x061C)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC4	(VA_START_OFFSET + 0x0620)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC5	(VA_START_OFFSET + 0x0624)
+#define BOLERO_CDC_VA_TX4_TX_PATH_SEC6	(VA_START_OFFSET + 0x0628)
+#define BOLERO_CDC_VA_TX5_TX_PATH_CTL	(VA_START_OFFSET + 0x0680)
+#define BOLERO_CDC_VA_TX5_TX_PATH_CFG0	(VA_START_OFFSET + 0x0684)
+#define BOLERO_CDC_VA_TX5_TX_PATH_CFG1	(VA_START_OFFSET + 0x0688)
+#define BOLERO_CDC_VA_TX5_TX_VOL_CTL	(VA_START_OFFSET + 0x068C)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC0	(VA_START_OFFSET + 0x0690)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC1	(VA_START_OFFSET + 0x0694)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC2	(VA_START_OFFSET + 0x0698)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC3	(VA_START_OFFSET + 0x069C)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC4	(VA_START_OFFSET + 0x06A0)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC5	(VA_START_OFFSET + 0x06A4)
+#define BOLERO_CDC_VA_TX5_TX_PATH_SEC6	(VA_START_OFFSET + 0x06A8)
+#define BOLERO_CDC_VA_TX6_TX_PATH_CTL	(VA_START_OFFSET + 0x0700)
+#define BOLERO_CDC_VA_TX6_TX_PATH_CFG0	(VA_START_OFFSET + 0x0704)
+#define BOLERO_CDC_VA_TX6_TX_PATH_CFG1	(VA_START_OFFSET + 0x0708)
+#define BOLERO_CDC_VA_TX6_TX_VOL_CTL	(VA_START_OFFSET + 0x070C)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC0	(VA_START_OFFSET + 0x0710)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC1	(VA_START_OFFSET + 0x0714)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC2	(VA_START_OFFSET + 0x0718)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC3	(VA_START_OFFSET + 0x071C)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC4	(VA_START_OFFSET + 0x0720)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC5	(VA_START_OFFSET + 0x0724)
+#define BOLERO_CDC_VA_TX6_TX_PATH_SEC6	(VA_START_OFFSET + 0x0728)
+#define BOLERO_CDC_VA_TX7_TX_PATH_CTL	(VA_START_OFFSET + 0x0780)
+#define BOLERO_CDC_VA_TX7_TX_PATH_CFG0	(VA_START_OFFSET + 0x0784)
+#define BOLERO_CDC_VA_TX7_TX_PATH_CFG1	(VA_START_OFFSET + 0x0788)
+#define BOLERO_CDC_VA_TX7_TX_VOL_CTL	(VA_START_OFFSET + 0x078C)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC0	(VA_START_OFFSET + 0x0790)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC1	(VA_START_OFFSET + 0x0794)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC2	(VA_START_OFFSET + 0x0798)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC3	(VA_START_OFFSET + 0x079C)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC4	(VA_START_OFFSET + 0x07A0)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC5	(VA_START_OFFSET + 0x07A4)
+#define BOLERO_CDC_VA_TX7_TX_PATH_SEC6	(VA_START_OFFSET + 0x07A8)
+#define VA_MAX_OFFSET			(VA_START_OFFSET + 0x07A8)
+
+#define BOLERO_CDC_VA_MACRO_MAX 0x1EB /* 7A8/4 = 1EA + 1 = 1EB */
+
+#define BOLERO_CDC_MAX_REGISTER VA_MAX_OFFSET
+
+#define BOLERO_REG(reg)  (((reg) & 0x0FFF)/4)
+
+#endif

+ 877 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-regmap.c

@@ -0,0 +1,877 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include "bolero-cdc.h"
+#include "internal.h"
+
+static const struct reg_default bolero_defaults[] = {
+	/* TX Macro */
+	{ BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+	{ BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+	{ BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_TOP_CFG0, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_ANC_CFG, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_DEBUG_EN, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C},
+	{ BOLERO_CDC_TX_TOP_CSR_I2S_CLK, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_I2S_RESET, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL, 0x00},
+	{ BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00},
+	{ BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00},
+	{ BOLERO_CDC_TX_ANC0_CLK_RESET_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_MODE_1_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_MODE_2_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_FF_SHIFT, 0x00},
+	{ BOLERO_CDC_TX_ANC0_FB_SHIFT, 0x00},
+	{ BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_LPF_FB_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_SMLPF_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00},
+	{ BOLERO_CDC_TX_ANC0_FB_GAIN_CTL, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX0_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX0_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX0_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX0_TX_PATH_SEC7, 0x25},
+	{ BOLERO_CDC_TX1_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX1_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX1_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX1_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX1_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX2_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX2_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX2_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX2_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX2_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX3_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX3_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX3_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX3_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX3_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX4_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX4_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX4_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX4_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX4_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX5_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX5_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX5_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX5_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX5_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX6_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX6_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX6_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX6_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX6_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_TX7_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_TX7_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_TX7_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_TX7_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_TX7_TX_PATH_SEC6, 0x00},
+
+	/* RX Macro */
+	{ BOLERO_CDC_RX_TOP_TOP_CFG0, 0x00},
+	{ BOLERO_CDC_RX_TOP_SWR_CTRL, 0x00},
+	{ BOLERO_CDC_RX_TOP_DEBUG, 0x00},
+	{ BOLERO_CDC_RX_TOP_DEBUG_BUS, 0x00},
+	{ BOLERO_CDC_RX_TOP_DEBUG_EN0, 0x00},
+	{ BOLERO_CDC_RX_TOP_DEBUG_EN1, 0x00},
+	{ BOLERO_CDC_RX_TOP_DEBUG_EN2, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHL_COMP_LUT, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHR_COMP_LUT, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00},
+	{ BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11},
+	{ BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20},
+	{ BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00},
+	{ BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00},
+	{ BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11},
+	{ BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20},
+	{ BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00},
+	{ BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00},
+	{ BOLERO_CDC_RX_TOP_RX_I2S_CTL, 0x0C},
+	{ BOLERO_CDC_RX_TOP_TX_I2S2_CTL, 0x0C},
+	{ BOLERO_CDC_RX_TOP_I2S_CLK, 0x0C},
+	{ BOLERO_CDC_RX_TOP_I2S_RESET, 0x00},
+	{ BOLERO_CDC_RX_TOP_I2S_MUX, 0x00},
+	{ BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ BOLERO_CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00},
+	{ BOLERO_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08},
+	{ BOLERO_CDC_RX_SOFTCLIP_CRC, 0x00},
+	{ BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00},
+	{ BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00},
+	{ BOLERO_CDC_RX_CLSH_CRC, 0x00},
+	{ BOLERO_CDC_RX_CLSH_DLY_CTRL, 0x03},
+	{ BOLERO_CDC_RX_CLSH_DECAY_CTRL, 0x02},
+	{ BOLERO_CDC_RX_CLSH_HPH_V_PA, 0x1C},
+	{ BOLERO_CDC_RX_CLSH_EAR_V_PA, 0x39},
+	{ BOLERO_CDC_RX_CLSH_HPH_V_HD, 0x0C},
+	{ BOLERO_CDC_RX_CLSH_EAR_V_HD, 0x0C},
+	{ BOLERO_CDC_RX_CLSH_K1_MSB, 0x01},
+	{ BOLERO_CDC_RX_CLSH_K1_LSB, 0x00},
+	{ BOLERO_CDC_RX_CLSH_K2_MSB, 0x00},
+	{ BOLERO_CDC_RX_CLSH_K2_LSB, 0x80},
+	{ BOLERO_CDC_RX_CLSH_IDLE_CTRL, 0x00},
+	{ BOLERO_CDC_RX_CLSH_IDLE_HPH, 0x00},
+	{ BOLERO_CDC_RX_CLSH_IDLE_EAR, 0x00},
+	{ BOLERO_CDC_RX_CLSH_TEST0, 0x07},
+	{ BOLERO_CDC_RX_CLSH_TEST1, 0x00},
+	{ BOLERO_CDC_RX_CLSH_OVR_VREF, 0x00},
+	{ BOLERO_CDC_RX_CLSH_CLSG_CTL, 0x02},
+	{ BOLERO_CDC_RX_CLSH_CLSG_CFG1, 0x9A},
+	{ BOLERO_CDC_RX_CLSH_CLSG_CFG2, 0x10},
+	{ BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_CFG, 0x10},
+	{ BOLERO_CDC_RX_BCL_VBAT_ADC_CAL1, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_ADC_CAL2, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_ADC_CAL3, 0x04},
+	{ BOLERO_CDC_RX_BCL_VBAT_PK_EST1, 0xE0},
+	{ BOLERO_CDC_RX_BCL_VBAT_PK_EST2, 0x01},
+	{ BOLERO_CDC_RX_BCL_VBAT_PK_EST3, 0x40},
+	{ BOLERO_CDC_RX_BCL_VBAT_RF_PROC1, 0x2A},
+	{ BOLERO_CDC_RX_BCL_VBAT_RF_PROC2, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_TAC1, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_TAC2, 0x18},
+	{ BOLERO_CDC_RX_BCL_VBAT_TAC3, 0x18},
+	{ BOLERO_CDC_RX_BCL_VBAT_TAC4, 0x03},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01},
+	{ BOLERO_CDC_RX_BCL_VBAT_DEBUG1, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_BAN, 0x0C},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_ATTN1, 0x04},
+	{ BOLERO_CDC_RX_BCL_VBAT_ATTN2, 0x08},
+	{ BOLERO_CDC_RX_BCL_VBAT_ATTN3, 0x0C},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00},
+	{ BOLERO_CDC_RX_BCL_VBAT_DECODE_ST, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_CFG, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_LEVEL0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_BYPASS0, 0x00},
+	{ BOLERO_CDC_RX_INTR_CTRL_SET0, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_CFG1, 0x64},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_CFG2, 0x8F},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_CFG3, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E},
+	{ BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x08},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_SEC2, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_SEC3, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_SEC4, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_SEC7, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55},
+	{ BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_CFG1, 0x64},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_CFG2, 0x8F},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_CFG3, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E},
+	{ BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x08},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_SEC2, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_SEC3, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_SEC4, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_SEC7, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55},
+	{ BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_CFG1, 0x64},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_CFG2, 0x8F},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_CFG3, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E},
+	{ BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC0, 0x04},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC1, 0x08},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC2, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC3, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC4, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_SEC7, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00},
+	{ BOLERO_CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00},
+	{ BOLERO_CDC_RX_IDLE_DETECT_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_IDLE_DETECT_CFG0, 0x07},
+	{ BOLERO_CDC_RX_IDLE_DETECT_CFG1, 0x3C},
+	{ BOLERO_CDC_RX_IDLE_DETECT_CFG2, 0x00},
+	{ BOLERO_CDC_RX_IDLE_DETECT_CFG3, 0x00},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL0, 0x60},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL1, 0xDB},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL2, 0xFF},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL3, 0x35},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL4, 0xFF},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL5, 0x00},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL6, 0x01},
+	{ BOLERO_CDC_RX_COMPANDER0_CTL7, 0x28},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL0, 0x60},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL1, 0xDB},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL2, 0xFF},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL3, 0x35},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL4, 0xFF},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL5, 0x00},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL6, 0x01},
+	{ BOLERO_CDC_RX_COMPANDER1_CTL7, 0x28},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00},
+	{ BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04},
+	{ BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00},
+	{ BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04},
+	{ BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00},
+	{ BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01},
+	{ BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01},
+	{ BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01},
+	{ BOLERO_CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_CTL0, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_CTL1, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8},
+	{ BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_CTL0, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_CTL1, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8},
+	{ BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_CTL0, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_CTL1, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8},
+	{ BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00},
+	{ BOLERO_CDC_RX_DSD0_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_DSD0_CFG0, 0x00},
+	{ BOLERO_CDC_RX_DSD0_CFG1, 0x62},
+	{ BOLERO_CDC_RX_DSD0_CFG2, 0x96},
+	{ BOLERO_CDC_RX_DSD1_PATH_CTL, 0x00},
+	{ BOLERO_CDC_RX_DSD1_CFG0, 0x00},
+	{ BOLERO_CDC_RX_DSD1_CFG1, 0x62},
+	{ BOLERO_CDC_RX_DSD1_CFG2, 0x96},
+
+	/* WSA Macro */
+	{ BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ BOLERO_CDC_WSA_TOP_TOP_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x00},
+	{ BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x00},
+	{ BOLERO_CDC_WSA_TOP_DEBUG_BUS_SEL, 0x00},
+	{ BOLERO_CDC_WSA_TOP_DEBUG_EN0, 0x00},
+	{ BOLERO_CDC_WSA_TOP_DEBUG_EN1, 0x00},
+	{ BOLERO_CDC_WSA_TOP_DEBUG_DSM_LB, 0x88},
+	{ BOLERO_CDC_WSA_TOP_RX_I2S_CTL, 0x0C},
+	{ BOLERO_CDC_WSA_TOP_TX_I2S_CTL, 0x0C},
+	{ BOLERO_CDC_WSA_TOP_I2S_CLK, 0x02},
+	{ BOLERO_CDC_WSA_TOP_I2S_RESET, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x10},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3, 0x04},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST1, 0xE0},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST2, 0x01},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST3, 0x40},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1, 0x2A},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC1, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC2, 0x18},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC3, 0x18},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC4, 0x03},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1, 0x01},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4, 0x64},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5, 0x01},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DEBUG1, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BAN, 0x0C},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1, 0x04},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2, 0x08},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3, 0x0C},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0xE0},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0x00},
+	{ BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST, 0x00},
+	{ BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02},
+	{ BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02},
+	{ BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02},
+	{ BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02},
+	{ BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_CFG, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN1_CLEAR0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN2_MASK0, 0xFF},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN2_STATUS0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_PIN2_CLEAR0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_LEVEL0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_BYPASS0, 0x00},
+	{ BOLERO_CDC_WSA_INTR_CTRL_SET0, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x64},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_CFG2, 0x8F},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_CFG3, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL, 0x04},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x7E},
+	{ BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC0, 0x04},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC1, 0x08},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC2, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC3, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_SEC7, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0, 0x08},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC1, 0x00},
+	{ BOLERO_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x64},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_CFG2, 0x8F},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_CFG3, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL, 0x04},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x7E},
+	{ BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC0, 0x04},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC1, 0x08},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC2, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC3, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_SEC7, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0, 0x08},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC1, 0x00},
+	{ BOLERO_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL, 0x00},
+	{ BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL, 0x00},
+	{ BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0xD0},
+	{ BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x89},
+	{ BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x04},
+	{ BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL, 0x00},
+	{ BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0xD0},
+	{ BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x89},
+	{ BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x04},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL0, 0x60},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL1, 0xDB},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL2, 0xFF},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x35},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL4, 0xFF},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL5, 0x00},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL6, 0x01},
+	{ BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x28},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL0, 0x60},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL1, 0xDB},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL2, 0xFF},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x35},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL4, 0xFF},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL5, 0x00},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL6, 0x01},
+	{ BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x28},
+	{ BOLERO_CDC_WSA_SOFTCLIP0_CRC, 0x00},
+	{ BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38},
+	{ BOLERO_CDC_WSA_SOFTCLIP1_CRC, 0x00},
+	{ BOLERO_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38},
+	{ BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00},
+	{ BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01},
+	{ BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00},
+	{ BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0, 0x01},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_CTL0, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_CTL1, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_FIFO_CTL, 0xA8},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_CTL0, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_CTL1, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_FIFO_CTL, 0xA8},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO, 0x00},
+
+	/* VA macro */
+	{ BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_TOP_CFG0, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, 0x80},
+	{ BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_DEBUG_EN, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C},
+	{ BOLERO_CDC_VA_TOP_CSR_I2S_CLK, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_I2S_RESET, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_0, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_1, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_2, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_3, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x06},
+
+	/* VA core */
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG1, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0, 0x00},
+	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG1, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX0_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX0_TX_PATH_SEC7, 0x25},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX1_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX1_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX2_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX2_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX3_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX3_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX4_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX4_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX5_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX5_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX6_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX6_TX_PATH_SEC6, 0x00},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_CTL, 0x04},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_CFG0, 0x10},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_CFG1, 0x0B},
+	{ BOLERO_CDC_VA_TX7_TX_VOL_CTL, 0x00},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC0, 0x00},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC1, 0x00},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC2, 0x01},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC3, 0x3C},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC4, 0x20},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC5, 0x00},
+	{ BOLERO_CDC_VA_TX7_TX_PATH_SEC6, 0x00},
+};
+
+static bool bolero_is_readable_register(struct device *dev,
+					unsigned int reg)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev);
+	u16 reg_offset;
+	int macro_id;
+	u8 *reg_tbl = NULL;
+
+	if (!priv)
+		return false;
+
+	macro_id = bolero_get_macro_id(priv->va_without_decimation,
+				       reg);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return false;
+
+	reg_tbl = bolero_reg_access[macro_id];
+	reg_offset = (reg - macro_id_base_offset[macro_id])/4;
+
+	if (reg_tbl)
+		return (reg_tbl[reg_offset] & RD_REG);
+
+	return false;
+}
+
+static bool bolero_is_writeable_register(struct device *dev,
+					 unsigned int reg)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev);
+	u16 reg_offset;
+	int macro_id;
+	const u8 *reg_tbl = NULL;
+
+	if (!priv)
+		return false;
+
+	macro_id = bolero_get_macro_id(priv->va_without_decimation,
+				       reg);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return false;
+
+	reg_tbl = bolero_reg_access[macro_id];
+	reg_offset = (reg - macro_id_base_offset[macro_id])/4;
+
+	if (reg_tbl)
+		return (reg_tbl[reg_offset] & WR_REG);
+
+	return false;
+}
+
+static bool bolero_is_volatile_register(struct device *dev,
+					unsigned int reg)
+{
+	/* Update volatile list for rx/tx macros */
+	switch (reg) {
+	case BOLERO_CDC_VA_TOP_CSR_CORE_ID_0:
+	case BOLERO_CDC_VA_TOP_CSR_CORE_ID_1:
+	case BOLERO_CDC_VA_TOP_CSR_CORE_ID_2:
+	case BOLERO_CDC_VA_TOP_CSR_CORE_ID_3:
+	case BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL:
+	case BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL:
+	case BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL:
+	case BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL:
+	case BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL:
+	case BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST:
+	case BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0:
+	case BOLERO_CDC_WSA_INTR_CTRL_PIN2_STATUS0:
+	case BOLERO_CDC_WSA_COMPANDER0_CTL6:
+	case BOLERO_CDC_WSA_COMPANDER1_CTL6:
+	case BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO:
+	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB:
+	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_RD_LSB:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_RD_MSB:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_RD_LSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_RD_MSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB:
+	case BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG2:
+	case BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG2:
+	case BOLERO_CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+	case BOLERO_CDC_RX_BCL_VBAT_DECODE_ST:
+	case BOLERO_CDC_RX_INTR_CTRL_PIN1_STATUS0:
+	case BOLERO_CDC_RX_INTR_CTRL_PIN2_STATUS0:
+	case BOLERO_CDC_RX_COMPANDER0_CTL6:
+	case BOLERO_CDC_RX_COMPANDER1_CTL6:
+	case BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC0_STATUS_FIFO:
+	case BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC1_STATUS_FIFO:
+	case BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+	case BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+	case BOLERO_CDC_RX_EC_ASRC2_STATUS_FIFO:
+	case BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL:
+	case BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL:
+	case BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL:
+	case BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL:
+		return true;
+	}
+	return false;
+}
+
+const struct regmap_config bolero_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.reg_stride = 4,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = bolero_defaults,
+	.num_reg_defaults = ARRAY_SIZE(bolero_defaults),
+	.max_register = BOLERO_CDC_MAX_REGISTER,
+	.writeable_reg = bolero_is_writeable_register,
+	.volatile_reg = bolero_is_volatile_register,
+	.readable_reg = bolero_is_readable_register,
+};

+ 982 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-tables.c

@@ -0,0 +1,982 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include "bolero-cdc.h"
+#include "internal.h"
+
+u8 bolero_tx_reg_access[BOLERO_CDC_TX_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX4_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX5_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX6_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_rx_reg_access[BOLERO_CDC_RX_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DEBUG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DEBUG_EN0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DEBUG_EN1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DEBUG_EN2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHL_COMP_LUT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHL_COMP_RD_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHL_COMP_RD_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHR_COMP_LUT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHR_COMP_RD_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_HPHR_COMP_RD_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_RX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_TX_I2S2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_TOP_I2S_MUX)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLK_RST_CTRL_DSD_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SOFTCLIP_CRC)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_CRC)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_DLY_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_DECAY_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_HPH_V_PA)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_EAR_V_PA)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_HPH_V_HD)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_EAR_V_HD)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_K1_MSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_K1_LSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_K2_MSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_K2_LSB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_IDLE_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_IDLE_HPH)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_IDLE_EAR)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_TEST0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_TEST1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_OVR_VREF)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_CLSG_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_CLSG_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_CLSH_CLSG_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_PK_EST1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_PK_EST2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_PK_EST3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_RF_PROC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_RF_PROC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_TAC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_TAC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_TAC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_TAC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DEBUG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BAN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ATTN1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ATTN2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_ATTN3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_BCL_VBAT_DECODE_ST)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_CLR_COMMIT)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN1_STATUS0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN1_CLEAR0)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN2_STATUS0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_PIN2_CLEAR0)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_LEVEL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_BYPASS0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_INTR_CTRL_SET0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX0_RX_PATH_DSM_DATA6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX1_RX_PATH_DSM_DATA6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_RX2_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IDLE_DETECT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IDLE_DETECT_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IDLE_DETECT_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IDLE_DETECT_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IDLE_DETECT_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL6)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER0_CTL7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL6)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_COMPANDER1_CTL7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] =
+								RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL)] =
+								RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_CLK_RST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_FIFO_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC0_STATUS_FIFO)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_CLK_RST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_FIFO_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC1_STATUS_FIFO)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_CLK_RST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_FIFO_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_EC_ASRC2_STATUS_FIFO)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD0_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD0_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD1_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_RX_DSD1_CFG2)] = RD_WR_REG,
+};
+
+u8 bolero_va_reg_access[BOLERO_CDC_VA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX4_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX5_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX6_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX7_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+};
+
+u8 bolero_va_reg_access_v2[BOLERO_CDC_VA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_va_reg_access_v3[BOLERO_CDC_VA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_wsa_reg_access[BOLERO_CDC_WSA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_TOP_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_FREQ_MCLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_DEBUG_BUS_SEL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_DEBUG_EN0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_DEBUG_EN1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_DEBUG_DSM_LB)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_RX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TOP_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_RX_EC_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_PK_EST3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_TAC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DEBUG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BAN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_CLR_COMMIT)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN1_CLEAR0)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN2_STATUS0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_PIN2_CLEAR0)] = WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_LEVEL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_BYPASS0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_INTR_CTRL_SET0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_CFG3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST0_BOOST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST0_BOOST_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST0_BOOST_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST1_BOOST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST1_BOOST_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_BOOST1_BOOST_CFG2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL6)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER0_CTL7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL6)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_COMPANDER1_CTL7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SOFTCLIP0_CRC)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SOFTCLIP1_CRC)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_FIFO_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_FIFO_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO)] = RD_REG,
+};
+
+u8 *bolero_reg_access[MAX_MACRO] = {
+	[TX_MACRO] = bolero_tx_reg_access,
+	[RX_MACRO] = bolero_rx_reg_access,
+	[WSA_MACRO] = bolero_wsa_reg_access,
+	[VA_MACRO] = bolero_va_reg_access,
+};

+ 172 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc-utils.c

@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include "bolero-cdc.h"
+#include "internal.h"
+
+#define REG_BYTES 2
+#define VAL_BYTES 1
+
+const u16 macro_id_base_offset[MAX_MACRO] = {
+	TX_START_OFFSET,
+	RX_START_OFFSET,
+	WSA_START_OFFSET,
+	VA_START_OFFSET,
+};
+
+int bolero_get_macro_id(bool va_no_dec_flag, u16 reg)
+{
+	if (reg >= TX_START_OFFSET
+		&& reg <= TX_MAX_OFFSET)
+		return TX_MACRO;
+	if (reg >= RX_START_OFFSET
+		&& reg <= RX_MAX_OFFSET)
+		return RX_MACRO;
+	if (reg >= WSA_START_OFFSET
+		&& reg <= WSA_MAX_OFFSET)
+		return WSA_MACRO;
+	if (!va_no_dec_flag &&
+		(reg >= VA_START_OFFSET &&
+		reg <= VA_MAX_OFFSET))
+		return VA_MACRO;
+	if (va_no_dec_flag &&
+		(reg >= VA_START_OFFSET &&
+		reg <= VA_TOP_MAX_OFFSET))
+		return VA_MACRO;
+
+	return -EINVAL;
+}
+
+static int regmap_bus_read(void *context, const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct bolero_priv *priv = dev_get_drvdata(dev);
+	u16 *reg_p;
+	u16 __reg;
+	int macro_id, i;
+	u8 temp = 0;
+	int ret = -EINVAL;
+
+	if (!priv) {
+		dev_err(dev, "%s: priv is NULL\n", __func__);
+		return ret;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return ret;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return ret;
+	}
+
+	reg_p = (u16 *)reg;
+	macro_id = bolero_get_macro_id(priv->va_without_decimation,
+					   reg_p[0]);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
+	mutex_lock(&priv->io_lock);
+	for (i = 0; i < val_size; i++) {
+		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
+		ret = priv->read_dev(priv, macro_id, __reg, &temp);
+		if (ret < 0) {
+			dev_err_ratelimited(dev,
+			"%s: Codec read failed (%d), reg: 0x%x, size:%zd\n",
+			__func__, ret, reg_p[0] + i * 4, val_size);
+			break;
+		}
+		((u8 *)val)[i] = temp;
+		dev_dbg(dev, "%s: Read 0x%02x from reg 0x%x\n",
+			__func__, temp, reg_p[0] + i * 4);
+	}
+	mutex_unlock(&priv->io_lock);
+
+	return ret;
+}
+
+static int regmap_bus_gather_write(void *context,
+				   const void *reg, size_t reg_size,
+				   const void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct bolero_priv *priv = dev_get_drvdata(dev);
+	u16 *reg_p;
+	u16 __reg;
+	int macro_id, i;
+	int ret = -EINVAL;
+
+	if (!priv) {
+		dev_err(dev, "%s: priv is NULL\n", __func__);
+		return ret;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return ret;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return ret;
+	}
+
+	reg_p = (u16 *)reg;
+	macro_id = bolero_get_macro_id(priv->va_without_decimation,
+					reg_p[0]);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
+	mutex_lock(&priv->io_lock);
+	for (i = 0; i < val_size; i++) {
+		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
+		ret = priv->write_dev(priv, macro_id, __reg, ((u8 *)val)[i]);
+		if (ret < 0) {
+			dev_err_ratelimited(dev,
+			"%s: Codec write failed (%d), reg:0x%x, size:%zd\n",
+			__func__, ret, reg_p[0] + i * 4, val_size);
+			break;
+		}
+		dev_dbg(dev, "Write %02x to reg 0x%x\n", ((u8 *)val)[i],
+			reg_p[0] + i * 4);
+	}
+	mutex_unlock(&priv->io_lock);
+	return ret;
+}
+
+static int regmap_bus_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct bolero_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	if (count < REG_BYTES) {
+		dev_err(dev, "%s: count %zd bytes < %d, not supported\n",
+			__func__, count, REG_BYTES);
+		return -EINVAL;
+	}
+
+	return regmap_bus_gather_write(context, data, REG_BYTES,
+				       data + REG_BYTES,
+				       count - REG_BYTES);
+}
+
+static struct regmap_bus regmap_bus_config = {
+	.write = regmap_bus_write,
+	.gather_write = regmap_bus_gather_write,
+	.read = regmap_bus_read,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+struct regmap *bolero_regmap_init(struct device *dev,
+				      const struct regmap_config *config)
+{
+	return devm_regmap_init(dev, &regmap_bus_config, dev, config);
+}

+ 1621 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc.c

@@ -0,0 +1,1621 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <soc/snd_event.h>
+#include <linux/pm_runtime.h>
+#include <soc/swr-common.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+#include <linux/ratelimit.h>
+#include "bolero-cdc.h"
+#include "internal.h"
+#include "bolero-clk-rsc.h"
+#include "asoc/bolero-slave-internal.h"
+#include <linux/qti-regmap-debugfs.h>
+
+#define DRV_NAME "bolero_codec"
+
+#define BOLERO_VERSION_ENTRY_SIZE 32
+#define BOLERO_CDC_STRING_LEN 80
+
+static const struct snd_soc_component_driver bolero;
+
+/* pm runtime auto suspend timer in msecs */
+#define BOLERO_AUTO_SUSPEND_DELAY          100 /* delay in msec */
+
+/* MCLK_MUX table for all macros */
+static u16 bolero_mclk_mux_tbl[MAX_MACRO][MCLK_MUX_MAX] = {
+	{TX_MACRO, VA_MACRO},
+	{TX_MACRO, RX_MACRO},
+	{TX_MACRO, WSA_MACRO},
+	{TX_MACRO, VA_MACRO},
+};
+
+static bool bolero_is_valid_codec_dev(struct device *dev);
+
+int bolero_set_port_map(struct snd_soc_component *component,
+			u32 size, void *data)
+{
+	struct bolero_priv *priv = NULL;
+	struct swr_mstr_port_map *map = NULL;
+	u16 idx;
+
+	if (!component || (size == 0) || !data)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!bolero_is_valid_codec_dev(priv->dev)) {
+		dev_err(priv->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+	map = (struct swr_mstr_port_map *)data;
+
+	for (idx = 0; idx < size; idx++) {
+		if (priv->macro_params[map->id].set_port_map)
+			priv->macro_params[map->id].set_port_map(component,
+						map->uc,
+						SWR_MSTR_PORT_LEN,
+						map->swr_port_params);
+		map += 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(bolero_set_port_map);
+
+static void bolero_ahb_write_device(char __iomem *io_base,
+				    u16 reg, u8 value)
+{
+	u32 temp = (u32)(value) & 0x000000FF;
+
+	iowrite32(temp, io_base + reg);
+}
+
+static void bolero_ahb_read_device(char __iomem *io_base,
+				   u16 reg, u8 *value)
+{
+	u32 temp;
+
+	temp = ioread32(io_base + reg);
+	*value = (u8)temp;
+}
+
+static int __bolero_reg_read(struct bolero_priv *priv,
+			     u16 macro_id, u16 reg, u8 *val)
+{
+	int ret = 0;
+
+	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		ret = -EINVAL;
+		goto ssr_err;
+	}
+
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+		if (!bolero_check_core_votes(priv->macro_params[VA_MACRO].dev))
+			goto ssr_err;
+	}
+
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+				priv->macro_params[macro_id].default_clk_id,
+				priv->macro_params[macro_id].clk_id_req,
+				true);
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
+	}
+
+	bolero_ahb_read_device(
+		priv->macro_params[macro_id].io_base, reg, val);
+
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+				priv->macro_params[macro_id].default_clk_id,
+				priv->macro_params[macro_id].clk_id_req,
+				false);
+
+err:
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
+		pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
+	}
+ssr_err:
+	mutex_unlock(&priv->clk_lock);
+	return ret;
+}
+
+static int __bolero_reg_write(struct bolero_priv *priv,
+			      u16 macro_id, u16 reg, u8 val)
+{
+	int ret = 0;
+
+	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		ret = -EINVAL;
+		goto ssr_err;
+	}
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+		if (!bolero_check_core_votes(priv->macro_params[VA_MACRO].dev))
+			goto ssr_err;
+	}
+
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+				priv->macro_params[macro_id].default_clk_id,
+				priv->macro_params[macro_id].clk_id_req,
+				true);
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
+	}
+
+	bolero_ahb_write_device(
+			priv->macro_params[macro_id].io_base, reg, val);
+
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+				priv->macro_params[macro_id].default_clk_id,
+				priv->macro_params[macro_id].clk_id_req,
+				false);
+
+err:
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
+		pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
+	}
+ssr_err:
+	mutex_unlock(&priv->clk_lock);
+	return ret;
+}
+
+static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data)
+{
+	struct bolero_priv *priv = (struct bolero_priv *)handle;
+
+	if (!priv) {
+		pr_err("%s:Invalid bolero priv handle\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SLV_BOLERO_EVT_RX_MUTE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_RX_MUTE, data);
+		break;
+	case SLV_BOLERO_EVT_IMPED_TRUE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_IMPED_TRUE, data);
+		break;
+	case SLV_BOLERO_EVT_IMPED_FALSE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_IMPED_FALSE, data);
+		break;
+	case SLV_BOLERO_EVT_RX_COMPANDER_SOFT_RST:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, data);
+		break;
+	case SLV_BOLERO_EVT_BCS_CLK_OFF:
+		if (priv->macro_params[TX_MACRO].event_handler)
+			priv->macro_params[TX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_BCS_CLK_OFF, data);
+		break;
+	case SLV_BOLERO_EVT_RX_PA_GAIN_UPDATE:
+		/* Update PA Gain for bolero version 2.1 and 2.2*/
+		if ((priv->version == BOLERO_VERSION_2_1) ||
+		    (priv->version == BOLERO_VERSION_2_2))
+			if (priv->macro_params[RX_MACRO].event_handler)
+				priv->macro_params[RX_MACRO].event_handler(
+					priv->component,
+					BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE,
+					data);
+		break;
+	case SLV_BOLERO_EVT_HPHL_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, data);
+		break;
+	case SLV_BOLERO_EVT_HPHR_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, data);
+		break;
+	default:
+		dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
+			__func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bolero_cdc_register_notifier(void *handle,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct bolero_priv *priv = (struct bolero_priv *)handle;
+
+	if (!priv) {
+		pr_err("%s: bolero priv is null\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		return blocking_notifier_chain_register(&priv->notifier,
+							nblock);
+
+	return blocking_notifier_chain_unregister(&priv->notifier,
+						  nblock);
+}
+
+static void bolero_cdc_notifier_call(struct bolero_priv *priv,
+				     u32 data)
+{
+	dev_dbg(priv->dev, "%s: notifier call, data:%d\n", __func__, data);
+	blocking_notifier_call_chain(&priv->notifier,
+				     data, (void *)priv->wcd_dev);
+}
+
+static bool bolero_is_valid_child_dev(struct device *dev)
+{
+	if (of_device_is_compatible(dev->parent->of_node, "qcom,bolero-codec"))
+		return true;
+
+	return false;
+}
+
+static bool bolero_is_valid_codec_dev(struct device *dev)
+{
+	if (of_device_is_compatible(dev->of_node, "qcom,bolero-codec"))
+		return true;
+
+	return false;
+}
+
+/**
+ * bolero_clear_amic_tx_hold - clears AMIC register on analog codec
+ *
+ * @dev: bolero device ptr.
+ *
+ */
+void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+	struct bolero_priv *priv;
+	u16 event;
+	u16 amic = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+
+	if (!bolero_is_valid_codec_dev(dev)) {
+		pr_err("%s: invalid codec\n", __func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	event = BOLERO_SLV_EVT_TX_CH_HOLD_CLEAR;
+	if (adc_n == BOLERO_ADC0)
+		amic = 0x1;
+	else if (adc_n == BOLERO_ADC1)
+		amic = 0x2;
+	else if (adc_n == BOLERO_ADC2)
+		amic = 0x2;
+	else if (adc_n == BOLERO_ADC3)
+		amic = 0x3;
+	else
+		return;
+
+	bolero_cdc_notifier_call(priv, (amic << 0x10 | event));
+}
+EXPORT_SYMBOL(bolero_clear_amic_tx_hold);
+
+/**
+ * bolero_get_device_ptr - Get child or macro device ptr
+ *
+ * @dev: bolero device ptr.
+ * @macro_id: ID of macro calling this API.
+ *
+ * Returns dev ptr on success or NULL on error.
+ */
+struct device *bolero_get_device_ptr(struct device *dev, u16 macro_id)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return NULL;
+	}
+
+	if (!bolero_is_valid_codec_dev(dev)) {
+		pr_err("%s: invalid codec\n", __func__);
+		return NULL;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err(dev, "%s: priv is null or invalid macro\n", __func__);
+		return NULL;
+	}
+
+	return priv->macro_params[macro_id].dev;
+}
+EXPORT_SYMBOL(bolero_get_device_ptr);
+
+/**
+ * bolero_get_rsc_clk_device_ptr - Get rsc clk device ptr
+ *
+ * @dev: bolero device ptr.
+ *
+ * Returns dev ptr on success or NULL on error.
+ */
+struct device *bolero_get_rsc_clk_device_ptr(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return NULL;
+	}
+
+	if (!bolero_is_valid_codec_dev(dev)) {
+		pr_err("%s: invalid codec\n", __func__);
+		return NULL;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return NULL;
+	}
+
+	return priv->clk_dev;
+}
+EXPORT_SYMBOL(bolero_get_rsc_clk_device_ptr);
+
+static int bolero_copy_dais_from_macro(struct bolero_priv *priv)
+{
+	struct snd_soc_dai_driver *dai_ptr;
+	u16 macro_idx;
+
+	/* memcpy into bolero_dais all macro dais */
+	if (!priv->bolero_dais)
+		priv->bolero_dais = devm_kzalloc(priv->dev,
+						priv->num_dais *
+						sizeof(
+						struct snd_soc_dai_driver),
+						GFP_KERNEL);
+	if (!priv->bolero_dais)
+		return -ENOMEM;
+
+	dai_ptr = priv->bolero_dais;
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].dai_ptr) {
+			memcpy(dai_ptr,
+			       priv->macro_params[macro_idx].dai_ptr,
+			       priv->macro_params[macro_idx].num_dais *
+			       sizeof(struct snd_soc_dai_driver));
+			dai_ptr += priv->macro_params[macro_idx].num_dais;
+		}
+	}
+	return 0;
+}
+
+/**
+ * bolero_register_res_clk - Registers rsc clk driver to bolero
+ *
+ * @dev: rsc clk device ptr.
+ * @rsc_clk_cb: event handler callback for notifications like SSR
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t rsc_clk_cb)
+{
+	struct bolero_priv *priv;
+
+	if (!dev || !rsc_clk_cb) {
+		pr_err("%s: dev or rsc_clk_cb is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device :%pK not added yet\n",
+			__func__, dev);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->clk_dev = dev;
+	priv->rsc_clk_cb = rsc_clk_cb;
+
+	return 0;
+}
+EXPORT_SYMBOL(bolero_register_res_clk);
+
+/**
+ * bolero_unregister_res_clk - Unregisters rsc clk driver from bolero
+ *
+ * @dev: resource clk device ptr.
+ */
+void bolero_unregister_res_clk(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is NULL\n", __func__);
+		return;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device :%pK not added\n",
+			__func__, dev);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+
+	priv->clk_dev = NULL;
+	priv->rsc_clk_cb = NULL;
+}
+EXPORT_SYMBOL(bolero_unregister_res_clk);
+
+static u8 bolero_dmic_clk_div_get(struct snd_soc_component *component,
+				   int mode)
+{
+	struct bolero_priv* priv = snd_soc_component_get_drvdata(component);
+	int macro = (mode ? VA_MACRO : TX_MACRO);
+	int ret = 0;
+
+	if (priv->macro_params[macro].clk_div_get) {
+		ret = priv->macro_params[macro].clk_div_get(component);
+		if (ret >= 0)
+			return ret;
+	}
+
+	return 1;
+}
+
+int bolero_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable)
+{
+	struct bolero_priv* priv = snd_soc_component_get_drvdata(component);
+	u8  dmic_clk_en = 0x01;
+	u16 dmic_clk_reg = 0;
+	s32 *dmic_clk_cnt = NULL;
+	u8 *dmic_clk_div = NULL;
+	u8 freq_change_mask = 0;
+	u8 clk_div = 0;
+
+	dev_dbg(component->dev, "%s: enable: %d, tx_mode:%d, dmic: %d\n",
+		__func__, enable, tx_mode, dmic);
+
+	switch (dmic) {
+	case 0:
+	case 1:
+		dmic_clk_cnt = &(priv->dmic_0_1_clk_cnt);
+		dmic_clk_div = &(priv->dmic_0_1_clk_div);
+		dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL;
+		freq_change_mask = 0x01;
+		break;
+	case 2:
+	case 3:
+		dmic_clk_cnt = &(priv->dmic_2_3_clk_cnt);
+		dmic_clk_div = &(priv->dmic_2_3_clk_div);
+		dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL;
+		freq_change_mask = 0x02;
+		break;
+	case 4:
+	case 5:
+		dmic_clk_cnt = &(priv->dmic_4_5_clk_cnt);
+		dmic_clk_div = &(priv->dmic_4_5_clk_div);
+		dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL;
+		freq_change_mask = 0x04;
+		break;
+	case 6:
+	case 7:
+		dmic_clk_cnt = &(priv->dmic_6_7_clk_cnt);
+		dmic_clk_div = &(priv->dmic_6_7_clk_div);
+		dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL;
+		freq_change_mask = 0x08;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	}
+	dev_dbg(component->dev, "%s: DMIC%d dmic_clk_cnt %d\n",
+			__func__, dmic, *dmic_clk_cnt);
+	if (enable) {
+		clk_div = bolero_dmic_clk_div_get(component, tx_mode);
+		(*dmic_clk_cnt)++;
+		if (*dmic_clk_cnt == 1) {
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+						0x0E, clk_div << 0x1);
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+					dmic_clk_en, dmic_clk_en);
+		} else {
+			if (*dmic_clk_div > clk_div) {
+				snd_soc_component_update_bits(component,
+						BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+						freq_change_mask, freq_change_mask);
+				snd_soc_component_update_bits(component, dmic_clk_reg,
+						0x0E, clk_div << 0x1);
+				snd_soc_component_update_bits(component,
+						BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+						freq_change_mask, 0x00);
+			} else {
+				clk_div = *dmic_clk_div;
+			}
+		}
+		*dmic_clk_div = clk_div;
+	} else {
+		(*dmic_clk_cnt)--;
+		if (*dmic_clk_cnt  == 0) {
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+					dmic_clk_en, 0);
+			clk_div = 0;
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+							0x0E, clk_div << 0x1);
+		} else {
+			clk_div = bolero_dmic_clk_div_get(component, tx_mode);
+			if (*dmic_clk_div > clk_div) {
+				clk_div = bolero_dmic_clk_div_get(component, !tx_mode);
+				snd_soc_component_update_bits(component,
+							BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+							freq_change_mask, freq_change_mask);
+				snd_soc_component_update_bits(component, dmic_clk_reg,
+								0x0E, clk_div << 0x1);
+				snd_soc_component_update_bits(component,
+							BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+							freq_change_mask, 0x00);
+			} else {
+				clk_div = *dmic_clk_div;
+			}
+		}
+		*dmic_clk_div = clk_div;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(bolero_dmic_clk_enable);
+
+bool bolero_is_va_macro_registered(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return false;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device calling is not added yet\n",
+			__func__);
+		return false;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return false;
+	}
+	return priv->macros_supported[VA_MACRO];
+}
+EXPORT_SYMBOL(bolero_is_va_macro_registered);
+
+/**
+ * bolero_register_macro - Registers macro to bolero
+ *
+ * @dev: macro device ptr.
+ * @macro_id: ID of macro calling this API.
+ * @ops: macro params to register.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_register_macro(struct device *dev, u16 macro_id,
+			  struct macro_ops *ops)
+{
+	struct bolero_priv *priv;
+	int ret = -EINVAL;
+
+	if (!dev || !ops) {
+		pr_err("%s: dev or ops is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro:%d not added yet\n",
+			__func__, macro_id);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err(dev, "%s: priv is null or invalid macro\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->macro_params[macro_id].clk_id_req = ops->clk_id_req;
+	priv->macro_params[macro_id].default_clk_id = ops->default_clk_id;
+	priv->macro_params[macro_id].init = ops->init;
+	priv->macro_params[macro_id].exit = ops->exit;
+	priv->macro_params[macro_id].io_base = ops->io_base;
+	priv->macro_params[macro_id].num_dais = ops->num_dais;
+	priv->macro_params[macro_id].dai_ptr = ops->dai_ptr;
+	priv->macro_params[macro_id].event_handler = ops->event_handler;
+	priv->macro_params[macro_id].set_port_map = ops->set_port_map;
+	priv->macro_params[macro_id].dev = dev;
+	priv->current_mclk_mux_macro[macro_id] =
+				bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
+	if (macro_id == TX_MACRO) {
+		priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq;
+		priv->macro_params[macro_id].clk_switch = ops->clk_switch;
+		priv->macro_params[macro_id].reg_evt_listener =
+							ops->reg_evt_listener;
+		priv->macro_params[macro_id].clk_enable = ops->clk_enable;
+	}
+	if (macro_id == TX_MACRO || macro_id == VA_MACRO)
+		priv->macro_params[macro_id].clk_div_get = ops->clk_div_get;
+
+	if ((priv->version == BOLERO_VERSION_2_1) ||
+	    (priv->version == BOLERO_VERSION_2_2)) {
+		if (macro_id == VA_MACRO)
+			priv->macro_params[macro_id].reg_wake_irq =
+						ops->reg_wake_irq;
+	}
+	priv->num_dais += ops->num_dais;
+	priv->num_macros_registered++;
+	priv->macros_supported[macro_id] = true;
+
+	dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id);
+
+	if (priv->num_macros_registered == priv->num_macros) {
+		ret = bolero_copy_dais_from_macro(priv);
+		if (ret < 0) {
+			dev_err(dev, "%s: copy_dais failed\n", __func__);
+			return ret;
+		}
+		if (priv->macros_supported[TX_MACRO] == false) {
+			bolero_mclk_mux_tbl[WSA_MACRO][MCLK_MUX0] = WSA_MACRO;
+			priv->current_mclk_mux_macro[WSA_MACRO] = WSA_MACRO;
+			bolero_mclk_mux_tbl[VA_MACRO][MCLK_MUX0] = VA_MACRO;
+			priv->current_mclk_mux_macro[VA_MACRO] = VA_MACRO;
+		}
+		ret = snd_soc_register_component(dev->parent, &bolero,
+				priv->bolero_dais, priv->num_dais);
+		if (ret < 0) {
+			dev_err(dev, "%s: register codec failed\n", __func__);
+			return ret;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(bolero_register_macro);
+
+/**
+ * bolero_unregister_macro - De-Register macro from bolero
+ *
+ * @dev: macro device ptr.
+ * @macro_id: ID of macro calling this API.
+ *
+ */
+void bolero_unregister_macro(struct device *dev, u16 macro_id)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: macro:%d not in valid registered macro-list\n",
+			__func__, macro_id);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err(dev, "%s: priv is null or invalid macro\n", __func__);
+		return;
+	}
+
+	priv->macro_params[macro_id].init = NULL;
+	priv->macro_params[macro_id].num_dais = 0;
+	priv->macro_params[macro_id].dai_ptr = NULL;
+	priv->macro_params[macro_id].event_handler = NULL;
+	priv->macro_params[macro_id].dev = NULL;
+	if (macro_id == TX_MACRO) {
+		priv->macro_params[macro_id].reg_wake_irq = NULL;
+		priv->macro_params[macro_id].clk_switch = NULL;
+		priv->macro_params[macro_id].reg_evt_listener = NULL;
+		priv->macro_params[macro_id].clk_enable = NULL;
+	}
+	if (macro_id == TX_MACRO || macro_id == VA_MACRO)
+		priv->macro_params[macro_id].clk_div_get = NULL;
+
+	priv->num_dais -= priv->macro_params[macro_id].num_dais;
+	priv->num_macros_registered--;
+
+	/* UNREGISTER CODEC HERE */
+	if (priv->num_macros - 1 == priv->num_macros_registered)
+		snd_soc_unregister_component(dev->parent);
+}
+EXPORT_SYMBOL(bolero_unregister_macro);
+
+/**
+ * bolero_rx_pa_on - Send PA on event from RX macro to slave.
+ *
+ * @dev: macro device ptr.
+ */
+void bolero_rx_pa_on(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: not a valid child dev\n",
+			__func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+
+	bolero_cdc_notifier_call(priv, BOLERO_SLV_EVT_RX_MACRO_PA_ON);
+}
+EXPORT_SYMBOL_GPL(bolero_rx_pa_on);
+
+void bolero_wsa_pa_on(struct device *dev, bool adie_lb)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: not a valid child dev\n",
+			__func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	if (adie_lb)
+		bolero_cdc_notifier_call(priv,
+			BOLERO_SLV_EVT_PA_ON_POST_FSCLK_ADIE_LB);
+	else
+		bolero_cdc_notifier_call(priv,
+			BOLERO_SLV_EVT_PA_ON_POST_FSCLK);
+}
+EXPORT_SYMBOL(bolero_wsa_pa_on);
+
+int bolero_get_version(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro not added yet\n",
+			__func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+	return priv->version;
+}
+EXPORT_SYMBOL(bolero_get_version);
+
+static ssize_t bolero_version_read(struct snd_info_entry *entry,
+				   void *file_private_data,
+				   struct file *file,
+				   char __user *buf, size_t count,
+				   loff_t pos)
+{
+	struct bolero_priv *priv;
+	char buffer[BOLERO_VERSION_ENTRY_SIZE];
+	int len = 0;
+
+	priv = (struct bolero_priv *) entry->private_data;
+	if (!priv) {
+		pr_err("%s: bolero priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (priv->version) {
+	case BOLERO_VERSION_1_0:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_0\n");
+		break;
+	case BOLERO_VERSION_1_1:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_1\n");
+		break;
+	case BOLERO_VERSION_1_2:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_2\n");
+		break;
+	case BOLERO_VERSION_2_0:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_0\n");
+		break;
+	case BOLERO_VERSION_2_1:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_1\n");
+		break;
+	default:
+		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
+	}
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static int bolero_ssr_enable(struct device *dev, void *data)
+{
+	struct bolero_priv *priv = data;
+	int macro_idx;
+
+	if (priv->initial_boot) {
+		priv->initial_boot = false;
+		return 0;
+	}
+
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_UP);
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].event_handler)
+			priv->macro_params[macro_idx].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_CLK_RESET, 0x0);
+	}
+
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_GFMUX_UP);
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			BOLERO_MACRO_EVT_PRE_SSR_UP, 0x0);
+	}
+
+	regcache_cache_only(priv->regmap, false);
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = true;
+	mutex_unlock(&priv->clk_lock);
+	regcache_mark_dirty(priv->regmap);
+	bolero_clk_rsc_enable_all_clocks(priv->clk_dev, true);
+	regcache_sync(priv->regmap);
+	/* Add a 100usec sleep to ensure last register write is done */
+	usleep_range(100,110);
+	bolero_clk_rsc_enable_all_clocks(priv->clk_dev, false);
+	/* call ssr event for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			BOLERO_MACRO_EVT_SSR_UP, 0x0);
+	}
+	bolero_cdc_notifier_call(priv, BOLERO_SLV_EVT_SSR_UP);
+	return 0;
+}
+
+static void bolero_ssr_disable(struct device *dev, void *data)
+{
+	struct bolero_priv *priv = data;
+	int macro_idx;
+
+	if (!priv->dev_up) {
+		dev_err_ratelimited(priv->dev,
+				    "%s: already disabled\n", __func__);
+		return;
+	}
+
+	bolero_cdc_notifier_call(priv, BOLERO_SLV_EVT_PA_OFF_PRE_SSR);
+	regcache_cache_only(priv->regmap, true);
+
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = false;
+	mutex_unlock(&priv->clk_lock);
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_DOWN);
+	/* call ssr event for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			BOLERO_MACRO_EVT_SSR_DOWN, 0x0);
+	}
+	bolero_cdc_notifier_call(priv, BOLERO_SLV_EVT_SSR_DOWN);
+}
+
+static struct snd_info_entry_ops bolero_info_ops = {
+	.read = bolero_version_read,
+};
+
+static const struct snd_event_ops bolero_ssr_ops = {
+	.enable = bolero_ssr_enable,
+	.disable = bolero_ssr_disable,
+};
+
+/*
+ * bolero_info_create_codec_entry - creates bolero module
+ * @codec_root: The parent directory
+ * @component: Codec component instance
+ *
+ * Creates bolero module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int bolero_info_create_codec_entry(struct snd_info_entry *codec_root,
+				   struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct bolero_priv *priv;
+	struct snd_soc_card *card;
+
+	if (!codec_root || !component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (priv->entry) {
+		dev_dbg(priv->dev,
+			"%s:bolero module already created\n", __func__);
+		return 0;
+	}
+	card = component->card;
+	priv->entry = snd_info_create_module_entry(codec_root->module,
+					     "bolero", codec_root);
+	if (!priv->entry) {
+		dev_dbg(component->dev, "%s: failed to create bolero entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+	priv->entry->mode = S_IFDIR | 0555;
+	if (snd_info_register(priv->entry) < 0) {
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+
+	version_entry = snd_info_create_card_entry(card->snd_card,
+						   "version",
+						   priv->entry);
+	if (!version_entry) {
+		dev_err(component->dev, "%s: failed to create bolero version entry\n",
+			__func__);
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = priv;
+	version_entry->size = BOLERO_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &bolero_info_ops;
+
+	if (snd_info_register(version_entry) < 0) {
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+	priv->version_entry = version_entry;
+
+	return 0;
+}
+EXPORT_SYMBOL(bolero_info_create_codec_entry);
+
+/**
+ * bolero_register_wake_irq - Register wake irq of Tx macro
+ *
+ * @component: codec component ptr.
+ * @ipc_wakeup: bool to identify ipc_wakeup to be used or HW interrupt line.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int bolero_register_wake_irq(struct snd_soc_component *component,
+			     u32 ipc_wakeup)
+{
+	struct bolero_priv *priv = NULL;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!bolero_is_valid_codec_dev(priv->dev)) {
+		dev_err(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((priv->version == BOLERO_VERSION_2_1) ||
+	    (priv->version == BOLERO_VERSION_2_2)) {
+		if (priv->macro_params[VA_MACRO].reg_wake_irq)
+			priv->macro_params[VA_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	} else {
+		if (priv->macro_params[TX_MACRO].reg_wake_irq)
+			priv->macro_params[TX_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(bolero_register_wake_irq);
+
+/**
+ * bolero_tx_clk_switch - Switch tx macro clock
+ *
+ * @component: pointer to codec component instance.
+ *
+ * @clk_src: clk source
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src)
+{
+	struct bolero_priv *priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!bolero_is_valid_codec_dev(priv->dev)) {
+		dev_err(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[TX_MACRO].clk_switch)
+		ret = priv->macro_params[TX_MACRO].clk_switch(component,
+							      clk_src);
+
+	return ret;
+}
+EXPORT_SYMBOL(bolero_tx_clk_switch);
+
+/**
+ * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk
+ *
+ * @component: pointer to codec component instance.
+ * @enable: set true to enable, otherwise false.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_tx_mclk_enable(struct snd_soc_component *component,
+			  bool enable)
+{
+	struct bolero_priv *priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!bolero_is_valid_codec_dev(priv->dev)) {
+		dev_err(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[TX_MACRO].clk_enable)
+		ret = priv->macro_params[TX_MACRO].clk_enable(component,
+								enable);
+
+	return ret;
+}
+EXPORT_SYMBOL(bolero_tx_mclk_enable);
+
+/**
+ * bolero_register_event_listener - Register/Deregister to event listener
+ *
+ * @component: pointer to codec component instance.
+ * @enable: when set to 1 registers to event listener otherwise, derigisters
+ *          from the event listener
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_register_event_listener(struct snd_soc_component *component,
+				   bool enable)
+{
+	struct bolero_priv *priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!bolero_is_valid_codec_dev(priv->dev)) {
+		dev_err(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[TX_MACRO].reg_evt_listener)
+		ret = priv->macro_params[TX_MACRO].reg_evt_listener(component,
+								    enable);
+
+	return ret;
+}
+EXPORT_SYMBOL(bolero_register_event_listener);
+
+static int bolero_soc_codec_probe(struct snd_soc_component *component)
+{
+	struct bolero_priv *priv = dev_get_drvdata(component->dev);
+	int macro_idx, ret = 0;
+	u8 core_id_0 = 0, core_id_1 = 0, core_id_2 = 0;
+
+	snd_soc_component_init_regmap(component, priv->regmap);
+
+	if (!priv->version) {
+		/*
+		 * In order for the ADIE RTC to differentiate between targets
+		 * version info is used.
+		 * Assign 1.0 for target with only one macro
+		 * Assign 1.1 for target with two macros
+		 * Assign 1.2 for target with more than two macros
+		 */
+		if (priv->num_macros_registered == 1)
+			priv->version = BOLERO_VERSION_1_0;
+		else if (priv->num_macros_registered == 2)
+			priv->version = BOLERO_VERSION_1_1;
+		else if (priv->num_macros_registered > 2)
+			priv->version = BOLERO_VERSION_1_2;
+	}
+
+	/* Assign bolero version */
+	core_id_0 = snd_soc_component_read(component,
+					BOLERO_CDC_VA_TOP_CSR_CORE_ID_0);
+	core_id_1 = snd_soc_component_read(component,
+					BOLERO_CDC_VA_TOP_CSR_CORE_ID_1);
+	core_id_2 = snd_soc_component_read(component,
+					BOLERO_CDC_VA_TOP_CSR_CORE_ID_2);
+	if ((core_id_0 == 0x01) && (core_id_1 == 0x0F))
+		priv->version = BOLERO_VERSION_2_0;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0E)) {
+		if (core_id_2 == 0x20)
+			priv->version = BOLERO_VERSION_2_2;
+		else
+			priv->version = BOLERO_VERSION_2_1;
+	}
+
+	/* call init for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].init) {
+			ret = priv->macro_params[macro_idx].init(component);
+			if (ret < 0) {
+				dev_err(component->dev,
+					"%s: init for macro %d failed\n",
+					__func__, macro_idx);
+				goto err;
+			}
+		}
+	}
+	priv->component = component;
+
+	ret = snd_event_client_register(priv->dev, &bolero_ssr_ops, priv);
+	if (!ret) {
+		snd_event_notify(priv->dev, SND_EVENT_UP);
+	} else {
+		dev_err(component->dev,
+			"%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	dev_dbg(component->dev, "%s: bolero soc codec probe success\n",
+		__func__);
+err:
+	return ret;
+}
+
+static void bolero_soc_codec_remove(struct snd_soc_component *component)
+{
+	struct bolero_priv *priv = dev_get_drvdata(component->dev);
+	int macro_idx;
+
+	snd_event_client_deregister(priv->dev);
+	/* call exit for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++)
+		if (priv->macro_params[macro_idx].exit)
+			priv->macro_params[macro_idx].exit(component);
+
+	return;
+}
+
+static const struct snd_soc_component_driver bolero = {
+	.name = DRV_NAME,
+	.probe = bolero_soc_codec_probe,
+	.remove = bolero_soc_codec_remove,
+};
+
+static void bolero_add_child_devices(struct work_struct *work)
+{
+	struct bolero_priv *priv;
+	bool split_codec = false;
+	struct platform_device *pdev;
+	struct device_node *node;
+	int ret = 0, count = 0;
+	struct wcd_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[BOLERO_CDC_STRING_LEN] = "";
+
+	priv = container_of(work, struct bolero_priv,
+			    bolero_add_child_devices_work);
+	if (!priv) {
+		pr_err("%s: Memory for bolero priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!priv->dev || !priv->dev->of_node) {
+		dev_err(priv->dev, "%s: DT node for bolero does not exist\n",
+			__func__);
+		return;
+	}
+
+	platdata = &priv->plat_data;
+	priv->child_count = 0;
+
+	for_each_available_child_of_node(priv->dev->of_node, node) {
+		split_codec = false;
+		if (of_find_property(node, "qcom,split-codec", NULL)) {
+			split_codec = true;
+			dev_dbg(priv->dev, "%s: split codec slave exists\n",
+				__func__);
+		}
+
+		strlcpy(plat_dev_name, node->name,
+				(BOLERO_CDC_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = priv->dev;
+		pdev->dev.of_node = node;
+
+		priv->dev->platform_data = platdata;
+		if (split_codec)
+			priv->wcd_dev = &pdev->dev;
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			platform_device_put(pdev);
+			goto fail_pdev_add;
+		}
+
+		if (priv->child_count < BOLERO_CDC_CHILD_DEVICES_MAX)
+			priv->pdev_child_devices[priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < priv->child_count; count++)
+		platform_device_put(priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int bolero_probe(struct platform_device *pdev)
+{
+	struct bolero_priv *priv;
+	u32 num_macros = 0;
+	int ret;
+	struct clk *lpass_core_hw_vote = NULL;
+	struct clk *lpass_audio_hw_vote = NULL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct bolero_priv),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-macros",
+				   &num_macros);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s:num-macros property not found\n",
+			__func__);
+		return ret;
+	}
+	priv->num_macros = num_macros;
+	if (priv->num_macros > MAX_MACRO) {
+		dev_err(&pdev->dev,
+			"%s:num_macros(%d) > MAX_MACRO(%d) than supported\n",
+			__func__, priv->num_macros, MAX_MACRO);
+		return -EINVAL;
+	}
+	priv->va_without_decimation = of_property_read_bool(pdev->dev.of_node,
+						"qcom,va-without-decimation");
+	if (priv->va_without_decimation)
+		bolero_reg_access[VA_MACRO] = bolero_va_top_reg_access;
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,bolero-version", &priv->version);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s:bolero version not specified\n",
+			__func__);
+		ret = 0;
+	}
+	if ((priv->version == BOLERO_VERSION_2_1) ||
+	    (priv->version == BOLERO_VERSION_2_2)) {
+		bolero_reg_access[TX_MACRO] = bolero_tx_reg_access_v2;
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v2;
+	} else if (priv->version == BOLERO_VERSION_2_0) {
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v3;
+	}
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier);
+	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->initial_boot = true;
+	priv->regmap = bolero_regmap_init(priv->dev,
+					  &bolero_regmap_config);
+	if (IS_ERR_OR_NULL((void *)(priv->regmap))) {
+		dev_err(&pdev->dev, "%s:regmap init failed\n", __func__);
+		return -EINVAL;
+	}
+
+	devm_regmap_qti_debugfs_register(priv->dev, priv->regmap);
+
+	priv->read_dev = __bolero_reg_read;
+	priv->write_dev = __bolero_reg_write;
+
+	priv->plat_data.handle = (void *) priv;
+	priv->plat_data.update_wcd_event = bolero_cdc_update_wcd_event;
+	priv->plat_data.register_notifier = bolero_cdc_register_notifier;
+
+	priv->core_hw_vote_count = 0;
+	priv->core_audio_vote_count = 0;
+
+	dev_set_drvdata(&pdev->dev, priv);
+	mutex_init(&priv->io_lock);
+	mutex_init(&priv->clk_lock);
+	mutex_init(&priv->vote_lock);
+	INIT_WORK(&priv->bolero_add_child_devices_work,
+		  bolero_add_child_devices);
+
+	/* Register LPASS core hw vote */
+	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
+	if (IS_ERR(lpass_core_hw_vote)) {
+		ret = PTR_ERR(lpass_core_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_core_hw_vote", ret);
+		lpass_core_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_core_hw_vote = lpass_core_hw_vote;
+
+	/* Register LPASS audio hw vote */
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_audio_hw_vote = lpass_audio_hw_vote;
+	schedule_work(&priv->bolero_add_child_devices_work);
+	return 0;
+}
+
+static int bolero_remove(struct platform_device *pdev)
+{
+	struct bolero_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	of_platform_depopulate(&pdev->dev);
+	mutex_destroy(&priv->io_lock);
+	mutex_destroy(&priv->clk_lock);
+	mutex_destroy(&priv->vote_lock);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int bolero_runtime_resume(struct device *dev)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
+	int ret = 0;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
+		goto audio_vote;
+	}
+
+	if (priv->core_hw_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote, dev);
+		if (ret < 0) {
+			dev_err(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+			goto audio_vote;
+		}
+	}
+	priv->core_hw_vote_count++;
+
+audio_vote:
+	if (priv->lpass_audio_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__);
+		goto done;
+	}
+
+	if (priv->core_audio_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote, dev);
+		if (ret < 0) {
+			if (__ratelimit(&rtl))
+				dev_err(dev, "%s:lpass audio hw enable failed\n",
+					__func__);
+			goto done;
+		}
+	}
+	priv->core_audio_vote_count++;
+
+done:
+	mutex_unlock(&priv->vote_lock);
+	pm_runtime_set_autosuspend_delay(priv->dev, BOLERO_AUTO_SUSPEND_DELAY);
+	return 0;
+}
+EXPORT_SYMBOL(bolero_runtime_resume);
+
+int bolero_runtime_suspend(struct device *dev)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
+
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote != NULL) {
+		if (--priv->core_hw_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_core_hw_vote, dev);
+		if (priv->core_hw_vote_count < 0)
+			priv->core_hw_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n",
+			__func__);
+	}
+
+	if (priv->lpass_audio_hw_vote != NULL) {
+		if (--priv->core_audio_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_audio_hw_vote, dev);
+		if (priv->core_audio_vote_count < 0)
+			priv->core_audio_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n",
+			__func__);
+	}
+
+	mutex_unlock(&priv->vote_lock);
+	return 0;
+}
+EXPORT_SYMBOL(bolero_runtime_suspend);
+#endif /* CONFIG_PM */
+
+bool bolero_check_core_votes(struct device *dev)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
+	bool ret = true;
+
+	mutex_lock(&priv->vote_lock);
+	if ((priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+		(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))
+		ret = false;
+	mutex_unlock(&priv->vote_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(bolero_check_core_votes);
+
+static const struct of_device_id bolero_dt_match[] = {
+	{.compatible = "qcom,bolero-codec"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, bolero_dt_match);
+
+static struct platform_driver bolero_drv = {
+	.driver = {
+		.name = "bolero-codec",
+		.owner = THIS_MODULE,
+		.of_match_table = bolero_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = bolero_probe,
+	.remove = bolero_remove,
+};
+
+static int bolero_drv_init(void)
+{
+	return platform_driver_register(&bolero_drv);
+}
+
+static void bolero_drv_exit(void)
+{
+	platform_driver_unregister(&bolero_drv);
+}
+
+static int __init bolero_init(void)
+{
+	bolero_drv_init();
+	bolero_clk_rsc_mgr_init();
+	return 0;
+}
+module_init(bolero_init);
+
+static void __exit bolero_exit(void)
+{
+	bolero_clk_rsc_mgr_exit();
+	bolero_drv_exit();
+}
+module_exit(bolero_exit);
+
+MODULE_DESCRIPTION("Bolero driver");
+MODULE_LICENSE("GPL v2");

+ 228 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-cdc.h

@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef BOLERO_CDC_H
+#define BOLERO_CDC_H
+
+#include <sound/soc.h>
+#include <linux/regmap.h>
+
+#define BOLERO_VERSION_1_0 0x0001
+#define BOLERO_VERSION_1_1 0x0002
+#define BOLERO_VERSION_1_2 0x0003
+#define BOLERO_VERSION_2_0 0x0004
+#define BOLERO_VERSION_2_1 0x0005
+#define BOLERO_VERSION_2_2 0x0006
+
+enum {
+	START_MACRO,
+	TX_MACRO = START_MACRO,
+	RX_MACRO,
+	WSA_MACRO,
+	VA_MACRO,
+	MAX_MACRO
+};
+
+enum mclk_mux {
+	MCLK_MUX0,
+	MCLK_MUX1,
+	MCLK_MUX_MAX
+};
+
+enum {
+	BOLERO_ADC0 = 1,
+	BOLERO_ADC1,
+	BOLERO_ADC2,
+	BOLERO_ADC3,
+	BOLERO_ADC_MAX
+};
+
+enum {
+	CLK_SRC_TX_RCG = 0,
+	CLK_SRC_VA_RCG,
+};
+
+enum {
+	BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
+	BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */
+	BOLERO_MACRO_EVT_IMPED_FALSE, /* for imped false */
+	BOLERO_MACRO_EVT_SSR_DOWN,
+	BOLERO_MACRO_EVT_SSR_UP,
+	BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET,
+	BOLERO_MACRO_EVT_CLK_RESET,
+	BOLERO_MACRO_EVT_REG_WAKE_IRQ,
+	BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST,
+	BOLERO_MACRO_EVT_BCS_CLK_OFF,
+	BOLERO_MACRO_EVT_SSR_GFMUX_UP,
+	BOLERO_MACRO_EVT_PRE_SSR_UP,
+	BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE,
+	BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, /* Enable HD2 cfg for HPHL */
+	BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, /* Enable HD2 cfg for HPHR */
+};
+
+enum {
+	DMIC_TX = 0,
+	DMIC_VA = 1,
+
+};
+
+struct macro_ops {
+	int (*init)(struct snd_soc_component *component);
+	int (*exit)(struct snd_soc_component *component);
+	u16 num_dais;
+	struct device *dev;
+	struct snd_soc_dai_driver *dai_ptr;
+	int (*mclk_fn)(struct device *dev, bool enable);
+	int (*event_handler)(struct snd_soc_component *component, u16 event,
+			     u32 data);
+	int (*reg_wake_irq)(struct snd_soc_component *component, u32 data);
+	int (*set_port_map)(struct snd_soc_component *component, u32 uc,
+			    u32 size, void *data);
+	int (*clk_div_get)(struct snd_soc_component *component);
+	int (*clk_switch)(struct snd_soc_component *component, int clk_src);
+	int (*reg_evt_listener)(struct snd_soc_component *component, bool en);
+	int (*clk_enable)(struct snd_soc_component *c, bool en);
+	char __iomem *io_base;
+	u16 clk_id_req;
+	u16 default_clk_id;
+};
+
+typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event);
+
+#if IS_ENABLED(CONFIG_SND_SOC_BOLERO)
+int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb);
+void bolero_unregister_res_clk(struct device *dev);
+bool bolero_is_va_macro_registered(struct device *dev);
+int bolero_register_macro(struct device *dev, u16 macro_id,
+			  struct macro_ops *ops);
+void bolero_unregister_macro(struct device *dev, u16 macro_id);
+struct device *bolero_get_device_ptr(struct device *dev, u16 macro_id);
+struct device *bolero_get_rsc_clk_device_ptr(struct device *dev);
+int bolero_info_create_codec_entry(
+		struct snd_info_entry *codec_root,
+		struct snd_soc_component *component);
+int bolero_register_wake_irq(struct snd_soc_component *component, u32 data);
+void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n);
+int bolero_runtime_resume(struct device *dev);
+int bolero_runtime_suspend(struct device *dev);
+int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data);
+int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src);
+int bolero_register_event_listener(struct snd_soc_component *component,
+				   bool enable);
+void bolero_wsa_pa_on(struct device *dev, bool adie_lb);
+bool bolero_check_core_votes(struct device *dev);
+int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable);
+int bolero_get_version(struct device *dev);
+int bolero_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable);
+void bolero_rx_pa_on(struct device *dev);
+#else
+static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb)
+{
+	return 0;
+}
+static inline void bolero_unregister_res_clk(struct device *dev)
+{
+}
+
+static bool bolero_is_va_macro_registered(struct device *dev)
+{
+	return false;
+}
+
+static inline int bolero_register_macro(struct device *dev,
+					u16 macro_id,
+					struct macro_ops *ops)
+{
+	return 0;
+}
+
+static inline void bolero_unregister_macro(struct device *dev, u16 macro_id)
+{
+}
+
+static inline struct device *bolero_get_device_ptr(struct device *dev,
+						   u16 macro_id)
+{
+	return NULL;
+}
+
+static int bolero_info_create_codec_entry(
+		struct snd_info_entry *codec_root,
+		struct snd_soc_component *component)
+{
+	return 0;
+}
+
+static inline void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+}
+
+static inline int bolero_register_wake_irq(struct snd_soc_component *component,
+					   u32 data)
+{
+	return 0;
+}
+
+static inline int bolero_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+static int bolero_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static inline int bolero_set_port_map(struct snd_soc_component *component,
+				u32 size, void *data)
+{
+	return 0;
+}
+
+static inline int bolero_tx_clk_switch(struct snd_soc_component *component,
+					int clk_src)
+{
+	return 0;
+}
+
+static inline int bolero_register_event_listener(
+					struct snd_soc_component *component,
+					bool enable)
+{
+	return 0;
+}
+
+static void bolero_wsa_pa_on(struct device *dev, bool adie_lb)
+{
+}
+
+static inline bool bolero_check_core_votes(struct device *dev)
+{
+	return false;
+}
+
+static int bolero_get_version(struct device *dev)
+{
+	return 0;
+}
+
+static int bolero_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable)
+{
+	return 0;
+}
+static int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable)
+{
+	return 0;
+}
+
+static inline void bolero_rx_pa_on(struct device *dev)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SND_SOC_BOLERO */
+#endif /* BOLERO_CDC_H */

+ 768 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-clk-rsc.c

@@ -0,0 +1,768 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/ratelimit.h>
+#include "bolero-cdc.h"
+#include "bolero-clk-rsc.h"
+
+#define DRV_NAME "bolero-clk-rsc"
+#define BOLERO_CLK_NAME_LENGTH 30
+#define NPL_CLK_OFFSET (TX_NPL_CLK - TX_CORE_CLK)
+
+static char clk_src_name[MAX_CLK][BOLERO_CLK_NAME_LENGTH] = {
+	"tx_core_clk",
+	"rx_core_clk",
+	"wsa_core_clk",
+	"va_core_clk",
+	"tx_npl_clk",
+	"rx_npl_clk",
+	"wsa_npl_clk",
+	"va_npl_clk",
+};
+
+struct bolero_clk_rsc {
+	struct device *dev;
+	struct mutex rsc_clk_lock;
+	struct mutex fs_gen_lock;
+	struct clk *clk[MAX_CLK];
+	int clk_cnt[MAX_CLK];
+	int reg_seq_en_cnt;
+	int va_tx_clk_cnt;
+	bool dev_up;
+	bool dev_up_gfmux;
+	u32 num_fs_reg;
+	u32 *fs_gen_seq;
+	int default_clk_id[MAX_CLK];
+	struct regmap *regmap;
+	char __iomem *rx_clk_muxsel;
+	char __iomem *wsa_clk_muxsel;
+	char __iomem *va_clk_muxsel;
+};
+
+static int bolero_clk_rsc_cb(struct device *dev, u16 event)
+{
+	struct bolero_clk_rsc *priv;
+
+	if (!dev) {
+		pr_err("%s: Invalid device pointer\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		pr_err("%s: Invalid clk rsc priviate data\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&priv->rsc_clk_lock);
+	if (event == BOLERO_MACRO_EVT_SSR_UP) {
+		priv->dev_up = true;
+	} else if (event == BOLERO_MACRO_EVT_SSR_DOWN) {
+		priv->dev_up = false;
+		priv->dev_up_gfmux = false;
+	} else if (event == BOLERO_MACRO_EVT_SSR_GFMUX_UP) {
+		priv->dev_up_gfmux = true;
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+
+	return 0;
+}
+
+static char __iomem *bolero_clk_rsc_get_clk_muxsel(struct bolero_clk_rsc *priv,
+						 int clk_id)
+{
+	switch (clk_id) {
+	case RX_CORE_CLK:
+		return priv->rx_clk_muxsel;
+	case WSA_CORE_CLK:
+		return priv->wsa_clk_muxsel;
+	case VA_CORE_CLK:
+		return priv->va_clk_muxsel;
+	case TX_CORE_CLK:
+	default:
+		dev_err_ratelimited(priv->dev, "%s: Invalid case\n", __func__);
+		break;
+	}
+
+	return NULL;
+}
+
+int bolero_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+	int count = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+
+	if (clk_id < 0 || clk_id >= MAX_CLK - NPL_CLK_OFFSET) {
+		pr_err("%s: Invalid clk_id: %d\n",
+			__func__, clk_id);
+		return -EINVAL;
+	}
+
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return -EINVAL;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return -EINVAL;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+	while (__clk_is_enabled(priv->clk[clk_id])) {
+		clk_disable_unprepare(priv->clk[clk_id + NPL_CLK_OFFSET]);
+		clk_disable_unprepare(priv->clk[clk_id]);
+		count++;
+	}
+	dev_dbg(priv->dev,
+		"%s: clock reset after ssr, count %d\n", __func__, count);
+
+	while (count--) {
+		clk_prepare_enable(priv->clk[clk_id]);
+		clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]);
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return 0;
+}
+EXPORT_SYMBOL(bolero_rsc_clk_reset);
+
+void bolero_clk_rsc_enable_all_clocks(struct device *dev, bool enable)
+{
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+	int i = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk private data\n", __func__);
+		return;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+	for (i = 0; i < MAX_CLK - NPL_CLK_OFFSET; i++) {
+		if (enable) {
+			if (priv->clk[i])
+				clk_prepare_enable(priv->clk[i]);
+			if (priv->clk[i + NPL_CLK_OFFSET])
+				clk_prepare_enable(
+					priv->clk[i + NPL_CLK_OFFSET]);
+		} else {
+			if (priv->clk[i + NPL_CLK_OFFSET])
+				clk_disable_unprepare(
+					priv->clk[i + NPL_CLK_OFFSET]);
+			if (priv->clk[i])
+				clk_disable_unprepare(priv->clk[i]);
+		}
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return;
+}
+EXPORT_SYMBOL(bolero_clk_rsc_enable_all_clocks);
+
+static int bolero_clk_rsc_mux0_clk_request(struct bolero_clk_rsc *priv,
+					   int clk_id,
+					   bool enable)
+{
+	int ret = 0;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	if (enable) {
+		/* Enable Requested Core clk */
+		if (priv->clk_cnt[clk_id] == 0) {
+			ret = clk_prepare_enable(priv->clk[clk_id]);
+			if (ret < 0) {
+				if (__ratelimit(&rtl))
+					dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+							__func__, clk_id);
+				goto done;
+			}
+			if (priv->clk[clk_id + NPL_CLK_OFFSET]) {
+				ret = clk_prepare_enable(
+					priv->clk[clk_id + NPL_CLK_OFFSET]);
+				if (ret < 0) {
+					if (__ratelimit(&rtl))
+						dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+						__func__,
+						clk_id + NPL_CLK_OFFSET);
+					goto err;
+				}
+			}
+		}
+		priv->clk_cnt[clk_id]++;
+	} else {
+		if (priv->clk_cnt[clk_id] <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n",
+					__func__, clk_id);
+			priv->clk_cnt[clk_id] = 0;
+			goto done;
+		}
+		priv->clk_cnt[clk_id]--;
+		if (priv->clk_cnt[clk_id] == 0) {
+			if (priv->clk[clk_id + NPL_CLK_OFFSET])
+				clk_disable_unprepare(
+					priv->clk[clk_id + NPL_CLK_OFFSET]);
+			clk_disable_unprepare(priv->clk[clk_id]);
+		}
+	}
+	return ret;
+
+err:
+	clk_disable_unprepare(priv->clk[clk_id]);
+done:
+	return ret;
+}
+
+static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv,
+					   int clk_id,
+					   bool enable)
+{
+	char __iomem *clk_muxsel = NULL;
+	int ret = 0;
+	int default_clk_id = priv->default_clk_id[clk_id];
+	u32 muxsel = 0;
+	static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
+
+	clk_muxsel = bolero_clk_rsc_get_clk_muxsel(priv, clk_id);
+	if (!clk_muxsel) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (enable) {
+		if (priv->clk_cnt[clk_id] == 0) {
+			if (clk_id != VA_CORE_CLK) {
+				ret = bolero_clk_rsc_mux0_clk_request(priv,
+								default_clk_id,
+								true);
+				if (ret < 0)
+					goto done;
+			}
+
+			ret = clk_prepare_enable(priv->clk[clk_id]);
+			if (ret < 0) {
+				if (__ratelimit(&rtl))
+					dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+						__func__, clk_id);
+				goto err_clk;
+			}
+			if (priv->clk[clk_id + NPL_CLK_OFFSET]) {
+				ret = clk_prepare_enable(
+					priv->clk[clk_id + NPL_CLK_OFFSET]);
+				if (ret < 0) {
+					if (__ratelimit(&rtl))
+						dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+						__func__,
+						clk_id + NPL_CLK_OFFSET);
+					goto err_npl_clk;
+				}
+			}
+
+			/*
+			 * Temp SW workaround to address a glitch issue of
+			 * VA GFMux instance responsible for switching from
+			 * TX MCLK to VA MCLK. This configuration would be taken
+			 * care in DSP itself
+			 */
+			if (clk_id != VA_CORE_CLK) {
+				if (priv->dev_up_gfmux) {
+					iowrite32(0x1, clk_muxsel);
+					muxsel = ioread32(clk_muxsel);
+				}
+				bolero_clk_rsc_mux0_clk_request(priv,
+							default_clk_id,
+							false);
+			}
+		}
+		priv->clk_cnt[clk_id]++;
+	} else {
+		if (priv->clk_cnt[clk_id] <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n",
+				__func__, clk_id);
+			priv->clk_cnt[clk_id] = 0;
+			goto done;
+		}
+		priv->clk_cnt[clk_id]--;
+		if (priv->clk_cnt[clk_id] == 0) {
+			if (clk_id != VA_CORE_CLK) {
+				ret = bolero_clk_rsc_mux0_clk_request(priv,
+						default_clk_id, true);
+
+				if (!ret) {
+					/*
+					 * Temp SW workaround to address a glitch issue
+					 * of VA GFMux instance responsible for
+					 * switching from TX MCLK to VA MCLK.
+					 * This configuration would be taken
+					 * care in DSP itself.
+					 */
+					if (priv->dev_up_gfmux) {
+						iowrite32(0x0, clk_muxsel);
+						muxsel = ioread32(clk_muxsel);
+					}
+				}
+			}
+			if (priv->clk[clk_id + NPL_CLK_OFFSET])
+				clk_disable_unprepare(
+					priv->clk[clk_id + NPL_CLK_OFFSET]);
+			clk_disable_unprepare(priv->clk[clk_id]);
+
+			if (clk_id != VA_CORE_CLK) {
+				if (!ret)
+					bolero_clk_rsc_mux0_clk_request(priv,
+						default_clk_id, false);
+			}
+		}
+	}
+	return ret;
+
+err_npl_clk:
+	clk_disable_unprepare(priv->clk[clk_id]);
+
+err_clk:
+	if (clk_id != VA_CORE_CLK)
+		bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, false);
+done:
+	return ret;
+}
+
+static int bolero_clk_rsc_check_and_update_va_clk(struct bolero_clk_rsc *priv,
+						  bool mux_switch,
+						  int clk_id,
+						  bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		if (clk_id == VA_CORE_CLK && mux_switch) {
+			/*
+			 * Handle the following usecase scenarios during enable
+			 * 1. VA only, Active clk is VA_CORE_CLK
+			 * 2. record -> record + VA, Active clk is TX_CORE_CLK
+			 */
+			if (priv->clk_cnt[TX_CORE_CLK] == 0) {
+				ret = bolero_clk_rsc_mux1_clk_request(priv,
+							 VA_CORE_CLK, enable);
+				if (ret < 0)
+					goto err;
+			} else {
+				ret = bolero_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, enable);
+				if (ret < 0)
+					goto err;
+				priv->va_tx_clk_cnt++;
+			}
+		} else if ((priv->clk_cnt[TX_CORE_CLK] > 0) &&
+			   (priv->clk_cnt[VA_CORE_CLK] > 0)) {
+			/*
+			 * Handle following concurrency scenario during enable
+			 * 1. VA-> Record+VA, Increment TX CLK and Disable VA
+			 * 2. VA-> Playback+VA, Increment TX CLK and Disable VA
+			 */
+			while (priv->clk_cnt[VA_CORE_CLK] > 0) {
+				ret = bolero_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, true);
+				if (ret < 0)
+					goto err;
+
+				bolero_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, false);
+				priv->va_tx_clk_cnt++;
+			}
+		}
+	} else {
+		if (clk_id == VA_CORE_CLK && mux_switch) {
+			/*
+			 * Handle the following usecase scenarios during disable
+			 * 1. VA only, disable VA_CORE_CLK
+			 * 2. Record + VA -> Record, decrement TX CLK count
+			 */
+			if (priv->clk_cnt[VA_CORE_CLK]) {
+				bolero_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, enable);
+			} else if (priv->va_tx_clk_cnt) {
+				bolero_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, enable);
+				priv->va_tx_clk_cnt--;
+			}
+		} else if (priv->va_tx_clk_cnt == priv->clk_cnt[TX_CORE_CLK]) {
+			/*
+			 * Handle the following usecase scenarios during disable
+			 * Record+VA-> VA: enable VA CLK, decrement TX CLK count
+			 */
+			while (priv->va_tx_clk_cnt) {
+				ret = bolero_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, true);
+				if (ret < 0)
+					goto err;
+
+				bolero_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, false);
+				priv->va_tx_clk_cnt--;
+			}
+		}
+	}
+
+err:
+	return ret;
+}
+
+/**
+ * bolero_clk_rsc_fs_gen_request - request to enable/disable fs generation
+ * sequence
+ *
+ * @dev: Macro device pointer
+ * @enable: enable or disable flag
+ */
+void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable)
+{
+	int i;
+	struct regmap *regmap;
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return;
+	}
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return;
+	}
+	regmap = dev_get_regmap(priv->dev->parent, NULL);
+	if (!regmap) {
+		pr_err("%s: regmap is null\n", __func__);
+		return;
+	}
+	mutex_lock(&priv->fs_gen_lock);
+	if (enable) {
+		if (priv->reg_seq_en_cnt++ == 0) {
+			for (i = 0; i < (priv->num_fs_reg * 3); i += 3) {
+				dev_dbg(priv->dev, "%s: Register: %d, mask: %d, value %d\n",
+					__func__, priv->fs_gen_seq[i],
+					priv->fs_gen_seq[i + 1],
+					priv->fs_gen_seq[i + 2]);
+				regmap_update_bits(regmap,
+						   priv->fs_gen_seq[i],
+						   priv->fs_gen_seq[i + 1],
+						   priv->fs_gen_seq[i + 2]);
+			}
+		}
+	} else {
+		if (priv->reg_seq_en_cnt <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: req_seq_cnt: %d is already disabled\n",
+				__func__, priv->reg_seq_en_cnt);
+			priv->reg_seq_en_cnt = 0;
+			mutex_unlock(&priv->fs_gen_lock);
+			return;
+		}
+		if (--priv->reg_seq_en_cnt == 0) {
+			for (i = ((priv->num_fs_reg - 1) * 3); i >= 0; i -= 3) {
+				dev_dbg(priv->dev, "%s: Register: %d, mask: %d\n",
+					__func__, priv->fs_gen_seq[i],
+					priv->fs_gen_seq[i + 1]);
+				regmap_update_bits(regmap, priv->fs_gen_seq[i],
+						priv->fs_gen_seq[i + 1], 0x0);
+			}
+		}
+	}
+	mutex_unlock(&priv->fs_gen_lock);
+}
+EXPORT_SYMBOL(bolero_clk_rsc_fs_gen_request);
+
+/**
+ * bolero_clk_rsc_request_clock - request for clock to
+ * enable/disable
+ *
+ * @dev: Macro device pointer.
+ * @default_clk_id: mux0 Core clock ID input.
+ * @clk_id_req: Core clock ID requested to enable/disable
+ * @enable: enable or disable clock flag
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int bolero_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable)
+{
+	int ret = 0;
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+	bool mux_switch = false;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if ((clk_id_req < 0 || clk_id_req >= MAX_CLK) &&
+		(default_clk_id < 0 || default_clk_id >= MAX_CLK)) {
+		pr_err("%s: Invalid clk_id_req: %d or default_clk_id: %d\n",
+				__func__, clk_id_req, default_clk_id);
+		return -EINVAL;
+	}
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&priv->rsc_clk_lock);
+	if (!priv->dev_up && enable) {
+		dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	priv->default_clk_id[clk_id_req] = default_clk_id;
+	if (default_clk_id != clk_id_req)
+		mux_switch = true;
+
+	if (mux_switch) {
+		if (clk_id_req != VA_CORE_CLK) {
+			ret = bolero_clk_rsc_mux1_clk_request(priv, clk_id_req,
+							enable);
+			if (ret < 0)
+				goto err;
+		}
+	} else {
+		ret = bolero_clk_rsc_mux0_clk_request(priv, clk_id_req, enable);
+		if (ret < 0)
+			goto err;
+	}
+
+	ret = bolero_clk_rsc_check_and_update_va_clk(priv, mux_switch,
+						 clk_id_req,
+						 enable);
+	if (ret < 0)
+		goto err;
+
+	dev_dbg(priv->dev, "%s: clk_cnt: %d for requested clk: %d, enable: %d\n",
+		__func__,  priv->clk_cnt[clk_id_req], clk_id_req,
+		enable);
+
+	mutex_unlock(&priv->rsc_clk_lock);
+
+	return 0;
+
+err:
+	mutex_unlock(&priv->rsc_clk_lock);
+	return ret;
+}
+EXPORT_SYMBOL(bolero_clk_rsc_request_clock);
+
+
+static int bolero_clk_rsc_probe(struct platform_device *pdev)
+{
+	int ret = 0, fs_gen_size, i, j;
+	const char **clk_name_array;
+	int clk_cnt;
+	struct clk *clk;
+	struct bolero_clk_rsc *priv = NULL;
+	u32 muxsel = 0;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct bolero_clk_rsc),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* Get clk fs gen sequence from device tree */
+	if (!of_find_property(pdev->dev.of_node, "qcom,fs-gen-sequence",
+						  &fs_gen_size)) {
+		dev_err(&pdev->dev, "%s: unable to find qcom,fs-gen-sequence property\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	priv->num_fs_reg = fs_gen_size/(3 * sizeof(u32));
+	priv->fs_gen_seq = devm_kzalloc(&pdev->dev, fs_gen_size, GFP_KERNEL);
+	if (!priv->fs_gen_seq) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	dev_dbg(&pdev->dev, "%s: num_fs_reg %d\n", __func__, priv->num_fs_reg);
+	/* Parse fs-gen-sequence */
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+					 "qcom,fs-gen-sequence",
+					 priv->fs_gen_seq,
+					 priv->num_fs_reg * 3);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: unable to parse fs-gen-sequence, ret = %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* Get clk details from device tree */
+	clk_cnt = of_property_count_strings(pdev->dev.of_node, "clock-names");
+	if (clk_cnt <= 0 || clk_cnt > MAX_CLK) {
+		dev_err(&pdev->dev, "%s: Invalid number of clocks %d",
+				__func__, clk_cnt);
+		ret = -EINVAL;
+		goto err;
+	}
+	clk_name_array = devm_kzalloc(&pdev->dev, clk_cnt * sizeof(char *),
+					  GFP_KERNEL);
+	if (!clk_name_array) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = of_property_read_string_array(pdev->dev.of_node, "clock-names",
+					clk_name_array, clk_cnt);
+
+	for (i = 0; i < MAX_CLK; i++) {
+		priv->clk[i] = NULL;
+		for (j = 0; j < clk_cnt; j++) {
+			if (!strcmp(clk_src_name[i], clk_name_array[j])) {
+				clk = devm_clk_get(&pdev->dev, clk_src_name[i]);
+				if (IS_ERR(clk)) {
+					ret = PTR_ERR(clk);
+					dev_err(&pdev->dev, "%s: clk get failed for %s with ret %d\n",
+						__func__, clk_src_name[i], ret);
+					goto err;
+				}
+				priv->clk[i] = clk;
+				dev_dbg(&pdev->dev, "%s: clk get success for clk name %s\n",
+						__func__, clk_src_name[i]);
+			}
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				 "qcom,rx_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,rx_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->rx_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->rx_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for rx muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,wsa_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,wsa_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->wsa_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->wsa_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for wsa muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				 "qcom,va_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,va_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->va_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->va_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for va muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+
+	ret = bolero_register_res_clk(&pdev->dev, bolero_clk_rsc_cb);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: Failed to register cb %d",
+				__func__, ret);
+		goto err;
+	}
+	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->dev_up_gfmux = true;
+	mutex_init(&priv->rsc_clk_lock);
+	mutex_init(&priv->fs_gen_lock);
+	dev_set_drvdata(&pdev->dev, priv);
+
+err:
+	return ret;
+}
+
+static int bolero_clk_rsc_remove(struct platform_device *pdev)
+{
+	struct bolero_clk_rsc *priv = dev_get_drvdata(&pdev->dev);
+
+	bolero_unregister_res_clk(&pdev->dev);
+	of_platform_depopulate(&pdev->dev);
+	if (!priv)
+		return -EINVAL;
+	mutex_destroy(&priv->rsc_clk_lock);
+	mutex_destroy(&priv->fs_gen_lock);
+
+	return 0;
+}
+
+static const struct of_device_id bolero_clk_rsc_dt_match[] = {
+	{.compatible = "qcom,bolero-clk-rsc-mngr"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, bolero_clk_rsc_dt_match);
+
+static struct platform_driver bolero_clk_rsc_mgr = {
+	.driver = {
+		.name = "bolero-clk-rsc-mngr",
+		.owner = THIS_MODULE,
+		.of_match_table = bolero_clk_rsc_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = bolero_clk_rsc_probe,
+	.remove = bolero_clk_rsc_remove,
+};
+
+int bolero_clk_rsc_mgr_init(void)
+{
+	return platform_driver_register(&bolero_clk_rsc_mgr);
+}
+
+void bolero_clk_rsc_mgr_exit(void)
+{
+	platform_driver_unregister(&bolero_clk_rsc_mgr);
+}
+MODULE_DESCRIPTION("Bolero clock resource manager driver");
+MODULE_LICENSE("GPL v2");

+ 53 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/bolero-clk-rsc.h

@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef BOLERO_CLK_RSC_H
+#define BOLERO_CLK_RSC_H
+
+#include <linux/regmap.h>
+#include <bindings/qcom,bolero-clk-rsc.h>
+
+#if IS_ENABLED(CONFIG_SND_SOC_BOLERO)
+int bolero_clk_rsc_mgr_init(void);
+void bolero_clk_rsc_mgr_exit(void);
+void bolero_clk_rsc_fs_gen_request(struct device *dev,
+						bool enable);
+int bolero_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable);
+int bolero_rsc_clk_reset(struct device *dev, int clk_id);
+void bolero_clk_rsc_enable_all_clocks(struct device *dev, bool enable);
+#else
+static inline void bolero_clk_rsc_fs_gen_request(struct device *dev,
+						bool enable)
+{
+}
+static inline int bolero_clk_rsc_mgr_init(void)
+{
+	return 0;
+}
+static inline void bolero_clk_rsc_mgr_exit(void)
+{
+}
+static inline int bolero_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable)
+{
+	return 0;
+}
+static inline int bolero_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	return 0;
+}
+static inline void bolero_clk_rsc_enable_all_clocks(struct device *dev,
+						    bool enable)
+{
+	return;
+}
+#endif /* CONFIG_SND_SOC_BOLERO */
+#endif /* BOLERO_CLK_RSC_H */

+ 89 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/internal.h

@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _BOLERO_INTERNAL_H
+#define _BOLERO_INTERNAL_H
+
+#include "bolero-cdc-registers.h"
+
+#define BOLERO_CDC_CHILD_DEVICES_MAX 6
+
+enum {
+	REG_NO_ACCESS,
+	RD_REG,
+	WR_REG,
+	RD_WR_REG
+};
+
+struct wcd_ctrl_platform_data {
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				 struct notifier_block *nblock,
+				 bool enable);
+};
+
+struct bolero_priv {
+	struct device *dev;
+	struct snd_soc_component *component;
+	struct regmap *regmap;
+	struct mutex io_lock;
+	struct mutex clk_lock;
+	struct mutex vote_lock;
+	bool va_without_decimation;
+	bool macros_supported[MAX_MACRO];
+	bool dev_up;
+	bool initial_boot;
+	struct macro_ops macro_params[MAX_MACRO];
+	struct snd_soc_dai_driver *bolero_dais;
+	u16 num_dais;
+	u16 num_macros_registered;
+	u16 num_macros;
+	u16 current_mclk_mux_macro[MAX_MACRO];
+	struct work_struct bolero_add_child_devices_work;
+	u32 version;
+	struct clk *lpass_core_hw_vote;
+	struct clk *lpass_audio_hw_vote;
+	int core_hw_vote_count;
+	int core_audio_vote_count;
+
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+
+	int (*read_dev)(struct bolero_priv *priv,
+			u16 macro_id, u16 reg, u8 *val);
+	int (*write_dev)(struct bolero_priv *priv,
+			 u16 macro_id, u16 reg, u8 val);
+	struct platform_device *pdev_child_devices
+			[BOLERO_CDC_CHILD_DEVICES_MAX];
+	u16 child_count;
+	struct wcd_ctrl_platform_data plat_data;
+	struct device *wcd_dev;
+	struct blocking_notifier_head notifier;
+	struct device *clk_dev;
+	rsc_clk_cb_t rsc_clk_cb;
+	s32 dmic_0_1_clk_cnt;
+	s32 dmic_2_3_clk_cnt;
+	s32 dmic_4_5_clk_cnt;
+	s32 dmic_6_7_clk_cnt;
+	u8 dmic_0_1_clk_div;
+	u8 dmic_2_3_clk_div;
+	u8 dmic_4_5_clk_div;
+	u8 dmic_6_7_clk_div;
+};
+
+struct regmap *bolero_regmap_init(struct device *dev,
+				  const struct regmap_config *config);
+int bolero_get_macro_id(bool va_no_dec_flag, u16 reg);
+
+extern const struct regmap_config bolero_regmap_config;
+extern u8 *bolero_reg_access[MAX_MACRO];
+extern u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX];
+extern u8 bolero_va_reg_access_v2[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_va_reg_access_v3[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX];
+extern const u16 macro_id_base_offset[MAX_MACRO];
+
+#endif

+ 4310 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/rx-macro.c

@@ -0,0 +1,4310 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+
+#include <asoc/msm-cdc-pinctrl.h>
+#include "bolero-cdc.h"
+#include "bolero-cdc-registers.h"
+#include "bolero-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#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 SAMPLING_RATE_44P1KHZ   44100
+#define SAMPLING_RATE_88P2KHZ   88200
+#define SAMPLING_RATE_176P4KHZ  176400
+#define SAMPLING_RATE_352P8KHZ  352800
+
+#define RX_MACRO_MAX_OFFSET 0x1000
+
+#define RX_MACRO_MAX_DMA_CH_PER_PORT 2
+#define RX_SWR_STRING_LEN 80
+#define RX_MACRO_CHILD_DEVICES_MAX 3
+
+#define RX_MACRO_INTERP_MUX_NUM_INPUTS 3
+#define RX_MACRO_SIDETONE_IIR_COEFF_MAX 5
+
+#define STRING(name) #name
+#define RX_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define RX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define RX_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+#define RX_MACRO_RX_PATH_OFFSET 0x80
+#define RX_MACRO_COMP_OFFSET 0x40
+
+#define MAX_IMPED_PARAMS 6
+
+#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 RX_MACRO_GAIN_MAX_VAL 0x28
+#define RX_MACRO_GAIN_VAL_UNITY 0x0
+/* Define macros to increase PA Gain by half */
+#define RX_MACRO_MOD_GAIN (RX_MACRO_GAIN_VAL_UNITY + 6)
+
+#define COMP_MAX_COEFF 25
+
+struct wcd_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+static const struct wcd_imped_val imped_index[] = {
+	{4, 0},
+	{5, 1},
+	{6, 2},
+	{7, 3},
+	{8, 4},
+	{9, 5},
+	{10, 6},
+	{11, 7},
+	{12, 8},
+	{13, 9},
+};
+
+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;
+};
+
+static const struct rx_macro_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+};
+
+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,
+};
+
+struct rx_macro_idle_detect_config {
+	u8 hph_idle_thr;
+	u8 hph_idle_detect_en;
+};
+
+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},
+};
+
+struct rx_macro_bcl_pmic_params {
+	u8 id;
+	u8 sid;
+	u8 ppid;
+};
+
+static int rx_macro_core_vote(void *handle, bool enable);
+static int rx_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+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);
+static int rx_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
+static int rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol);
+static int rx_macro_mux_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol);
+static int rx_macro_mux_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol);
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx);
+
+/* Hold instance to soundwire platform device */
+struct rx_swr_ctrl_data {
+	struct platform_device *rx_swr_pdev;
+};
+
+struct rx_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+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_AIF5_PB,
+	RX_MACRO_AIF6_PB,
+	RX_MACRO_MAX_DAIS,
+};
+
+enum {
+	RX_MACRO_AIF1_CAP = 0,
+	RX_MACRO_AIF2_CAP,
+	RX_MACRO_AIF3_CAP,
+	RX_MACRO_MAX_AIF_CAP_DAIS
+};
+/*
+ * @dev: rx macro device pointer
+ * @comp_enabled: compander enable mixer value set
+ * @prim_int_users: Users of interpolator
+ * @rx_mclk_users: RX MCLK users count
+ * @vi_feed_value: VI sense mask
+ * @swr_clk_lock: to lock swr master clock operations
+ * @swr_ctrl_data: SoundWire data structure
+ * @swr_plat_data: Soundwire platform data
+ * @rx_macro_add_child_devices_work: work for adding child devices
+ * @rx_swr_gpio_p: used by pinctrl API
+ * @component: codec handle
+ */
+struct rx_macro_priv {
+	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;
+	int swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	int clsh_users;
+	int rx_mclk_cnt;
+	bool is_native_on;
+	bool is_ear_mode_on;
+	bool dev_up;
+	bool hph_pwr_mode;
+	bool hph_hd2_mode;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct rx_swr_ctrl_data *swr_ctrl_data;
+	struct rx_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct rx_macro_add_child_devices_work;
+	struct device_node *rx_swr_gpio_p;
+	struct snd_soc_component *component;
+	unsigned long active_ch_mask[RX_MACRO_MAX_DAIS];
+	u16 bit_width[RX_MACRO_MAX_DAIS];
+	char __iomem *rx_io_base;
+	char __iomem *rx_mclk_mode_muxsel;
+	struct rx_macro_idle_detect_config idle_det_cfg;
+	u8 sidetone_coeff_array[IIR_MAX][BAND_MAX]
+		[RX_MACRO_SIDETONE_IIR_COEFF_MAX * 4];
+
+	struct platform_device *pdev_child_devices
+			[RX_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int is_softclip_on;
+	int is_aux_hpf_on;
+	int softclip_clk_users;
+	struct rx_macro_bcl_pmic_params bcl_pmic_params;
+	u16 clk_id;
+	u16 default_clk_id;
+	int8_t rx0_gain_val;
+	int8_t rx1_gain_val;
+	u32 rx_macro_wsa_slv;
+};
+
+static struct snd_soc_dai_driver rx_macro_dai[];
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+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_ear_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum rx_macro_ear_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, rx_macro_ear_mode_text);
+
+static const char *const rx_macro_hph_hd2_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum rx_macro_hph_hd2_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_hd2_mode_text);
+
+static const char *const rx_macro_hph_pwr_mode_text[] = {"ULP", "LOHIFI"};
+static const struct soc_enum rx_macro_hph_pwr_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_pwr_mode_text);
+
+static const char * const rx_macro_vbat_bcl_gsm_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum rx_macro_vbat_bcl_gsm_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, rx_macro_vbat_bcl_gsm_mode_text);
+
+static const struct snd_kcontrol_new rx_int2_1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("RX AUX VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const char * const hph_idle_detect_text[] = {"OFF", "ON"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
+
+RX_MACRO_DAPM_ENUM(rx_int0_2, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
+		rx_int_mix_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int1_2, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
+		rx_int_mix_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int2_2, BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
+		rx_int_mix_mux_text);
+
+
+RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp0, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp1, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp2, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp0, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp1, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp2, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp0, BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp1, BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
+		rx_prim_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp2, BOLERO_CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
+		rx_prim_mix_text);
+
+RX_MACRO_DAPM_ENUM(rx_int0_mix2_inp, BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
+		rx_sidetone_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int1_mix2_inp, BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
+		rx_sidetone_mix_text);
+RX_MACRO_DAPM_ENUM(rx_int2_mix2_inp, BOLERO_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
+		rx_sidetone_mix_text);
+
+RX_MACRO_DAPM_ENUM(iir0_inp0, BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir0_inp1, BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir0_inp2, BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir0_inp3, BOLERO_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir1_inp0, BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir1_inp1, BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir1_inp2, BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
+	iir_inp_mux_text);
+RX_MACRO_DAPM_ENUM(iir1_inp3, BOLERO_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
+	iir_inp_mux_text);
+
+RX_MACRO_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0,
+	rx_int0_1_interp_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0,
+	rx_int1_1_interp_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0,
+	rx_int2_1_interp_mux_text);
+
+RX_MACRO_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0,
+	rx_int0_2_interp_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0,
+	rx_int1_2_interp_mux_text);
+RX_MACRO_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0,
+	rx_int2_2_interp_mux_text);
+
+RX_MACRO_DAPM_ENUM_EXT(rx_int0_dem_inp, BOLERO_CDC_RX_RX0_RX_PATH_CFG1, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	rx_macro_int_dem_inp_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_int1_dem_inp, BOLERO_CDC_RX_RX1_RX_PATH_CFG1, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	rx_macro_int_dem_inp_mux_put);
+
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx0, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx1, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx2, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx3, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx4, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+RX_MACRO_DAPM_ENUM_EXT(rx_macro_rx5, SND_SOC_NOPM, 0, rx_macro_mux_text,
+	rx_macro_mux_get, rx_macro_mux_put);
+
+static const char * const rx_echo_mux_text[] = {
+	"ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2"
+};
+
+static const struct soc_enum rx_mix_tx2_mux_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4,
+			rx_echo_mux_text);
+
+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 soc_enum rx_mix_tx1_mux_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4,
+			rx_echo_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 soc_enum rx_mix_tx0_mux_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4,
+			rx_echo_mux_text);
+
+static const struct snd_kcontrol_new rx_mix_tx0_mux =
+	SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum);
+
+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_mute_stream,
+};
+
+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,
+	},
+	{
+		.name = "rx_macro_rx5",
+		.id = RX_MACRO_AIF5_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF5 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx6",
+		.id = RX_MACRO_AIF6_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF6 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+};
+
+static int get_impedance_index(int imped)
+{
+	int i = 0;
+
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than %d Ohm\n",
+			__func__, imped_index[i].imped_val);
+		i = 0;
+		goto ret;
+	}
+	if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
+		pr_debug("%s, detected impedance is greater than %d Ohm\n",
+			__func__,
+			imped_index[ARRAY_SIZE(imped_index) - 1].imped_val);
+		i = ARRAY_SIZE(imped_index) - 1;
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+/*
+ * rx_macro_wcd_clsh_imped_config -
+ * This function updates HPHL and HPHR gain settings
+ * according to the impedance value.
+ *
+ * @component: codec pointer handle
+ * @imped: impedance value of HPHL/R
+ * @reset: bool variable to reset registers when teardown
+ */
+static void rx_macro_wcd_clsh_imped_config(struct snd_soc_component *component,
+					   int imped, bool reset)
+{
+	int i;
+	int index = 0;
+	int table_size;
+
+	static const struct rx_macro_reg_mask_val
+				(*imped_table_ptr)[MAX_IMPED_PARAMS];
+
+	table_size = ARRAY_SIZE(imped_table);
+	imped_table_ptr = imped_table;
+	/* reset = 1, which means request is to reset the register values */
+	if (reset) {
+		for (i = 0; i < MAX_IMPED_PARAMS; i++)
+			snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask, 0);
+		return;
+	}
+	index = get_impedance_index(imped);
+	if (index >= (ARRAY_SIZE(imped_index) - 1)) {
+		pr_debug("%s, impedance not in range = %d\n", __func__, imped);
+		return;
+	}
+	if (index >= table_size) {
+		pr_debug("%s, impedance index not in range = %d\n", __func__,
+			index);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask,
+				imped_table_ptr[index][i].val);
+}
+
+static bool rx_macro_get_data(struct snd_soc_component *component,
+			       struct device **rx_dev,
+			       struct rx_macro_priv **rx_priv,
+			       const char *func_name)
+{
+	*rx_dev = bolero_get_device_ptr(component->dev, RX_MACRO);
+
+	if (!(*rx_dev)) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+
+	*rx_priv = dev_get_drvdata((*rx_dev));
+	if (!(*rx_priv)) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+
+	if (!(*rx_priv)->component) {
+		dev_err(component->dev,
+			"%s: rx_priv component is not initialized!\n", func_name);
+		return false;
+	}
+
+	return true;
+}
+
+static int rx_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (rx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+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 int val = 0;
+	unsigned short look_ahead_dly_reg =
+				BOLERO_CDC_RX_RX0_RX_PATH_CFG0;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val >= e->items)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	if (e->reg == BOLERO_CDC_RX_RX0_RX_PATH_CFG1)
+		look_ahead_dly_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0;
+	else if (e->reg == BOLERO_CDC_RX_RX1_RX_PATH_CFG1)
+		look_ahead_dly_reg = BOLERO_CDC_RX_RX1_RX_PATH_CFG0;
+
+	/* Set Look Ahead Delay */
+	snd_soc_component_update_bits(component, look_ahead_dly_reg,
+			    0x08, (val ? 0x08 : 0x00));
+	/* Set DEM INP Select */
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					    u8 rate_reg_val,
+					    u32 sample_rate)
+{
+	u8 int_1_mix1_inp = 0;
+	u32 j = 0, port = 0;
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u16 int_fs_reg = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 inp0_sel = 0, inp1_sel = 0, inp2_sel = 0;
+	struct snd_soc_component *component = dai->component;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id],
+			 RX_MACRO_PORTS_MAX) {
+		int_1_mix1_inp = port;
+		if ((int_1_mix1_inp < RX_MACRO_RX0) ||
+			(int_1_mix1_inp > RX_MACRO_PORTS_MAX)) {
+			pr_err("%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg0 = BOLERO_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;
+
+			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 & 0x0F;
+			inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F;
+			inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F;
+			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 = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
+					     0x80 * j;
+				pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_1\n",
+					  __func__, dai->id, j);
+				pr_debug("%s: set INT%u_1 sample rate to %u\n",
+					__func__, j, sample_rate);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						0x0F, rate_reg_val);
+			}
+			int_mux_cfg0 += 8;
+		}
+	}
+
+	return 0;
+}
+
+static int rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					u8 rate_reg_val,
+					u32 sample_rate)
+{
+	u8 int_2_inp = 0;
+	u32 j = 0, port = 0;
+	u16 int_mux_cfg1 = 0, int_fs_reg = 0;
+	u8 int_mux_cfg1_val = 0;
+	struct snd_soc_component *component = dai->component;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id],
+			 RX_MACRO_PORTS_MAX) {
+		int_2_inp = port;
+		if ((int_2_inp < RX_MACRO_RX0) ||
+			(int_2_inp > RX_MACRO_PORTS_MAX)) {
+			pr_err("%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg1 = BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1;
+		for (j = 0; j < INTERP_MAX; j++) {
+			int_mux_cfg1_val = snd_soc_component_read(
+						component, int_mux_cfg1) &
+						0x0F;
+			if (int_mux_cfg1_val == int_2_inp +
+							INTn_2_INP_SEL_RX0) {
+				int_fs_reg = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL +
+						0x80 * j;
+				pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_2\n",
+					  __func__, dai->id, j);
+				pr_debug("%s: set INT%u_2 sample rate to %u\n",
+					__func__, j, sample_rate);
+				snd_soc_component_update_bits(
+						component, int_fs_reg,
+						0x0F, rate_reg_val);
+			}
+			int_mux_cfg1 += 8;
+		}
+	}
+	return 0;
+}
+
+static bool rx_macro_is_fractional_sample_rate(u32 sample_rate)
+{
+	switch (sample_rate) {
+	case SAMPLING_RATE_44P1KHZ:
+	case SAMPLING_RATE_88P2KHZ:
+	case SAMPLING_RATE_176P4KHZ:
+	case SAMPLING_RATE_352P8KHZ:
+		return true;
+	default:
+		return false;
+	}
+	return false;
+}
+
+static int rx_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+					  u32 sample_rate)
+{
+	struct snd_soc_component *component = dai->component;
+	int rate_val = 0;
+	int i = 0, ret = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+
+	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;
+			if (rx_macro_is_fractional_sample_rate(sample_rate))
+				rx_priv->is_native_on = true;
+			else
+				rx_priv->is_native_on = false;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
+		dev_err(component->dev, "%s: Unsupported sample rate: %d\n",
+			__func__, sample_rate);
+		return -EINVAL;
+	}
+
+	ret = rx_macro_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate);
+	if (ret)
+		return ret;
+	ret = rx_macro_set_mix_interpolator_rate(dai, (u8)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;
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = rx_macro_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			pr_err("%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		rx_priv->bit_width[dai->id] = params_width(params);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+	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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	unsigned int temp = 0, ch_mask = 0;
+	u16 val = 0, mask = 0, cnt = 0, i = 0;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	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_priv->active_ch_mask[dai->id],
+			 RX_MACRO_PORTS_MAX) {
+			ch_mask |= (1 << temp);
+			if (++i == 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)
+		 * Above is reflected in machine driver BE dailink
+		 */
+		if (ch_mask & 0x0C)
+			ch_mask = ch_mask >> 2;
+		if ((ch_mask & 0x10) || (ch_mask & 0x20))
+			ch_mask = 0x1;
+		*rx_slot = ch_mask;
+		*rx_num = hweight_long(ch_mask);
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n",
+			__func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]);
+		break;
+	case RX_MACRO_AIF5_PB:
+		*rx_slot = 0x1;
+		*rx_num = 0x01;
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
+			__func__, dai->id, *rx_slot, *rx_num);
+		break;
+	case RX_MACRO_AIF6_PB:
+		*rx_slot = 0x1;
+		*rx_num = 0x01;
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
+			__func__, dai->id, *rx_slot, *rx_num);
+		break;
+	case RX_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,
+			BOLERO_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,
+			BOLERO_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(rx_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static int rx_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0;
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+
+	if (mute)
+		return 0;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	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 = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
+				(j * RX_MACRO_RX_PATH_OFFSET);
+		mix_reg = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL +
+				(j * RX_MACRO_RX_PATH_OFFSET);
+		dsm_reg = BOLERO_CDC_RX_RX0_RX_PATH_DSM_CTL +
+				(j * RX_MACRO_RX_PATH_OFFSET);
+		if (j == INTERP_AUX)
+			dsm_reg = BOLERO_CDC_RX_RX2_RX_PATH_DSM_CTL;
+		int_mux_cfg0 = BOLERO_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);
+			}
+		}
+	}
+
+	if (rx_priv->rx_macro_wsa_slv)
+		bolero_rx_pa_on(rx_dev);
+	break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv,
+				 bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(rx_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, rx_priv->rx_mclk_users);
+
+	mutex_lock(&rx_priv->mclk_lock);
+	if (mclk_enable) {
+		if (rx_priv->rx_mclk_users == 0) {
+			if (rx_priv->is_native_on)
+				rx_priv->clk_id = RX_CORE_CLK;
+			rx_macro_core_vote(rx_priv, true);
+			ret = bolero_clk_rsc_request_clock(rx_priv->dev,
+							   rx_priv->default_clk_id,
+							   rx_priv->clk_id,
+							   true);
+			rx_macro_core_vote(rx_priv, false);
+			if (ret < 0) {
+				dev_err(rx_priv->dev,
+					"%s: rx request clock enable failed\n",
+					__func__);
+				goto exit;
+			}
+			bolero_clk_rsc_fs_gen_request(rx_priv->dev,
+							true);
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					RX_START_OFFSET,
+					RX_MAX_OFFSET);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x00);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		rx_priv->rx_mclk_users++;
+	} else {
+		if (rx_priv->rx_mclk_users <= 0) {
+			dev_err(rx_priv->dev, "%s: clock already disabled\n",
+				__func__);
+			rx_priv->rx_mclk_users = 0;
+			goto exit;
+		}
+		rx_priv->rx_mclk_users--;
+		if (rx_priv->rx_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x02, 0x00);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+			bolero_clk_rsc_fs_gen_request(rx_priv->dev,
+			   false);
+			rx_macro_core_vote(rx_priv, true);
+			bolero_clk_rsc_request_clock(rx_priv->dev,
+						 rx_priv->default_clk_id,
+						 rx_priv->clk_id,
+						 false);
+			rx_macro_core_vote(rx_priv, false);
+			rx_priv->clk_id = rx_priv->default_clk_id;
+		}
+	}
+exit:
+	mutex_unlock(&rx_priv->mclk_lock);
+	return ret;
+}
+
+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);
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	int mclk_freq = MCLK_FREQ;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(rx_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (rx_priv->is_native_on)
+			mclk_freq = MCLK_FREQ_NATIVE;
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_CLK_FREQ, &mclk_freq);
+		ret = rx_macro_mclk_enable(rx_priv, 1, true);
+		if (ret)
+			rx_priv->dapm_mclk_enable = false;
+		else
+			rx_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (rx_priv->dapm_mclk_enable)
+			ret = rx_macro_mclk_enable(rx_priv, 0, true);
+		break;
+	default:
+		dev_err(rx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int rx_macro_event_handler(struct snd_soc_component *component,
+				  u16 event, u32 data)
+{
+	u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0, val = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	int ret = 0;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_RX_MUTE:
+		rx_idx = data >> 0x10;
+		mute = data & 0xffff;
+		val = mute ? 0x10 : 0x00;
+		reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + (rx_idx *
+					RX_MACRO_RX_PATH_OFFSET);
+		reg_mix = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL + (rx_idx *
+					RX_MACRO_RX_PATH_OFFSET);
+		snd_soc_component_update_bits(component, reg,
+				0x10, val);
+		snd_soc_component_update_bits(component, reg_mix,
+				0x10, val);
+		break;
+	case BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST:
+		rx_idx = data >> 0x10;
+		if (rx_idx == INTERP_AUX)
+			goto done;
+		reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
+				(rx_idx * RX_MACRO_COMP_OFFSET);
+		snd_soc_component_write(component, reg,
+				snd_soc_component_read(component, reg));
+		break;
+	case BOLERO_MACRO_EVT_IMPED_TRUE:
+		rx_macro_wcd_clsh_imped_config(component, data, true);
+		break;
+	case BOLERO_MACRO_EVT_IMPED_FALSE:
+		rx_macro_wcd_clsh_imped_config(component, data, false);
+		break;
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		rx_priv->dev_up = false;
+		if (rx_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(rx_dev) ||
+		     !pm_runtime_suspended(rx_dev))) {
+			ret = bolero_runtime_suspend(rx_dev);
+			if (!ret) {
+				pm_runtime_disable(rx_dev);
+				pm_runtime_set_suspended(rx_dev);
+				pm_runtime_enable(rx_dev);
+			}
+		}
+		break;
+	case BOLERO_MACRO_EVT_PRE_SSR_UP:
+		rx_macro_core_vote(rx_priv, true);
+		/* enable&disable RX_CORE_CLK to reset GFMUX reg */
+		ret = bolero_clk_rsc_request_clock(rx_priv->dev,
+						rx_priv->default_clk_id,
+						RX_CORE_CLK, true);
+		if (ret < 0) {
+			dev_err_ratelimited(rx_priv->dev,
+				"%s, failed to enable clk, ret:%d\n",
+				__func__, ret);
+		} else {
+			bolero_clk_rsc_request_clock(rx_priv->dev,
+						rx_priv->default_clk_id,
+						RX_CORE_CLK, false);
+		}
+		rx_macro_core_vote(rx_priv, false);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		rx_priv->dev_up = true;
+		/* reset swr after ssr/pdr */
+		rx_priv->reset_swr = true;
+
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(rx_dev, RX_CORE_CLK);
+		break;
+	case BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE:
+		rx_priv->rx0_gain_val = snd_soc_component_read(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL);
+		rx_priv->rx1_gain_val = snd_soc_component_read(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL);
+		if (data) {
+			/* Reduce gain by half only if its greater than -6DB */
+			if ((rx_priv->rx0_gain_val >= RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx0_gain_val <= RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val -
+					 RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >= RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx1_gain_val <= RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val -
+					 RX_MACRO_MOD_GAIN));
+		}
+		else {
+			/* Reset gain value to default */
+			if ((rx_priv->rx0_gain_val >=
+			    (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx0_gain_val <= (RX_MACRO_GAIN_MAX_VAL -
+			    RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val +
+					 RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >=
+			    (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx1_gain_val <= (RX_MACRO_GAIN_MAX_VAL -
+			    RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val +
+					 RX_MACRO_MOD_GAIN));
+		}
+		break;
+	case BOLERO_MACRO_EVT_HPHL_HD2_ENABLE:
+		/* Enable hd2 config for hphl*/
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX0_RX_PATH_CFG0, 0x04, data);
+		break;
+	case BOLERO_MACRO_EVT_HPHR_HD2_ENABLE:
+		/* Enable hd2 config for hphr*/
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX1_RX_PATH_CFG0, 0x04, data);
+		break;
+	}
+done:
+	return ret;
+}
+
+static int rx_macro_find_playback_dai_id_for_port(int port_id,
+						  struct rx_macro_priv *rx_priv)
+{
+	int i = 0;
+
+	for (i = RX_MACRO_AIF1_PB; i < RX_MACRO_MAX_DAIS; i++) {
+		if (test_bit(port_id, &rx_priv->active_ch_mask[i]))
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static int rx_macro_set_idle_detect_thr(struct snd_soc_component *component,
+					struct rx_macro_priv *rx_priv,
+					int interp, int path_type)
+{
+	int port_id[4] = { 0, 0, 0, 0 };
+	int *port_ptr = NULL;
+	int num_ports = 0;
+	int bit_width = 0, i = 0;
+	int mux_reg = 0, mux_reg_val = 0;
+	int dai_id = 0, idle_thr = 0;
+
+	if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
+		return 0;
+
+	if (!rx_priv->idle_det_cfg.hph_idle_detect_en)
+		return 0;
+
+	port_ptr = &port_id[0];
+	num_ports = 0;
+
+	/*
+	 * Read interpolator MUX input registers and find
+	 * which cdc_dma port is connected and store the port
+	 * numbers in port_id array.
+	 */
+	if (path_type == INTERP_MIX_PATH) {
+		mux_reg = BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1 +
+						2 * interp;
+		mux_reg_val = snd_soc_component_read(component, mux_reg) &
+				0x0f;
+
+		if ((mux_reg_val >= INTn_2_INP_SEL_RX0) &&
+		   (mux_reg_val <= INTn_2_INP_SEL_RX5)) {
+			*port_ptr++ = mux_reg_val - 1;
+			num_ports++;
+		}
+	}
+
+	if (path_type == INTERP_MAIN_PATH) {
+		mux_reg = BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG0 +
+			  2 * (interp - 1);
+		mux_reg_val = snd_soc_component_read(component, mux_reg) &
+				0x0f;
+		i = RX_MACRO_INTERP_MUX_NUM_INPUTS;
+
+		while (i) {
+			if ((mux_reg_val >= INTn_1_INP_SEL_RX0) &&
+			    (mux_reg_val <= INTn_1_INP_SEL_RX5)) {
+				*port_ptr++ = mux_reg_val -
+					INTn_1_INP_SEL_RX0;
+				num_ports++;
+			}
+			mux_reg_val =
+				(snd_soc_component_read(component, mux_reg) &
+					0xf0) >> 4;
+			mux_reg += 1;
+			i--;
+		}
+	}
+
+	dev_dbg(component->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n",
+		__func__, num_ports, port_id[0], port_id[1],
+		port_id[2], port_id[3]);
+
+	i = 0;
+	while (num_ports) {
+		dai_id = rx_macro_find_playback_dai_id_for_port(port_id[i++],
+								rx_priv);
+
+		if ((dai_id >= 0) && (dai_id < RX_MACRO_MAX_DAIS)) {
+			dev_dbg(component->dev, "%s: dai_id: %d bit_width: %d\n",
+				__func__, dai_id,
+				rx_priv->bit_width[dai_id]);
+
+			if (rx_priv->bit_width[dai_id] > bit_width)
+				bit_width = rx_priv->bit_width[dai_id];
+		}
+		num_ports--;
+	}
+
+	switch (bit_width) {
+	case 16:
+		idle_thr = 0xff; /* F16 */
+		break;
+	case 24:
+	case 32:
+		idle_thr = 0x03; /* F22 */
+		break;
+	default:
+		idle_thr = 0x00;
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
+		__func__, idle_thr, rx_priv->idle_det_cfg.hph_idle_thr);
+
+	if ((rx_priv->idle_det_cfg.hph_idle_thr == 0) ||
+	    (idle_thr < rx_priv->idle_det_cfg.hph_idle_thr)) {
+		snd_soc_component_write(component,
+			BOLERO_CDC_RX_IDLE_DETECT_CFG3, idle_thr);
+		rx_priv->idle_det_cfg.hph_idle_thr = idle_thr;
+	}
+
+	return 0;
+}
+
+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 = 0, mix_reg = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (w->shift >= INTERP_MAX) {
+		dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	}
+
+	gain_reg = BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL +
+				(w->shift * RX_MACRO_RX_PATH_OFFSET);
+	mix_reg = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL +
+				(w->shift * RX_MACRO_RX_PATH_OFFSET);
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_set_idle_detect_thr(component, rx_priv, w->shift,
+					INTERP_MIX_PATH);
+		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, 0x20, 0x00);
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		/* Reset enable and disable */
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static bool rx_macro_adie_lb(struct snd_soc_component *component,
+			     int interp_idx)
+{
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
+
+	int_mux_cfg0 = BOLERO_CDC_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;
+	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;
+
+	int_n_inp1 = int_mux_cfg0_val >> 4;
+	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;
+
+	int_n_inp2 = int_mux_cfg1_val >> 4;
+	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_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 = 0;
+	u16 reg = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (w->shift >= INTERP_MAX) {
+		dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	}
+
+	reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + (w->shift *
+						RX_MACRO_RX_PATH_OFFSET);
+	gain_reg = BOLERO_CDC_RX_RX0_RX_VOL_CTL + (w->shift *
+						RX_MACRO_RX_PATH_OFFSET);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_set_idle_detect_thr(component, rx_priv, w->shift,
+						INTERP_MAIN_PATH);
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		if (rx_macro_adie_lb(component, w->shift))
+			snd_soc_component_update_bits(component,
+						reg, 0x20, 0x20);
+		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_priv *rx_priv,
+				int interp_n, int event)
+{
+	int comp = 0;
+	u16 comp_ctl0_reg = 0, rx_path_cfg0_reg = 0, rx_path_cfg3_reg = 0;
+	u16 rx0_path_ctl_reg = 0;
+	u8 pcm_rate = 0, val = 0;
+
+	/* AUX does not have compander */
+	if (interp_n == INTERP_AUX)
+		return 0;
+
+	comp = interp_n;
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp + 1, rx_priv->comp_enabled[comp]);
+
+	rx_path_cfg3_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG3 +
+					(comp * RX_MACRO_RX_PATH_OFFSET);
+	rx0_path_ctl_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
+					(comp * RX_MACRO_RX_PATH_OFFSET);
+	pcm_rate = (snd_soc_component_read(component, rx0_path_ctl_reg)
+						& 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, rx_path_cfg3_reg,
+					0x03, val);
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		snd_soc_component_update_bits(component, rx_path_cfg3_reg,
+					0x03, 0x03);
+	if (!rx_priv->comp_enabled[comp])
+		return 0;
+
+	comp_ctl0_reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
+					(comp * RX_MACRO_COMP_OFFSET);
+	rx_path_cfg0_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0 +
+					(comp * RX_MACRO_RX_PATH_OFFSET);
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x01, 0x01);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+					0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x04, 0x04);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x01, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static int rx_macro_load_compander_coeff(struct snd_soc_component *component,
+					 struct rx_macro_priv *rx_priv,
+					 int interp_n, int event)
+{
+	int comp = 0;
+	u16 comp_coeff_lsb_reg = 0, comp_coeff_msb_reg = 0;
+	int i = 0;
+	int hph_pwr_mode = HPH_LOHIFI;
+
+	if (!rx_priv->comp_enabled[comp])
+		return 0;
+
+	if (interp_n == INTERP_HPHL) {
+		comp_coeff_lsb_reg = BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB;
+		comp_coeff_msb_reg = BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB;
+	} else if (interp_n == INTERP_HPHR) {
+		comp_coeff_lsb_reg = BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB;
+		comp_coeff_msb_reg = BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB;
+	} else {
+		/* compander coefficients are loaded only for hph path */
+		return 0;
+	}
+
+	comp = interp_n;
+	hph_pwr_mode = rx_priv->hph_pwr_mode;
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp + 1, rx_priv->comp_enabled[comp]);
+
+	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_priv *rx_priv,
+					 bool enable)
+{
+	if (enable) {
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x01);
+		rx_priv->softclip_clk_users++;
+	} else {
+		rx_priv->softclip_clk_users--;
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x00);
+	}
+}
+
+static int rx_macro_config_softclip(struct snd_soc_component *component,
+				struct rx_macro_priv *rx_priv,
+				int event)
+{
+	dev_dbg(component->dev, "%s: event %d, enabled %d\n",
+		__func__, event, rx_priv->is_softclip_on);
+
+	if (!rx_priv->is_softclip_on)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock */
+		rx_macro_enable_softclip_clk(component, rx_priv, true);
+		/* Enable Softclip control */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x00);
+		rx_macro_enable_softclip_clk(component, rx_priv, false);
+	}
+
+	return 0;
+}
+
+static int rx_macro_config_aux_hpf(struct snd_soc_component *component,
+				struct rx_macro_priv *rx_priv,
+				int event)
+{
+	dev_dbg(component->dev, "%s: event %d, enabled %d\n",
+		__func__, event, rx_priv->is_aux_hpf_on);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Update Aux HPF control */
+		if (!rx_priv->is_aux_hpf_on)
+			snd_soc_component_update_bits(component,
+				BOLERO_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,
+			BOLERO_CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04);
+	}
+
+	return 0;
+}
+
+
+static inline void
+rx_macro_enable_clsh_block(struct rx_macro_priv *rx_priv, bool enable)
+{
+	if ((enable && ++rx_priv->clsh_users == 1) ||
+	    (!enable && --rx_priv->clsh_users == 0))
+		snd_soc_component_update_bits(rx_priv->component,
+				BOLERO_CDC_RX_CLSH_CRC, 0x01,
+				(u8) enable);
+	if (rx_priv->clsh_users < 0)
+		rx_priv->clsh_users = 0;
+	dev_dbg(rx_priv->dev, "%s: clsh_users %d, enable %d", __func__,
+		rx_priv->clsh_users, enable);
+}
+
+static int rx_macro_config_classh(struct snd_soc_component *component,
+				struct rx_macro_priv *rx_priv,
+				int interp_n, int event)
+{
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		rx_macro_enable_clsh_block(rx_priv, false);
+		return 0;
+	}
+
+	if (!SND_SOC_DAPM_EVENT_ON(event))
+		return 0;
+
+	rx_macro_enable_clsh_block(rx_priv, 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_update_bits(component,
+					BOLERO_CDC_RX_CLSH_K1_LSB,
+					0xFF, 0xC0);
+		snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_CLSH_K1_MSB,
+					0x0F, 0x00);
+	}
+	switch (interp_n) {
+	case INTERP_HPHL:
+		if (rx_priv->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x1C);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_DECAY_CTRL,
+				0x07, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX0_RX_PATH_CFG0,
+				0x40, 0x40);
+		break;
+	case INTERP_HPHR:
+		if (rx_priv->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x1C);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_DECAY_CTRL,
+				0x07, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX1_RX_PATH_CFG0,
+				0x40, 0x40);
+		break;
+	case INTERP_AUX:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX2_RX_PATH_CFG0,
+				0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX2_RX_PATH_CFG0,
+				0x10, 0x10);
+		break;
+	}
+
+	return 0;
+}
+
+static void rx_macro_hd2_control(struct snd_soc_component *component,
+				 u16 interp_idx, int event)
+{
+	u16 hd2_scale_reg = 0;
+	u16 hd2_enable_reg = 0;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hd2_scale_reg = BOLERO_CDC_RX_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0;
+		break;
+	case INTERP_HPHR:
+		hd2_scale_reg = BOLERO_CDC_RX_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = BOLERO_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,
+				0x3C, 0x14);
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+				0x04, 0x04);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+				0x04, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+				0x3C, 0x00);
+	}
+}
+
+static int rx_macro_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro_priv *rx_priv = NULL;
+	struct device *rx_dev = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+		rx_priv->idle_det_cfg.hph_idle_detect_en;
+
+	return 0;
+}
+
+static int rx_macro_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro_priv *rx_priv = NULL;
+	struct device *rx_dev = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->idle_det_cfg.hph_idle_detect_en =
+		ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		__func__, comp + 1, rx_priv->comp_enabled[comp], value);
+	rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			rx_priv->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 = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	aif_rst = rx_priv->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err(rx_dev, "%s:AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst > RX_MACRO_AIF4_PB) {
+			dev_err(rx_dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	rx_priv->rx_port_value[widget->shift] = rx_port_value;
+
+	dev_dbg(rx_dev, "%s: mux input: %d, mux output: %d, aif_rst: %d\n",
+		__func__, rx_port_value, widget->shift, aif_rst);
+
+	switch (rx_port_value) {
+	case 0:
+		clear_bit(widget->shift, &rx_priv->active_ch_mask[aif_rst]);
+		break;
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		set_bit(widget->shift,
+			&rx_priv->active_ch_mask[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 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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->hph_pwr_mode = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int rx_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+		((snd_soc_component_read(
+			component, BOLERO_CDC_RX_BCL_VBAT_CFG) & 0x04) ?
+		  1 : 0);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int rx_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_BCL_VBAT_CFG,
+					0x04, 0x04);
+	else
+		snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_BCL_VBAT_CFG,
+					0x04, 0x00);
+
+	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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_softclip_on;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_softclip_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: soft clip enable = %d\n", __func__,
+		rx_priv->is_softclip_on);
+
+	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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_aux_hpf_on;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_aux_hpf_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: aux hpf enable = %d\n", __func__,
+		rx_priv->is_aux_hpf_on);
+
+	return 0;
+}
+
+
+static int rx_macro_enable_vbat(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 device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_RX2_RX_PATH_CFG1, 0x80, 0x80);
+		/* Update DSM FS rate */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_RX2_RX_PATH_SEC7, 0x02, 0x02);
+		/* Use attenuation mode */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_CFG, 0x02, 0x00);
+		/* BCL block needs softclip clock to be enabled */
+		rx_macro_enable_softclip_clk(component, rx_priv, true);
+		/* Enable VBAT at channel level */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_RX2_RX_PATH_CFG1, 0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX2_RX_PATH_SEC7,
+				0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_CFG,
+				0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+				0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+				0xFF, 0x00);
+		rx_macro_enable_softclip_clk(component, rx_priv, false);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err(rx_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static void rx_macro_idle_detect_control(struct snd_soc_component *component,
+					 struct rx_macro_priv *rx_priv,
+					 int interp, int event)
+{
+	int reg = 0, mask = 0, val = 0;
+
+	if (!rx_priv->idle_det_cfg.hph_idle_detect_en)
+		return;
+
+	if (interp == INTERP_HPHL) {
+		reg = BOLERO_CDC_RX_IDLE_DETECT_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == INTERP_HPHR) {
+		reg = BOLERO_CDC_RX_IDLE_DETECT_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event))
+		snd_soc_component_update_bits(component, reg, mask, val);
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		rx_priv->idle_det_cfg.hph_idle_thr = 0;
+		snd_soc_component_write(component,
+				BOLERO_CDC_RX_IDLE_DETECT_CFG3, 0x0);
+	}
+}
+
+static void rx_macro_hphdelay_lutbypass(struct snd_soc_component *component,
+					struct rx_macro_priv *rx_priv,
+					u16 interp_idx, int event)
+{
+	u16 hph_lut_bypass_reg = 0;
+	u16 hph_comp_ctrl7 = 0;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hph_lut_bypass_reg = BOLERO_CDC_RX_TOP_HPHL_COMP_LUT;
+		hph_comp_ctrl7 = BOLERO_CDC_RX_COMPANDER0_CTL7;
+		break;
+	case INTERP_HPHR:
+		hph_lut_bypass_reg = BOLERO_CDC_RX_TOP_HPHR_COMP_LUT;
+		hph_comp_ctrl7 = BOLERO_CDC_RX_COMPANDER1_CTL7;
+		break;
+	default:
+		break;
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		if (interp_idx == INTERP_HPHL) {
+			if (rx_priv->is_ear_mode_on)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_PATH_CFG1,
+					0x02, 0x02);
+			else
+				snd_soc_component_update_bits(component,
+					hph_lut_bypass_reg,
+					0x80, 0x80);
+		} else {
+			snd_soc_component_update_bits(component,
+					hph_lut_bypass_reg,
+					0x80, 0x80);
+		}
+		if (rx_priv->hph_pwr_mode)
+			snd_soc_component_update_bits(component,
+					hph_comp_ctrl7,
+					0x20, 0x00);
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_PATH_CFG1,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+					0x80, 0x00);
+		snd_soc_component_update_bits(component, hph_comp_ctrl7,
+					0x20, 0x20);
+	}
+}
+
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx)
+{
+	u16 main_reg = 0, dsm_reg = 0, rx_cfg2_reg = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	main_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
+			(interp_idx * RX_MACRO_RX_PATH_OFFSET);
+	dsm_reg = BOLERO_CDC_RX_RX0_RX_PATH_DSM_CTL +
+			(interp_idx * RX_MACRO_RX_PATH_OFFSET);
+	if (interp_idx == INTERP_AUX)
+		dsm_reg = BOLERO_CDC_RX_RX2_RX_PATH_DSM_CTL;
+	rx_cfg2_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG2 +
+			(interp_idx * RX_MACRO_RX_PATH_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (rx_priv->main_clk_users[interp_idx] == 0) {
+			/* Main path PGA mute enable */
+			snd_soc_component_update_bits(component, main_reg,
+					0x10, 0x10);
+			snd_soc_component_update_bits(component, dsm_reg,
+					0x01, 0x01);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+					0x03, 0x03);
+			rx_macro_load_compander_coeff(component, rx_priv,
+						      interp_idx, event);
+			rx_macro_idle_detect_control(component, rx_priv,
+					interp_idx, event);
+			if (rx_priv->hph_hd2_mode)
+				rx_macro_hd2_control(
+					component, interp_idx, event);
+			rx_macro_hphdelay_lutbypass(component, rx_priv,
+						    interp_idx, event);
+			rx_macro_config_compander(component, rx_priv,
+						interp_idx, event);
+			if (interp_idx == INTERP_AUX) {
+				rx_macro_config_softclip(component, rx_priv,
+							event);
+				rx_macro_config_aux_hpf(component, rx_priv,
+							event);
+			}
+			rx_macro_config_classh(component, rx_priv,
+						interp_idx, event);
+		}
+		rx_priv->main_clk_users[interp_idx]++;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		rx_priv->main_clk_users[interp_idx]--;
+		if (rx_priv->main_clk_users[interp_idx] <= 0) {
+			rx_priv->main_clk_users[interp_idx] = 0;
+			/* Main path PGA mute enable */
+			snd_soc_component_update_bits(component, main_reg,
+					0x10, 0x10);
+			/* Clk Disable */
+			snd_soc_component_update_bits(component, dsm_reg,
+						0x01, 0x00);
+			snd_soc_component_update_bits(component, main_reg,
+						0x20, 0x00);
+			/* Reset enable and disable */
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x40);
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x00);
+			/* Reset rate to 48K*/
+			snd_soc_component_update_bits(component, main_reg,
+						0x0F, 0x04);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+						0x03, 0x00);
+			rx_macro_config_classh(component, rx_priv,
+						interp_idx, event);
+			rx_macro_config_compander(component, rx_priv,
+						interp_idx, event);
+			if (interp_idx ==  INTERP_AUX) {
+				rx_macro_config_softclip(component, rx_priv,
+							event);
+				rx_macro_config_aux_hpf(component, rx_priv,
+				event);
+			}
+			rx_macro_hphdelay_lutbypass(component, rx_priv,
+						interp_idx, event);
+			if (rx_priv->hph_hd2_mode)
+				rx_macro_hd2_control(component, interp_idx,
+						event);
+			rx_macro_idle_detect_control(component, rx_priv,
+					interp_idx, event);
+		}
+	}
+
+	dev_dbg(component->dev, "%s event %d main_clk_users %d\n",
+		__func__,  event, rx_priv->main_clk_users[interp_idx]);
+
+	return rx_priv->main_clk_users[interp_idx];
+}
+
+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);
+	u16 sidetone_reg = 0, fs_reg = 0;
+
+	dev_dbg(component->dev, "%s %d %d\n", __func__, event, w->shift);
+	sidetone_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG1 +
+			RX_MACRO_RX_PATH_OFFSET * (w->shift);
+	fs_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
+			RX_MACRO_RX_PATH_OFFSET * (w->shift);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		snd_soc_component_update_bits(component, sidetone_reg,
+					0x10, 0x10);
+		snd_soc_component_update_bits(component, fs_reg,
+					0x20, 0x20);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, sidetone_reg,
+					0x10, 0x00);
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	default:
+		break;
+	};
+	return 0;
+}
+
+static void rx_macro_restore_iir_coeff(struct rx_macro_priv *rx_priv, int iir_idx,
+				int band_idx)
+{
+	u16 reg_add = 0, coeff_idx = 0, idx = 0;
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return;
+	}
+
+	regmap_write(regmap,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	reg_add = BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx;
+
+	/* 5 coefficients per band and 4 writes per coefficient */
+	for (coeff_idx = 0; coeff_idx < RX_MACRO_SIDETONE_IIR_COEFF_MAX;
+		coeff_idx++) {
+		/* Four 8 bit values(one 32 bit) per coefficient */
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+	}
+}
+
+static int rx_macro_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	/* IIR filter band registers are at integer multiples of 0x80 */
+	u16 iir_reg = BOLERO_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx;
+
+	ucontrol->value.integer.value[0] = (
+				snd_soc_component_read(component, iir_reg) &
+				(1 << band_idx)) != 0;
+
+	dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int rx_macro_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	bool iir_band_en_status = 0;
+	int value = ucontrol->value.integer.value[0];
+	u16 iir_reg = BOLERO_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_macro_restore_iir_coeff(rx_priv, iir_idx, band_idx);
+
+	/* Mask first 5 bits, 6-8 are reserved */
+	snd_soc_component_update_bits(component, iir_reg, (1 << band_idx),
+			    (value << band_idx));
+
+	iir_band_en_status = ((snd_soc_component_read(component, iir_reg) &
+			      (1 << band_idx)) != 0);
+	dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx, iir_band_en_status);
+	return 0;
+}
+
+static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+				   int iir_idx, int band_idx,
+				   int coeff_idx)
+{
+	uint32_t value = 0;
+
+	/* Address does not automatically update if reading */
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t)) & 0x7F);
+
+	value |= snd_soc_component_read(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx));
+
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_component_read(component,
+			       (BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				0x80 * iir_idx)) << 8);
+
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_component_read(component,
+			       (BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				0x80 * iir_idx)) << 16);
+
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((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,
+				(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				 0x80 * iir_idx)) & 0x3F) << 24);
+
+	return value;
+}
+
+static int rx_macro_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		get_iir_band_coeff(component, iir_idx, band_idx, 0);
+	ucontrol->value.integer.value[1] =
+		get_iir_band_coeff(component, iir_idx, band_idx, 1);
+	ucontrol->value.integer.value[2] =
+		get_iir_band_coeff(component, iir_idx, band_idx, 2);
+	ucontrol->value.integer.value[3] =
+		get_iir_band_coeff(component, iir_idx, band_idx, 3);
+	ucontrol->value.integer.value[4] =
+		get_iir_band_coeff(component, iir_idx, band_idx, 4);
+
+	dev_dbg(component->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[1],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[2],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[3],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[4]);
+	return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_component *component,
+			       int iir_idx, int band_idx,
+			       uint32_t value)
+{
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value & 0xFF));
+
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 8) & 0xFF);
+
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 16) & 0xFF);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 24) & 0x3F);
+}
+
+static int rx_macro_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int coeff_idx, idx = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	/*
+	 * Mask top bit it is reserved
+	 * Updates addr automatically for each B2 write
+	 */
+	snd_soc_component_write(component,
+		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	/* Store the coefficients in sidetone coeff array */
+	for (coeff_idx = 0; coeff_idx < RX_MACRO_SIDETONE_IIR_COEFF_MAX;
+		coeff_idx++) {
+		uint32_t value = ucontrol->value.integer.value[coeff_idx];
+
+		set_iir_band_coeff(component, iir_idx, band_idx, value);
+
+		/* Four 8 bit values(one 32 bit) per coefficient */
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+								(value & 0xFF);
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 8) & 0xFF;
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 16) & 0xFF;
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 24) & 0xFF;
+	}
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 0),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 1),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 2),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 3),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 4));
+	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);
+
+	dev_dbg(component->dev, "%s: event = %d\n", __func__, event);
+
+	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,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
+		} else {
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL));
+		}
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume",
+			  BOLERO_CDC_RX_RX0_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume",
+			  BOLERO_CDC_RX_RX1_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume",
+			  BOLERO_CDC_RX_RX2_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume",
+			  BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume",
+			  BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume",
+			  BOLERO_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_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
+		rx_macro_hph_idle_detect_get, rx_macro_hph_idle_detect_put),
+
+	SOC_ENUM_EXT("RX_EAR Mode", rx_macro_ear_mode_enum,
+		rx_macro_get_ear_mode, rx_macro_put_ear_mode),
+
+	SOC_ENUM_EXT("RX_HPH HD2 Mode", rx_macro_hph_hd2_mode_enum,
+		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_ENUM_EXT("RX_GSM mode Enable", rx_macro_vbat_bcl_gsm_mode_enum,
+			rx_macro_vbat_bcl_gsm_mode_func_get,
+			rx_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_SINGLE_EXT("RX_Softclip Enable", SND_SOC_NOPM, 0, 1, 0,
+		     rx_macro_soft_clip_enable_get,
+		     rx_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("AUX_HPF Enable", 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",
+		BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+		BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+
+	SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+		rx_macro_iir_enable_audio_mixer_get,
+		rx_macro_iir_enable_audio_mixer_put),
+
+	SOC_SINGLE_MULTI_EXT("IIR0 Band1", IIR0, BAND1, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR0 Band2", IIR0, BAND2, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR0 Band3", IIR0, BAND3, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR0 Band4", IIR0, BAND4, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR0 Band5", IIR0, BAND5, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+		rx_macro_iir_band_audio_mixer_get,
+		rx_macro_iir_band_audio_mixer_put),
+};
+
+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);
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	u16 val = 0, ec_hq_reg = 0;
+	int ec_tx = 0;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(rx_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_component_read(component,
+			BOLERO_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,
+			BOLERO_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(rx_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	ec_hq_reg = BOLERO_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 = BOLERO_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_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	RX_MACRO_DAPM_MUX("RX_MACRO RX0 MUX", RX_MACRO_RX0, rx_macro_rx0),
+	RX_MACRO_DAPM_MUX("RX_MACRO RX1 MUX", RX_MACRO_RX1, rx_macro_rx1),
+	RX_MACRO_DAPM_MUX("RX_MACRO RX2 MUX", RX_MACRO_RX2, rx_macro_rx2),
+	RX_MACRO_DAPM_MUX("RX_MACRO RX3 MUX", RX_MACRO_RX3, rx_macro_rx3),
+	RX_MACRO_DAPM_MUX("RX_MACRO RX4 MUX", RX_MACRO_RX4, rx_macro_rx4),
+	RX_MACRO_DAPM_MUX("RX_MACRO RX5 MUX", RX_MACRO_RX5, rx_macro_rx5),
+
+	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),
+
+	RX_MACRO_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0),
+	RX_MACRO_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1),
+	RX_MACRO_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2),
+	RX_MACRO_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3),
+	RX_MACRO_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0),
+	RX_MACRO_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1),
+	RX_MACRO_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2),
+	RX_MACRO_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3),
+
+	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", BOLERO_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", BOLERO_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", BOLERO_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SRC1", BOLERO_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+
+	RX_MACRO_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp),
+	RX_MACRO_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp),
+
+	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),
+
+	RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0),
+	RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1),
+	RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2),
+	RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0),
+	RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1),
+	RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2),
+	RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0),
+	RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1),
+	RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2),
+
+	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),
+
+	RX_MACRO_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp),
+	RX_MACRO_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp),
+	RX_MACRO_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp),
+
+	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_E("RX INT2_1 VBAT", SND_SOC_NOPM,
+		0, 0, rx_int2_1_vbat_mix_switch,
+		ARRAY_SIZE(rx_int2_1_vbat_mix_switch),
+		rx_macro_enable_vbat,
+		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_OUTPUT("PCM_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 AIF6 PB", NULL, "RX_MCLK"},
+	{"PCM_OUT", NULL, "RX AIF6 PB"},
+
+	{"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_1 VBAT", "RX AUX VBAT Enable", "RX INT2_1 INTERP"},
+	{"RX INT2 SEC MIX", NULL, "RX INT2_1 VBAT"},
+
+	{"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_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct rx_macro_priv *rx_priv = (struct rx_macro_priv *) handle;
+
+	if (rx_priv == NULL) {
+		pr_err("%s: rx priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(rx_priv->dev);
+		if (bolero_check_core_votes(rx_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(rx_priv->dev);
+		pm_runtime_mark_last_busy(rx_priv->dev);
+	}
+	return rc;
+}
+
+static int rx_swrm_clock(void *handle, bool enable)
+{
+	struct rx_macro_priv *rx_priv = (struct rx_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&rx_priv->swr_clk_lock);
+
+	dev_dbg(rx_priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(rx_priv->dev);
+		if (rx_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						rx_priv->rx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err(rx_priv->dev,
+					"%s: rx swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(rx_priv->dev);
+				pm_runtime_put_autosuspend(rx_priv->dev);
+				goto exit;
+			}
+			ret = rx_macro_mclk_enable(rx_priv, 1, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						rx_priv->rx_swr_gpio_p);
+				dev_err(rx_priv->dev,
+					"%s: rx request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(rx_priv->dev);
+				pm_runtime_put_autosuspend(rx_priv->dev);
+				goto exit;
+			}
+			if (rx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (rx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			rx_priv->reset_swr = false;
+		}
+		pm_runtime_mark_last_busy(rx_priv->dev);
+		pm_runtime_put_autosuspend(rx_priv->dev);
+		rx_priv->swr_clk_users++;
+	} else {
+		if (rx_priv->swr_clk_users <= 0) {
+			dev_err(rx_priv->dev,
+				"%s: rx swrm clock users already reset\n",
+				__func__);
+			rx_priv->swr_clk_users = 0;
+			goto exit;
+		}
+		rx_priv->swr_clk_users--;
+		if (rx_priv->swr_clk_users == 0) {
+			regmap_update_bits(regmap,
+				BOLERO_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+			rx_macro_mclk_enable(rx_priv, 0, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						rx_priv->rx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err(rx_priv->dev,
+					"%s: rx swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(rx_priv->dev, "%s: swrm clock users %d\n",
+		__func__, rx_priv->swr_clk_users);
+exit:
+	mutex_unlock(&rx_priv->swr_clk_lock);
+	return ret;
+}
+
+static const struct rx_macro_reg_mask_val rx_macro_reg_init[] = {
+	{BOLERO_CDC_RX_RX0_RX_PATH_SEC7, 0x07, 0x02},
+	{BOLERO_CDC_RX_RX1_RX_PATH_SEC7, 0x07, 0x02},
+	{BOLERO_CDC_RX_RX2_RX_PATH_SEC7, 0x07, 0x02},
+	{BOLERO_CDC_RX_RX0_RX_PATH_CFG3, 0x03, 0x02},
+	{BOLERO_CDC_RX_RX1_RX_PATH_CFG3, 0x03, 0x02},
+	{BOLERO_CDC_RX_RX2_RX_PATH_CFG3, 0x03, 0x02},
+};
+
+static void rx_macro_init_bcl_pmic_reg(struct snd_soc_component *component)
+{
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: NULL component pointer!\n", __func__);
+		return;
+	}
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return;
+
+	switch (rx_priv->bcl_pmic_params.id) {
+	case 0:
+		/* Enable ID0 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
+		/* Update MC_SID0 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID0 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	case 1:
+		/* Enable ID1 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
+		/* Update MC_SID1 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID1 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	default:
+		dev_err(rx_dev, "%s: PMIC ID is invalid %d\n",
+		       __func__, rx_priv->bcl_pmic_params.id);
+		break;
+	}
+}
+
+static int rx_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+	int i;
+
+	rx_dev = bolero_get_device_ptr(component->dev, RX_MACRO);
+	if (!rx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	rx_priv = dev_get_drvdata(rx_dev);
+	if (!rx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dapm_new_controls(dapm, rx_macro_dapm_widgets,
+					ARRAY_SIZE(rx_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add controls\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_dapm_add_routes(dapm, rx_audio_map,
+					ARRAY_SIZE(rx_audio_map));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add routes\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add widgets\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_add_component_controls(component, rx_macro_snd_controls,
+				   ARRAY_SIZE(rx_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add snd_ctls\n", __func__);
+		return ret;
+	}
+	rx_priv->dev_up = true;
+	rx_priv->rx0_gain_val = 0;
+	rx_priv->rx1_gain_val = 0;
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "AUX_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "PCM_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC1_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC2_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC3_INP");
+	snd_soc_dapm_sync(dapm);
+
+	for (i = 0; i < ARRAY_SIZE(rx_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				rx_macro_reg_init[i].reg,
+				rx_macro_reg_init[i].mask,
+				rx_macro_reg_init[i].val);
+
+	rx_priv->component = component;
+	rx_macro_init_bcl_pmic_reg(component);
+
+	return 0;
+}
+
+static int rx_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->component = NULL;
+
+	return 0;
+}
+
+static void rx_macro_add_child_devices(struct work_struct *work)
+{
+	struct rx_macro_priv *rx_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct rx_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct rx_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[RX_SWR_STRING_LEN] = "";
+	bool rx_swr_master_node = false;
+
+	rx_priv = container_of(work, struct rx_macro_priv,
+			     rx_macro_add_child_devices_work);
+	if (!rx_priv) {
+		pr_err("%s: Memory for rx_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!rx_priv->dev) {
+		pr_err("%s: RX device does not exist\n", __func__);
+		return;
+	}
+
+	if(!rx_priv->dev->of_node) {
+		dev_err(rx_priv->dev,
+			"%s: DT node for RX dev does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &rx_priv->swr_plat_data;
+	rx_priv->child_count = 0;
+
+	for_each_available_child_of_node(rx_priv->dev->of_node, node) {
+		rx_swr_master_node = false;
+		if (strnstr(node->name, "rx_swr_master",
+				strlen("rx_swr_master")) != NULL)
+			rx_swr_master_node = true;
+
+		if(rx_swr_master_node)
+			strlcpy(plat_dev_name, "rx_swr_ctrl",
+				(RX_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(RX_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(rx_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = rx_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (rx_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct rx_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].rx_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			rx_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (rx_priv->child_count < RX_MACRO_CHILD_DEVICES_MAX)
+			rx_priv->pdev_child_devices[
+					rx_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < rx_priv->child_count; count++)
+		platform_device_put(rx_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static void rx_macro_init_ops(struct macro_ops *ops, char __iomem *rx_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = rx_macro_init;
+	ops->exit = rx_macro_deinit;
+	ops->io_base = rx_io_base;
+	ops->dai_ptr = rx_macro_dai;
+	ops->num_dais = ARRAY_SIZE(rx_macro_dai);
+	ops->event_handler = rx_macro_event_handler;
+	ops->set_port_map = rx_macro_set_port_map;
+}
+
+static int rx_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops = {0};
+	struct rx_macro_priv *rx_priv = NULL;
+	u32 rx_base_addr = 0, muxsel = 0;
+	char __iomem *rx_io_base = NULL, *muxsel_io = NULL;
+	int ret = 0, val = 0;
+	u8 bcl_pmic_params[3];
+	u32 default_clk_id = 0;
+	u32 is_used_rx_swr_gpio = 1;
+	const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
+			    GFP_KERNEL);
+	if (!rx_priv)
+		return -ENOMEM;
+
+	rx_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &rx_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,rx_mclk_mode_muxsel",
+				   &muxsel);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,rx-wsa-enable", &val);
+	if (ret == 0) {
+		rx_priv->rx_macro_wsa_slv = (val == 1) ? 1 : 0;
+		dev_info(&pdev->dev, "RX macro wsa slave is %s\n",
+			(val == 1) ? "connected" : "not connected");
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,default-clk-id");
+		default_clk_id = RX_CORE_CLK;
+	}
+	if (of_find_property(pdev->dev.of_node, is_used_rx_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_rx_swr_gpio_dt,
+					   &is_used_rx_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_rx_swr_gpio_dt);
+			is_used_rx_swr_gpio = 1;
+		}
+	}
+	rx_priv->rx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,rx-swr-gpios", 0);
+	if (!rx_priv->rx_swr_gpio_p && is_used_rx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(rx_priv->rx_swr_gpio_p) < 0 &&
+		is_used_rx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				rx_priv->rx_swr_gpio_p, false);
+
+	rx_io_base = devm_ioremap(&pdev->dev, rx_base_addr,
+				  RX_MACRO_MAX_OFFSET);
+	if (!rx_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+	rx_priv->rx_io_base = rx_io_base;
+	muxsel_io = devm_ioremap(&pdev->dev, muxsel, 0x4);
+	if (!muxsel_io) {
+		dev_err(&pdev->dev, "%s: ioremap failed for muxsel\n",
+			__func__);
+		return -ENOMEM;
+	}
+	rx_priv->rx_mclk_mode_muxsel = muxsel_io;
+	rx_priv->reset_swr = true;
+	INIT_WORK(&rx_priv->rx_macro_add_child_devices_work,
+		  rx_macro_add_child_devices);
+	rx_priv->swr_plat_data.handle = (void *) rx_priv;
+	rx_priv->swr_plat_data.read = NULL;
+	rx_priv->swr_plat_data.write = NULL;
+	rx_priv->swr_plat_data.bulk_write = NULL;
+	rx_priv->swr_plat_data.clk = rx_swrm_clock;
+	rx_priv->swr_plat_data.core_vote = rx_macro_core_vote;
+	rx_priv->swr_plat_data.handle_irq = NULL;
+
+	ret = of_property_read_u8_array(pdev->dev.of_node,
+				"qcom,rx-bcl-pmic-params", bcl_pmic_params,
+				sizeof(bcl_pmic_params));
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,rx-bcl-pmic-params");
+	} else {
+		rx_priv->bcl_pmic_params.id = bcl_pmic_params[0];
+		rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
+		rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
+	}
+	rx_priv->clk_id = default_clk_id;
+	rx_priv->default_clk_id  = default_clk_id;
+	ops.clk_id_req = rx_priv->clk_id;
+	ops.default_clk_id = default_clk_id;
+
+	rx_priv->is_aux_hpf_on = 1;
+
+	dev_set_drvdata(&pdev->dev, rx_priv);
+	mutex_init(&rx_priv->mclk_lock);
+	mutex_init(&rx_priv->swr_clk_lock);
+	rx_macro_init_ops(&ops, rx_io_base);
+
+	ret = bolero_register_macro(&pdev->dev, RX_MACRO, &ops);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: register macro failed\n", __func__);
+		goto err_reg_macro;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	schedule_work(&rx_priv->rx_macro_add_child_devices_work);
+	return 0;
+
+err_reg_macro:
+	mutex_destroy(&rx_priv->mclk_lock);
+	mutex_destroy(&rx_priv->swr_clk_lock);
+	return ret;
+}
+
+static int rx_macro_remove(struct platform_device *pdev)
+{
+	struct rx_macro_priv *rx_priv = NULL;
+	u16 count = 0;
+
+	rx_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!rx_priv)
+		return -EINVAL;
+
+	for (count = 0; count < rx_priv->child_count &&
+		count < RX_MACRO_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(rx_priv->pdev_child_devices[count]);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	bolero_unregister_macro(&pdev->dev, RX_MACRO);
+	mutex_destroy(&rx_priv->mclk_lock);
+	mutex_destroy(&rx_priv->swr_clk_lock);
+	kfree(rx_priv->swr_ctrl_data);
+	return 0;
+}
+
+static const struct of_device_id rx_macro_dt_match[] = {
+	{.compatible = "qcom,rx-macro"},
+	{}
+};
+
+static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		bolero_runtime_suspend,
+		bolero_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver rx_macro_driver = {
+	.driver = {
+		.name = "rx_macro",
+		.owner = THIS_MODULE,
+		.pm = &bolero_dev_pm_ops,
+		.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 v2");

+ 3807 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/tx-macro.c

@@ -0,0 +1,3807 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include "bolero-cdc.h"
+#include "bolero-cdc-registers.h"
+#include "bolero-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define TX_MACRO_MAX_OFFSET 0x1000
+
+#define NUM_DECIMATORS 8
+
+#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  TX_HPF_CUT_OFF_FREQ_MASK	0x60
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+#define TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define TX_MACRO_MCLK_FREQ 9600000
+#define TX_MACRO_TX_PATH_OFFSET 0x80
+#define TX_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
+#define TX_MACRO_ADC_MUX_CFG_OFFSET 0x8
+#define TX_MACRO_ADC_MODE_CFG0_SHIFT 1
+
+#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
+
+static int tx_unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+module_param(tx_unmute_delay, int, 0664);
+MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path");
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+static int tx_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+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);
+
+#define TX_MACRO_SWR_STRING_LEN 80
+#define TX_MACRO_CHILD_DEVICES_MAX 3
+
+/* Hold instance to soundwire platform device */
+struct tx_macro_swr_ctrl_data {
+	struct platform_device *tx_swr_pdev;
+};
+
+struct tx_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+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
+};
+
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
+struct tx_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+struct tx_mute_work {
+	struct tx_macro_priv *tx_priv;
+	u32 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct tx_macro_priv *tx_priv;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+struct tx_macro_priv {
+	struct device *dev;
+	bool dec_active[NUM_DECIMATORS];
+	int tx_mclk_users;
+	int swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct snd_soc_component *component;
+	struct device_node *tx_swr_gpio_p;
+	struct tx_macro_swr_ctrl_data *swr_ctrl_data;
+	struct tx_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct tx_macro_add_child_devices_work;
+	struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+	struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS];
+	u16 dmic_clk_div;
+	u32 version;
+	u32 is_used_tx_swr_gpio;
+	unsigned long active_ch_mask[TX_MACRO_MAX_DAIS];
+	char __iomem *tx_io_base;
+	struct platform_device *pdev_child_devices
+			[TX_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int tx_swr_clk_cnt;
+	int va_swr_clk_cnt;
+	int va_clk_status;
+	int tx_clk_status;
+	bool bcs_enable;
+	int dec_mode[NUM_DECIMATORS];
+	int bcs_ch;
+	bool bcs_clk_en;
+	bool hs_slow_insert_complete;
+	int pcm_rate[NUM_DECIMATORS];
+	bool lpi_enable;
+	bool register_event_listener;
+	u16 current_clk_id;
+	int disable_afe_wakeup_event_listener;
+};
+
+static bool tx_macro_get_data(struct snd_soc_component *component,
+			      struct device **tx_dev,
+			      struct tx_macro_priv **tx_priv,
+			      const char *func_name)
+{
+	*tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
+	if (!(*tx_dev)) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+
+	*tx_priv = dev_get_drvdata((*tx_dev));
+	if (!(*tx_priv)) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+
+	if (!(*tx_priv)->component) {
+		dev_err(component->dev,
+			"%s: tx_priv->component not initialized!\n", func_name);
+		return false;
+	}
+
+	return true;
+}
+
+static int tx_macro_mclk_enable(struct tx_macro_priv *tx_priv,
+				bool mclk_enable)
+{
+	struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(tx_priv->dev, "%s: mclk_enable = %u,clk_users= %d\n",
+		__func__, mclk_enable, tx_priv->tx_mclk_users);
+
+	mutex_lock(&tx_priv->mclk_lock);
+	if (mclk_enable) {
+		ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						TX_CORE_CLK,
+						TX_CORE_CLK,
+						true);
+		if (ret < 0) {
+			dev_err_ratelimited(tx_priv->dev,
+				"%s: request clock enable failed\n",
+				__func__);
+			goto exit;
+		}
+		bolero_clk_rsc_fs_gen_request(tx_priv->dev,
+					true);
+		regcache_mark_dirty(regmap);
+		regcache_sync_region(regmap,
+				TX_START_OFFSET,
+				TX_MAX_OFFSET);
+		if (tx_priv->tx_mclk_users == 0) {
+			/* 9.6MHz MCLK, set value 0x00 if other frequency */
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		tx_priv->tx_mclk_users++;
+	} else {
+		if (tx_priv->tx_mclk_users <= 0) {
+			dev_err(tx_priv->dev, "%s: clock already disabled\n",
+				__func__);
+			tx_priv->tx_mclk_users = 0;
+			goto exit;
+		}
+		tx_priv->tx_mclk_users--;
+		if (tx_priv->tx_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+		}
+
+		bolero_clk_rsc_fs_gen_request(tx_priv->dev,
+				false);
+		bolero_clk_rsc_request_clock(tx_priv->dev,
+				 TX_CORE_CLK,
+				 TX_CORE_CLK,
+				 false);
+	}
+exit:
+	mutex_unlock(&tx_priv->mclk_lock);
+	return ret;
+}
+
+static int __tx_macro_mclk_enable(struct snd_soc_component *component,
+				  bool enable)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	return tx_macro_mclk_enable(tx_priv, enable);
+}
+
+static int tx_macro_va_swr_clk_event(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++tx_priv->va_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--tx_priv->va_swr_clk_cnt;
+
+	return 0;
+}
+
+static int tx_macro_tx_swr_clk_event(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++tx_priv->tx_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--tx_priv->tx_swr_clk_cnt;
+
+	return 0;
+}
+
+static int tx_macro_swr_pwr_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);
+	int ret = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(tx_dev, "%s: event = %d, lpi_enable = %d\n",
+		__func__, event, tx_priv->lpi_enable);
+
+	if (!tx_priv->lpi_enable)
+		return ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (tx_priv->lpi_enable) {
+			bolero_register_event_listener(component, true);
+			tx_priv->register_event_listener = true;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (tx_priv->register_event_listener) {
+			tx_priv->register_event_listener = false;
+			bolero_register_event_listener(component, false);
+		}
+		break;
+	default:
+		dev_err(tx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+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);
+	int ret = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(tx_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = tx_macro_mclk_enable(tx_priv, 1);
+		if (ret)
+			tx_priv->dapm_mclk_enable = false;
+		else
+			tx_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (tx_priv->dapm_mclk_enable)
+			ret = tx_macro_mclk_enable(tx_priv, 0);
+		break;
+	default:
+		dev_err(tx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int tx_macro_event_handler(struct snd_soc_component *component,
+				u16 event, u32 data)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	int ret = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		if (tx_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(tx_dev) ||
+		     !pm_runtime_suspended(tx_dev))) {
+			ret = bolero_runtime_suspend(tx_dev);
+			if (!ret) {
+				pm_runtime_disable(tx_dev);
+				pm_runtime_set_suspended(tx_dev);
+				pm_runtime_enable(tx_dev);
+			}
+		}
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		/* reset swr after ssr/pdr */
+		tx_priv->reset_swr = true;
+		if (tx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(tx_dev, TX_CORE_CLK);
+		break;
+	case BOLERO_MACRO_EVT_BCS_CLK_OFF:
+		if (tx_priv->bcs_clk_en)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6);
+		if (data)
+			tx_priv->hs_slow_insert_complete = true;
+		else
+			tx_priv->hs_slow_insert_complete = false;
+		break;
+	default:
+		pr_debug("%s Invalid Event\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static int tx_macro_reg_wake_irq(struct snd_soc_component *component,
+				 u32 data)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	u32 ipc_wakeup = data;
+	int ret = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (tx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+
+	return ret;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+	u16 adc_mux_reg = 0, adc_reg = 0;
+	u16 adc_n = BOLERO_ADC_MAX;
+	bool ret = false;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return ret;
+
+	adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+		if (tx_priv->version == BOLERO_VERSION_2_1)
+			return true;
+		adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+		if (adc_n < BOLERO_ADC_MAX)
+			return true;
+	}
+
+	return ret;
+}
+
+static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work = NULL;
+	struct hpf_work *hpf_work = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	struct snd_soc_component *component = NULL;
+	u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
+	u8 hpf_cut_off_freq = 0;
+	u16 adc_reg = 0, adc_n = 0;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	tx_priv = hpf_work->tx_priv;
+	component = tx_priv->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = BOLERO_CDC_TX0_TX_PATH_CFG0 +
+			TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+	hpf_gate_reg = BOLERO_CDC_TX0_TX_PATH_SEC2 +
+			TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+
+	dev_dbg(component->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
+		__func__, hpf_work->decimator, hpf_cut_off_freq);
+
+	if (is_amic_enabled(component, hpf_work->decimator)) {
+		adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+		/* analog mic clear TX hold */
+		bolero_clear_amic_tx_hold(component->dev, adc_n);
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x03, 0x02);
+		/* Add delay between toggle hpf gate based on sample rate */
+		switch (tx_priv->pcm_rate[hpf_work->decimator]) {
+		case 0:
+			usleep_range(125, 130);
+			break;
+		case 1:
+			usleep_range(62, 65);
+			break;
+		case 3:
+			usleep_range(31, 32);
+			break;
+		case 4:
+			usleep_range(20, 21);
+			break;
+		case 5:
+			usleep_range(10, 11);
+			break;
+		case 6:
+			usleep_range(5, 6);
+			break;
+		default:
+			usleep_range(125, 130);
+		}
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x03, 0x01);
+	} else {
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x02, 0x02);
+		/* Minimum 1 clk cycle delay is required as per HW spec */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x02, 0x00);
+	}
+}
+
+static void tx_macro_mute_update_callback(struct work_struct *work)
+{
+	struct tx_mute_work *tx_mute_dwork = NULL;
+	struct snd_soc_component *component = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	struct delayed_work *delayed_work = NULL;
+	u16 tx_vol_ctl_reg = 0;
+	u8 decimator = 0;
+
+	delayed_work = to_delayed_work(work);
+	tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
+	tx_priv = tx_mute_dwork->tx_priv;
+	component = tx_priv->component;
+	decimator = tx_mute_dwork->decimator;
+
+	tx_vol_ctl_reg =
+		BOLERO_CDC_TX0_TX_PATH_CTL +
+			TX_MACRO_TX_PATH_OFFSET * decimator;
+	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
+	dev_dbg(tx_priv->dev, "%s: decimator %u unmute\n",
+		__func__, decimator);
+}
+
+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 = 0;
+	u16 mic_sel_reg = 0;
+	u16 dmic_clk_reg = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	switch (e->reg) {
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX0_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX1_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX2_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX3_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX4_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX5_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX6_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX7_TX_PATH_CFG0;
+		break;
+	default:
+		dev_err(component->dev, "%s: e->reg: 0x%x not expected\n",
+			__func__, e->reg);
+		return -EINVAL;
+	}
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
+		if (val != 0) {
+			if (val < 5) {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x0 << 7);
+			} else {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x1 << 7);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+				dmic_clk_reg =
+					BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL +
+						((val - 5)/2) * 4;
+				snd_soc_component_update_bits(component,
+					dmic_clk_reg,
+					0x0E, tx_priv->dmic_clk_div << 0x1);
+			}
+		}
+	} else {
+		/* DMIC selected */
+		if (val != 0)
+			snd_soc_component_update_bits(component, mic_sel_reg,
+							1 << 7, 1 << 7);
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int tx_macro_put_dec_enum_v2(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 = 0;
+	u16 mic_sel_reg = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	switch (e->reg) {
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX0_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX1_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX2_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = BOLERO_CDC_TX3_TX_PATH_CFG0;
+		break;
+	default:
+		dev_err(component->dev, "%s: e->reg: 0x%x not expected\n",
+			__func__, e->reg);
+		return -EINVAL;
+	}
+
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
+		if (val != 0) {
+			snd_soc_component_update_bits(component,
+					mic_sel_reg,
+					1 << 7, 0x0 << 7);
+		}
+	} else {
+		/* DMIC selected */
+		if (val != 0)
+			snd_soc_component_update_bits(component, mic_sel_reg,
+							1 << 7, 1 << 7);
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int tx_macro_put_pcm_in_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 = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s\n", __func__, widget->name);
+
+	snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_I2S_CLK,
+					0x1, val);
+
+	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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(dec_id, &tx_priv->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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (enable)
+		set_bit(dec_id, &tx_priv->active_ch_mask[dai_id]);
+	else
+		clear_bit(dec_id, &tx_priv->active_ch_mask[dai_id]);
+
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+	return 0;
+}
+
+static inline int tx_macro_path_get(const char *wname,
+				    unsigned int *path_num)
+{
+	int ret = 0;
+	char *widget_name = NULL;
+	char *w_name = NULL;
+	char *path_num_char = NULL;
+	char *path_name = NULL;
+
+	widget_name = kstrndup(wname, 10, GFP_KERNEL);
+	if (!widget_name)
+		return -EINVAL;
+
+	w_name = widget_name;
+
+	path_name = strsep(&widget_name, " ");
+	if (!path_name) {
+		pr_err("%s: Invalid widget name = %s\n",
+			__func__, widget_name);
+		ret = -EINVAL;
+		goto err;
+	}
+	path_num_char = strpbrk(path_name, "01234567");
+	if (!path_num_char) {
+		pr_err("%s: tx path index not found\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = kstrtouint(path_num_char, 10, path_num);
+	if (ret < 0)
+		pr_err("%s: Invalid tx path = %s\n",
+			__func__, w_name);
+
+err:
+	kfree(w_name);
+	return ret;
+}
+
+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_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int ret = 0;
+	int path = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ret = tx_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	ucontrol->value.integer.value[0] = tx_priv->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);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int ret = 0;
+	int path = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ret = tx_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	tx_priv->dec_mode[path] = value;
+
+	return 0;
+}
+
+static int tx_macro_lpi_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = tx_priv->lpi_enable;
+
+	return 0;
+}
+
+static int tx_macro_lpi_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->lpi_enable = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int tx_macro_bcs_ch_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.enumerated.item[0] = tx_priv->bcs_ch;
+
+	return 0;
+}
+
+static int tx_macro_bcs_ch_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.enumerated.item[0];
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->bcs_ch = 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_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+	return -EINVAL;
+
+	ucontrol->value.integer.value[0] = tx_priv->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);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->bcs_enable = value;
+
+	return 0;
+}
+
+static const char * const bcs_ch_sel_mux_text[] = {
+	"SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11",
+};
+
+static const struct soc_enum bcs_ch_sel_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_sel_mux_text),
+			    bcs_ch_sel_mux_text);
+
+static int tx_macro_get_bcs_ch_sel(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if ((tx_priv->version == BOLERO_VERSION_2_1) ||
+	    (tx_priv->version == BOLERO_VERSION_2_2))
+		value = (snd_soc_component_read(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)) & 0x0F;
+	else if (tx_priv->version == BOLERO_VERSION_2_0)
+		value = (snd_soc_component_read(component,
+			BOLERO_CDC_TX_TOP_CSR_SWR_CTRL)) & 0x0F;
+
+	ucontrol->value.integer.value[0] = value;
+	return 0;
+}
+
+static int tx_macro_put_bcs_ch_sel(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+	    ucontrol->value.integer.value[0] > ARRAY_SIZE(bcs_ch_sel_mux_text))
+		return -EINVAL;
+
+	value = ucontrol->value.integer.value[0];
+	if ((tx_priv->version == BOLERO_VERSION_2_1) ||
+	    (tx_priv->version == BOLERO_VERSION_2_2))
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F, value);
+	else if (tx_priv->version == BOLERO_VERSION_2_0)
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x0F, value);
+
+	return 0;
+}
+
+static int tx_macro_enable_dmic(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 dmic = 0;
+	int ret = 0;
+	char *wname = NULL;
+
+	wname = strpbrk(w->name, "01234567");
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d\n",
+			__func__, event,  dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		bolero_dmic_clk_enable(component, dmic, DMIC_TX, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		bolero_dmic_clk_enable(component, dmic, DMIC_TX, false);
+		break;
+	}
+
+	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 = 0;
+	u16 tx_vol_ctl_reg = 0;
+	u16 dec_cfg_reg = 0;
+	u16 hpf_gate_reg = 0;
+	u16 tx_gain_ctl_reg = 0;
+	u16 tx_fs_reg = 0;
+	u8 hpf_cut_off_freq = 0;
+	u16 adc_mux_reg = 0;
+	int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
+	int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	decimator = w->shift;
+
+	dev_dbg(component->dev, "%s(): widget = %s decimator = %u\n", __func__,
+			w->name, decimator);
+
+	tx_vol_ctl_reg = BOLERO_CDC_TX0_TX_PATH_CTL +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+	hpf_gate_reg = BOLERO_CDC_TX0_TX_PATH_SEC2 +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+	dec_cfg_reg = BOLERO_CDC_TX0_TX_PATH_CFG0 +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+	tx_gain_ctl_reg = BOLERO_CDC_TX0_TX_VOL_CTL +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+	adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+
+	tx_priv->pcm_rate[decimator] = (snd_soc_component_read(component,
+				     tx_fs_reg) & 0x0F);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, tx_priv->dec_mode[decimator] <<
+			TX_MACRO_ADC_MODE_CFG0_SHIFT);
+		/* Enable TX PGA Mute */
+		snd_soc_component_update_bits(component,
+			tx_vol_ctl_reg, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component,
+			tx_vol_ctl_reg, 0x20, 0x20);
+		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(component, dec_cfg_reg) &
+				TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+
+		tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq =
+						hpf_cut_off_freq;
+
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						CF_MIN_3DB_150HZ << 5);
+
+		if (is_amic_enabled(component, decimator)) {
+			hpf_delay = TX_MACRO_AMIC_HPF_DELAY_MS;
+			unmute_delay = TX_MACRO_AMIC_UNMUTE_DELAY_MS;
+		}
+		if (tx_unmute_delay < unmute_delay)
+			tx_unmute_delay = unmute_delay;
+		/* schedule work queue to Remove Mute */
+		queue_delayed_work(system_freezable_wq,
+				   &tx_priv->tx_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(tx_unmute_delay));
+		if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq !=
+							CF_MIN_3DB_150HZ) {
+			queue_delayed_work(system_freezable_wq,
+				&tx_priv->tx_hpf_work[decimator].dwork,
+				msecs_to_jiffies(hpf_delay));
+			snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 0x02);
+			if (!is_amic_enabled(component, decimator))
+				snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 0x00);
+			snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 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_priv->bcs_enable) {
+			if ((tx_priv->version == BOLERO_VERSION_2_1) ||
+			    (tx_priv->version == BOLERO_VERSION_2_2))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F,
+					tx_priv->bcs_ch);
+			else if (tx_priv->version == BOLERO_VERSION_2_0)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0,
+					(tx_priv->bcs_ch << 4));
+
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					0x01, 0x01);
+			tx_priv->bcs_clk_en = true;
+			if (tx_priv->hs_slow_insert_complete)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40,
+					0x40);
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read(component, adc_mux_reg)
+							& SWR_MIC) {
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x01);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL,
+					0x0E, 0x00);
+			}
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x10, 0x10);
+		if (cancel_delayed_work_sync(
+		    &tx_priv->tx_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						hpf_cut_off_freq << 5);
+				if (is_amic_enabled(component, decimator))
+					snd_soc_component_update_bits(component,
+							hpf_gate_reg,
+							0x03, 0x02);
+				else
+					snd_soc_component_update_bits(component,
+							hpf_gate_reg,
+							0x03, 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,
+						0x03, 0x01);
+			}
+		}
+		cancel_delayed_work_sync(
+				&tx_priv->tx_mute_dwork[decimator].dwork);
+
+		if (tx_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read(component, adc_mux_reg)
+							& SWR_MIC)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x00);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x20, 0x00);
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+			0x40, 0x40);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+			0x40, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x10, 0x00);
+		if (tx_priv->bcs_enable) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00);
+			tx_priv->bcs_clk_en = false;
+			if ((tx_priv->version == BOLERO_VERSION_2_1) ||
+			    (tx_priv->version == BOLERO_VERSION_2_2))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F,
+					0x00);
+			else if (tx_priv->version == BOLERO_VERSION_2_0)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0,
+					0x00);
+		}
+		break;
+	}
+	return 0;
+}
+
+static int tx_macro_enable_micbias(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	return 0;
+}
+
+/* Cutoff frequency for high pass filter */
+static const char * const cf_text[] = {
+	"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
+};
+
+static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, BOLERO_CDC_TX0_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, BOLERO_CDC_TX1_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, BOLERO_CDC_TX2_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, BOLERO_CDC_TX3_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, BOLERO_CDC_TX4_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, BOLERO_CDC_TX5_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, BOLERO_CDC_TX6_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, BOLERO_CDC_TX7_TX_PATH_CFG0, 5,
+							cf_text);
+
+static int tx_macro_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	int tx_fs_rate = -EINVAL;
+	struct snd_soc_component *component = dai->component;
+	u32 decimator = 0;
+	u32 sample_rate = 0;
+	u16 tx_fs_reg = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	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_priv->active_ch_mask[dai->id],
+			 TX_MACRO_DEC_MAX) {
+		if (decimator >= 0) {
+			tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL +
+				    TX_MACRO_TX_PATH_OFFSET * decimator;
+			dev_dbg(component->dev, "%s: set DEC%u rate to %u\n",
+				__func__, decimator, sample_rate);
+			snd_soc_component_update_bits(component, tx_fs_reg,
+						0x0F, tx_fs_rate);
+		} else {
+			dev_err(component->dev,
+				"%s: ERROR: Invalid decimator: %d\n",
+				__func__, decimator);
+			return -EINVAL;
+		}
+	}
+	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 device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	switch (dai->id) {
+	case TX_MACRO_AIF1_CAP:
+	case TX_MACRO_AIF2_CAP:
+	case TX_MACRO_AIF3_CAP:
+		*tx_slot = tx_priv->active_ch_mask[dai->id];
+		*tx_num = hweight_long(tx_priv->active_ch_mask[dai->id]);
+		break;
+	default:
+		dev_err(tx_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	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,
+};
+
+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,
+	},
+};
+
+#define STRING(name) #name
+#define TX_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define TX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define TX_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+static const char * const adc_mux_text[] = {
+	"MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1"
+};
+
+TX_MACRO_DAPM_ENUM(tx_dec0, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec1, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec3, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec4, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec5, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec6, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG1,
+		   0, adc_mux_text);
+TX_MACRO_DAPM_ENUM(tx_dec7, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG1,
+		   0, adc_mux_text);
+
+
+static const char * const dmic_mux_text[] = {
+	"ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
+	"DMIC4", "DMIC5", "DMIC6", "DMIC7"
+};
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic0, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic1, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic3, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic4, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic5, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic6, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_dmic7, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_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"
+};
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic0, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic1, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic3, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic4, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic5, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic6, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic7, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic0_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic1_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic2_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic3_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic4_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic5_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic6_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic7_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic0_v4, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum_v2);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic1_v4, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum_v2);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic2_v4, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum_v2);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic3_v4, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum_v2);
+
+static const char * const pcm_in0_mux_text[] = {
+	"SWR_MIC", "RX_SWR_TX_PCM_IN0",
+};
+
+static const char * const pcm_in1_mux_text[] = {
+	"SWR_MIC", "RX_SWR_TX_PCM_IN1",
+};
+
+TX_MACRO_DAPM_ENUM_EXT(rx_swr_tx_pcm_in0, SND_SOC_NOPM,
+			0, pcm_in0_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_pcm_in_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(rx_swr_tx_pcm_in1, SND_SOC_NOPM,
+			0, pcm_in1_mux_text, snd_soc_dapm_get_enum_double,
+			tx_macro_put_pcm_in_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_EXT(ARRAY_SIZE(dec_mode_mux_text),
+			    dec_mode_mux_text);
+
+static const char * const bcs_ch_enum_text[] = {
+	"CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8", "CH9",
+	"CH10", "CH11",
+};
+
+static const struct soc_enum bcs_ch_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_enum_text),
+			    bcs_ch_enum_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_kcontrol_new tx_aif1_cap_mixer_v2[] = {
+	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),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer_v2[] = {
+	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),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer_v2[] = {
+	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),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_common[] = {
+	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),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3),
+
+	SND_SOC_DAPM_SUPPLY("TX MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("TX SWR_INPUT"),
+
+	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_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_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      tx_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer_v2, ARRAY_SIZE(tx_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer_v2, ARRAY_SIZE(tx_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer_v2, ARRAY_SIZE(tx_aif3_cap_mixer_v2)),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v2),
+
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v3[] = {
+	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)),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7_v3),
+
+	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_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			tx_macro_tx_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			tx_macro_va_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v4[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer_v2, ARRAY_SIZE(tx_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer_v2, ARRAY_SIZE(tx_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer_v2, ARRAY_SIZE(tx_aif3_cap_mixer_v2)),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v4),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v4),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v4),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v4),
+
+	TX_MACRO_DAPM_MUX("RX SWR TX MUX0", 0, rx_swr_tx_pcm_in0),
+	TX_MACRO_DAPM_MUX("RX SWR TX MUX1", 0, rx_swr_tx_pcm_in1),
+
+	SND_SOC_DAPM_INPUT("RX_SWR_TX_PCM_IN0"),
+	SND_SOC_DAPM_INPUT("RX_SWR_TX_PCM_IN1"),
+};
+
+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)),
+
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7),
+
+	SND_SOC_DAPM_SUPPLY("TX MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	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,
+			tx_macro_tx_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_va_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_common[] = {
+	{"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_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_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 DEC0 MUX", NULL, "TX_MCLK"},
+	{"TX DEC1 MUX", NULL, "TX_MCLK"},
+	{"TX DEC2 MUX", NULL, "TX_MCLK"},
+	{"TX DEC3 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC0 MUX", "MSM_DMIC", "TX DMIC MUX0"},
+	{"TX DMIC MUX0", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX0", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX0", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX0", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX0", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX0", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX0", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX0", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+	{"TX SMIC MUX0", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC9", "TX SWR_INPUT"},
+
+	{"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"},
+	{"TX DMIC MUX1", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX1", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX1", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX1", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX1", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX1", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX1", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX1", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+	{"TX SMIC MUX1", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC9", "TX SWR_INPUT"},
+
+	{"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"},
+	{"TX DMIC MUX2", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX2", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX2", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX2", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX2", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX2", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX2", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX2", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+	{"TX SMIC MUX2", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC9", "TX SWR_INPUT"},
+
+	{"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"},
+	{"TX DMIC MUX3", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX3", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX3", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX3", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX3", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX3", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX3", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX3", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+	{"TX SMIC MUX3", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC9", "TX SWR_INPUT"},
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_v2[] = {
+	{"TX SMIC MUX0", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX1", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX2", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX3", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC11", "TX SWR_INPUT"},
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_v3[] = {
+	{"TX SMIC MUX0", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX1", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX2", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX3", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"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", "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", "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 DEC4 MUX", NULL, "TX_MCLK"},
+	{"TX DEC5 MUX", NULL, "TX_MCLK"},
+	{"TX DEC6 MUX", NULL, "TX_MCLK"},
+	{"TX DEC7 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"},
+	{"TX DMIC MUX4", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX4", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX4", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX4", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX4", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX4", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX4", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX4", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+	{"TX SMIC MUX4", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"},
+	{"TX DMIC MUX5", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX5", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX5", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX5", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX5", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX5", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX5", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX5", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+	{"TX SMIC MUX5", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"},
+	{"TX DMIC MUX6", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX6", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX6", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX6", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX6", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX6", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX6", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX6", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+	{"TX SMIC MUX6", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"},
+	{"TX DMIC MUX7", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX7", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX7", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX7", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX7", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX7", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX7", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX7", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+	{"TX SMIC MUX7", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX SMIC MUX0", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX1", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX2", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX3", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX4", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
+
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_v4[] = {
+	{"TX SMIC MUX0", "SWR_MIC10", "RX SWR TX MUX0"},
+	{"RX SWR TX MUX0", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX0", "RX_SWR_TX_PCM_IN0", "RX_SWR_TX_PCM_IN0"},
+	{"TX SMIC MUX0", "SWR_MIC11", "RX SWR TX MUX1"},
+	{"RX SWR TX MUX1", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX1", "RX_SWR_TX_PCM_IN1", "RX_SWR_TX_PCM_IN1"},
+
+	{"TX SMIC MUX1", "SWR_MIC10", "RX SWR TX MUX0"},
+	{"RX SWR TX MUX0", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX0", "RX_SWR_TX_PCM_IN0", "RX_SWR_TX_PCM_IN0"},
+	{"TX SMIC MUX1", "SWR_MIC11", "RX SWR TX MUX1"},
+	{"RX SWR TX MUX1", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX1", "RX_SWR_TX_PCM_IN1", "RX_SWR_TX_PCM_IN1"},
+
+	{"TX SMIC MUX2", "SWR_MIC10", "RX SWR TX MUX0"},
+	{"RX SWR TX MUX0", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX0", "RX_SWR_TX_PCM_IN0", "RX_SWR_TX_PCM_IN0"},
+	{"TX SMIC MUX2", "SWR_MIC11", "RX SWR TX MUX1"},
+	{"RX SWR TX MUX1", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX1", "RX_SWR_TX_PCM_IN1", "RX_SWR_TX_PCM_IN1"},
+
+	{"TX SMIC MUX3", "SWR_MIC10", "RX SWR TX MUX0"},
+	{"RX SWR TX MUX0", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX0", "RX_SWR_TX_PCM_IN0", "RX_SWR_TX_PCM_IN0"},
+	{"TX SMIC MUX3", "SWR_MIC11", "RX SWR TX MUX1"},
+	{"RX SWR TX MUX1", "SWR_MIC", "TX SWR_INPUT"},
+	{"RX SWR TX MUX1", "RX_SWR_TX_PCM_IN1", "RX_SWR_TX_PCM_IN1"},
+
+	{"RX SWR TX MUX0", NULL, "TX_MCLK"},
+	{"RX SWR TX MUX1", NULL, "TX_MCLK"},
+};
+
+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", "MSM_DMIC", "TX DMIC MUX0"},
+	{"TX DMIC MUX0", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX0", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX0", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX0", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX0", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX0", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX0", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX0", "DMIC7", "TX DMIC7"},
+
+	{"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", "MSM_DMIC", "TX DMIC MUX1"},
+	{"TX DMIC MUX1", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX1", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX1", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX1", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX1", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX1", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX1", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX1", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX2"},
+	{"TX DMIC MUX2", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX2", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX2", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX2", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX2", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX2", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX2", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX2", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX3"},
+	{"TX DMIC MUX3", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX3", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX3", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX3", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX3", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX3", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX3", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX3", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX4"},
+	{"TX DMIC MUX4", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX4", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX4", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX4", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX4", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX4", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX4", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX4", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX5"},
+	{"TX DMIC MUX5", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX5", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX5", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX5", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX5", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX5", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX5", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX5", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX6"},
+	{"TX DMIC MUX6", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX6", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX6", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX6", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX6", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX6", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX6", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX6", "DMIC7", "TX 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", "MSM_DMIC", "TX DMIC MUX7"},
+	{"TX DMIC MUX7", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX7", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX7", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX7", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX7", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX7", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX7", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX7", "DMIC7", "TX 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_common[] = {
+	SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
+			  BOLERO_CDC_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
+			  BOLERO_CDC_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
+			  BOLERO_CDC_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
+			  BOLERO_CDC_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_SINGLE_EXT("TX LPI Enable", 0, 0, 1, 0,
+		tx_macro_lpi_get, tx_macro_lpi_put),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum,
+			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),
+
+	SOC_ENUM_EXT("BCS Channel", bcs_ch_enum,
+			tx_macro_bcs_ch_get, tx_macro_bcs_ch_put),
+
+	SOC_ENUM_EXT("BCS CH_SEL", bcs_ch_sel_mux_enum,
+			tx_macro_get_bcs_ch_sel, tx_macro_put_bcs_ch_sel),
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = {
+	SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
+			  BOLERO_CDC_TX4_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
+			  BOLERO_CDC_TX5_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
+			  BOLERO_CDC_TX6_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
+			  BOLERO_CDC_TX7_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
+			  BOLERO_CDC_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
+			  BOLERO_CDC_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
+			  BOLERO_CDC_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
+			  BOLERO_CDC_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
+			  BOLERO_CDC_TX4_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
+			  BOLERO_CDC_TX5_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
+			  BOLERO_CDC_TX6_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
+			  BOLERO_CDC_TX7_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+	SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
+
+	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+
+	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+
+	SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+
+	SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+
+	SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+
+	SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+
+	SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+		       tx_macro_get_bcs, tx_macro_set_bcs),
+};
+
+static int tx_macro_register_event_listener(struct snd_soc_component *component,
+					    bool enable)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
+	if (!tx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv = dev_get_drvdata(tx_dev);
+	if (!tx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+	if (tx_priv->swr_ctrl_data &&
+		(!tx_priv->tx_swr_clk_cnt || !tx_priv->va_swr_clk_cnt)) {
+		if (enable) {
+			if (!tx_priv->disable_afe_wakeup_event_listener)
+				ret = swrm_wcd_notify(
+					tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+					SWR_REGISTER_WAKEUP, NULL);
+		} else {
+			if (!tx_priv->disable_afe_wakeup_event_listener)
+				ret = swrm_wcd_notify(
+					tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+					SWR_DEREGISTER_WAKEUP, NULL);
+		}
+	}
+
+	return ret;
+}
+
+static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
+				      struct regmap *regmap, int clk_type,
+				      bool enable)
+{
+	int ret = 0, clk_tx_ret = 0;
+
+	dev_dbg(tx_priv->dev,
+		"%s: clock type %s, enable: %s tx_mclk_users: %d\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"), tx_priv->tx_mclk_users);
+
+	if (enable) {
+		if (tx_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						tx_priv->tx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: tx swr pinctrl enable failed\n",
+					__func__);
+				goto exit;
+			}
+			msm_cdc_pinctrl_set_wakeup_capable(
+					tx_priv->tx_swr_gpio_p, false);
+		}
+
+		clk_tx_ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		if (clk_type == TX_MCLK) {
+			ret = tx_macro_mclk_enable(tx_priv, 1);
+			if (ret < 0) {
+				if (tx_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							tx_priv->tx_swr_gpio_p);
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: request clock enable failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (clk_type == VA_MCLK) {
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   VA_CORE_CLK,
+							   true);
+			if (ret < 0) {
+				if (tx_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							tx_priv->tx_swr_gpio_p);
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+			bolero_clk_rsc_fs_gen_request(tx_priv->dev,
+						  true);
+			mutex_lock(&tx_priv->mclk_lock);
+			if (tx_priv->tx_mclk_users == 0) {
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK,
+					0x01, 0x01);
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+					0x01, 0x01);
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					0x01, 0x01);
+			}
+			tx_priv->tx_mclk_users++;
+			mutex_unlock(&tx_priv->mclk_lock);
+		}
+		if (tx_priv->swr_clk_users == 0) {
+			dev_dbg(tx_priv->dev, "%s: reset_swr: %d\n",
+				__func__, tx_priv->reset_swr);
+			if (tx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (tx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			tx_priv->reset_swr = false;
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		tx_priv->swr_clk_users++;
+	} else {
+		if (tx_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(tx_priv->dev,
+				"tx swrm clock users already 0\n");
+			tx_priv->swr_clk_users = 0;
+			return 0;
+		}
+		clk_tx_ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		tx_priv->swr_clk_users--;
+		if (tx_priv->swr_clk_users == 0)
+			regmap_update_bits(regmap,
+				BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+		if (clk_type == TX_MCLK)
+			tx_macro_mclk_enable(tx_priv, 0);
+		if (clk_type == VA_MCLK) {
+			mutex_lock(&tx_priv->mclk_lock);
+			if (tx_priv->tx_mclk_users <= 0) {
+				dev_err(tx_priv->dev, "%s: clock already disabled\n",
+						__func__);
+				tx_priv->tx_mclk_users = 0;
+				mutex_unlock(&tx_priv->mclk_lock);
+				goto tx_clk;
+			}
+			tx_priv->tx_mclk_users--;
+			if (tx_priv->tx_mclk_users == 0) {
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					0x01, 0x00);
+				regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+					0x01, 0x00);
+			}
+			mutex_unlock(&tx_priv->mclk_lock);
+			bolero_clk_rsc_fs_gen_request(tx_priv->dev,
+						false);
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   VA_CORE_CLK,
+							   false);
+			if (ret < 0) {
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+		}
+tx_clk:
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		if (tx_priv->swr_clk_users == 0) {
+			msm_cdc_pinctrl_set_wakeup_capable(
+					tx_priv->tx_swr_gpio_p, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						tx_priv->tx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: tx swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	return 0;
+
+done:
+	if (!clk_tx_ret)
+		bolero_clk_rsc_request_clock(tx_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+exit:
+	return ret;
+}
+
+static int tx_macro_clk_div_get(struct snd_soc_component *component)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	return tx_priv->dmic_clk_div;
+}
+
+static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
+	if (!tx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv = dev_get_drvdata(tx_dev);
+	if (!tx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+	dev_dbg(component->dev,
+		"%s: va_swr_clk_cnt %d, tx_swr_clk_cnt %d, tx_clk_status %d\n",
+		__func__, tx_priv->va_swr_clk_cnt,
+		tx_priv->tx_swr_clk_cnt, tx_priv->tx_clk_status);
+	if (tx_priv->current_clk_id == clk_src) {
+		dev_dbg(component->dev,
+			"%s: requested clk %d is same as current\n",
+			__func__, clk_src);
+		return 0;
+	} else if (tx_priv->va_swr_clk_cnt != 0 && tx_priv->tx_clk_status) {
+		ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+				TX_CORE_CLK,
+				clk_src,
+				true);
+		if (ret) {
+			dev_dbg(component->dev,
+				"%s: request clock %d enable failed\n",
+				__func__, clk_src);
+			goto ret;
+		}
+		ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+				TX_CORE_CLK,
+				tx_priv->current_clk_id,
+				false);
+		if (ret) {
+			dev_dbg(component->dev,
+				"%s: request clock  disable failed\n",
+				__func__);
+			bolero_clk_rsc_request_clock(tx_priv->dev,
+				TX_CORE_CLK,
+				clk_src,
+				false);
+			goto ret;
+		}
+		tx_priv->current_clk_id = clk_src;
+	} else {
+		ret = -EBUSY;
+	}
+
+ret:
+	return ret;
+}
+
+static int tx_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
+
+	if (tx_priv == NULL) {
+		pr_err("%s: tx priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(tx_priv->dev);
+		if (bolero_check_core_votes(tx_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(tx_priv->dev);
+		pm_runtime_mark_last_busy(tx_priv->dev);
+	}
+	return rc;
+}
+
+static int tx_macro_swrm_clock(void *handle, bool enable)
+{
+	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&tx_priv->swr_clk_lock);
+	dev_dbg(tx_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		tx_priv->tx_swr_clk_cnt, tx_priv->va_swr_clk_cnt);
+
+	if (enable) {
+		pm_runtime_get_sync(tx_priv->dev);
+		if (tx_priv->va_swr_clk_cnt && !tx_priv->tx_swr_clk_cnt) {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							VA_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(tx_priv->dev);
+				pm_runtime_put_autosuspend(tx_priv->dev);
+				goto done;
+			}
+			tx_priv->va_clk_status++;
+		} else {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							TX_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(tx_priv->dev);
+				pm_runtime_put_autosuspend(tx_priv->dev);
+				goto done;
+			}
+			tx_priv->tx_clk_status++;
+		}
+		pm_runtime_mark_last_busy(tx_priv->dev);
+		pm_runtime_put_autosuspend(tx_priv->dev);
+	} else {
+		if (tx_priv->va_clk_status && !tx_priv->tx_clk_status) {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			--tx_priv->va_clk_status;
+		} else if (!tx_priv->va_clk_status && tx_priv->tx_clk_status) {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			--tx_priv->tx_clk_status;
+		} else if (tx_priv->va_clk_status && tx_priv->tx_clk_status) {
+			if (!tx_priv->va_swr_clk_cnt && tx_priv->tx_swr_clk_cnt) {
+				ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+								VA_MCLK, enable);
+				if (ret)
+					goto done;
+				--tx_priv->va_clk_status;
+			} else {
+				ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+								TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--tx_priv->tx_clk_status;
+			}
+
+		} else {
+			dev_dbg(tx_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
+		}
+	}
+
+	dev_dbg(tx_priv->dev,
+		"%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, tx_priv->swr_clk_users, tx_priv->tx_clk_status,
+		tx_priv->va_clk_status);
+done:
+	mutex_unlock(&tx_priv->swr_clk_lock);
+	return ret;
+}
+
+static int tx_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
+				      struct tx_macro_priv *tx_priv)
+{
+	u32 div_factor = TX_MACRO_CLK_DIV_2;
+	u32 mclk_rate = TX_MACRO_MCLK_FREQ;
+
+	if (dmic_sample_rate == TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
+	    mclk_rate % dmic_sample_rate != 0)
+		goto undefined_rate;
+
+	div_factor = mclk_rate / dmic_sample_rate;
+
+	switch (div_factor) {
+	case 2:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_2;
+		break;
+	case 3:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_3;
+		break;
+	case 4:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_4;
+		break;
+	case 6:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_6;
+		break;
+	case 8:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_8;
+		break;
+	case 16:
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_16;
+		break;
+	default:
+		/* Any other DIV factor is invalid */
+		goto undefined_rate;
+	}
+
+	/* Valid dmic DIV factors */
+	dev_dbg(tx_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+		__func__, div_factor, mclk_rate);
+
+	return dmic_sample_rate;
+
+undefined_rate:
+	dev_dbg(tx_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
+		 __func__, dmic_sample_rate, mclk_rate);
+	dmic_sample_rate = TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
+
+	return dmic_sample_rate;
+}
+
+static const struct tx_macro_reg_mask_val tx_macro_reg_init[] = {
+	{BOLERO_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x0A},
+};
+
+static int tx_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+			snd_soc_component_get_dapm(component);
+	int ret = 0, i = 0;
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
+	if (!tx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv = dev_get_drvdata(tx_dev);
+	if (!tx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv->lpi_enable = false;
+	tx_priv->register_event_listener = false;
+	tx_priv->version = bolero_get_version(tx_dev);
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_common,
+				ARRAY_SIZE(tx_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v2,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v2));
+		else if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v3,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v3));
+		else if (tx_priv->version == BOLERO_VERSION_2_2)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v4,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v4));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, tx_macro_dapm_widgets,
+					ARRAY_SIZE(tx_macro_dapm_widgets));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_common,
+					ARRAY_SIZE(tx_audio_map_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_v2,
+					ARRAY_SIZE(tx_audio_map_v2));
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_v3,
+					ARRAY_SIZE(tx_audio_map_v3));
+		if (tx_priv->version == BOLERO_VERSION_2_2)
+			ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_v4,
+					ARRAY_SIZE(tx_audio_map_v4));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
+					ARRAY_SIZE(tx_audio_map));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(tx_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+			tx_macro_snd_controls_common,
+			ARRAY_SIZE(tx_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls_v3,
+				ARRAY_SIZE(tx_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls,
+				ARRAY_SIZE(tx_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF1 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF2 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF3 Capture");
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_INPUT");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7");
+	}
+	snd_soc_dapm_sync(dapm);
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx_priv->tx_hpf_work[i].tx_priv = tx_priv;
+		tx_priv->tx_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&tx_priv->tx_hpf_work[i].dwork,
+			tx_macro_tx_hpf_corner_freq_callback);
+	}
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx_priv->tx_mute_dwork[i].tx_priv = tx_priv;
+		tx_priv->tx_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&tx_priv->tx_mute_dwork[i].dwork,
+			  tx_macro_mute_update_callback);
+	}
+	tx_priv->component = component;
+
+	for (i = 0; i < ARRAY_SIZE(tx_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				tx_macro_reg_init[i].reg,
+				tx_macro_reg_init[i].mask,
+				tx_macro_reg_init[i].val);
+
+	return 0;
+}
+
+static int tx_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->component = NULL;
+	return 0;
+}
+
+static void tx_macro_add_child_devices(struct work_struct *work)
+{
+	struct tx_macro_priv *tx_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct tx_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct tx_macro_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[TX_MACRO_SWR_STRING_LEN] = "";
+	bool tx_swr_master_node = false;
+
+	tx_priv = container_of(work, struct tx_macro_priv,
+			     tx_macro_add_child_devices_work);
+	if (!tx_priv) {
+		pr_err("%s: Memory for tx_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!tx_priv->dev) {
+		pr_err("%s: tx dev does not exist\n", __func__);
+		return;
+	}
+
+	if (!tx_priv->dev->of_node) {
+		dev_err(tx_priv->dev,
+			"%s: DT node for tx_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &tx_priv->swr_plat_data;
+	tx_priv->child_count = 0;
+
+	for_each_available_child_of_node(tx_priv->dev->of_node, node) {
+		tx_swr_master_node = false;
+		if (strnstr(node->name, "tx_swr_master",
+                                strlen("tx_swr_master")) != NULL)
+			tx_swr_master_node = true;
+
+		if (tx_swr_master_node)
+			strlcpy(plat_dev_name, "tx_swr_ctrl",
+				(TX_MACRO_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(TX_MACRO_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(tx_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = tx_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (tx_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct tx_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].tx_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			tx_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (tx_priv->child_count < TX_MACRO_CHILD_DEVICES_MAX)
+			tx_priv->pdev_child_devices[
+					tx_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < tx_priv->child_count; count++)
+		platform_device_put(tx_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int tx_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (tx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static void tx_macro_init_ops(struct macro_ops *ops,
+			       char __iomem *tx_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = tx_macro_init;
+	ops->exit = tx_macro_deinit;
+	ops->io_base = tx_io_base;
+	ops->dai_ptr = tx_macro_dai;
+	ops->num_dais = ARRAY_SIZE(tx_macro_dai);
+	ops->event_handler = tx_macro_event_handler;
+	ops->reg_wake_irq = tx_macro_reg_wake_irq;
+	ops->set_port_map = tx_macro_set_port_map;
+	ops->clk_div_get = tx_macro_clk_div_get;
+	ops->clk_switch = tx_macro_clk_switch;
+	ops->reg_evt_listener = tx_macro_register_event_listener;
+	ops->clk_enable = __tx_macro_mclk_enable;
+}
+
+static int tx_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops = {0};
+	struct tx_macro_priv *tx_priv = NULL;
+	u32 tx_base_addr = 0, sample_rate = 0;
+	char __iomem *tx_io_base = NULL;
+	int ret = 0;
+	const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate";
+	u32 is_used_tx_swr_gpio = 1;
+	const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio";
+	u32 disable_afe_wakeup_event_listener = 0;
+	const char *disable_afe_wakeup_event_listener_dt =
+			"qcom,disable-afe-wakeup-event-listener";
+
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv),
+			    GFP_KERNEL);
+	if (!tx_priv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, tx_priv);
+
+	tx_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &tx_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	dev_set_drvdata(&pdev->dev, tx_priv);
+	if (of_find_property(pdev->dev.of_node, is_used_tx_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_tx_swr_gpio_dt,
+					   &is_used_tx_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_tx_swr_gpio_dt);
+			is_used_tx_swr_gpio = 1;
+		}
+	}
+	tx_priv->tx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,tx-swr-gpios", 0);
+	if (!tx_priv->tx_swr_gpio_p && is_used_tx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(tx_priv->tx_swr_gpio_p) < 0 &&
+			is_used_tx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
+	tx_io_base = devm_ioremap(&pdev->dev,
+				   tx_base_addr, TX_MACRO_MAX_OFFSET);
+	if (!tx_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+	tx_priv->tx_io_base = tx_io_base;
+	ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
+				   &sample_rate);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: could not find sample_rate entry in dt\n",
+			__func__);
+		tx_priv->dmic_clk_div = TX_MACRO_CLK_DIV_2;
+	} else {
+		if (tx_macro_validate_dmic_sample_rate(
+		sample_rate, tx_priv) == TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
+			return -EINVAL;
+	}
+
+	if (of_find_property(pdev->dev.of_node,
+			     disable_afe_wakeup_event_listener_dt, NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   disable_afe_wakeup_event_listener_dt,
+					   &disable_afe_wakeup_event_listener);
+		if (ret)
+			dev_dbg(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, disable_afe_wakeup_event_listener_dt);
+	}
+	tx_priv->disable_afe_wakeup_event_listener =
+			disable_afe_wakeup_event_listener;
+
+	if (is_used_tx_swr_gpio) {
+		tx_priv->reset_swr = true;
+		INIT_WORK(&tx_priv->tx_macro_add_child_devices_work,
+			  tx_macro_add_child_devices);
+		tx_priv->swr_plat_data.handle = (void *) tx_priv;
+		tx_priv->swr_plat_data.read = NULL;
+		tx_priv->swr_plat_data.write = NULL;
+		tx_priv->swr_plat_data.bulk_write = NULL;
+		tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
+		tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
+		tx_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&tx_priv->swr_clk_lock);
+	}
+	tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio;
+	mutex_init(&tx_priv->mclk_lock);
+	tx_macro_init_ops(&ops, tx_io_base);
+	ops.clk_id_req = TX_CORE_CLK;
+	ops.default_clk_id = TX_CORE_CLK;
+	tx_priv->current_clk_id = TX_CORE_CLK;
+	ret = bolero_register_macro(&pdev->dev, TX_MACRO, &ops);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: register macro failed\n", __func__);
+		goto err_reg_macro;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	if (is_used_tx_swr_gpio)
+		schedule_work(&tx_priv->tx_macro_add_child_devices_work);
+
+	return 0;
+err_reg_macro:
+	mutex_destroy(&tx_priv->mclk_lock);
+	if (is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
+	return ret;
+}
+
+static int tx_macro_remove(struct platform_device *pdev)
+{
+	struct tx_macro_priv *tx_priv = NULL;
+	u16 count = 0;
+
+	tx_priv = platform_get_drvdata(pdev);
+
+	if (!tx_priv)
+		return -EINVAL;
+
+	if (tx_priv->is_used_tx_swr_gpio) {
+		if (tx_priv->swr_ctrl_data)
+			kfree(tx_priv->swr_ctrl_data);
+		for (count = 0; count < tx_priv->child_count &&
+			count < TX_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				tx_priv->pdev_child_devices[count]);
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	mutex_destroy(&tx_priv->mclk_lock);
+	if (tx_priv->is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
+	bolero_unregister_macro(&pdev->dev, TX_MACRO);
+	return 0;
+}
+
+
+static const struct of_device_id tx_macro_dt_match[] = {
+	{.compatible = "qcom,tx-macro"},
+	{}
+};
+
+static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		bolero_runtime_suspend,
+		bolero_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver tx_macro_driver = {
+	.driver = {
+		.name = "tx_macro",
+		.owner = THIS_MODULE,
+		.pm = &bolero_dev_pm_ops,
+		.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 v2");

+ 3324 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/va-macro.c

@@ -0,0 +1,3324 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/pm_runtime.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+#include "bolero-cdc.h"
+#include "bolero-cdc-registers.h"
+#include "bolero-clk-rsc.h"
+
+/* pm runtime auto suspend timer in msecs */
+#define VA_AUTO_SUSPEND_DELAY          100 /* delay in msec */
+#define VA_MACRO_MAX_OFFSET 0x1000
+
+#define VA_MACRO_NUM_DECIMATORS 8
+
+#define VA_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 VA_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define  TX_HPF_CUT_OFF_FREQ_MASK	0x60
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+#define VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define VA_MACRO_MCLK_FREQ 9600000
+#define VA_MACRO_TX_PATH_OFFSET 0x80
+#define VA_MACRO_TX_DMIC_CLK_DIV_MASK 0x0E
+#define VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01
+#define VA_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
+#define VA_MACRO_ADC_MUX_CFG_OFFSET 0x8
+#define VA_MACRO_ADC_MODE_CFG0_SHIFT 1
+
+#define BOLERO_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS       40
+#define BOLERO_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS       100
+#define BOLERO_CDC_VA_TX_DMIC_HPF_DELAY_MS       300
+#define BOLERO_CDC_VA_TX_AMIC_HPF_DELAY_MS       300
+#define MAX_RETRY_ATTEMPTS 500
+#define VA_MACRO_SWR_STRING_LEN 80
+#define VA_MACRO_CHILD_DEVICES_MAX 3
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static int va_tx_unmute_delay = BOLERO_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS;
+module_param(va_tx_unmute_delay, int, 0664);
+MODULE_PARM_DESC(va_tx_unmute_delay, "delay to unmute the tx path");
+
+static int va_macro_core_vote(void *handle, bool enable);
+
+enum {
+	VA_MACRO_AIF_INVALID = 0,
+	VA_MACRO_AIF1_CAP,
+	VA_MACRO_AIF2_CAP,
+	VA_MACRO_AIF3_CAP,
+	VA_MACRO_MAX_DAIS,
+};
+
+enum {
+	VA_MACRO_DEC0,
+	VA_MACRO_DEC1,
+	VA_MACRO_DEC2,
+	VA_MACRO_DEC3,
+	VA_MACRO_DEC4,
+	VA_MACRO_DEC5,
+	VA_MACRO_DEC6,
+	VA_MACRO_DEC7,
+	VA_MACRO_DEC_MAX,
+};
+
+enum {
+	VA_MACRO_CLK_DIV_2,
+	VA_MACRO_CLK_DIV_3,
+	VA_MACRO_CLK_DIV_4,
+	VA_MACRO_CLK_DIV_6,
+	VA_MACRO_CLK_DIV_8,
+	VA_MACRO_CLK_DIV_16,
+};
+
+enum {
+	MSM_DMIC,
+	SWR_MIC,
+};
+
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
+struct va_mute_work {
+	struct va_macro_priv *va_priv;
+	u32 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct va_macro_priv *va_priv;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+/* Hold instance to soundwire platform device */
+struct va_macro_swr_ctrl_data {
+	struct platform_device *va_swr_pdev;
+};
+
+struct va_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+struct va_macro_priv {
+	struct device *dev;
+	bool dec_active[VA_MACRO_NUM_DECIMATORS];
+	bool va_without_decimation;
+	struct clk *lpass_audio_hw_vote;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct snd_soc_component *component;
+	struct hpf_work va_hpf_work[VA_MACRO_NUM_DECIMATORS];
+	struct va_mute_work va_mute_dwork[VA_MACRO_NUM_DECIMATORS];
+	unsigned long active_ch_mask[VA_MACRO_MAX_DAIS];
+	u16 dmic_clk_div;
+	u16 va_mclk_users;
+	int swr_clk_users;
+	bool reset_swr;
+	struct device_node *va_swr_gpio_p;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data;
+	struct va_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct va_macro_add_child_devices_work;
+	int child_count;
+	u16 mclk_mux_sel;
+	char __iomem *va_io_base;
+	char __iomem *va_island_mode_muxsel;
+	struct platform_device *pdev_child_devices
+			[VA_MACRO_CHILD_DEVICES_MAX];
+	struct regulator *micb_supply;
+	u32 micb_voltage;
+	u32 micb_current;
+	u32 version;
+	u32 is_used_va_swr_gpio;
+	int micb_users;
+	u16 default_clk_id;
+	u16 clk_id;
+	int tx_swr_clk_cnt;
+	int va_swr_clk_cnt;
+	int va_clk_status;
+	int tx_clk_status;
+	int dapm_tx_clk_status;
+	bool lpi_enable;
+	bool register_event_listener;
+	bool clk_div_switch;
+	int dec_mode[VA_MACRO_NUM_DECIMATORS];
+	u16 current_clk_id;
+	int pcm_rate[VA_MACRO_NUM_DECIMATORS];
+	bool dev_up;
+};
+
+static bool va_macro_get_data(struct snd_soc_component *component,
+			      struct device **va_dev,
+			      struct va_macro_priv **va_priv,
+			      const char *func_name)
+{
+	*va_dev = bolero_get_device_ptr(component->dev, VA_MACRO);
+	if (!(*va_dev)) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+	*va_priv = dev_get_drvdata((*va_dev));
+	if (!(*va_priv) || !(*va_priv)->component) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+	return true;
+}
+
+static int va_macro_clk_div_get(struct snd_soc_component *component)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if ((va_priv->version >= BOLERO_VERSION_2_0)
+		&& va_priv->clk_div_switch
+		&& (va_priv->dmic_clk_div == VA_MACRO_CLK_DIV_16))
+		return VA_MACRO_CLK_DIV_8;
+
+	return va_priv->dmic_clk_div;
+}
+
+static int va_macro_mclk_enable(struct va_macro_priv *va_priv,
+				 bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(va_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, va_priv->va_mclk_users);
+
+	mutex_lock(&va_priv->mclk_lock);
+	if (mclk_enable) {
+		ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   va_priv->clk_id,
+						   true);
+		if (ret < 0) {
+			dev_err(va_priv->dev,
+				"%s: va request clock en failed\n",
+				__func__);
+			goto exit;
+		}
+		bolero_clk_rsc_fs_gen_request(va_priv->dev,
+					      true);
+		if (va_priv->va_mclk_users == 0) {
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					VA_START_OFFSET,
+					VA_MAX_OFFSET);
+		}
+		va_priv->va_mclk_users++;
+	} else {
+		if (va_priv->va_mclk_users <= 0) {
+			dev_err(va_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			va_priv->va_mclk_users = 0;
+			goto exit;
+		}
+		va_priv->va_mclk_users--;
+		bolero_clk_rsc_fs_gen_request(va_priv->dev,
+					  false);
+		bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					va_priv->clk_id,
+					false);
+	}
+exit:
+	mutex_unlock(&va_priv->mclk_lock);
+	return ret;
+}
+
+static int va_macro_event_handler(struct snd_soc_component *component,
+				  u16 event, u32 data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	int retry_cnt = MAX_RETRY_ATTEMPTS;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET:
+		while ((va_priv->va_mclk_users != 0) && (retry_cnt != 0)) {
+			dev_dbg_ratelimited(va_dev, "%s:retry_cnt: %d\n",
+				__func__, retry_cnt);
+			/*
+			 * Userspace takes 10 seconds to close
+			 * the session when pcm_start fails due to concurrency
+			 * with PDR/SSR. Loop and check every 20ms till 10
+			 * seconds for va_mclk user count to get reset to 0
+			 * which ensures userspace teardown is done and SSR
+			 * powerup seq can proceed.
+			 */
+			msleep(20);
+			retry_cnt--;
+		}
+		if (retry_cnt == 0)
+			dev_err(va_dev,
+				"%s: va_mclk_users is non-zero still, audio SSR fail!!\n",
+				__func__);
+		break;
+	case BOLERO_MACRO_EVT_PRE_SSR_UP:
+		/* enable&disable VA_CORE_CLK to reset GFMUX reg */
+		va_macro_core_vote(va_priv, true);
+		ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						va_priv->default_clk_id,
+						VA_CORE_CLK, true);
+		if (ret < 0)
+			dev_err_ratelimited(va_priv->dev,
+				"%s, failed to enable clk, ret:%d\n",
+				__func__, ret);
+		else
+			bolero_clk_rsc_request_clock(va_priv->dev,
+						va_priv->default_clk_id,
+						VA_CORE_CLK, false);
+		va_macro_core_vote(va_priv, false);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		/* reset swr after ssr/pdr */
+		va_priv->reset_swr = true;
+		va_priv->dev_up = true;
+		if (va_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(va_dev, VA_CORE_CLK);
+		break;
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		va_priv->dev_up = false;
+		if (va_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(va_dev) ||
+		     !pm_runtime_suspended(va_dev))) {
+			ret = bolero_runtime_suspend(va_dev);
+			if (!ret) {
+				pm_runtime_disable(va_dev);
+				pm_runtime_set_suspended(va_dev);
+				pm_runtime_enable(va_dev);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int va_macro_swr_clk_event_v2(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 device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		va_priv->va_swr_clk_cnt++;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		va_priv->va_swr_clk_cnt--;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
+		__func__, event, va_priv->lpi_enable);
+
+	if (!va_priv->lpi_enable)
+		return ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		dev_dbg(component->dev,
+			"%s: va_swr_clk_cnt %d, tx_swr_clk_cnt %d, tx_clk_status %d\n",
+			__func__, va_priv->va_swr_clk_cnt,
+			va_priv->tx_swr_clk_cnt, va_priv->tx_clk_status);
+		if (va_priv->current_clk_id == VA_CORE_CLK) {
+			return 0;
+		} else if ( va_priv->va_swr_clk_cnt != 0 &&
+				va_priv->tx_clk_status) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					true);
+			if (ret) {
+				dev_dbg(component->dev,
+					"%s: request clock VA_CLK enable failed\n",
+					__func__);
+				break;
+			}
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					TX_CORE_CLK,
+					false);
+			if (ret) {
+				dev_dbg(component->dev,
+					"%s: request clock TX_CLK enable failed\n",
+					__func__);
+				bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					false);
+				break;
+			}
+			va_priv->current_clk_id = VA_CORE_CLK;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (va_priv->current_clk_id == VA_CORE_CLK) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					TX_CORE_CLK,
+					true);
+			if (ret) {
+				dev_err(component->dev,
+					"%s: request clock TX_CLK enable failed\n",
+					__func__);
+				if (va_priv->dev_up)
+					break;
+			}
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					false);
+			if (ret) {
+				dev_err(component->dev,
+					"%s: request clock VA_CLK disable failed\n",
+					__func__);
+				if (va_priv->dev_up)
+					bolero_clk_rsc_request_clock(va_priv->dev,
+						TX_CORE_CLK,
+						TX_CORE_CLK,
+						false);
+				break;
+			}
+			va_priv->current_clk_id = TX_CORE_CLK;
+		}
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int va_macro_swr_pwr_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);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
+		__func__, event, va_priv->lpi_enable);
+
+	if (!va_priv->lpi_enable)
+		return ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (va_priv->lpass_audio_hw_vote) {
+			ret = digital_cdc_rsc_mgr_hw_vote_enable(
+					va_priv->lpass_audio_hw_vote, va_dev);
+			if (ret)
+				dev_err(va_dev,
+					"%s: lpass audio hw enable failed\n",
+					__func__);
+		}
+		if (!ret) {
+			if (bolero_tx_clk_switch(component, VA_CORE_CLK))
+				dev_dbg(va_dev, "%s: clock switch failed\n",
+					__func__);
+		}
+		if (va_priv->lpi_enable) {
+			bolero_register_event_listener(component, true);
+			va_priv->register_event_listener = true;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (va_priv->register_event_listener) {
+			va_priv->register_event_listener = false;
+			bolero_register_event_listener(component, false);
+		}
+		if (bolero_tx_clk_switch(component, TX_CORE_CLK))
+			dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
+		if (va_priv->lpass_audio_hw_vote)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+				va_priv->lpass_audio_hw_vote, va_dev);
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++va_priv->tx_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--va_priv->tx_swr_clk_cnt;
+
+	return 0;
+}
+
+static int va_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);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   true);
+		if (!ret)
+			va_priv->dapm_tx_clk_status++;
+
+		if (va_priv->lpi_enable)
+			ret = va_macro_mclk_enable(va_priv, 1, true);
+		else
+			ret = bolero_tx_mclk_enable(component, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (va_priv->lpi_enable) {
+			va_macro_mclk_enable(va_priv, 0, true);
+		} else {
+			bolero_tx_mclk_enable(component, 0);
+		}
+
+		if (va_priv->dapm_tx_clk_status > 0) {
+			bolero_clk_rsc_request_clock(va_priv->dev,
+					   va_priv->default_clk_id,
+					   TX_CORE_CLK,
+					   false);
+			va_priv->dapm_tx_clk_status--;
+		}
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,
+				      struct regmap *regmap, int clk_type,
+				      bool enable)
+{
+	int ret = 0, clk_tx_ret = 0;
+
+	dev_dbg(va_priv->dev,
+		"%s: clock type %s, enable: %s tx_mclk_users: %d\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"), va_priv->va_mclk_users);
+
+	if (enable) {
+		if (va_priv->swr_clk_users == 0) {
+			msm_cdc_pinctrl_select_active_state(
+						va_priv->va_swr_gpio_p);
+			msm_cdc_pinctrl_set_wakeup_capable(
+					va_priv->va_swr_gpio_p, false);
+		}
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		if (clk_type == TX_MCLK) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  true);
+		}
+		if (clk_type == VA_MCLK) {
+			ret = va_macro_mclk_enable(va_priv, 1, true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: request clock enable failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (va_priv->swr_clk_users == 0) {
+			dev_dbg(va_priv->dev, "%s: reset_swr: %d\n",
+				__func__, va_priv->reset_swr);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			va_priv->reset_swr = false;
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		va_priv->swr_clk_users++;
+	} else {
+		if (va_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"va swrm clock users already 0\n");
+			va_priv->swr_clk_users = 0;
+			return 0;
+		}
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		va_priv->swr_clk_users--;
+		if (va_priv->swr_clk_users == 0)
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+		if (clk_type == VA_MCLK)
+			va_macro_mclk_enable(va_priv, 0, true);
+		if (clk_type == TX_MCLK) {
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  false);
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
+			if (ret < 0) {
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		if (va_priv->swr_clk_users == 0) {
+			msm_cdc_pinctrl_set_wakeup_capable(
+					va_priv->va_swr_gpio_p, true);
+			msm_cdc_pinctrl_select_sleep_state(
+						va_priv->va_swr_gpio_p);
+		}
+	}
+	return 0;
+
+done:
+	if (!clk_tx_ret)
+		bolero_clk_rsc_request_clock(va_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+	return ret;
+}
+
+static int va_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct va_macro_priv *va_priv = (struct va_macro_priv *) handle;
+
+	if (va_priv == NULL) {
+		pr_err("%s: va priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (bolero_check_core_votes(va_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(va_priv->dev);
+		pm_runtime_mark_last_busy(va_priv->dev);
+	}
+	return rc;
+}
+
+static int va_macro_swrm_clock(void *handle, bool enable)
+{
+	struct va_macro_priv *va_priv = (struct va_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&va_priv->swr_clk_lock);
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		va_priv->tx_swr_clk_cnt, va_priv->va_swr_clk_cnt);
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (va_priv->va_swr_clk_cnt && !va_priv->tx_swr_clk_cnt) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(va_priv->dev);
+				pm_runtime_put_autosuspend(va_priv->dev);
+				goto done;
+			}
+			va_priv->va_clk_status++;
+		} else {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(va_priv->dev);
+				pm_runtime_put_autosuspend(va_priv->dev);
+				goto done;
+			}
+			va_priv->tx_clk_status++;
+		}
+		pm_runtime_mark_last_busy(va_priv->dev);
+		pm_runtime_put_autosuspend(va_priv->dev);
+	} else {
+		if (va_priv->va_clk_status && !va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->va_clk_status;
+		} else if (!va_priv->va_clk_status && va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->tx_clk_status;
+		} else if (va_priv->va_clk_status && va_priv->tx_clk_status) {
+			if (!va_priv->va_swr_clk_cnt && va_priv->tx_swr_clk_cnt) {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								VA_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->va_clk_status;
+			} else {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->tx_clk_status;
+			}
+
+		} else {
+			dev_dbg(va_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
+		}
+	}
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, va_priv->swr_clk_users, va_priv->tx_clk_status,
+		va_priv->va_clk_status);
+done:
+	mutex_unlock(&va_priv->swr_clk_lock);
+	return ret;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+	u16 adc_mux_reg = 0, adc_reg = 0;
+	u16 adc_n = BOLERO_ADC_MAX;
+	bool ret = false;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return ret;
+
+	adc_mux_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1 +
+			VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+		if (va_priv->version == BOLERO_VERSION_2_1)
+			return true;
+		adc_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
+			VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				VA_MACRO_SWR_MIC_MUX_SEL_MASK;
+		if (adc_n < BOLERO_ADC_MAX)
+			return true;
+	}
+
+	return ret;
+}
+
+static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct va_macro_priv *va_priv;
+	struct snd_soc_component *component;
+	u16 dec_cfg_reg, hpf_gate_reg;
+	u8 hpf_cut_off_freq;
+	u16 adc_reg = 0, adc_n = 0;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	va_priv = hpf_work->va_priv;
+	component = va_priv->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = BOLERO_CDC_VA_TX0_TX_PATH_CFG0 +
+			VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+	hpf_gate_reg = BOLERO_CDC_VA_TX0_TX_PATH_SEC2 +
+			VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+
+	dev_dbg(va_priv->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
+		__func__, hpf_work->decimator, hpf_cut_off_freq);
+
+	if (is_amic_enabled(component, hpf_work->decimator)) {
+		adc_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
+			VA_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				VA_MACRO_SWR_MIC_MUX_SEL_MASK;
+		/* analog mic clear TX hold */
+		bolero_clear_amic_tx_hold(component->dev, adc_n);
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x03, 0x02);
+		/* Add delay between toggle hpf gate based on sample rate */
+		switch (va_priv->pcm_rate[hpf_work->decimator]) {
+		case 0:
+			usleep_range(125, 130);
+			break;
+		case 1:
+			usleep_range(62, 65);
+			break;
+		case 3:
+			usleep_range(31, 32);
+			break;
+		case 4:
+			usleep_range(20, 21);
+			break;
+		case 5:
+			usleep_range(10, 11);
+			break;
+		case 6:
+			usleep_range(5, 6);
+			break;
+		default:
+			usleep_range(125, 130);
+		}
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x03, 0x01);
+	} else {
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x02, 0x02);
+		/* Minimum 1 clk cycle delay is required as per HW spec */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x02, 0x00);
+	}
+}
+
+static void va_macro_mute_update_callback(struct work_struct *work)
+{
+	struct va_mute_work *va_mute_dwork;
+	struct snd_soc_component *component = NULL;
+	struct va_macro_priv *va_priv;
+	struct delayed_work *delayed_work;
+	u16 tx_vol_ctl_reg, decimator;
+
+	delayed_work = to_delayed_work(work);
+	va_mute_dwork = container_of(delayed_work, struct va_mute_work, dwork);
+	va_priv = va_mute_dwork->va_priv;
+	component = va_priv->component;
+	decimator = va_mute_dwork->decimator;
+
+	tx_vol_ctl_reg =
+		BOLERO_CDC_VA_TX0_TX_PATH_CTL +
+			VA_MACRO_TX_PATH_OFFSET * decimator;
+	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
+	dev_dbg(va_priv->dev, "%s: decimator %u unmute\n",
+		__func__, decimator);
+}
+
+static int va_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;
+	u16 mic_sel_reg, dmic_clk_reg;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	switch (e->reg) {
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX0_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX1_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX2_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX3_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX4_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX5_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX6_TX_PATH_CFG0;
+		break;
+	case BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0:
+		mic_sel_reg = BOLERO_CDC_VA_TX7_TX_PATH_CFG0;
+		break;
+	default:
+		dev_err(component->dev, "%s: e->reg: 0x%x not expected\n",
+			__func__, e->reg);
+		return -EINVAL;
+	}
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
+		if (val != 0) {
+			if (val < 5) {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x0 << 7);
+			} else {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x1 << 7);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+				dmic_clk_reg =
+					BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL +
+						((val - 5)/2) * 4;
+				snd_soc_component_update_bits(component,
+					dmic_clk_reg,
+					0x0E, va_priv->dmic_clk_div << 0x1);
+			}
+		}
+	} else {
+		/* DMIC selected */
+		if (val != 0)
+			snd_soc_component_update_bits(component, mic_sel_reg,
+					1 << 7, 1 << 7);
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int va_macro_lpi_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = va_priv->lpi_enable;
+
+	return 0;
+}
+
+static int va_macro_lpi_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	va_priv->lpi_enable = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int va_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(dec_id, &va_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int va_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (enable)
+		set_bit(dec_id, &va_priv->active_ch_mask[dai_id]);
+	else
+		clear_bit(dec_id, &va_priv->active_ch_mask[dai_id]);
+
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+	return 0;
+}
+
+static int va_macro_enable_dmic(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 dmic = 0;
+	int ret = 0;
+	char *wname;
+
+	wname = strpbrk(w->name, "01234567");
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d\n",
+		__func__, event,  dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		bolero_dmic_clk_enable(component, dmic, DMIC_VA, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		bolero_dmic_clk_enable(component, dmic, DMIC_VA, false);
+		break;
+	}
+
+	return 0;
+}
+
+static int va_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;
+	u16 tx_gain_ctl_reg;
+	u8 hpf_cut_off_freq;
+	u16 adc_mux_reg = 0;
+	u16 tx_fs_reg = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	int hpf_delay = BOLERO_CDC_VA_TX_DMIC_HPF_DELAY_MS;
+	int unmute_delay = BOLERO_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	decimator = w->shift;
+
+	dev_dbg(va_dev, "%s(): widget = %s decimator = %u\n", __func__,
+		w->name, decimator);
+
+	tx_vol_ctl_reg = BOLERO_CDC_VA_TX0_TX_PATH_CTL +
+				VA_MACRO_TX_PATH_OFFSET * decimator;
+	hpf_gate_reg = BOLERO_CDC_VA_TX0_TX_PATH_SEC2 +
+				VA_MACRO_TX_PATH_OFFSET * decimator;
+	dec_cfg_reg = BOLERO_CDC_VA_TX0_TX_PATH_CFG0 +
+				VA_MACRO_TX_PATH_OFFSET * decimator;
+	tx_gain_ctl_reg = BOLERO_CDC_VA_TX0_TX_VOL_CTL +
+				VA_MACRO_TX_PATH_OFFSET * decimator;
+	adc_mux_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1 +
+				VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	tx_fs_reg = BOLERO_CDC_VA_TX0_TX_PATH_CTL +
+				VA_MACRO_TX_PATH_OFFSET * decimator;
+	va_priv->pcm_rate[decimator] = (snd_soc_component_read(component,
+				tx_fs_reg) & 0x0F);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, va_priv->dec_mode[decimator] <<
+			VA_MACRO_ADC_MODE_CFG0_SHIFT);
+		/* Enable TX PGA Mute */
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* Enable TX CLK */
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x20, 0x20);
+		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(
+					component, dec_cfg_reg) &
+				   TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+		va_priv->va_hpf_work[decimator].hpf_cut_off_freq =
+							hpf_cut_off_freq;
+
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					    TX_HPF_CUT_OFF_FREQ_MASK,
+					    CF_MIN_3DB_150HZ << 5);
+		}
+		if (is_amic_enabled(component, decimator) < BOLERO_ADC_MAX) {
+			hpf_delay = BOLERO_CDC_VA_TX_AMIC_HPF_DELAY_MS;
+			unmute_delay = BOLERO_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS;
+			if (va_tx_unmute_delay < unmute_delay)
+				va_tx_unmute_delay = unmute_delay;
+		}
+		snd_soc_component_update_bits(component,
+				hpf_gate_reg, 0x03, 0x02);
+		if (!is_amic_enabled(component, decimator))
+			snd_soc_component_update_bits(component,
+				hpf_gate_reg, 0x03, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+			hpf_gate_reg, 0x03, 0x01);
+		/*
+		 * 6ms delay is required as per HW spec
+		 */
+		usleep_range(6000, 6010);
+		/* schedule work queue to Remove Mute */
+		queue_delayed_work(system_freezable_wq,
+				   &va_priv->va_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(va_tx_unmute_delay));
+		if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq !=
+							CF_MIN_3DB_150HZ)
+			queue_delayed_work(system_freezable_wq,
+					&va_priv->va_hpf_work[decimator].dwork,
+					msecs_to_jiffies(hpf_delay));
+		/* 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 (va_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read(component, adc_mux_reg)
+							& SWR_MIC) {
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x01);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL,
+					0x0E, 0x00);
+			}
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			va_priv->va_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x10, 0x10);
+		if (cancel_delayed_work_sync(
+		    &va_priv->va_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_update_bits(component,
+						dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						hpf_cut_off_freq << 5);
+				if (is_amic_enabled(component, decimator))
+					snd_soc_component_update_bits(component,
+						hpf_gate_reg,
+						0x03, 0x02);
+				else
+					snd_soc_component_update_bits(component,
+						hpf_gate_reg,
+						0x03, 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,
+						0x03, 0x01);
+			}
+		}
+		cancel_delayed_work_sync(
+				&va_priv->va_mute_dwork[decimator].dwork);
+		if (va_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read(component, adc_mux_reg)
+							& SWR_MIC)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x00);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable TX CLK */
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x20, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+			0x40, 0x40);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+			0x40, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x10, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int va_macro_enable_tx(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 device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (va_priv->dapm_tx_clk_status > 0) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   false);
+			va_priv->dapm_tx_clk_status--;
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   true);
+		if (!ret)
+			va_priv->dapm_tx_clk_status++;
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int va_macro_enable_micbias(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 device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (!va_priv->micb_supply) {
+		dev_err(va_dev,
+			"%s:regulator not provided in dtsi\n", __func__);
+		return -EINVAL;
+	}
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (va_priv->micb_users++ > 0)
+			return 0;
+		ret = regulator_set_voltage(va_priv->micb_supply,
+				      va_priv->micb_voltage,
+				      va_priv->micb_voltage);
+		if (ret) {
+			dev_err(va_dev, "%s: Setting voltage failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = regulator_set_load(va_priv->micb_supply,
+					 va_priv->micb_current);
+		if (ret) {
+			dev_err(va_dev, "%s: Setting current failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = regulator_enable(va_priv->micb_supply);
+		if (ret) {
+			dev_err(va_dev, "%s: regulator enable failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (--va_priv->micb_users > 0)
+			return 0;
+		if (va_priv->micb_users < 0) {
+			va_priv->micb_users = 0;
+			dev_dbg(va_dev, "%s: regulator already disabled\n",
+				__func__);
+			return 0;
+		}
+		ret = regulator_disable(va_priv->micb_supply);
+		if (ret) {
+			dev_err(va_dev, "%s: regulator disable failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		regulator_set_voltage(va_priv->micb_supply, 0,
+				va_priv->micb_voltage);
+		regulator_set_load(va_priv->micb_supply, 0);
+		break;
+	}
+	return 0;
+}
+
+static inline int va_macro_path_get(const char *wname,
+				    unsigned int *path_num)
+{
+	int ret = 0;
+	char *widget_name = NULL;
+	char *w_name = NULL;
+	char *path_num_char = NULL;
+	char *path_name = NULL;
+
+	widget_name = kstrndup(wname, 10, GFP_KERNEL);
+	if (!widget_name)
+		return -EINVAL;
+
+	w_name = widget_name;
+
+	path_name = strsep(&widget_name, " ");
+	if (!path_name) {
+		pr_err("%s: Invalid widget name = %s\n",
+			__func__, widget_name);
+		ret = -EINVAL;
+		goto err;
+	}
+	path_num_char = strpbrk(path_name, "01234567");
+	if (!path_num_char) {
+		pr_err("%s: va path index not found\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = kstrtouint(path_num_char, 10, path_num);
+	if (ret < 0)
+		pr_err("%s: Invalid tx path = %s\n",
+			__func__, w_name);
+
+err:
+	kfree(w_name);
+	return ret;
+}
+
+static int va_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 va_macro_priv *priv = NULL;
+	struct device *va_dev = NULL;
+	int ret = 0;
+	int path = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &priv, __func__))
+		return -EINVAL;
+
+	ret = va_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	ucontrol->value.integer.value[0] = priv->dec_mode[path];
+
+	return 0;
+}
+
+static int va_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct va_macro_priv *priv = NULL;
+	struct device *va_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int ret = 0;
+	int path = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &priv, __func__))
+		return -EINVAL;
+
+	ret = va_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	priv->dec_mode[path] = value;
+
+	return 0;
+}
+
+static int va_macro_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	int tx_fs_rate = -EINVAL;
+	struct snd_soc_component *component = dai->component;
+	u32 decimator, sample_rate;
+	u16 tx_fs_reg = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		dai->name, dai->id, params_rate(params),
+		params_channels(params));
+
+	sample_rate = params_rate(params);
+	if (sample_rate > 16000)
+		va_priv->clk_div_switch = true;
+	else
+		va_priv->clk_div_switch = false;
+	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(va_dev, "%s: Invalid TX sample rate: %d\n",
+			__func__, params_rate(params));
+		return -EINVAL;
+	}
+	for_each_set_bit(decimator, &va_priv->active_ch_mask[dai->id],
+			 VA_MACRO_DEC_MAX) {
+		if (decimator >= 0) {
+			tx_fs_reg = BOLERO_CDC_VA_TX0_TX_PATH_CTL +
+				    VA_MACRO_TX_PATH_OFFSET * decimator;
+			dev_dbg(va_dev, "%s: set DEC%u rate to %u\n",
+				__func__, decimator, sample_rate);
+			snd_soc_component_update_bits(component, tx_fs_reg,
+						0x0F, tx_fs_rate);
+		} else {
+			dev_err(va_dev,
+				"%s: ERROR: Invalid decimator: %d\n",
+				__func__, decimator);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int va_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 device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	switch (dai->id) {
+	case VA_MACRO_AIF1_CAP:
+	case VA_MACRO_AIF2_CAP:
+	case VA_MACRO_AIF3_CAP:
+		*tx_slot = va_priv->active_ch_mask[dai->id];
+		*tx_num = hweight_long(va_priv->active_ch_mask[dai->id]);
+		break;
+	default:
+		dev_err(va_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static struct snd_soc_dai_ops va_macro_dai_ops = {
+	.hw_params = va_macro_hw_params,
+	.get_channel_map = va_macro_get_channel_map,
+};
+
+static struct snd_soc_dai_driver va_macro_dai[] = {
+	{
+		.name = "va_macro_tx1",
+		.id = VA_MACRO_AIF1_CAP,
+		.capture = {
+			.stream_name = "VA_AIF1 Capture",
+			.rates = VA_MACRO_RATES,
+			.formats = VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &va_macro_dai_ops,
+	},
+	{
+		.name = "va_macro_tx2",
+		.id = VA_MACRO_AIF2_CAP,
+		.capture = {
+			.stream_name = "VA_AIF2 Capture",
+			.rates = VA_MACRO_RATES,
+			.formats = VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &va_macro_dai_ops,
+	},
+	{
+		.name = "va_macro_tx3",
+		.id = VA_MACRO_AIF3_CAP,
+		.capture = {
+			.stream_name = "VA_AIF3 Capture",
+			.rates = VA_MACRO_RATES,
+			.formats = VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &va_macro_dai_ops,
+	},
+};
+
+#define STRING(name) #name
+#define VA_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define VA_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define VA_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+static const char * const adc_mux_text[] = {
+	"MSM_DMIC", "SWR_MIC"
+};
+
+VA_MACRO_DAPM_ENUM(va_dec0, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec1, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec2, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec4, BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec5, BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec6, BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG1,
+		   0, adc_mux_text);
+VA_MACRO_DAPM_ENUM(va_dec7, BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG1,
+		   0, adc_mux_text);
+
+static const char * const dmic_mux_text[] = {
+	"ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
+	"DMIC4", "DMIC5", "DMIC6", "DMIC7"
+};
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic0, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic1, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic2, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic4, BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic5, BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic6, BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_dmic7, BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_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"
+};
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic0, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic1, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic2, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic4, BOLERO_CDC_VA_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic5, BOLERO_CDC_VA_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic6, BOLERO_CDC_VA_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic7, BOLERO_CDC_VA_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic0_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic1_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic2_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic3_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_common[] = {
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0_v2),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1_v2),
+
+	SND_SOC_DAPM_INPUT("VA SWR_INPUT"),
+
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		va_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, VA_MACRO_DEC0, 0,
+			   &va_dec0_mux, va_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("VA DEC1 MUX", SND_SOC_NOPM, VA_MACRO_DEC1, 0,
+			   &va_dec1_mux, va_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("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v2, ARRAY_SIZE(va_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v2, ARRAY_SIZE(va_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v2, ARRAY_SIZE(va_aif3_cap_mixer_v2)),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", 0, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_tx_swr_clk_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_clk_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v3, ARRAY_SIZE(va_aif1_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v3, ARRAY_SIZE(va_aif2_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v3, ARRAY_SIZE(va_aif3_cap_mixer_v3)),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2_v3),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3_v3),
+
+	SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, VA_MACRO_DEC2, 0,
+			   &va_dec2_mux, va_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("VA DEC3 MUX", SND_SOC_NOPM, VA_MACRO_DEC3, 0,
+			   &va_dec3_mux, va_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("VA_SWR_PWR", 0, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer, ARRAY_SIZE(va_aif1_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer, ARRAY_SIZE(va_aif2_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer, ARRAY_SIZE(va_aif3_cap_mixer)),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX4", 0, va_dmic4),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX5", 0, va_dmic5),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX6", 0, va_dmic6),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX7", 0, va_dmic7),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX4", 0, va_smic4),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX5", 0, va_smic5),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX6", 0, va_smic6),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX7", 0, va_smic7),
+
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		va_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("VA SWR_ADC0"),
+	SND_SOC_DAPM_INPUT("VA SWR_ADC1"),
+	SND_SOC_DAPM_INPUT("VA SWR_ADC2"),
+	SND_SOC_DAPM_INPUT("VA SWR_ADC3"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC0"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC1"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC2"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC3"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC4"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC5"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC6"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC7"),
+
+	SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, VA_MACRO_DEC0, 0,
+			   &va_dec0_mux, va_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("VA DEC1 MUX", SND_SOC_NOPM, VA_MACRO_DEC1, 0,
+			   &va_dec1_mux, va_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("VA DEC2 MUX", SND_SOC_NOPM, VA_MACRO_DEC2, 0,
+			   &va_dec2_mux, va_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("VA DEC3 MUX", SND_SOC_NOPM, VA_MACRO_DEC3, 0,
+			   &va_dec3_mux, va_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("VA DEC4 MUX", SND_SOC_NOPM, VA_MACRO_DEC4, 0,
+			   &va_dec4_mux, va_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("VA DEC5 MUX", SND_SOC_NOPM, VA_MACRO_DEC5, 0,
+			   &va_dec5_mux, va_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("VA DEC6 MUX", SND_SOC_NOPM, VA_MACRO_DEC6, 0,
+			   &va_dec6_mux, va_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("VA DEC7 MUX", SND_SOC_NOPM, VA_MACRO_DEC7, 0,
+			   &va_dec7_mux, va_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("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = {
+	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route va_audio_map_common[] = {
+	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF3 CAP", NULL, "VA_MCLK"},
+
+	{"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"},
+	{"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"},
+	{"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"},
+
+	{"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"},
+	{"VA DMIC MUX0", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX0", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX0", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX0", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX0", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX0", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX0", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX0", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"},
+	{"VA SMIC MUX0", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"},
+	{"VA DMIC MUX1", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX1", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX1", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX1", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX1", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX1", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX1", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX1", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"},
+	{"VA SMIC MUX1", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA SWR_INPUT", NULL, "VA_SWR_PWR"},
+};
+
+static const struct snd_soc_dapm_route va_audio_map_v3[] = {
+	{"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"},
+	{"VA DMIC MUX2", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX2", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX2", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX2", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX2", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX2", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX2", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX2", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"},
+	{"VA SMIC MUX2", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"},
+	{"VA DMIC MUX3", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX3", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX3", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX3", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX3", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX3", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX3", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX3", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"},
+	{"VA SMIC MUX3", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"},
+};
+
+static const struct snd_soc_dapm_route va_audio_map_v2[] = {
+	{"VA SWR_INPUT", NULL, "VA_SWR_CLK"},
+};
+
+static const struct snd_soc_dapm_route va_audio_map[] = {
+	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF3 CAP", NULL, "VA_MCLK"},
+
+	{"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"},
+	{"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"},
+	{"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"},
+
+	{"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC4", "VA DEC4 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC5", "VA DEC5 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC6", "VA DEC6 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC7", "VA DEC7 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC4", "VA DEC4 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC5", "VA DEC5 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC6", "VA DEC6 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC7", "VA DEC7 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC4", "VA DEC4 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC5", "VA DEC5 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC6", "VA DEC6 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC7", "VA DEC7 MUX"},
+
+	{"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"},
+	{"VA DMIC MUX0", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX0", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX0", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX0", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX0", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX0", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX0", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX0", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"},
+	{"VA SMIC MUX0", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX0", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX0", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX0", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX0", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX0", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX0", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX0", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX0", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX0", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX0", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX0", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"},
+	{"VA DMIC MUX1", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX1", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX1", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX1", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX1", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX1", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX1", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX1", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"},
+	{"VA SMIC MUX1", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX1", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX1", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX1", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX1", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX1", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX1", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX1", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX1", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX1", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX1", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX1", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"},
+	{"VA DMIC MUX2", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX2", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX2", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX2", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX2", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX2", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX2", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX2", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"},
+	{"VA SMIC MUX2", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX2", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX2", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX2", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX2", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX2", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX2", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX2", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX2", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX2", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX2", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX2", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"},
+	{"VA DMIC MUX3", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX3", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX3", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX3", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX3", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX3", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX3", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX3", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"},
+	{"VA SMIC MUX3", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX3", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX3", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX3", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX3", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX3", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX3", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX3", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX3", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX3", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX3", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX3", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC4 MUX", "MSM_DMIC", "VA DMIC MUX4"},
+	{"VA DMIC MUX4", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX4", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX4", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX4", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX4", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX4", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX4", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX4", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC4 MUX", "SWR_MIC", "VA SMIC MUX4"},
+	{"VA SMIC MUX4", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX4", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX4", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX4", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX4", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX4", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX4", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX4", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX4", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX4", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX4", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX4", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC5 MUX", "MSM_DMIC", "VA DMIC MUX5"},
+	{"VA DMIC MUX5", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX5", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX5", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX5", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX5", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX5", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX5", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX5", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC5 MUX", "SWR_MIC", "VA SMIC MUX5"},
+	{"VA SMIC MUX5", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX5", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX5", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX5", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX5", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX5", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX5", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX5", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX5", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX5", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX5", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX5", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC6 MUX", "MSM_DMIC", "VA DMIC MUX6"},
+	{"VA DMIC MUX6", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX6", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX6", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX6", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX6", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX6", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX6", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX6", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC6 MUX", "SWR_MIC", "VA SMIC MUX6"},
+	{"VA SMIC MUX6", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX6", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX6", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX6", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX6", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX6", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX6", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX6", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX6", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX6", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX6", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX6", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA DEC7 MUX", "MSM_DMIC", "VA DMIC MUX7"},
+	{"VA DMIC MUX7", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX7", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX7", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX7", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX7", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX7", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX7", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX7", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC7 MUX", "SWR_MIC", "VA SMIC MUX7"},
+	{"VA SMIC MUX7", "ADC0", "VA SWR_ADC0"},
+	{"VA SMIC MUX7", "ADC1", "VA SWR_ADC1"},
+	{"VA SMIC MUX7", "ADC2", "VA SWR_ADC2"},
+	{"VA SMIC MUX7", "ADC3", "VA SWR_ADC3"},
+	{"VA SMIC MUX7", "SWR_DMIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX7", "SWR_DMIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX7", "SWR_DMIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX7", "SWR_DMIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX7", "SWR_DMIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX7", "SWR_DMIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"},
+
+	{"VA SWR_ADC0", NULL, "VA_SWR_PWR"},
+	{"VA SWR_ADC1", NULL, "VA_SWR_PWR"},
+	{"VA SWR_ADC2", NULL, "VA_SWR_PWR"},
+	{"VA SWR_ADC3", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC0", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC1", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC2", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC3", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC4", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC5", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC6", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC7", NULL, "VA_SWR_PWR"},
+};
+
+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_EXT(ARRAY_SIZE(dec_mode_mux_text),
+			    dec_mode_mux_text);
+
+static const struct snd_kcontrol_new va_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("VA_DEC0 Volume",
+			  BOLERO_CDC_VA_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC1 Volume",
+			  BOLERO_CDC_VA_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC2 Volume",
+			  BOLERO_CDC_VA_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC3 Volume",
+			  BOLERO_CDC_VA_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC4 Volume",
+			  BOLERO_CDC_VA_TX4_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC5 Volume",
+			  BOLERO_CDC_VA_TX5_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC6 Volume",
+			  BOLERO_CDC_VA_TX6_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC7 Volume",
+			  BOLERO_CDC_VA_TX7_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
+		va_macro_lpi_get, va_macro_lpi_put),
+
+	SOC_ENUM_EXT("VA_DEC0 MODE", dec_mode_mux_enum,
+			va_macro_dec_mode_get, va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC1 MODE", dec_mode_mux_enum,
+			va_macro_dec_mode_get, va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC2 MODE", dec_mode_mux_enum,
+			va_macro_dec_mode_get, va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC3 MODE", dec_mode_mux_enum,
+			va_macro_dec_mode_get, va_macro_dec_mode_put),
+};
+
+static const struct snd_kcontrol_new va_macro_snd_controls_common[] = {
+	SOC_SINGLE_S8_TLV("VA_DEC0 Volume",
+			  BOLERO_CDC_VA_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC1 Volume",
+			  BOLERO_CDC_VA_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
+		va_macro_lpi_get, va_macro_lpi_put),
+};
+
+static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = {
+	SOC_SINGLE_S8_TLV("VA_DEC2 Volume",
+			  BOLERO_CDC_VA_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC3 Volume",
+			  BOLERO_CDC_VA_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+};
+
+static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
+				      struct va_macro_priv *va_priv)
+{
+	u32 div_factor;
+	u32 mclk_rate = VA_MACRO_MCLK_FREQ;
+
+	if (dmic_sample_rate == VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
+	    mclk_rate % dmic_sample_rate != 0)
+		goto undefined_rate;
+
+	div_factor = mclk_rate / dmic_sample_rate;
+
+	switch (div_factor) {
+	case 2:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_2;
+		break;
+	case 3:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_3;
+		break;
+	case 4:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_4;
+		break;
+	case 6:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_6;
+		break;
+	case 8:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_8;
+		break;
+	case 16:
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_16;
+		break;
+	default:
+		/* Any other DIV factor is invalid */
+		goto undefined_rate;
+	}
+
+	/* Valid dmic DIV factors */
+	dev_dbg(va_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+		__func__, div_factor, mclk_rate);
+
+	return dmic_sample_rate;
+
+undefined_rate:
+	dev_dbg(va_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
+		 __func__, dmic_sample_rate, mclk_rate);
+	dmic_sample_rate = VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
+
+	return dmic_sample_rate;
+}
+
+static int va_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret, i;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	va_dev = bolero_get_device_ptr(component->dev, VA_MACRO);
+	if (!va_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	va_priv = dev_get_drvdata(va_dev);
+	if (!va_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	va_priv->lpi_enable = false;
+	va_priv->register_event_listener = false;
+
+	if (va_priv->va_without_decimation) {
+		ret = snd_soc_dapm_new_controls(dapm, va_macro_wod_dapm_widgets,
+					ARRAY_SIZE(va_macro_wod_dapm_widgets));
+		if (ret < 0) {
+			dev_err(va_dev,
+				"%s: Failed to add without dec controls\n",
+				__func__);
+			return ret;
+		}
+		va_priv->component = component;
+		return 0;
+	}
+
+	va_priv->version = bolero_get_version(va_dev);
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_common,
+				ARRAY_SIZE(va_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if ((va_priv->version == BOLERO_VERSION_2_1) ||
+		    (va_priv->version == BOLERO_VERSION_2_2))
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v2,
+				ARRAY_SIZE(va_macro_dapm_widgets_v2));
+		else if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v3,
+				ARRAY_SIZE(va_macro_dapm_widgets_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, va_macro_dapm_widgets,
+					ARRAY_SIZE(va_macro_dapm_widgets));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_common,
+					ARRAY_SIZE(va_audio_map_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0) {
+			ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_v3,
+					ARRAY_SIZE(va_audio_map_v3));
+			if (ret < 0) {
+				dev_err(va_dev, "%s: Failed to add routes\n",
+					__func__);
+				return ret;
+			}
+		}
+		if ((va_priv->version == BOLERO_VERSION_2_1) ||
+		    (va_priv->version == BOLERO_VERSION_2_2)) {
+			ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_v2,
+					ARRAY_SIZE(va_audio_map_v2));
+			if (ret < 0) {
+				dev_err(va_dev, "%s: Failed to add routes\n",
+					__func__);
+				return ret;
+			}
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
+					ARRAY_SIZE(va_audio_map));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(va_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls_common,
+				ARRAY_SIZE(va_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+					va_macro_snd_controls_v3,
+					ARRAY_SIZE(va_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls,
+				ARRAY_SIZE(va_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF1 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF2 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF3 Capture");
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_INPUT");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+	}
+	snd_soc_dapm_sync(dapm);
+
+	va_priv->dev_up = true;
+
+	for (i = 0; i < VA_MACRO_NUM_DECIMATORS; i++) {
+		va_priv->va_hpf_work[i].va_priv = va_priv;
+		va_priv->va_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&va_priv->va_hpf_work[i].dwork,
+			va_macro_tx_hpf_corner_freq_callback);
+	}
+
+	for (i = 0; i < VA_MACRO_NUM_DECIMATORS; i++) {
+		va_priv->va_mute_dwork[i].va_priv = va_priv;
+		va_priv->va_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&va_priv->va_mute_dwork[i].dwork,
+			  va_macro_mute_update_callback);
+	}
+	va_priv->component = component;
+
+	if ((va_priv->version == BOLERO_VERSION_2_1) ||
+	    (va_priv->version == BOLERO_VERSION_2_2)) {
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE, 0xCC);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE, 0xCC);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE, 0xCC);
+	}
+
+	return 0;
+}
+
+static int va_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	va_priv->component = NULL;
+	return 0;
+}
+
+static void va_macro_add_child_devices(struct work_struct *work)
+{
+	struct va_macro_priv *va_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct va_macro_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[VA_MACRO_SWR_STRING_LEN] = "";
+	bool va_swr_master_node = false;
+
+	va_priv = container_of(work, struct va_macro_priv,
+			     va_macro_add_child_devices_work);
+	if (!va_priv) {
+		pr_err("%s: Memory for va_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!va_priv->dev) {
+		pr_err("%s: VA dev does not exist\n", __func__);
+		return;
+	}
+
+	if (!va_priv->dev->of_node) {
+		dev_err(va_priv->dev,
+			"%s: DT node for va_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &va_priv->swr_plat_data;
+	va_priv->child_count = 0;
+
+	for_each_available_child_of_node(va_priv->dev->of_node, node) {
+		va_swr_master_node = false;
+		if (strnstr(node->name, "va_swr_master",
+                                strlen("va_swr_master")) != NULL)
+			va_swr_master_node = true;
+
+		if (va_swr_master_node)
+			strlcpy(plat_dev_name, "va_swr_ctrl",
+				(VA_MACRO_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(VA_MACRO_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(va_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = va_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (va_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct va_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].va_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			va_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (va_priv->child_count < VA_MACRO_CHILD_DEVICES_MAX)
+			va_priv->pdev_child_devices[
+					va_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < va_priv->child_count; count++)
+		platform_device_put(va_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int va_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int va_macro_reg_wake_irq(struct snd_soc_component *component,
+				 u32 data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	u32 ipc_wakeup = data;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+
+	return ret;
+}
+
+static void va_macro_init_ops(struct macro_ops *ops,
+			      char __iomem *va_io_base,
+			      bool va_without_decimation)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	if (!va_without_decimation) {
+		ops->dai_ptr = va_macro_dai;
+		ops->num_dais = ARRAY_SIZE(va_macro_dai);
+	} else {
+		ops->dai_ptr = NULL;
+		ops->num_dais = 0;
+	}
+	ops->init = va_macro_init;
+	ops->exit = va_macro_deinit;
+	ops->io_base = va_io_base;
+	ops->event_handler = va_macro_event_handler;
+	ops->set_port_map = va_macro_set_port_map;
+	ops->reg_wake_irq = va_macro_reg_wake_irq;
+	ops->clk_div_get = va_macro_clk_div_get;
+}
+
+static int va_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops;
+	struct va_macro_priv *va_priv;
+	u32 va_base_addr, sample_rate = 0;
+	char __iomem *va_io_base;
+	bool va_without_decimation = false;
+	const char *micb_supply_str = "va-vdd-micb-supply";
+	const char *micb_supply_str1 = "va-vdd-micb";
+	const char *micb_voltage_str = "qcom,va-vdd-micb-voltage";
+	const char *micb_current_str = "qcom,va-vdd-micb-current";
+	int ret = 0;
+	const char *dmic_sample_rate = "qcom,va-dmic-sample-rate";
+	u32 default_clk_id = 0;
+	struct clk *lpass_audio_hw_vote = NULL;
+	u32 is_used_va_swr_gpio = 0;
+	const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv),
+			    GFP_KERNEL);
+	if (!va_priv)
+		return -ENOMEM;
+
+	va_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &va_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	va_without_decimation = of_property_read_bool(pdev->dev.parent->of_node,
+					"qcom,va-without-decimation");
+
+	va_priv->va_without_decimation = va_without_decimation;
+	ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
+				   &sample_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %d entry in dt\n",
+			__func__, sample_rate);
+		va_priv->dmic_clk_div = VA_MACRO_CLK_DIV_2;
+	} else {
+		if (va_macro_validate_dmic_sample_rate(
+		sample_rate, va_priv) == VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
+			return -EINVAL;
+	}
+
+	if (of_find_property(pdev->dev.of_node, is_used_va_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_va_swr_gpio_dt,
+					   &is_used_va_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_va_swr_gpio_dt);
+			is_used_va_swr_gpio = 0;
+		}
+	}
+
+	va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,va-swr-gpios", 0);
+	if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if ((msm_cdc_pinctrl_get_state(va_priv->va_swr_gpio_p) < 0) &&
+		is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
+	va_io_base = devm_ioremap(&pdev->dev, va_base_addr,
+				  VA_MACRO_MAX_OFFSET);
+	if (!va_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -EINVAL;
+	}
+	va_priv->va_io_base = va_io_base;
+
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	va_priv->lpass_audio_hw_vote = lpass_audio_hw_vote;
+
+	if (of_parse_phandle(pdev->dev.of_node, micb_supply_str, 0)) {
+		va_priv->micb_supply = devm_regulator_get(&pdev->dev,
+						micb_supply_str1);
+		if (IS_ERR(va_priv->micb_supply)) {
+			ret = PTR_ERR(va_priv->micb_supply);
+			dev_err(&pdev->dev,
+				"%s:Failed to get micbias supply for VA Mic %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					micb_voltage_str,
+					&va_priv->micb_voltage);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s:Looking up %s property in node %s failed\n",
+				__func__, micb_voltage_str,
+				pdev->dev.of_node->full_name);
+			return ret;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					micb_current_str,
+					&va_priv->micb_current);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s:Looking up %s property in node %s failed\n",
+				__func__, micb_current_str,
+				pdev->dev.of_node->full_name);
+			return ret;
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,default-clk-id");
+		default_clk_id = VA_CORE_CLK;
+	}
+	va_priv->clk_id = VA_CORE_CLK;
+	va_priv->default_clk_id = default_clk_id;
+	va_priv->current_clk_id = TX_CORE_CLK;
+
+	if (is_used_va_swr_gpio) {
+		va_priv->reset_swr = true;
+		INIT_WORK(&va_priv->va_macro_add_child_devices_work,
+			  va_macro_add_child_devices);
+		va_priv->swr_plat_data.handle = (void *) va_priv;
+		va_priv->swr_plat_data.read = NULL;
+		va_priv->swr_plat_data.write = NULL;
+		va_priv->swr_plat_data.bulk_write = NULL;
+		va_priv->swr_plat_data.clk = va_macro_swrm_clock;
+		va_priv->swr_plat_data.core_vote = va_macro_core_vote;
+		va_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&va_priv->swr_clk_lock);
+	}
+	va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
+
+	mutex_init(&va_priv->mclk_lock);
+	dev_set_drvdata(&pdev->dev, va_priv);
+	va_macro_init_ops(&ops, va_io_base, va_without_decimation);
+	ops.clk_id_req = va_priv->default_clk_id;
+	ops.default_clk_id = va_priv->default_clk_id;
+	ret = bolero_register_macro(&pdev->dev, VA_MACRO, &ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
+		goto reg_macro_fail;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	if (is_used_va_swr_gpio)
+		schedule_work(&va_priv->va_macro_add_child_devices_work);
+	return ret;
+
+reg_macro_fail:
+	mutex_destroy(&va_priv->mclk_lock);
+	if (is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
+	return ret;
+}
+
+static int va_macro_remove(struct platform_device *pdev)
+{
+	struct va_macro_priv *va_priv;
+	int count = 0;
+
+	va_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!va_priv)
+		return -EINVAL;
+	if (va_priv->is_used_va_swr_gpio) {
+		if (va_priv->swr_ctrl_data)
+			kfree(va_priv->swr_ctrl_data);
+		for (count = 0; count < va_priv->child_count &&
+			count < VA_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				va_priv->pdev_child_devices[count]);
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	bolero_unregister_macro(&pdev->dev, VA_MACRO);
+	mutex_destroy(&va_priv->mclk_lock);
+	if (va_priv->is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
+	return 0;
+}
+
+
+static const struct of_device_id va_macro_dt_match[] = {
+	{.compatible = "qcom,va-macro"},
+	{}
+};
+
+static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		bolero_runtime_suspend,
+		bolero_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver va_macro_driver = {
+	.driver = {
+		.name = "va_macro",
+		.owner = THIS_MODULE,
+		.pm = &bolero_dev_pm_ops,
+		.of_match_table = va_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = va_macro_probe,
+	.remove = va_macro_remove,
+};
+
+module_platform_driver(va_macro_driver);
+
+MODULE_DESCRIPTION("VA macro driver");
+MODULE_LICENSE("GPL v2");

+ 3362 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/wsa-macro.c

@@ -0,0 +1,3362 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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 <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+
+#include <asoc/msm-cdc-pinctrl.h>
+#include "bolero-cdc.h"
+#include "bolero-cdc-registers.h"
+#include "wsa-macro.h"
+#include "bolero-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define WSA_MACRO_MAX_OFFSET 0x1000
+
+#define WSA_MACRO_RX_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 WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_48000)
+#define WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define NUM_INTERPOLATORS 2
+
+#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
+#define WSA_MACRO_RX_COMP_OFFSET 0x40
+#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
+#define WSA_MACRO_RX_PATH_OFFSET 0x80
+#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
+#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
+#define WSA_MACRO_FS_RATE_MASK 0x0F
+#define WSA_MACRO_EC_MIX_TX0_MASK 0x03
+#define WSA_MACRO_EC_MIX_TX1_MASK 0x18
+
+#define WSA_MACRO_MAX_DMA_CH_PER_PORT 0x2
+
+enum {
+	WSA_MACRO_RX0 = 0,
+	WSA_MACRO_RX1,
+	WSA_MACRO_RX_MIX,
+	WSA_MACRO_RX_MIX0 = WSA_MACRO_RX_MIX,
+	WSA_MACRO_RX_MIX1,
+	WSA_MACRO_RX_MAX,
+};
+
+enum {
+	WSA_MACRO_TX0 = 0,
+	WSA_MACRO_TX1,
+	WSA_MACRO_TX_MAX,
+};
+
+enum {
+	WSA_MACRO_EC0_MUX = 0,
+	WSA_MACRO_EC1_MUX,
+	WSA_MACRO_EC_MUX_MAX,
+};
+
+enum {
+	WSA_MACRO_COMP1, /* SPK_L */
+	WSA_MACRO_COMP2, /* SPK_R */
+	WSA_MACRO_COMP_MAX
+};
+
+enum {
+	WSA_MACRO_SOFTCLIP0, /* RX0 */
+	WSA_MACRO_SOFTCLIP1, /* RX1 */
+	WSA_MACRO_SOFTCLIP_MAX
+};
+
+enum {
+	INTn_1_INP_SEL_ZERO = 0,
+	INTn_1_INP_SEL_RX0,
+	INTn_1_INP_SEL_RX1,
+	INTn_1_INP_SEL_RX2,
+	INTn_1_INP_SEL_RX3,
+	INTn_1_INP_SEL_DEC0,
+	INTn_1_INP_SEL_DEC1,
+};
+
+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,
+};
+
+struct interp_sample_rate {
+	int sample_rate;
+	int rate_val;
+};
+
+/*
+ * Structure used to update codec
+ * register defaults after reset
+ */
+struct wsa_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static struct interp_sample_rate int_prim_sample_rate_val[] = {
+	{8000, 0x0},	/* 8K */
+	{16000, 0x1},	/* 16K */
+	{24000, -EINVAL},/* 24K */
+	{32000, 0x3},	/* 32K */
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+	{384000, 0x7},	/* 384K */
+	{44100, 0x8}, /* 44.1K */
+};
+
+static struct interp_sample_rate int_mix_sample_rate_val[] = {
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+};
+
+#define WSA_MACRO_SWR_STRING_LEN 80
+
+static int wsa_macro_core_vote(void *handle, bool enable);
+static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+static int wsa_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);
+static int wsa_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
+/* Hold instance to soundwire platform device */
+struct wsa_macro_swr_ctrl_data {
+	struct platform_device *wsa_swr_pdev;
+};
+
+struct wsa_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+struct wsa_macro_bcl_pmic_params {
+	u8 id;
+	u8 sid;
+	u8 ppid;
+};
+
+enum {
+	WSA_MACRO_AIF_INVALID = 0,
+	WSA_MACRO_AIF1_PB,
+	WSA_MACRO_AIF_MIX1_PB,
+	WSA_MACRO_AIF_VI,
+	WSA_MACRO_AIF_ECHO,
+	WSA_MACRO_MAX_DAIS,
+};
+
+#define WSA_MACRO_CHILD_DEVICES_MAX 3
+
+/*
+ * @dev: wsa macro device pointer
+ * @comp_enabled: compander enable mixer value set
+ * @ec_hq: echo HQ enable mixer value set
+ * @prim_int_users: Users of interpolator
+ * @wsa_mclk_users: WSA MCLK users count
+ * @swr_clk_users: SWR clk users count
+ * @vi_feed_value: VI sense mask
+ * @mclk_lock: to lock mclk operations
+ * @swr_clk_lock: to lock swr master clock operations
+ * @swr_ctrl_data: SoundWire data structure
+ * @swr_plat_data: Soundwire platform data
+ * @wsa_macro_add_child_devices_work: work for adding child devices
+ * @wsa_swr_gpio_p: used by pinctrl API
+ * @component: codec handle
+ * @rx_0_count: RX0 interpolation users
+ * @rx_1_count: RX1 interpolation users
+ * @active_ch_mask: channel mask for all AIF DAIs
+ * @rx_port_value: mixer ctl value of WSA RX MUXes
+ * @wsa_io_base: Base address of WSA macro addr space
+ */
+struct wsa_macro_priv {
+	struct device *dev;
+	int comp_enabled[WSA_MACRO_COMP_MAX];
+	int ec_hq[WSA_MACRO_RX1 + 1];
+	u16 prim_int_users[WSA_MACRO_RX1 + 1];
+	u16 wsa_mclk_users;
+	u16 swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	unsigned int vi_feed_value;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct wsa_macro_swr_ctrl_data *swr_ctrl_data;
+	struct wsa_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct wsa_macro_add_child_devices_work;
+	struct device_node *wsa_swr_gpio_p;
+	struct snd_soc_component *component;
+	int rx_0_count;
+	int rx_1_count;
+	unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS];
+	int rx_port_value[WSA_MACRO_RX_MAX];
+	char __iomem *wsa_io_base;
+	struct platform_device *pdev_child_devices
+			[WSA_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int ear_spkr_gain;
+	int wsa_spkrrecv;
+	int spkr_gain_offset;
+	int spkr_mode;
+	int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
+	int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
+	struct wsa_macro_bcl_pmic_params bcl_pmic_params;
+	char __iomem *mclk_mode_muxsel;
+	u16 default_clk_id;
+	u32 pcm_rate_vi;
+	int wsa_digital_mute_status[WSA_MACRO_RX_MAX];
+};
+
+static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
+					struct wsa_macro_priv *wsa_priv,
+					int event, int gain_reg);
+static struct snd_soc_dai_driver wsa_macro_dai[];
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+static const char *const rx_text[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1"
+};
+
+static const char *const rx_mix_text[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1"
+};
+
+static const char *const rx_mix_ec_text[] = {
+	"ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
+};
+
+static const char *const rx_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF_MIX1_PB"
+};
+
+static const char *const rx_sidetone_mix_text[] = {
+	"ZERO", "SRC0"
+};
+
+static const char * const wsa_macro_ear_spkr_pa_gain_text[] = {
+	"G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
+	"G_4_DB", "G_5_DB", "G_6_DB"
+};
+
+static const char * const wsa_macro_speaker_boost_stage_text[] = {
+	"NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
+};
+
+static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
+	"OFF", "ON"
+};
+
+static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const char *const wsa_macro_ear_spkrrecv_text[] = {
+	"OFF", "ON"
+};
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkrrecv_enum,
+				wsa_macro_ear_spkrrecv_text);
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
+				wsa_macro_ear_spkr_pa_gain_text);
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
+			wsa_macro_speaker_boost_stage_text);
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
+			wsa_macro_vbat_bcl_gsm_mode_text);
+
+/* RX INT0 */
+static const struct soc_enum rx0_prim_inp0_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		0, 7, rx_text);
+
+static const struct soc_enum rx0_prim_inp1_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		3, 7, rx_text);
+
+static const struct soc_enum rx0_prim_inp2_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		3, 7, rx_text);
+
+static const struct soc_enum rx0_mix_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		0, 5, rx_mix_text);
+
+static const struct soc_enum rx0_sidetone_mix_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
+
+static const struct snd_kcontrol_new rx0_prim_inp0_mux =
+	SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx0_prim_inp1_mux =
+	SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx0_prim_inp2_mux =
+	SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx0_mix_mux =
+	SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum);
+
+static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
+	SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
+
+/* RX INT1 */
+static const struct soc_enum rx1_prim_inp0_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		0, 7, rx_text);
+
+static const struct soc_enum rx1_prim_inp1_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		3, 7, rx_text);
+
+static const struct soc_enum rx1_prim_inp2_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		3, 7, rx_text);
+
+static const struct soc_enum rx1_mix_chain_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		0, 5, rx_mix_text);
+
+static const struct snd_kcontrol_new rx1_prim_inp0_mux =
+	SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx1_prim_inp1_mux =
+	SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx1_prim_inp2_mux =
+	SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix_mux =
+	SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum);
+
+static const struct soc_enum rx_mix_ec0_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		0, 3, rx_mix_ec_text);
+
+static const struct soc_enum rx_mix_ec1_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		3, 3, rx_mix_ec_text);
+
+static const struct snd_kcontrol_new rx_mix_ec0_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
+
+static const struct snd_kcontrol_new rx_mix_ec1_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
+
+static struct snd_soc_dai_ops wsa_macro_dai_ops = {
+	.hw_params = wsa_macro_hw_params,
+	.get_channel_map = wsa_macro_get_channel_map,
+	.mute_stream = wsa_macro_mute_stream,
+};
+
+static struct snd_soc_dai_driver wsa_macro_dai[] = {
+	{
+		.name = "wsa_macro_rx1",
+		.id = WSA_MACRO_AIF1_PB,
+		.playback = {
+			.stream_name = "WSA_AIF1 Playback",
+			.rates = WSA_MACRO_RX_RATES,
+			.formats = WSA_MACRO_RX_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_rx_mix",
+		.id = WSA_MACRO_AIF_MIX1_PB,
+		.playback = {
+			.stream_name = "WSA_AIF_MIX1 Playback",
+			.rates = WSA_MACRO_RX_MIX_RATES,
+			.formats = WSA_MACRO_RX_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_vifeedback",
+		.id = WSA_MACRO_AIF_VI,
+		.capture = {
+			.stream_name = "WSA_AIF_VI Capture",
+			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
+			.formats = WSA_MACRO_RX_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_echo",
+		.id = WSA_MACRO_AIF_ECHO,
+		.capture = {
+			.stream_name = "WSA_AIF_ECHO Capture",
+			.rates = WSA_MACRO_ECHO_RATES,
+			.formats = WSA_MACRO_ECHO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &wsa_macro_dai_ops,
+	},
+};
+
+static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
+	{BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
+	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
+	{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58},
+	{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58},
+};
+
+static const struct wsa_macro_reg_mask_val wsa_macro_spkr_mode1[] = {
+	{BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00},
+	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00},
+	{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44},
+	{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44},
+};
+
+static bool wsa_macro_get_data(struct snd_soc_component *component,
+			       struct device **wsa_dev,
+			       struct wsa_macro_priv **wsa_priv,
+			       const char *func_name)
+{
+	*wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
+	if (!(*wsa_dev)) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+	*wsa_priv = dev_get_drvdata((*wsa_dev));
+	if (!(*wsa_priv) || !(*wsa_priv)->component) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+	return true;
+}
+
+static int wsa_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (wsa_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+/**
+ * wsa_macro_set_spkr_gain_offset - offset the speaker path
+ * gain with the given offset value.
+ *
+ * @component: codec instance
+ * @offset: Indicates speaker path gain offset value.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component,
+				   int offset)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: NULL component pointer!\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->spkr_gain_offset = offset;
+	return 0;
+}
+EXPORT_SYMBOL(wsa_macro_set_spkr_gain_offset);
+
+/**
+ * wsa_macro_set_spkr_mode - Configures speaker compander and smartboost
+ * settings based on speaker mode.
+ *
+ * @component: codec instance
+ * @mode: Indicates speaker configuration mode.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode)
+{
+	int i;
+	const struct wsa_macro_reg_mask_val *regs;
+	int size;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: NULL codec pointer!\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (mode) {
+	case WSA_MACRO_SPKR_MODE_1:
+		regs = wsa_macro_spkr_mode1;
+		size = ARRAY_SIZE(wsa_macro_spkr_mode1);
+		break;
+	default:
+		regs = wsa_macro_spkr_default;
+		size = ARRAY_SIZE(wsa_macro_spkr_default);
+		break;
+	}
+
+	wsa_priv->spkr_mode = mode;
+	for (i = 0; i < size; i++)
+		snd_soc_component_update_bits(component, regs[i].reg,
+				    regs[i].mask, regs[i].val);
+	return 0;
+}
+EXPORT_SYMBOL(wsa_macro_set_spkr_mode);
+
+static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					    u8 int_prim_fs_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 int_mux_cfg0_val, int_mux_cfg1_val;
+	u8 inp0_sel, inp1_sel, inp2_sel;
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
+			 WSA_MACRO_RX_MAX) {
+		int_1_mix1_inp = port;
+		if ((int_1_mix1_inp < WSA_MACRO_RX0) ||
+			(int_1_mix1_inp > WSA_MACRO_RX_MIX1)) {
+			dev_err(wsa_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0;
+
+		/*
+		 * Loop through all interpolator MUX inputs and find out
+		 * to which interpolator input, the cdc_dma rx port
+		 * is connected
+		 */
+		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;
+			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 = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
+					     WSA_MACRO_RX_PATH_OFFSET * j;
+				dev_dbg(wsa_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_1\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa_dev,
+					"%s: set INT%u_1 sample rate to %u\n",
+					__func__, j, sample_rate);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						WSA_MACRO_FS_RATE_MASK,
+						int_prim_fs_rate_reg_val);
+			}
+			int_mux_cfg0 += WSA_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+
+	return 0;
+}
+
+static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					u8 int_mix_fs_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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+
+	for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
+			 WSA_MACRO_RX_MAX) {
+		int_2_inp = port;
+		if ((int_2_inp < WSA_MACRO_RX0) ||
+			(int_2_inp > WSA_MACRO_RX_MIX1)) {
+			dev_err(wsa_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg1 = BOLERO_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;
+			if (int_mux_cfg1_val == int_2_inp +
+							INTn_2_INP_SEL_RX0) {
+				int_fs_reg =
+					BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+					WSA_MACRO_RX_PATH_OFFSET * j;
+
+				dev_dbg(wsa_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_2\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa_dev,
+					"%s: set INT%u_2 sample rate to %u\n",
+					__func__, j, sample_rate);
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						WSA_MACRO_FS_RATE_MASK,
+						int_mix_fs_rate_reg_val);
+			}
+			int_mux_cfg1 += WSA_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+	return 0;
+}
+
+static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+				       u32 sample_rate)
+{
+	int rate_val = 0;
+	int i, ret;
+
+	/* set mixing path rate */
+	for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_mix_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_mix_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
+			(rate_val < 0))
+		goto prim_rate;
+	ret = wsa_macro_set_mix_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+prim_rate:
+	/* set primary path sample rate */
+	for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_prim_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_prim_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
+			(rate_val < 0))
+		return -EINVAL;
+	ret = wsa_macro_set_prim_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+	return ret;
+}
+
+static int wsa_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;
+	int ret;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv)
+		return -EINVAL;
+
+	dev_dbg(component->dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = wsa_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;
+		}
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		if (dai->id == WSA_MACRO_AIF_VI)
+			wsa_priv->pcm_rate_vi = params_rate(params);
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int wsa_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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u16 val = 0, mask = 0, cnt = 0, temp = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv)
+		return -EINVAL;
+
+	switch (dai->id) {
+	case WSA_MACRO_AIF_VI:
+		*tx_slot = wsa_priv->active_ch_mask[dai->id];
+		*tx_num = hweight_long(wsa_priv->active_ch_mask[dai->id]);
+		break;
+	case WSA_MACRO_AIF1_PB:
+	case WSA_MACRO_AIF_MIX1_PB:
+		for_each_set_bit(temp, &wsa_priv->active_ch_mask[dai->id],
+					WSA_MACRO_RX_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == WSA_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		if (mask & 0x0C)
+			mask = mask >> 0x2;
+		*rx_slot = mask;
+		*rx_num = cnt;
+		break;
+	case WSA_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,
+			BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
+		if (val & WSA_MACRO_EC_MIX_TX1_MASK) {
+			mask |= 0x2;
+			cnt++;
+		}
+		if (val & WSA_MACRO_EC_MIX_TX0_MASK) {
+			mask |= 0x1;
+			cnt++;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	default:
+		dev_err(wsa_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static int wsa_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0;
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	bool adie_lb = false;
+
+	if (mute)
+		return 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (dai->id) {
+	case WSA_MACRO_AIF1_PB:
+	case WSA_MACRO_AIF_MIX1_PB:
+	for (j = 0; j < NUM_INTERPOLATORS; j++) {
+		reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
+				(j * WSA_MACRO_RX_PATH_OFFSET);
+		mix_reg = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+				(j * WSA_MACRO_RX_PATH_OFFSET);
+		dsm_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
+				(j * WSA_MACRO_RX_PATH_OFFSET) +
+				WSA_MACRO_RX_PATH_DSMDEM_OFFSET;
+		int_mux_cfg0 = BOLERO_CDC_WSA_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 & 0x38))
+				snd_soc_component_update_bits(component, reg,
+							0x20, 0x20);
+			if (int_mux_cfg1_val & 0x07) {
+				snd_soc_component_update_bits(component, reg,
+							0x20, 0x20);
+				snd_soc_component_update_bits(component,
+						mix_reg, 0x20, 0x20);
+			}
+		}
+	}
+	bolero_wsa_pa_on(wsa_dev, adie_lb);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv,
+				 bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
+
+	mutex_lock(&wsa_priv->mclk_lock);
+	if (mclk_enable) {
+		if (wsa_priv->wsa_mclk_users == 0) {
+			ret = bolero_clk_rsc_request_clock(wsa_priv->dev,
+							wsa_priv->default_clk_id,
+							wsa_priv->default_clk_id,
+							true);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa request clock enable failed\n",
+					__func__);
+				goto exit;
+			}
+			bolero_clk_rsc_fs_gen_request(wsa_priv->dev,
+						  true);
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					WSA_START_OFFSET,
+					WSA_MAX_OFFSET);
+			/* 9.6MHz MCLK, set value 0x00 if other frequency */
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		wsa_priv->wsa_mclk_users++;
+	} else {
+		if (wsa_priv->wsa_mclk_users <= 0) {
+			dev_err(wsa_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa_priv->wsa_mclk_users = 0;
+			goto exit;
+		}
+		wsa_priv->wsa_mclk_users--;
+		if (wsa_priv->wsa_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+			bolero_clk_rsc_fs_gen_request(wsa_priv->dev,
+						  false);
+
+			bolero_clk_rsc_request_clock(wsa_priv->dev,
+						  wsa_priv->default_clk_id,
+						  wsa_priv->default_clk_id,
+						  false);
+		}
+	}
+exit:
+	mutex_unlock(&wsa_priv->mclk_lock);
+	return ret;
+}
+
+static int wsa_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);
+	int ret = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
+		if (ret)
+			wsa_priv->dapm_mclk_enable = false;
+		else
+			wsa_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (wsa_priv->dapm_mclk_enable)
+			wsa_macro_mclk_enable(wsa_priv, 0, true);
+		break;
+	default:
+		dev_err(wsa_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int wsa_macro_event_handler(struct snd_soc_component *component,
+				   u16 event, u32 data)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int ret = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(wsa_dev) ||
+		     !pm_runtime_suspended(wsa_dev))) {
+			ret = bolero_runtime_suspend(wsa_dev);
+			if (!ret) {
+				pm_runtime_disable(wsa_dev);
+				pm_runtime_set_suspended(wsa_dev);
+				pm_runtime_enable(wsa_dev);
+			}
+		}
+		break;
+	case BOLERO_MACRO_EVT_PRE_SSR_UP:
+		/* enable&disable WSA_CORE_CLK to reset GFMUX reg */
+		wsa_macro_core_vote(wsa_priv, true);
+		ret = bolero_clk_rsc_request_clock(wsa_priv->dev,
+						wsa_priv->default_clk_id,
+						WSA_CORE_CLK, true);
+		if (ret < 0)
+			dev_err_ratelimited(wsa_priv->dev,
+				"%s, failed to enable clk, ret:%d\n",
+				__func__, ret);
+		else
+			bolero_clk_rsc_request_clock(wsa_priv->dev,
+						wsa_priv->default_clk_id,
+						WSA_CORE_CLK, false);
+		wsa_macro_core_vote(wsa_priv, false);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		/* reset swr after ssr/pdr */
+		wsa_priv->reset_swr = true;
+		if (wsa_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(wsa_dev, WSA_CORE_CLK);
+		break;
+	}
+	return 0;
+}
+
+static int wsa_macro_enable_vi_feedback(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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u8 val = 0x0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (wsa_priv->pcm_rate_vi) {
+		case 48000:
+			val = 0x04;
+			break;
+		case 24000:
+			val = 0x02;
+			break;
+		case 8000:
+		default:
+			val = 0x00;
+			break;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (test_bit(WSA_MACRO_TX0,
+			&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
+			/* Enable V&I sensing */
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x0F, val);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x0F, val);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x10, 0x10);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x10, 0x10);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		if (test_bit(WSA_MACRO_TX1,
+			&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
+			/* Enable V&I sensing */
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x0F, val);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x0F, val);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x10, 0x10);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x10, 0x10);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (test_bit(WSA_MACRO_TX0,
+			&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+		}
+		if (test_bit(WSA_MACRO_TX1,
+			&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void wsa_macro_hd2_control(struct snd_soc_component *component,
+				  u16 reg, int event)
+{
+	u16 hd2_scale_reg;
+	u16 hd2_enable_reg = 0;
+
+	if (reg == BOLERO_CDC_WSA_RX0_RX_PATH_CTL) {
+		hd2_scale_reg = BOLERO_CDC_WSA_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0;
+	}
+	if (reg == BOLERO_CDC_WSA_RX1_RX_PATH_CTL) {
+		hd2_scale_reg = BOLERO_CDC_WSA_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG0;
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x10);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x01);
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x04);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x00);
+	}
+}
+
+static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+	int ch_cnt;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
+		    !wsa_priv->rx_0_count)
+			wsa_priv->rx_0_count++;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
+		    !wsa_priv->rx_1_count)
+			wsa_priv->rx_1_count++;
+		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
+
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_UP, NULL);
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_SET_NUM_RX_CH, &ch_cnt);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
+		    wsa_priv->rx_0_count)
+			wsa_priv->rx_0_count--;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
+		    wsa_priv->rx_1_count)
+			wsa_priv->rx_1_count--;
+		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
+
+		if (wsa_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_SET_NUM_RX_CH, &ch_cnt);
+		break;
+	}
+	dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
+		__func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
+
+	return 0;
+}
+
+static int wsa_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;
+	int offset_val = 0;
+	int val = 0;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) {
+		gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
+	} else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) {
+		gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
+	} else {
+		dev_err(component->dev, "%s: No gain register avail for %s\n",
+			__func__, w->name);
+		return 0;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wsa_macro_enable_swr(w, kcontrol, event);
+		val = snd_soc_component_read(component, gain_reg);
+		val += offset_val;
+		snd_soc_component_write(component, gain_reg, val);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+					w->reg, 0x20, 0x00);
+		wsa_macro_enable_swr(w, kcontrol, event);
+		break;
+	}
+
+	return 0;
+}
+
+static int wsa_macro_config_compander(struct snd_soc_component *component,
+				int comp, int event)
+{
+	u16 comp_ctl0_reg, rx_path_cfg0_reg;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
+
+	if (!wsa_priv->comp_enabled[comp])
+		return 0;
+
+	comp_ctl0_reg = BOLERO_CDC_WSA_COMPANDER0_CTL0 +
+					(comp * WSA_MACRO_RX_COMP_OFFSET);
+	rx_path_cfg0_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG0 +
+					(comp * WSA_MACRO_RX_PATH_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x04);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static void wsa_macro_enable_softclip_clk(struct snd_soc_component *component,
+					 struct wsa_macro_priv *wsa_priv,
+					 int path,
+					 bool enable)
+{
+	u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
+			(path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
+	u8 softclip_mux_mask = (1 << path);
+	u8 softclip_mux_value = (1 << path);
+
+	dev_dbg(component->dev, "%s: path %d, enable %d\n",
+		__func__, path, enable);
+	if (enable) {
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, softclip_mux_value);
+		}
+		wsa_priv->softclip_clk_users[path]++;
+	} else {
+		wsa_priv->softclip_clk_users[path]--;
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, 0x00);
+		}
+	}
+}
+
+static int wsa_macro_config_softclip(struct snd_soc_component *component,
+				int path, int event)
+{
+	u16 softclip_ctrl_reg = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int softclip_path = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (path == WSA_MACRO_COMP1)
+		softclip_path = WSA_MACRO_SOFTCLIP0;
+	else if (path == WSA_MACRO_COMP2)
+		softclip_path = WSA_MACRO_SOFTCLIP1;
+
+	dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n",
+		__func__, event, softclip_path,
+		wsa_priv->is_softclip_on[softclip_path]);
+
+	if (!wsa_priv->is_softclip_on[softclip_path])
+		return 0;
+
+	softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
+				(softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock and mux */
+		wsa_macro_enable_softclip_clk(component, wsa_priv,
+				softclip_path, true);
+		/* Enable Softclip control */
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x00);
+		wsa_macro_enable_softclip_clk(component, wsa_priv,
+				softclip_path, false);
+	}
+
+	return 0;
+}
+
+static bool wsa_macro_adie_lb(struct snd_soc_component *component,
+			      int interp_idx)
+{
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
+
+	int_mux_cfg0 = BOLERO_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;
+	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;
+	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;
+	if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
+		int_n_inp2 == INTn_1_INP_SEL_DEC1)
+		return true;
+
+	return false;
+}
+
+static int wsa_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 reg = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	bool adie_lb = false;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+
+	reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
+			WSA_MACRO_RX_PATH_OFFSET * w->shift;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (wsa_macro_adie_lb(component, w->shift)) {
+			adie_lb = true;
+			snd_soc_component_update_bits(component,
+						reg, 0x20, 0x20);
+			bolero_wsa_pa_on(wsa_dev, adie_lb);
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
+{
+	u16 prim_int_reg = 0;
+
+	switch (reg) {
+	case BOLERO_CDC_WSA_RX0_RX_PATH_CTL:
+	case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
+		prim_int_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
+		*ind = 0;
+		break;
+	case BOLERO_CDC_WSA_RX1_RX_PATH_CTL:
+	case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
+		prim_int_reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
+		*ind = 1;
+		break;
+	}
+
+	return prim_int_reg;
+}
+
+static int wsa_macro_enable_prim_interpolator(
+				struct snd_soc_component *component,
+				u16 reg, int event)
+{
+	u16 prim_int_reg;
+	u16 ind = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wsa_priv->prim_int_users[ind]++;
+		if (wsa_priv->prim_int_users[ind] == 1) {
+			snd_soc_component_update_bits(component,
+				prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET,
+				0x03, 0x03);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					    0x10, 0x10);
+			wsa_macro_hd2_control(component, prim_int_reg, event);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x1);
+		}
+		if ((reg != prim_int_reg) &&
+		    ((snd_soc_component_read(
+				component, prim_int_reg)) & 0x10))
+			snd_soc_component_update_bits(component, reg,
+					0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wsa_priv->prim_int_users[ind]--;
+		if (wsa_priv->prim_int_users[ind] == 0) {
+			snd_soc_component_update_bits(component, prim_int_reg,
+					1 << 0x5, 0 << 0x5);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x0);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x40);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x00);
+			wsa_macro_hd2_control(component, prim_int_reg, event);
+		}
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n",
+		__func__, ind, wsa_priv->prim_int_users[ind]);
+	return 0;
+}
+
+static int wsa_macro_enable_interpolator(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;
+	u16 reg;
+	int val;
+	int offset_val = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
+		reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
+		gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_CTL;
+	} else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
+		reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
+		gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_CTL;
+	} else {
+		dev_err(component->dev, "%s: Interpolator reg not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Reset if needed */
+		wsa_macro_enable_prim_interpolator(component, reg, event);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		wsa_macro_config_compander(component, w->shift, event);
+		wsa_macro_config_softclip(component, w->shift, event);
+		/* apply gain after int clk is enabled */
+		if ((wsa_priv->spkr_gain_offset ==
+			WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
+		    (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
+		     wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
+		    (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
+		     gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
+					0x01, 0x01);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
+					0x01, 0x01);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
+					0x01, 0x01);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
+					0x01, 0x01);
+			offset_val = -2;
+		}
+		val = snd_soc_component_read(component, gain_reg);
+		val += offset_val;
+		snd_soc_component_write(component, gain_reg, val);
+		wsa_macro_config_ear_spkr_gain(component, wsa_priv,
+						event, gain_reg);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wsa_macro_config_compander(component, w->shift, event);
+		wsa_macro_config_softclip(component, w->shift, event);
+		wsa_macro_enable_prim_interpolator(component, reg, event);
+		if ((wsa_priv->spkr_gain_offset ==
+			WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
+		    (wsa_priv->comp_enabled[WSA_MACRO_COMP1] ||
+		     wsa_priv->comp_enabled[WSA_MACRO_COMP2]) &&
+		    (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL ||
+		     gain_reg == BOLERO_CDC_WSA_RX1_RX_VOL_CTL)) {
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX0_RX_PATH_SEC1,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX0_RX_PATH_MIX_SEC0,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX1_RX_PATH_SEC1,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					BOLERO_CDC_WSA_RX1_RX_PATH_MIX_SEC0,
+					0x01, 0x00);
+			offset_val = 2;
+			val = snd_soc_component_read(component, gain_reg);
+			val += offset_val;
+			snd_soc_component_write(component, gain_reg, val);
+		}
+		wsa_macro_config_ear_spkr_gain(component, wsa_priv,
+						event, gain_reg);
+		break;
+	}
+
+	return 0;
+}
+
+static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
+					struct wsa_macro_priv *wsa_priv,
+					int event, int gain_reg)
+{
+	int comp_gain_offset, val;
+
+	switch (wsa_priv->spkr_mode) {
+	/* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */
+	case WSA_MACRO_SPKR_MODE_1:
+		comp_gain_offset = -12;
+		break;
+	/* Default case compander gain is 15 dB */
+	default:
+		comp_gain_offset = -15;
+		break;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* Apply ear spkr gain only if compander is enabled */
+		if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
+		    (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
+		    (wsa_priv->ear_spkr_gain != 0)) {
+			/* For example, val is -8(-12+5-1) for 4dB of gain */
+			val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1;
+			snd_soc_component_write(component, gain_reg, val);
+
+			dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
+				__func__, val);
+		}
+		if(wsa_priv->wsa_spkrrecv) {
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x00);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/*
+		 * Reset RX0 volume to 0 dB if compander is enabled and
+		 * ear_spkr_gain is non-zero.
+		 */
+		if (wsa_priv->comp_enabled[WSA_MACRO_COMP1] &&
+		    (gain_reg == BOLERO_CDC_WSA_RX0_RX_VOL_CTL) &&
+		    (wsa_priv->ear_spkr_gain != 0)) {
+			snd_soc_component_write(component, gain_reg, 0x0);
+
+			dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
+				__func__);
+		}
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static int wsa_macro_spk_boost_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);
+	u16 boost_path_ctl, boost_path_cfg1;
+	u16 reg, reg_mix;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
+		boost_path_ctl = BOLERO_CDC_WSA_BOOST0_BOOST_PATH_CTL;
+		boost_path_cfg1 = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
+		reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL;
+		reg_mix = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL;
+	} else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
+		boost_path_ctl = BOLERO_CDC_WSA_BOOST1_BOOST_PATH_CTL;
+		boost_path_cfg1 = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
+		reg = BOLERO_CDC_WSA_RX1_RX_PATH_CTL;
+		reg_mix = BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL;
+	} else {
+		dev_err(component->dev, "%s: unknown widget: %s\n",
+			__func__, w->name);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x10);
+		if ((snd_soc_component_read(component, reg_mix)) & 0x10)
+			snd_soc_component_update_bits(component, reg_mix,
+						0x10, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component, reg, 0x10, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x00);
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int wsa_macro_enable_vbat(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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u16 vbat_path_cfg = 0;
+	int softclip_path = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
+		vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
+		softclip_path = WSA_MACRO_SOFTCLIP0;
+	} else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
+		vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
+		softclip_path = WSA_MACRO_SOFTCLIP1;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x80);
+		/* Use attenuation mode */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x02, 0x00);
+		/*
+		 * BCL block needs softclip clock and mux config to be enabled
+		 */
+		wsa_macro_enable_softclip_clk(component, wsa_priv,
+					softclip_path, true);
+		/* Enable VBAT at channel level */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+				0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x02, 0x02);
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x02, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		wsa_macro_enable_softclip_clk(component, wsa_priv,
+			softclip_path, false);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static int wsa_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);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u16 val, ec_tx = 0, ec_hq_reg;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_component_read(component,
+				BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
+	if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
+		ec_tx = (val & 0x07) - 1;
+	else
+		ec_tx = ((val & 0x38) >> 0x3) - 1;
+
+	if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
+		dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (wsa_priv->ec_hq[ec_tx]) {
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+				0x1 << ec_tx, 0x1 << ec_tx);
+		ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
+							0x40 * ec_tx;
+		snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
+		ec_hq_reg = BOLERO_CDC_WSA_EC_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 int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
+	return 0;
+}
+
+static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
+		__func__, wsa_priv->ec_hq[ec_tx], value);
+	wsa_priv->ec_hq[ec_tx] = value;
+
+	return 0;
+}
+
+static int wsa_macro_get_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int wsa_rx_shift = ((struct soc_multi_mixer_control *)
+		       kcontrol->private_value)->shift;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+		wsa_priv->wsa_digital_mute_status[wsa_rx_shift];
+	return 0;
+}
+
+static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int wsa_rx_shift = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+	int ret = 0;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	pm_runtime_get_sync(wsa_priv->dev);
+	switch (wsa_rx_shift) {
+	case 0:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 1:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX1_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 2:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	case 3:
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	default:
+		pr_err("%s: invalid argument rx_shift = %d\n", __func__,
+			wsa_rx_shift);
+		ret = -EINVAL;
+	}
+	pm_runtime_mark_last_busy(wsa_priv->dev);
+	pm_runtime_put_autosuspend(wsa_priv->dev);
+
+	dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n",
+		__func__, wsa_rx_shift, value);
+	wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value;
+
+	return ret;
+}
+
+static int wsa_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
+	return 0;
+}
+
+static int wsa_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		__func__, comp + 1, wsa_priv->comp_enabled[comp], value);
+	wsa_priv->comp_enabled[comp] = value;
+
+	return 0;
+}
+
+static int wsa_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->wsa_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_component *component =
+                                snd_soc_kcontrol_component(kcontrol);
+        struct device *wsa_dev = NULL;
+        struct wsa_macro_priv *wsa_priv = NULL;
+
+        if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+                return -EINVAL;
+        wsa_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+
+        dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+                 __func__, wsa_priv->wsa_spkrrecv);
+
+        return 0;
+}
+
+static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->ear_spkr_gain =  ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: gain = %d\n", __func__,
+		wsa_priv->ear_spkr_gain);
+
+	return 0;
+}
+
+static int wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	u8 bst_state_max = 0;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+
+	bst_state_max = snd_soc_component_read(component,
+				BOLERO_CDC_WSA_BOOST0_BOOST_CTL);
+	bst_state_max = (bst_state_max & 0x0c) >> 2;
+	ucontrol->value.integer.value[0] = bst_state_max;
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	u8 bst_state_max;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+	bst_state_max =  ucontrol->value.integer.value[0] << 2;
+	/* bolero does not need to limit the boost levels */
+
+	return 0;
+}
+
+static int wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	u8 bst_state_max = 0;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+
+	bst_state_max = snd_soc_component_read(component,
+				BOLERO_CDC_WSA_BOOST1_BOOST_CTL);
+	bst_state_max = (bst_state_max & 0x0c) >> 2;
+	ucontrol->value.integer.value[0] = bst_state_max;
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	u8 bst_state_max;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+	bst_state_max =  ucontrol->value.integer.value[0] << 2;
+	/* bolero does not need to limit the boost levels */
+
+	return 0;
+}
+
+static int wsa_macro_rx_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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			wsa_priv->rx_port_value[widget->shift];
+	return 0;
+}
+
+static int wsa_macro_rx_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 bit_input = 0;
+	u32 aif_rst;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	aif_rst = wsa_priv->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err(wsa_dev, "%s: AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst >= WSA_MACRO_RX_MAX) {
+			dev_err(wsa_dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	wsa_priv->rx_port_value[widget->shift] = rx_port_value;
+
+	bit_input = widget->shift;
+
+	dev_dbg(wsa_dev,
+		"%s: mux input: %d, mux output: %d, bit: %d\n",
+		__func__, rx_port_value, widget->shift, bit_input);
+
+	switch (rx_port_value) {
+	case 0:
+		clear_bit(bit_input,
+			  &wsa_priv->active_ch_mask[aif_rst]);
+		break;
+	case 1:
+	case 2:
+		set_bit(bit_input,
+			&wsa_priv->active_ch_mask[rx_port_value]);
+		break;
+	default:
+		dev_err(wsa_dev,
+			"%s: Invalid AIF_ID for WSA RX MUX %d\n",
+			__func__, rx_port_value);
+		return -EINVAL;
+	}
+
+	snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+					rx_port_value, e, update);
+	return 0;
+}
+
+static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+	    ((snd_soc_component_read(
+		component, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
+	    1 : 0);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x04, 0x04);
+	else
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x04, 0x00);
+
+	return 0;
+}
+
+static int wsa_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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_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 device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->is_softclip_on[path] =  ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__,
+		path, wsa_priv->is_softclip_on[path]);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
+	SOC_ENUM_EXT("WSA SPKRRECV", wsa_macro_ear_spkrrecv_enum,
+			wsa_macro_ear_spkrrecv_get,
+			wsa_macro_ear_spkrrecv_put),
+	SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
+		     wsa_macro_ear_spkr_pa_gain_get,
+		     wsa_macro_ear_spkr_pa_gain_put),
+	SOC_ENUM_EXT("SPKR Left Boost Max State",
+		wsa_macro_spkr_boost_stage_enum,
+		wsa_macro_spkr_left_boost_stage_get,
+		wsa_macro_spkr_left_boost_stage_put),
+	SOC_ENUM_EXT("SPKR Right Boost Max State",
+		wsa_macro_spkr_boost_stage_enum,
+		wsa_macro_spkr_right_boost_stage_get,
+		wsa_macro_spkr_right_boost_stage_put),
+	SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
+		     wsa_macro_vbat_bcl_gsm_mode_func_get,
+		     wsa_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
+			WSA_MACRO_SOFTCLIP0, 1, 0,
+			wsa_macro_soft_clip_enable_get,
+			wsa_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
+			WSA_MACRO_SOFTCLIP1, 1, 0,
+			wsa_macro_soft_clip_enable_get,
+			wsa_macro_soft_clip_enable_put),
+	SOC_SINGLE_S8_TLV("WSA_RX0 Digital Volume",
+			  BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("WSA_RX1 Digital Volume",
+			  BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX0, 1,
+			0, wsa_macro_get_rx_mute_status,
+			wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX1 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX1, 1,
+			0, wsa_macro_get_rx_mute_status,
+			wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX0_MIX Digital Mute", SND_SOC_NOPM,
+			WSA_MACRO_RX_MIX0, 1, 0, wsa_macro_get_rx_mute_status,
+			wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX1_MIX Digital Mute", SND_SOC_NOPM,
+			WSA_MACRO_RX_MIX1, 1, 0, wsa_macro_get_rx_mute_status,
+			wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0,
+		wsa_macro_get_compander, wsa_macro_set_compander),
+	SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
+		wsa_macro_get_compander, wsa_macro_set_compander),
+	SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
+			1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
+			1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
+};
+
+static const struct soc_enum rx_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
+
+static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = {
+	SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
+			  wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
+			  wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
+			  wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
+			  wsa_macro_rx_mux_get, wsa_macro_rx_mux_put),
+};
+
+static int wsa_macro_vi_feed_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int wsa_macro_vi_feed_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 soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
+
+	if (enable) {
+		if (spk_tx_id == WSA_MACRO_TX0 &&
+			!test_bit(WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			set_bit(WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
+		}
+		if (spk_tx_id == WSA_MACRO_TX1 &&
+			!test_bit(WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			set_bit(WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
+		}
+	} else {
+		if (spk_tx_id == WSA_MACRO_TX0 &&
+			test_bit(WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			clear_bit(WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
+		}
+		if (spk_tx_id == WSA_MACRO_TX1 &&
+			test_bit(WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI])) {
+			clear_bit(WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[WSA_MACRO_AIF_VI]);
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_vi_mixer[] = {
+	SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0,
+			wsa_macro_vi_feed_mixer_get,
+			wsa_macro_vi_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0,
+			wsa_macro_vi_feed_mixer_get,
+			wsa_macro_vi_feed_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
+		SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0,
+		wsa_macro_enable_vi_feedback,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
+		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
+			WSA_MACRO_EC0_MUX, 0,
+			&rx_mix_ec0_mux, wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
+			WSA_MACRO_EC1_MUX, 0,
+			&rx_mix_ec1_mux, wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
+				&rx_mux[WSA_MACRO_RX0]),
+	SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0,
+				&rx_mux[WSA_MACRO_RX1]),
+	SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0,
+				&rx_mux[WSA_MACRO_RX_MIX0]),
+	SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0,
+				&rx_mux[WSA_MACRO_RX_MIX1]),
+
+	SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp0_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp1_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp2_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp0_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp1_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp2_mux, wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
+			0, 0, NULL, 0, wsa_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_PGA_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
+			1, 0, NULL, 0, wsa_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
+			   BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
+			   &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
+			  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
+
+	SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
+	SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
+		WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
+		WSA_MACRO_COMP2, 0, NULL, 0, wsa_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, wsa_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, wsa_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int0_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int0_vbat_mix_switch),
+		wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int1_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int1_vbat_mix_switch),
+		wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
+
+	SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
+	SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
+
+	SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route wsa_audio_map[] = {
+	/* VI Feedback */
+	{"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
+	{"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
+	{"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
+	{"WSA AIF_VI", NULL, "WSA_MCLK"},
+
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA_MCLK"},
+
+	{"WSA AIF1 PB", NULL, "WSA_MCLK"},
+	{"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
+
+	{"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
+
+	{"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+
+	{"WSA RX0", NULL, "WSA RX0 MUX"},
+	{"WSA RX1", NULL, "WSA RX1 MUX"},
+	{"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
+	{"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
+
+	{"WSA_RX0 INP0", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP0", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
+
+	{"WSA_RX0 INP1", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP1", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
+
+	{"WSA_RX0 INP2", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP2", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
+
+	{"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
+	{"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
+	{"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
+
+	{"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
+	{"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
+	{"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
+	{"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
+	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
+
+	{"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
+	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
+
+	{"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
+	{"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
+
+	{"WSA_RX1 INP0", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP0", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
+
+	{"WSA_RX1 INP1", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP1", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
+
+	{"WSA_RX1 INP2", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP2", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
+
+	{"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
+	{"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
+	{"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
+
+	{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
+	{"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
+
+	{"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
+	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
+
+	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
+	{"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
+	{"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
+};
+
+static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
+	{BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
+	{BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
+	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
+	{BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
+	{BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
+	{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
+	{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
+	{BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
+	{BOLERO_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
+	{BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
+	{BOLERO_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
+	{BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
+	{BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
+	{BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
+};
+
+static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_component *component)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: NULL component pointer!\n", __func__);
+		return;
+	}
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return;
+
+	switch (wsa_priv->bcl_pmic_params.id) {
+	case 0:
+		/* Enable ID0 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
+		/* Update MC_SID0 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
+			wsa_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID0 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
+			wsa_priv->bcl_pmic_params.ppid);
+		break;
+	case 1:
+		/* Enable ID1 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
+		/* Update MC_SID1 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
+			wsa_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID1 */
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
+			wsa_priv->bcl_pmic_params.ppid);
+		break;
+	default:
+		dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
+		       __func__, wsa_priv->bcl_pmic_params.id);
+		break;
+	}
+}
+
+static void wsa_macro_init_reg(struct snd_soc_component *component)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wsa_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				wsa_macro_reg_init[i].reg,
+				wsa_macro_reg_init[i].mask,
+				wsa_macro_reg_init[i].val);
+
+	wsa_macro_init_bcl_pmic_reg(component);
+}
+
+static int wsa_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
+
+	if (wsa_priv == NULL) {
+		pr_err("%s: wsa priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(wsa_priv->dev);
+		if (bolero_check_core_votes(wsa_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(wsa_priv->dev);
+		pm_runtime_mark_last_busy(wsa_priv->dev);
+	}
+	return rc;
+}
+
+static int wsa_swrm_clock(void *handle, bool enable)
+{
+	struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wsa_priv->swr_clk_lock);
+
+	dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(wsa_priv->dev);
+		if (wsa_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						wsa_priv->wsa_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa_priv->dev);
+				pm_runtime_put_autosuspend(wsa_priv->dev);
+				goto exit;
+			}
+			ret = wsa_macro_mclk_enable(wsa_priv, 1, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						wsa_priv->wsa_swr_gpio_p);
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa_priv->dev);
+				pm_runtime_put_autosuspend(wsa_priv->dev);
+				goto exit;
+			}
+			if (wsa_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (wsa_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			wsa_priv->reset_swr = false;
+		}
+		wsa_priv->swr_clk_users++;
+		pm_runtime_mark_last_busy(wsa_priv->dev);
+		pm_runtime_put_autosuspend(wsa_priv->dev);
+	} else {
+		if (wsa_priv->swr_clk_users <= 0) {
+			dev_err(wsa_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa_priv->swr_clk_users = 0;
+			goto exit;
+		}
+		wsa_priv->swr_clk_users--;
+		if (wsa_priv->swr_clk_users == 0) {
+			regmap_update_bits(regmap,
+				BOLERO_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+			wsa_macro_mclk_enable(wsa_priv, 0, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						wsa_priv->wsa_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
+		__func__, wsa_priv->swr_clk_users);
+exit:
+	mutex_unlock(&wsa_priv->swr_clk_lock);
+	return ret;
+}
+
+static int wsa_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	wsa_dev = bolero_get_device_ptr(component->dev, WSA_MACRO);
+	if (!wsa_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dapm_new_controls(dapm, wsa_macro_dapm_widgets,
+					ARRAY_SIZE(wsa_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
+					ARRAY_SIZE(wsa_audio_map));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component, wsa_macro_snd_controls,
+				   ARRAY_SIZE(wsa_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
+		return ret;
+	}
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");
+	snd_soc_dapm_sync(dapm);
+
+	wsa_priv->component = component;
+	wsa_priv->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_0_DB;
+	wsa_macro_init_reg(component);
+
+	return 0;
+}
+
+static int wsa_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->component = NULL;
+
+	return 0;
+}
+
+static void wsa_macro_add_child_devices(struct work_struct *work)
+{
+	struct wsa_macro_priv *wsa_priv;
+	struct platform_device *pdev;
+	struct device_node *node;
+	struct wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
+	int ret;
+	u16 count = 0, ctrl_num = 0;
+	struct wsa_macro_swr_ctrl_platform_data *platdata;
+	char plat_dev_name[WSA_MACRO_SWR_STRING_LEN];
+
+	wsa_priv = container_of(work, struct wsa_macro_priv,
+			     wsa_macro_add_child_devices_work);
+	if (!wsa_priv) {
+		pr_err("%s: Memory for wsa_priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
+		dev_err(wsa_priv->dev,
+			"%s: DT node for wsa_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &wsa_priv->swr_plat_data;
+	wsa_priv->child_count = 0;
+
+	for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
+		if (strnstr(node->name, "wsa_swr_master",
+				strlen("wsa_swr_master")) != NULL)
+			strlcpy(plat_dev_name, "wsa_swr_ctrl",
+				(WSA_MACRO_SWR_STRING_LEN - 1));
+		else if (strnstr(node->name, "msm_cdc_pinctrl",
+				 strlen("msm_cdc_pinctrl")) != NULL)
+			strlcpy(plat_dev_name, node->name,
+				(WSA_MACRO_SWR_STRING_LEN - 1));
+		else
+			continue;
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = wsa_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (strnstr(node->name, "wsa_swr_master",
+				strlen("wsa_swr_master")) != NULL) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct wsa_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				dev_err(&pdev->dev, "out of memory\n");
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			wsa_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (wsa_priv->child_count < WSA_MACRO_CHILD_DEVICES_MAX)
+			wsa_priv->pdev_child_devices[
+					wsa_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+
+	return;
+fail_pdev_add:
+	for (count = 0; count < wsa_priv->child_count; count++)
+		platform_device_put(wsa_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static void wsa_macro_init_ops(struct macro_ops *ops,
+			       char __iomem *wsa_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = wsa_macro_init;
+	ops->exit = wsa_macro_deinit;
+	ops->io_base = wsa_io_base;
+	ops->dai_ptr = wsa_macro_dai;
+	ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
+	ops->event_handler = wsa_macro_event_handler;
+	ops->set_port_map = wsa_macro_set_port_map;
+}
+
+static int wsa_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops;
+	struct wsa_macro_priv *wsa_priv;
+	u32 wsa_base_addr, default_clk_id;
+	char __iomem *wsa_io_base;
+	int ret = 0;
+	u8 bcl_pmic_params[3];
+	u32 is_used_wsa_swr_gpio = 1;
+	const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
+				GFP_KERNEL);
+	if (!wsa_priv)
+		return -ENOMEM;
+
+	wsa_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &wsa_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	if (of_find_property(pdev->dev.of_node, is_used_wsa_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_wsa_swr_gpio_dt,
+					   &is_used_wsa_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_wsa_swr_gpio_dt);
+			is_used_wsa_swr_gpio = 1;
+		}
+	}
+	wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,wsa-swr-gpios", 0);
+	if (!wsa_priv->wsa_swr_gpio_p && is_used_wsa_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(wsa_priv->wsa_swr_gpio_p) < 0 &&
+			is_used_wsa_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				wsa_priv->wsa_swr_gpio_p, false);
+
+	wsa_io_base = devm_ioremap(&pdev->dev,
+				   wsa_base_addr, WSA_MACRO_MAX_OFFSET);
+	if (!wsa_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -EINVAL;
+	}
+	wsa_priv->wsa_io_base = wsa_io_base;
+	wsa_priv->reset_swr = true;
+	INIT_WORK(&wsa_priv->wsa_macro_add_child_devices_work,
+		  wsa_macro_add_child_devices);
+	wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
+	wsa_priv->swr_plat_data.read = NULL;
+	wsa_priv->swr_plat_data.write = NULL;
+	wsa_priv->swr_plat_data.bulk_write = NULL;
+	wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
+	wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote;
+	wsa_priv->swr_plat_data.handle_irq = NULL;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,mux0-clk-id");
+		default_clk_id = WSA_CORE_CLK;
+	}
+
+	ret = of_property_read_u8_array(pdev->dev.of_node,
+				"qcom,wsa-bcl-pmic-params", bcl_pmic_params,
+				sizeof(bcl_pmic_params));
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,wsa-bcl-pmic-params");
+	} else {
+		wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
+		wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
+		wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
+	}
+	wsa_priv->default_clk_id  = default_clk_id;
+
+	dev_set_drvdata(&pdev->dev, wsa_priv);
+	mutex_init(&wsa_priv->mclk_lock);
+	mutex_init(&wsa_priv->swr_clk_lock);
+	wsa_macro_init_ops(&ops, wsa_io_base);
+	ops.clk_id_req = wsa_priv->default_clk_id;
+	ops.default_clk_id = wsa_priv->default_clk_id;
+
+	ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
+		goto reg_macro_fail;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	schedule_work(&wsa_priv->wsa_macro_add_child_devices_work);
+	return ret;
+reg_macro_fail:
+	mutex_destroy(&wsa_priv->mclk_lock);
+	mutex_destroy(&wsa_priv->swr_clk_lock);
+	return ret;
+}
+
+static int wsa_macro_remove(struct platform_device *pdev)
+{
+	struct wsa_macro_priv *wsa_priv;
+	u16 count = 0;
+
+	wsa_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!wsa_priv)
+		return -EINVAL;
+
+	for (count = 0; count < wsa_priv->child_count &&
+		count < WSA_MACRO_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(wsa_priv->pdev_child_devices[count]);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	bolero_unregister_macro(&pdev->dev, WSA_MACRO);
+	mutex_destroy(&wsa_priv->mclk_lock);
+	mutex_destroy(&wsa_priv->swr_clk_lock);
+	return 0;
+}
+
+static const struct of_device_id wsa_macro_dt_match[] = {
+	{.compatible = "qcom,wsa-macro"},
+	{}
+};
+
+static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		bolero_runtime_suspend,
+		bolero_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver wsa_macro_driver = {
+	.driver = {
+		.name = "wsa_macro",
+		.owner = THIS_MODULE,
+		.pm = &bolero_dev_pm_ops,
+		.of_match_table = wsa_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = wsa_macro_probe,
+	.remove = wsa_macro_remove,
+};
+
+module_platform_driver(wsa_macro_driver);
+
+MODULE_DESCRIPTION("WSA macro driver");
+MODULE_LICENSE("GPL v2");

+ 41 - 0
qcom/opensource/audio-kernel/asoc/codecs/bolero/wsa-macro.h

@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ */
+#ifndef WSA_MACRO_H
+#define WSA_MACRO_H
+
+/*
+ * Selects compander and smart boost settings
+ * for a given speaker mode
+ */
+enum {
+	WSA_MACRO_SPKR_MODE_DEFAULT,
+	WSA_MACRO_SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */
+};
+
+/* Rx path gain offsets */
+enum {
+	WSA_MACRO_GAIN_OFFSET_M1P5_DB,
+	WSA_MACRO_GAIN_OFFSET_0_DB,
+};
+
+
+#if IS_ENABLED(CONFIG_WSA_MACRO)
+extern int wsa_macro_set_spkr_mode(struct snd_soc_component *component,
+				   int mode);
+extern int wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component,
+					  int offset);
+#else /* CONFIG_WSA_MACRO */
+static inline int wsa_macro_set_spkr_mode(struct snd_soc_component *component,
+					  int mode)
+{
+	return 0;
+}
+static inline int wsa_macro_set_spkr_gain_offset(
+				struct snd_soc_component *component,
+				int offset)
+{
+	return 0;
+}
+#endif /* CONFIG_WSA_MACRO */
+#endif

+ 484 - 0
qcom/opensource/audio-kernel/asoc/codecs/cpe_cmi.h

@@ -0,0 +1,484 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __CPE_CMI_H__
+#define __CPE_CMI_H__
+
+#include <linux/types.h>
+
+#define CPE_AFE_PORT_1_TX 1
+#define CPE_AFE_PORT_3_TX 3
+#define CPE_AFE_PORT_ID_2_OUT 0x02
+#define CMI_INBAND_MESSAGE_SIZE 127
+
+/*
+ * Multiple mad types can be supported at once.
+ * these values can be OR'ed to form the set of
+ * supported mad types
+ */
+#define MAD_TYPE_AUDIO (1 << 0)
+#define MAD_TYPE_BEACON (1 << 1)
+#define MAD_TYPE_ULTRASND (1 << 2)
+
+/* Core service command opcodes */
+#define CPE_CORE_SVC_CMD_SHARED_MEM_ALLOC	(0x3001)
+#define CPE_CORE_SVC_CMDRSP_SHARED_MEM_ALLOC	(0x3002)
+#define CPE_CORE_SVC_CMD_SHARED_MEM_DEALLOC	(0x3003)
+#define CPE_CORE_SVC_CMD_DRAM_ACCESS_REQ	(0x3004)
+#define CPE_CORE_SVC_EVENT_SYSTEM_BOOT		(0x3005)
+/* core service command opcodes for WCD9335 */
+#define CPE_CORE_SVC_CMD_CFG_CLK_PLAN		(0x3006)
+#define CPE_CORE_SVC_CMD_CLK_FREQ_REQUEST	(0x3007)
+
+#define CPE_BOOT_SUCCESS 0x00
+#define CPE_BOOT_FAILED 0x01
+
+#define CPE_CORE_VERSION_SYSTEM_BOOT_EVENT 0x01
+
+/* LSM Service command opcodes */
+#define CPE_LSM_SESSION_CMD_OPEN_TX		(0x2000)
+#define CPE_LSM_SESSION_CMD_SET_PARAMS		(0x2001)
+#define CPE_LSM_SESSION_CMD_REGISTER_SOUND_MODEL (0x2002)
+#define CPE_LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL (0x2003)
+#define CPE_LSM_SESSION_CMD_START		(0x2004)
+#define CPE_LSM_SESSION_CMD_STOP		(0x2005)
+#define CPE_LSM_SESSION_EVENT_DETECTION_STATUS_V2 (0x2006)
+#define CPE_LSM_SESSION_CMD_CLOSE_TX		(0x2007)
+#define CPE_LSM_SESSION_CMD_SHARED_MEM_ALLOC	(0x2008)
+#define CPE_LSM_SESSION_CMDRSP_SHARED_MEM_ALLOC (0x2009)
+#define CPE_LSM_SESSION_CMD_SHARED_MEM_DEALLOC	(0x200A)
+#define CPE_LSM_SESSION_CMD_TX_BUFF_OUTPUT_CONFIG (0x200f)
+#define CPE_LSM_SESSION_CMD_OPEN_TX_V2		(0x200D)
+#define CPE_LSM_SESSION_CMD_SET_PARAMS_V2	(0x200E)
+
+/* LSM Service module and param IDs */
+#define CPE_LSM_MODULE_ID_VOICE_WAKEUP		(0x00012C00)
+#define CPE_LSM_MODULE_ID_VOICE_WAKEUP_V2	(0x00012C0D)
+#define CPE_LSM_MODULE_FRAMEWORK		(0x00012C0E)
+
+#define CPE_LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD (0x00012C01)
+#define CPE_LSM_PARAM_ID_OPERATION_MODE		(0x00012C02)
+#define CPE_LSM_PARAM_ID_GAIN			(0x00012C03)
+#define CPE_LSM_PARAM_ID_CONNECT_TO_PORT	(0x00012C04)
+#define CPE_LSM_PARAM_ID_MIN_CONFIDENCE_LEVELS	(0x00012C07)
+
+/* LSM LAB command opcodes */
+#define CPE_LSM_SESSION_CMD_EOB		0x0000200B
+#define CPE_LSM_MODULE_ID_LAB		0x00012C08
+/* used for enable/disable lab*/
+#define CPE_LSM_PARAM_ID_LAB_ENABLE	0x00012C09
+/* used for T in LAB config DSP internal buffer*/
+#define CPE_LSM_PARAM_ID_LAB_CONFIG	0x00012C0A
+#define CPE_LSM_PARAM_ID_REGISTER_SOUND_MODEL	(0x00012C14)
+#define CPE_LSM_PARAM_ID_DEREGISTER_SOUND_MODEL	(0x00012C15)
+#define CPE_LSM_PARAM_ID_MEDIA_FMT		(0x00012C1E)
+
+/* AFE Service command opcodes */
+#define CPE_AFE_PORT_CMD_START			(0x1001)
+#define CPE_AFE_PORT_CMD_STOP			(0x1002)
+#define CPE_AFE_PORT_CMD_SUSPEND		(0x1003)
+#define CPE_AFE_PORT_CMD_RESUME			(0x1004)
+#define CPE_AFE_PORT_CMD_SHARED_MEM_ALLOC	(0x1005)
+#define CPE_AFE_PORT_CMDRSP_SHARED_MEM_ALLOC	(0x1006)
+#define CPE_AFE_PORT_CMD_SHARED_MEM_DEALLOC	(0x1007)
+#define CPE_AFE_PORT_CMD_GENERIC_CONFIG		(0x1008)
+#define CPE_AFE_SVC_CMD_LAB_MODE		(0x1009)
+
+/* AFE Service module and param IDs */
+#define CPE_AFE_CMD_SET_PARAM			(0x1000)
+#define CPE_AFE_MODULE_ID_SW_MAD		(0x0001022D)
+#define CPE_AFE_PARAM_ID_SW_MAD_CFG		(0x0001022E)
+#define CPE_AFE_PARAM_ID_SVM_MODEL		(0x0001022F)
+
+#define CPE_AFE_MODULE_HW_MAD			(0x00010230)
+#define CPE_AFE_PARAM_ID_HW_MAD_CTL		(0x00010232)
+#define CPE_AFE_PARAM_ID_HW_MAD_CFG		(0x00010231)
+
+#define CPE_AFE_MODULE_AUDIO_DEV_INTERFACE	(0x0001020C)
+#define CPE_AFE_PARAM_ID_GENERIC_PORT_CONFIG	(0x00010253)
+
+#define CPE_CMI_BASIC_RSP_OPCODE	(0x0001)
+#define CPE_HDR_MAX_PLD_SIZE	(0x7F)
+
+#define CMI_OBM_FLAG_IN_BAND	0
+#define CMI_OBM_FLAG_OUT_BAND	1
+
+#define CMI_SHMEM_ALLOC_FAILED 0xff
+
+/*
+ * Future Service ID's can be added one line
+ * before the CMI_CPE_SERVICE_ID_MAX
+ */
+enum {
+	CMI_CPE_SERVICE_ID_MIN = 0,
+	CMI_CPE_CORE_SERVICE_ID,
+	CMI_CPE_AFE_SERVICE_ID,
+	CMI_CPE_LSM_SERVICE_ID,
+	CMI_CPE_SERVICE_ID_MAX,
+};
+
+#define CPE_LSM_SESSION_ID_MAX 2
+
+#define IS_VALID_SESSION_ID(s_id) \
+	(s_id <= CPE_LSM_SESSION_ID_MAX)
+
+#define IS_VALID_SERVICE_ID(s_id) \
+	(s_id > CMI_CPE_SERVICE_ID_MIN && \
+	 s_id < CMI_CPE_SERVICE_ID_MAX)
+
+#define IS_VALID_PLD_SIZE(p_size) \
+	(p_size <= CPE_HDR_MAX_PLD_SIZE)
+
+#define CMI_HDR_SET_OPCODE(hdr, cmd) (hdr->opcode = cmd)
+
+
+#define CMI_HDR_SET(hdr_info, mask, shift, value) \
+		(hdr_info = (((hdr_info) & ~(mask)) | \
+			((value << shift) & mask)))
+
+#define SVC_ID_SHIFT 4
+#define SVC_ID_MASK (0x07 << SVC_ID_SHIFT)
+
+#define SESSION_ID_SHIFT 0
+#define SESSION_ID_MASK (0x0F << SESSION_ID_SHIFT)
+
+#define PAYLD_SIZE_SHIFT 0
+#define PAYLD_SIZE_MASK (0x7F << PAYLD_SIZE_SHIFT)
+
+#define OBM_FLAG_SHIFT 7
+#define OBM_FLAG_MASK (1 << OBM_FLAG_SHIFT)
+
+#define VERSION_SHIFT 7
+#define VERSION_MASK (1 << VERSION_SHIFT)
+
+#define CMI_HDR_SET_SERVICE(hdr, s_id) \
+		CMI_HDR_SET(hdr->hdr_info, SVC_ID_MASK,\
+			    SVC_ID_SHIFT, s_id)
+#define CMI_HDR_GET_SERVICE(hdr) \
+		((hdr->hdr_info >> SVC_ID_SHIFT) & \
+			(SVC_ID_MASK >> SVC_ID_SHIFT))
+
+
+#define CMI_HDR_SET_SESSION(hdr, s_id) \
+		CMI_HDR_SET(hdr->hdr_info, SESSION_ID_MASK,\
+			    SESSION_ID_SHIFT, s_id)
+
+#define CMI_HDR_GET_SESSION_ID(hdr) \
+		((hdr->hdr_info >> SESSION_ID_SHIFT) & \
+			 (SESSION_ID_MASK >> SESSION_ID_SHIFT))
+
+#define CMI_GET_HEADER(msg)	((struct cmi_hdr *)(msg))
+#define CMI_GET_PAYLOAD(msg)	((void *)(CMI_GET_HEADER(msg) + 1))
+#define CMI_GET_OPCODE(msg)	(CMI_GET_HEADER(msg)->opcode)
+
+#define CMI_HDR_SET_VERSION(hdr, ver) \
+		CMI_HDR_SET(hdr->hdr_info, VERSION_MASK, \
+				VERSION_SHIFT, ver)
+
+#define CMI_HDR_SET_PAYLOAD_SIZE(hdr, p_size) \
+		CMI_HDR_SET(hdr->pld_info, PAYLD_SIZE_MASK, \
+			    PAYLD_SIZE_SHIFT, p_size)
+
+#define CMI_HDR_GET_PAYLOAD_SIZE(hdr) \
+		((hdr->pld_info >> PAYLD_SIZE_SHIFT) & \
+			(PAYLD_SIZE_MASK >> PAYLD_SIZE_SHIFT))
+
+#define CMI_HDR_SET_OBM(hdr, obm_flag) \
+		CMI_HDR_SET(hdr->pld_info, OBM_FLAG_MASK, \
+			    OBM_FLAG_SHIFT, obm_flag)
+
+#define CMI_HDR_GET_OBM_FLAG(hdr) \
+	((hdr->pld_info >> OBM_FLAG_SHIFT) & \
+		(OBM_FLAG_MASK >> OBM_FLAG_SHIFT))
+
+struct cmi_hdr {
+	/*
+	 * bits 0:3 is session id
+	 * bits 4:6 is service id
+	 * bit 7 is the version flag
+	 */
+	u8 hdr_info;
+
+	/*
+	 * bits 0:6 is payload size in case of in-band message
+	 * bits 0:6 is size (OBM message size)
+	 * bit 7 is the OBM flag
+	 */
+	u8 pld_info;
+
+	/* 16 bit command opcode */
+	u16 opcode;
+} __packed;
+
+union cpe_addr {
+	u64 msw_lsw;
+	void *kvaddr;
+} __packed;
+
+struct cmi_obm {
+	u32 version;
+	u32 size;
+	union cpe_addr data_ptr;
+	u32 mem_handle;
+} __packed;
+
+struct cmi_obm_msg {
+	struct cmi_hdr hdr;
+	struct cmi_obm pld;
+} __packed;
+
+struct cmi_core_svc_event_system_boot {
+	u8 status;
+	u8 version;
+	u16 sfr_buff_size;
+	u32 sfr_buff_address;
+} __packed;
+
+struct cmi_core_svc_cmd_shared_mem_alloc {
+	u32 size;
+} __packed;
+
+struct cmi_core_svc_cmdrsp_shared_mem_alloc {
+	u32 addr;
+} __packed;
+
+struct cmi_core_svc_cmd_clk_freq_request {
+	u32 clk_freq;
+} __packed;
+
+struct cmi_msg_transport {
+	u32 size;
+	u32 addr;
+} __packed;
+
+struct cmi_basic_rsp_result {
+	u8 status;
+} __packed;
+
+struct cpe_lsm_cmd_open_tx {
+	struct cmi_hdr	hdr;
+	u16 app_id;
+	u16 reserved;
+	u32 sampling_rate;
+} __packed;
+
+struct cpe_lsm_cmd_open_tx_v2 {
+	struct cmi_hdr hdr;
+	u32 topology_id;
+} __packed;
+
+struct cpe_cmd_shmem_alloc {
+	struct cmi_hdr hdr;
+	u32 size;
+} __packed;
+
+struct cpe_cmdrsp_shmem_alloc {
+	struct cmi_hdr hdr;
+	u32 addr;
+} __packed;
+
+struct cpe_cmd_shmem_dealloc {
+	struct cmi_hdr	hdr;
+	u32 addr;
+} __packed;
+
+struct cpe_lsm_event_detect_v2 {
+	struct cmi_hdr	hdr;
+	u8 detection_status;
+	u8 size;
+	u8 payload[0];
+} __packed;
+
+struct cpe_lsm_psize_res {
+	u16 param_size;
+	u16 reserved;
+} __packed;
+
+union cpe_lsm_param_size {
+	u32 param_size;
+	struct cpe_lsm_psize_res sr;
+} __packed;
+
+struct cpe_param_data {
+	u32 module_id;
+	u32 param_id;
+	union cpe_lsm_param_size p_size;
+} __packed;
+
+struct cpe_lsm_param_epd_thres {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u32 minor_version;
+	u32 epd_begin;
+	u32 epd_end;
+} __packed;
+
+struct cpe_lsm_param_gain {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u32 minor_version;
+	u16 gain;
+	u16 reserved;
+} __packed;
+
+struct cpe_afe_hw_mad_ctrl {
+	struct cpe_param_data param;
+	u32 minor_version;
+	u16 mad_type;
+	u16 mad_enable;
+} __packed;
+
+struct cpe_afe_port_cfg {
+	struct cpe_param_data param;
+	u32 minor_version;
+	u16 bit_width;
+	u16 num_channels;
+	u32 sample_rate;
+} __packed;
+
+struct cpe_afe_cmd_port_cfg {
+	struct cmi_hdr hdr;
+	u8 bit_width;
+	u8 num_channels;
+	u16 buffer_size;
+	u32 sample_rate;
+} __packed;
+
+struct cpe_afe_params {
+	struct cmi_hdr hdr;
+	struct cpe_afe_hw_mad_ctrl hw_mad_ctrl;
+	struct cpe_afe_port_cfg port_cfg;
+} __packed;
+
+struct cpe_afe_svc_cmd_mode {
+	struct cmi_hdr hdr;
+	u8 mode;
+} __packed;
+
+struct cpe_lsm_param_opmode {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u32 minor_version;
+	u16 mode;
+	u16 reserved;
+} __packed;
+
+struct cpe_lsm_param_connectport {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u32 minor_version;
+	u16 afe_port_id;
+	u16 reserved;
+} __packed;
+
+/*
+ * This cannot be sent to CPE as is,
+ * need to append the conf_levels dynamically
+ */
+struct cpe_lsm_conf_level {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u8 num_active_models;
+} __packed;
+
+struct cpe_lsm_output_format_cfg {
+	struct cmi_hdr hdr;
+	u8 format;
+	u8 packing;
+	u8 data_path_events;
+} __packed;
+
+struct cpe_lsm_lab_enable {
+	struct cpe_param_data param;
+	u16 enable;
+	u16 reserved;
+} __packed;
+
+struct cpe_lsm_control_lab {
+	struct cmi_hdr hdr;
+	struct cpe_lsm_lab_enable lab_enable;
+} __packed;
+
+struct cpe_lsm_lab_config {
+	struct cpe_param_data param;
+	u32 minor_ver;
+	u32 latency;
+} __packed;
+
+struct cpe_lsm_lab_latency_config {
+	struct cmi_hdr hdr;
+	struct cpe_lsm_lab_config latency_cfg;
+} __packed;
+
+struct cpe_lsm_media_fmt_param {
+	struct cmi_hdr hdr;
+	struct cpe_param_data param;
+	u32 minor_version;
+	u32 sample_rate;
+	u16 num_channels;
+	u16 bit_width;
+} __packed;
+
+
+#define CPE_PARAM_LSM_LAB_LATENCY_SIZE (\
+				sizeof(struct cpe_lsm_lab_latency_config) - \
+				sizeof(struct cmi_hdr))
+#define PARAM_SIZE_LSM_LATENCY_SIZE (\
+					sizeof(struct cpe_lsm_lab_config) - \
+					sizeof(struct cpe_param_data))
+#define CPE_PARAM_SIZE_LSM_LAB_CONTROL (\
+				sizeof(struct cpe_lsm_control_lab) - \
+				sizeof(struct cmi_hdr))
+#define PARAM_SIZE_LSM_CONTROL_SIZE (sizeof(struct cpe_lsm_lab_enable) - \
+					sizeof(struct cpe_param_data))
+#define PARAM_SIZE_AFE_HW_MAD_CTRL (sizeof(struct cpe_afe_hw_mad_ctrl) - \
+				sizeof(struct cpe_param_data))
+#define PARAM_SIZE_AFE_PORT_CFG (sizeof(struct cpe_afe_port_cfg) - \
+				 sizeof(struct cpe_param_data))
+#define CPE_AFE_PARAM_PAYLOAD_SIZE (sizeof(struct cpe_afe_params) - \
+				sizeof(struct cmi_hdr))
+
+#define OPEN_CMD_PAYLOAD_SIZE (sizeof(struct cpe_lsm_cmd_open_tx) - \
+			       sizeof(struct cmi_hdr))
+#define OPEN_V2_CMD_PAYLOAD_SIZE (sizeof(struct cpe_lsm_cmd_open_tx_v2) - \
+			       sizeof(struct cmi_hdr))
+#define SHMEM_ALLOC_CMD_PLD_SIZE (sizeof(struct cpe_cmd_shmem_alloc) - \
+				      sizeof(struct cmi_hdr))
+
+#define SHMEM_DEALLOC_CMD_PLD_SIZE (sizeof(struct cpe_cmd_shmem_dealloc) - \
+				      sizeof(struct cmi_hdr))
+#define OUT_FMT_CFG_CMD_PAYLOAD_SIZE ( \
+		sizeof(struct cpe_lsm_output_format_cfg) - \
+		sizeof(struct cmi_hdr))
+
+#define CPE_AFE_CMD_PORT_CFG_PAYLOAD_SIZE \
+		(sizeof(struct cpe_afe_cmd_port_cfg) - \
+		 sizeof(struct cmi_hdr))
+
+#define CPE_AFE_CMD_MODE_PAYLOAD_SIZE \
+		(sizeof(struct cpe_afe_svc_cmd_mode) - \
+		 sizeof(struct cmi_hdr))
+#define CPE_CMD_EPD_THRES_PLD_SIZE (sizeof(struct cpe_lsm_param_epd_thres) - \
+				    sizeof(struct cmi_hdr))
+#define CPE_EPD_THRES_PARAM_SIZE ((CPE_CMD_EPD_THRES_PLD_SIZE) - \
+				  sizeof(struct cpe_param_data))
+#define CPE_CMD_OPMODE_PLD_SIZE (sizeof(struct cpe_lsm_param_opmode) - \
+				 sizeof(struct cmi_hdr))
+#define CPE_OPMODE_PARAM_SIZE ((CPE_CMD_OPMODE_PLD_SIZE) -\
+			       sizeof(struct cpe_param_data))
+#define CPE_CMD_CONNECTPORT_PLD_SIZE \
+	(sizeof(struct cpe_lsm_param_connectport) - \
+	 sizeof(struct cmi_hdr))
+#define CPE_CONNECTPORT_PARAM_SIZE ((CPE_CMD_CONNECTPORT_PLD_SIZE) - \
+				    sizeof(struct cpe_param_data))
+#define CPE_CMD_GAIN_PLD_SIZE (sizeof(struct cpe_lsm_param_gain) - \
+			       sizeof(struct cmi_hdr))
+#define CPE_GAIN_PARAM_SIZE ((CPE_CMD_GAIN_PLD_SIZE) - \
+			     sizeof(struct cpe_param_data))
+#define CPE_MEDIA_FMT_PLD_SIZE (sizeof(struct cpe_lsm_media_fmt_param) - \
+				sizeof(struct cmi_hdr))
+#define CPE_MEDIA_FMT_PARAM_SIZE ((CPE_MEDIA_FMT_PLD_SIZE) - \
+				  sizeof(struct cpe_param_data))
+#endif /* __CPE_CMI_H__ */

+ 158 - 0
qcom/opensource/audio-kernel/asoc/codecs/cpe_err.h

@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __CPE_ERR__
+#define __CPE_ERR__
+
+#include <linux/errno.h>
+
+/* ERROR CODES */
+/* Success. The operation completed with no errors. */
+#define CPE_EOK          0x00000000
+/* General failure. */
+#define CPE_EFAILED      0x00000001
+/* Bad operation parameter. */
+#define CPE_EBADPARAM    0x00000002
+/* Unsupported routine or operation. */
+#define CPE_EUNSUPPORTED 0x00000003
+/* Unsupported version. */
+#define CPE_EVERSION     0x00000004
+/* Unexpected problem encountered. */
+#define CPE_EUNEXPECTED  0x00000005
+/* Unhandled problem occurred. */
+#define CPE_EPANIC       0x00000006
+/* Unable to allocate resource. */
+#define CPE_ENORESOURCE  0x00000007
+/* Invalid handle. */
+#define CPE_EHANDLE      0x00000008
+/* Operation is already processed. */
+#define CPE_EALREADY     0x00000009
+/* Operation is not ready to be processed. */
+#define CPE_ENOTREADY    0x0000000A
+/* Operation is pending completion. */
+#define CPE_EPENDING     0x0000000B
+/* Operation could not be accepted or processed. */
+#define CPE_EBUSY        0x0000000C
+/* Operation aborted due to an error. */
+#define CPE_EABORTED     0x0000000D
+/* Operation preempted by a higher priority. */
+#define CPE_EPREEMPTED   0x0000000E
+/* Operation requests intervention to complete. */
+#define CPE_ECONTINUE    0x0000000F
+/* Operation requests immediate intervention to complete. */
+#define CPE_EIMMEDIATE   0x00000010
+/* Operation is not implemented. */
+#define CPE_ENOTIMPL     0x00000011
+/* Operation needs more data or resources. */
+#define CPE_ENEEDMORE    0x00000012
+/* Operation does not have memory. */
+#define CPE_ENOMEMORY    0x00000014
+/* Item does not exist. */
+#define CPE_ENOTEXIST    0x00000015
+/* Operation is finished. */
+#define CPE_ETERMINATED  0x00000016
+/* Max count for adsp error code sent to HLOS*/
+#define CPE_ERR_MAX      (CPE_ETERMINATED + 1)
+
+
+/* ERROR STRING */
+/* Success. The operation completed with no errors. */
+#define CPE_EOK_STR          "CPE_EOK"
+/* General failure. */
+#define CPE_EFAILED_STR      "CPE_EFAILED"
+/* Bad operation parameter. */
+#define CPE_EBADPARAM_STR    "CPE_EBADPARAM"
+/* Unsupported routine or operation. */
+#define CPE_EUNSUPPORTED_STR "CPE_EUNSUPPORTED"
+/* Unsupported version. */
+#define CPE_EVERSION_STR     "CPE_EVERSION"
+/* Unexpected problem encountered. */
+#define CPE_EUNEXPECTED_STR  "CPE_EUNEXPECTED"
+/* Unhandled problem occurred. */
+#define CPE_EPANIC_STR       "CPE_EPANIC"
+/* Unable to allocate resource. */
+#define CPE_ENORESOURCE_STR  "CPE_ENORESOURCE"
+/* Invalid handle. */
+#define CPE_EHANDLE_STR      "CPE_EHANDLE"
+/* Operation is already processed. */
+#define CPE_EALREADY_STR     "CPE_EALREADY"
+/* Operation is not ready to be processed. */
+#define CPE_ENOTREADY_STR    "CPE_ENOTREADY"
+/* Operation is pending completion. */
+#define CPE_EPENDING_STR     "CPE_EPENDING"
+/* Operation could not be accepted or processed. */
+#define CPE_EBUSY_STR        "CPE_EBUSY"
+/* Operation aborted due to an error. */
+#define CPE_EABORTED_STR     "CPE_EABORTED"
+/* Operation preempted by a higher priority. */
+#define CPE_EPREEMPTED_STR   "CPE_EPREEMPTED"
+/* Operation requests intervention to complete. */
+#define CPE_ECONTINUE_STR    "CPE_ECONTINUE"
+/* Operation requests immediate intervention to complete. */
+#define CPE_EIMMEDIATE_STR   "CPE_EIMMEDIATE"
+/* Operation is not implemented. */
+#define CPE_ENOTIMPL_STR     "CPE_ENOTIMPL"
+/* Operation needs more data or resources. */
+#define CPE_ENEEDMORE_STR    "CPE_ENEEDMORE"
+/* Operation does not have memory. */
+#define CPE_ENOMEMORY_STR    "CPE_ENOMEMORY"
+/* Item does not exist. */
+#define CPE_ENOTEXIST_STR    "CPE_ENOTEXIST"
+/* Operation is finished. */
+#define CPE_ETERMINATED_STR  "CPE_ETERMINATED"
+/* Unexpected error code. */
+#define CPE_ERR_MAX_STR      "CPE_ERR_MAX"
+
+
+struct cpe_err_code {
+	int     lnx_err_code;
+	char    *cpe_err_str;
+};
+
+
+static struct cpe_err_code cpe_err_code_info[CPE_ERR_MAX+1] = {
+	{ 0, CPE_EOK_STR},
+	{ -ENOTRECOVERABLE, CPE_EFAILED_STR},
+	{ -EINVAL, CPE_EBADPARAM_STR},
+	{ -EOPNOTSUPP, CPE_EUNSUPPORTED_STR},
+	{ -ENOPROTOOPT, CPE_EVERSION_STR},
+	{ -ENOTRECOVERABLE, CPE_EUNEXPECTED_STR},
+	{ -ENOTRECOVERABLE, CPE_EPANIC_STR},
+	{ -ENOSPC, CPE_ENORESOURCE_STR},
+	{ -EBADR, CPE_EHANDLE_STR},
+	{ -EALREADY, CPE_EALREADY_STR},
+	{ -EPERM, CPE_ENOTREADY_STR},
+	{ -EINPROGRESS, CPE_EPENDING_STR},
+	{ -EBUSY, CPE_EBUSY_STR},
+	{ -ECANCELED, CPE_EABORTED_STR},
+	{ -EAGAIN, CPE_EPREEMPTED_STR},
+	{ -EAGAIN, CPE_ECONTINUE_STR},
+	{ -EAGAIN, CPE_EIMMEDIATE_STR},
+	{ -EAGAIN, CPE_ENOTIMPL_STR},
+	{ -ENODATA, CPE_ENEEDMORE_STR},
+	{ -EADV, CPE_ERR_MAX_STR},
+	{ -ENOMEM, CPE_ENOMEMORY_STR},
+	{ -ENODEV, CPE_ENOTEXIST_STR},
+	{ -EADV, CPE_ETERMINATED_STR},
+	{ -EADV, CPE_ERR_MAX_STR},
+};
+
+static inline int cpe_err_get_lnx_err_code(u32 cpe_error)
+{
+	if (cpe_error > CPE_ERR_MAX)
+		return cpe_err_code_info[CPE_ERR_MAX].lnx_err_code;
+	else
+		return cpe_err_code_info[cpe_error].lnx_err_code;
+}
+
+static inline char *cpe_err_get_err_str(u32 cpe_error)
+{
+	if (cpe_error > CPE_ERR_MAX)
+		return cpe_err_code_info[CPE_ERR_MAX].cpe_err_str;
+	else
+		return cpe_err_code_info[cpe_error].cpe_err_str;
+}
+
+#endif

+ 105 - 0
qcom/opensource/audio-kernel/asoc/codecs/csra66x0/Kbuild

@@ -0,0 +1,105 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ CSRA66X0 ############
+
+# for CSRA66X0 Codec
+ifdef CONFIG_SND_SOC_CSRA66X0
+	CSRA66X0_OBJS += csra66x0.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+#EXTRA_CFLAGS += $(INCS)
+ccflags-y += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+#EXTRA_CFLAGS += -Wmaybe-uninitialized
+ccflags-y += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+#EXTRA_CFLAGS += -Wheader-guard
+ccflags-y += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_CSRA66X0) += csra66x0_dlkm.o
+csra66x0_dlkm-y := $(CSRA66X0_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 1525 - 0
qcom/opensource/audio-kernel/asoc/codecs/csra66x0/csra66x0.c

@@ -0,0 +1,1525 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include "csra66x0.h"
+
+#define DRV_NAME "csra66x0_codec"
+#define CSRA66X0_SYSFS_ENTRY_MAX_LEN 64
+
+/* CSRA66X0 register default values */
+static struct reg_default csra66x0_reg_defaults[] = {
+	{CSRA66X0_AUDIO_IF_RX_CONFIG1,           0x00},
+	{CSRA66X0_AUDIO_IF_RX_CONFIG2,           0x0B},
+	{CSRA66X0_AUDIO_IF_RX_CONFIG3,           0x0F},
+	{CSRA66X0_AUDIO_IF_TX_EN,                0x00},
+	{CSRA66X0_AUDIO_IF_TX_CONFIG1,           0x6B},
+	{CSRA66X0_AUDIO_IF_TX_CONFIG2,           0x02},
+	{CSRA66X0_I2C_DEVICE_ADDRESS,            0x0D},
+	{CSRA66X0_CHIP_ID_FA,                    0x39},
+	{CSRA66X0_ROM_VER_FA,                    0x08},
+	{CSRA66X0_CHIP_REV_0_FA,                 0x05},
+	{CSRA66X0_CHIP_REV_1_FA,                 0x03},
+	{CSRA66X0_CH1_MIX_SEL,                   0x01},
+	{CSRA66X0_CH2_MIX_SEL,                   0x10},
+	{CSRA66X0_CH1_SAMPLE1_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE1_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE3_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE3_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE5_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE5_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE7_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE7_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE2_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE2_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE4_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE4_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE6_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE6_SCALE_1,           0x20},
+	{CSRA66X0_CH1_SAMPLE8_SCALE_0,           0x00},
+	{CSRA66X0_CH1_SAMPLE8_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE1_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE1_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE3_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE3_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE5_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE5_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE7_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE7_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE2_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE2_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE4_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE4_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE6_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE6_SCALE_1,           0x20},
+	{CSRA66X0_CH2_SAMPLE8_SCALE_0,           0x00},
+	{CSRA66X0_CH2_SAMPLE8_SCALE_1,           0x20},
+	{CSRA66X0_VOLUME_CONFIG_FA,              0x26},
+	{CSRA66X0_STARTUP_DELAY_FA,              0x00},
+	{CSRA66X0_CH1_VOLUME_0_FA,               0x19},
+	{CSRA66X0_CH1_VOLUME_1_FA,               0x01},
+	{CSRA66X0_CH2_VOLUME_0_FA,               0x19},
+	{CSRA66X0_CH2_VOLUME_1_FA,               0x01},
+	{CSRA66X0_QUAD_ENC_COUNT_0_FA,           0x00},
+	{CSRA66X0_QUAD_ENC_COUNT_1_FA,           0x00},
+	{CSRA66X0_SOFT_CLIP_CONFIG,              0x00},
+	{CSRA66X0_CH1_HARD_CLIP_THRESH,          0x00},
+	{CSRA66X0_CH2_HARD_CLIP_THRESH,          0x00},
+	{CSRA66X0_SOFT_CLIP_THRESH,              0x00},
+	{CSRA66X0_DS_ENABLE_THRESH_0,            0x05},
+	{CSRA66X0_DS_ENABLE_THRESH_1,            0x00},
+	{CSRA66X0_DS_TARGET_COUNT_0,             0x00},
+	{CSRA66X0_DS_TARGET_COUNT_1,             0xFF},
+	{CSRA66X0_DS_TARGET_COUNT_2,             0xFF},
+	{CSRA66X0_DS_DISABLE_THRESH_0,           0x0F},
+	{CSRA66X0_DS_DISABLE_THRESH_1,           0x00},
+	{CSRA66X0_DCA_CTRL,                      0x07},
+	{CSRA66X0_CH1_DCA_THRESH,                0x40},
+	{CSRA66X0_CH2_DCA_THRESH,                0x40},
+	{CSRA66X0_DCA_ATTACK_RATE,               0x00},
+	{CSRA66X0_DCA_RELEASE_RATE,              0x00},
+	{CSRA66X0_CH1_OUTPUT_INVERT_EN,          0x00},
+	{CSRA66X0_CH2_OUTPUT_INVERT_EN,          0x00},
+	{CSRA66X0_CH1_176P4K_DELAY,              0x00},
+	{CSRA66X0_CH2_176P4K_DELAY,              0x00},
+	{CSRA66X0_CH1_192K_DELAY,                0x00},
+	{CSRA66X0_CH2_192K_DELAY,                0x00},
+	{CSRA66X0_DEEMP_CONFIG_FA,               0x00},
+	{CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA,       0x00},
+	{CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA,       0x00},
+	{CSRA66X0_CH1_TREBLE_FC_CTRL_FA,         0x00},
+	{CSRA66X0_CH2_TREBLE_FC_CTRL_FA,         0x00},
+	{CSRA66X0_CH1_BASS_GAIN_CTRL_FA,         0x00},
+	{CSRA66X0_CH2_BASS_GAIN_CTRL_FA,         0x00},
+	{CSRA66X0_CH1_BASS_FC_CTRL_FA,           0x00},
+	{CSRA66X0_CH2_BASS_FC_CTRL_FA,           0x00},
+	{CSRA66X0_FILTER_SEL_8K,                 0x00},
+	{CSRA66X0_FILTER_SEL_11P025K,            0x00},
+	{CSRA66X0_FILTER_SEL_16K,                0x00},
+	{CSRA66X0_FILTER_SEL_22P05K,             0x00},
+	{CSRA66X0_FILTER_SEL_32K,                0x00},
+	{CSRA66X0_FILTER_SEL_44P1K_48K,          0x00},
+	{CSRA66X0_FILTER_SEL_88P2K_96K,          0x00},
+	{CSRA66X0_FILTER_SEL_176P4K_192K,        0x00},
+	/* RESERVED */
+	{CSRA66X0_USER_DSP_CTRL,                 0x00},
+	{CSRA66X0_TEST_TONE_CTRL,                0x00},
+	{CSRA66X0_TEST_TONE_FREQ_0,              0x00},
+	{CSRA66X0_TEST_TONE_FREQ_1,              0x00},
+	{CSRA66X0_TEST_TONE_FREQ_2,              0x00},
+	{CSRA66X0_AUDIO_RATE_CTRL_FA,            0x08},
+	{CSRA66X0_MODULATION_INDEX_CTRL,         0x3F},
+	{CSRA66X0_MODULATION_INDEX_COUNT,        0x10},
+	{CSRA66X0_MIN_MODULATION_PULSE_WIDTH,    0x7A},
+	{CSRA66X0_DEAD_TIME_CTRL,                0x00},
+	{CSRA66X0_DEAD_TIME_THRESHOLD_0,         0xE7},
+	{CSRA66X0_DEAD_TIME_THRESHOLD_1,         0x26},
+	{CSRA66X0_DEAD_TIME_THRESHOLD_2,         0x40},
+	{CSRA66X0_CH1_LOW_SIDE_DLY,              0x00},
+	{CSRA66X0_CH2_LOW_SIDE_DLY,              0x00},
+	{CSRA66X0_SPECTRUM_CTRL,                 0x00},
+	/* RESERVED */
+	{CSRA66X0_SPECTRUM_SPREAD_CTRL,          0x0C},
+	/* RESERVED */
+	{CSRA66X0_EXT_PA_PROTECT_POLARITY,       0x03},
+	{CSRA66X0_TEMP0_BACKOFF_COMP_VALUE,      0x98},
+	{CSRA66X0_TEMP0_SHUTDOWN_COMP_VALUE,     0xA3},
+	{CSRA66X0_TEMP1_BACKOFF_COMP_VALUE,      0x98},
+	{CSRA66X0_TEMP1_SHUTDOWN_COMP_VALUE,     0xA3},
+	{CSRA66X0_TEMP_PROT_BACKOFF,             0x00},
+	{CSRA66X0_TEMP_READ0_FA,                 0x00},
+	{CSRA66X0_TEMP_READ1_FA,                 0x00},
+	{CSRA66X0_CHIP_STATE_CTRL_FA,            0x02},
+	/* RESERVED */
+	{CSRA66X0_PWM_OUTPUT_CONFIG,             0x00},
+	{CSRA66X0_MISC_CONTROL_STATUS_0,         0x08},
+	{CSRA66X0_MISC_CONTROL_STATUS_1_FA,      0x40},
+	{CSRA66X0_PIO0_SELECT,                   0x00},
+	{CSRA66X0_PIO1_SELECT,                   0x00},
+	{CSRA66X0_PIO2_SELECT,                   0x00},
+	{CSRA66X0_PIO3_SELECT,                   0x00},
+	{CSRA66X0_PIO4_SELECT,                   0x00},
+	{CSRA66X0_PIO5_SELECT,                   0x00},
+	{CSRA66X0_PIO6_SELECT,                   0x00},
+	{CSRA66X0_PIO7_SELECT,                   0x00},
+	{CSRA66X0_PIO8_SELECT,                   0x00},
+	{CSRA66X0_PIO_DIRN0,                     0xFF},
+	{CSRA66X0_PIO_DIRN1,                     0x01},
+	{CSRA66X0_PIO_PULL_EN0,                  0xFF},
+	{CSRA66X0_PIO_PULL_EN1,                  0x01},
+	{CSRA66X0_PIO_PULL_DIR0,                 0x00},
+	{CSRA66X0_PIO_PULL_DIR1,                 0x00},
+	{CSRA66X0_PIO_DRIVE_OUT0_FA,             0x00},
+	{CSRA66X0_PIO_DRIVE_OUT1_FA,             0x00},
+	{CSRA66X0_PIO_STATUS_IN0_FA,             0x00},
+	{CSRA66X0_PIO_STATUS_IN1_FA,             0x00},
+	/* RESERVED */
+	{CSRA66X0_IRQ_OUTPUT_ENABLE,             0x00},
+	{CSRA66X0_IRQ_OUTPUT_POLARITY,           0x01},
+	{CSRA66X0_IRQ_OUTPUT_STATUS_FA,          0x00},
+	{CSRA66X0_CLIP_DCA_STATUS_FA,            0x00},
+	{CSRA66X0_CHIP_STATE_STATUS_FA,          0x02},
+	{CSRA66X0_FAULT_STATUS_FA,               0x00},
+	{CSRA66X0_OTP_STATUS_FA,                 0x00},
+	{CSRA66X0_AUDIO_IF_STATUS_FA,            0x00},
+	/* RESERVED */
+	{CSRA66X0_DSP_SATURATION_STATUS_FA,      0x00},
+	{CSRA66X0_AUDIO_RATE_STATUS_FA,          0x00},
+	/* RESERVED */
+	{CSRA66X0_DISABLE_PWM_OUTPUT,            0x00},
+	/* RESERVED */
+	{CSRA66X0_OTP_VER_FA,                    0x03},
+	{CSRA66X0_RAM_VER_FA,                    0x02},
+	/* RESERVED */
+	{CSRA66X0_AUDIO_SATURATION_FLAGS_FA,     0x00},
+	{CSRA66X0_DCOFFSET_CHAN_1_01_FA,         0x00},
+	{CSRA66X0_DCOFFSET_CHAN_1_02_FA,         0x00},
+	{CSRA66X0_DCOFFSET_CHAN_1_03_FA,         0x00},
+	{CSRA66X0_DCOFFSET_CHAN_2_01_FA,         0x00},
+	{CSRA66X0_DCOFFSET_CHAN_2_02_FA,         0x00},
+	{CSRA66X0_DCOFFSET_CHAN_2_03_FA,         0x00},
+	{CSRA66X0_FORCED_PA_SWITCHING_CTRL,      0x90},
+	{CSRA66X0_PA_FORCE_PULSE_WIDTH,          0x07},
+	{CSRA66X0_PA_HIGH_MODULATION_CTRL_CH1,   0x00},
+	/* RESERVED */
+	{CSRA66X0_HIGH_MODULATION_THRESHOLD_LOW, 0xD4},
+	{CSRA66X0_HIGH_MODULATION_THRESHOLD_HIGH, 0x78},
+	/* RESERVED */
+	{CSRA66X0_PA_FREEZE_CTRL,                0x00},
+	{CSRA66X0_DCA_FREEZE_CTRL,               0x3C},
+	/* RESERVED */
+};
+
+static bool csra66x0_addr_is_in_range(unsigned int addr,
+	unsigned int addr_min, unsigned int addr_max)
+{
+	if ((addr >= addr_min)
+			&& (addr <= addr_max))
+		return true;
+	else
+		return false;
+}
+
+static bool csra66x0_volatile_register(struct device *dev, unsigned int reg)
+{
+	/* coeff registers */
+	if (csra66x0_addr_is_in_range(reg, CSRA66X0_COEFF_BASE,
+		CSRA66X0_MAX_COEFF_ADDR))
+		return true;
+
+	/* control registers */
+	switch (reg) {
+	case CSRA66X0_CHIP_ID_FA:
+	case CSRA66X0_ROM_VER_FA:
+	case CSRA66X0_CHIP_REV_0_FA:
+	case CSRA66X0_CHIP_REV_1_FA:
+	case CSRA66X0_TEMP_READ0_FA:
+	case CSRA66X0_TEMP_READ1_FA:
+	case CSRA66X0_CHIP_STATE_CTRL_FA:
+	case CSRA66X0_MISC_CONTROL_STATUS_1_FA:
+	case CSRA66X0_IRQ_OUTPUT_STATUS_FA:
+	case CSRA66X0_CLIP_DCA_STATUS_FA:
+	case CSRA66X0_CHIP_STATE_STATUS_FA:
+	case CSRA66X0_FAULT_STATUS_FA:
+	case CSRA66X0_OTP_STATUS_FA:
+	case CSRA66X0_AUDIO_IF_STATUS_FA:
+	case CSRA66X0_DSP_SATURATION_STATUS_FA:
+	case CSRA66X0_AUDIO_RATE_STATUS_FA:
+	case CSRA66X0_CH1_MIX_SEL:
+	case CSRA66X0_CH2_MIX_SEL:
+	case CSRA66X0_CH1_SAMPLE1_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE1_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE3_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE3_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE5_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE5_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE7_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE7_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE2_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE2_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE4_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE4_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE6_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE6_SCALE_1:
+	case CSRA66X0_CH1_SAMPLE8_SCALE_0:
+	case CSRA66X0_CH1_SAMPLE8_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE1_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE1_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE3_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE3_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE5_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE5_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE7_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE7_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE2_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE2_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE4_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE4_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE6_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE6_SCALE_1:
+	case CSRA66X0_CH2_SAMPLE8_SCALE_0:
+	case CSRA66X0_CH2_SAMPLE8_SCALE_1:
+	case CSRA66X0_RAM_VER_FA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool csra66x0_writeable_registers(struct device *dev, unsigned int reg)
+{
+	if (csra66x0_addr_is_in_range(reg, CSRA66X0_BASE,
+		CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(reg, CSRA66X0_COEFF_BASE,
+		CSRA66X0_MAX_COEFF_ADDR))
+		return true;
+	else
+		return false;
+}
+
+static bool csra66x0_readable_registers(struct device *dev, unsigned int reg)
+{
+	if (csra66x0_addr_is_in_range(reg, CSRA66X0_BASE,
+		CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(reg, CSRA66X0_COEFF_BASE,
+		CSRA66X0_MAX_COEFF_ADDR))
+		return true;
+	else
+		return false;
+}
+
+/* codec private data */
+struct csra66x0_priv {
+	struct regmap *regmap;
+	struct snd_soc_component *component;
+	int spk_volume_ch1;
+	int spk_volume_ch2;
+	int irq;
+	int vreg_gpio;
+	u32 irq_active_low;
+	u32 in_cluster;
+	u32 is_master;
+	bool is_probed;
+	u32 max_num_cluster_devices;
+	u32 num_cluster_devices;
+	u32 sysfs_reg_addr;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	struct dentry *debugfs_dir;
+	struct dentry *debugfs_file_wo;
+	struct dentry *debugfs_file_ro;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+struct csra66x0_cluster_device {
+	struct csra66x0_priv *csra66x0_ptr;
+	const char *csra66x0_prefix;
+};
+
+struct csra66x0_cluster_device csra_clust_dev_tbl[] = {
+	{NULL, "CSRA_12"},
+	{NULL, "CSRA_34"},
+	{NULL, "CSRA_56"},
+	{NULL, "CSRA_78"},
+	{NULL, "CSRA_9A"},
+	{NULL, "CSRA_BC"},
+	{NULL, "CSRA_DE"},
+	{NULL, "CSRA_F0"}
+};
+
+static int sysfs_get_param(char *buf, u32 *param, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtou32(token, base, &param[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else {
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static int debugfs_codec_open_op(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t debugfs_codec_write_op(struct file *filp,
+		const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	struct csra66x0_priv *csra66x0 =
+			(struct csra66x0_priv *) filp->private_data;
+	struct snd_soc_component *component = csra66x0->component;
+	char lbuf[32];
+	int rc;
+	u32 param[2];
+
+	if (!filp || !ppos || !ubuf || !component)
+		return -EINVAL;
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+	lbuf[cnt] = '\0';
+	rc = sysfs_get_param(lbuf, param, 2);
+
+	if (!(csra66x0_addr_is_in_range(param[0],
+		CSRA66X0_BASE, CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(param[0],
+		CSRA66X0_COEFF_BASE, CSRA66X0_MAX_COEFF_ADDR))) {
+		dev_err(component->dev, "%s: register address 0x%04X out of range\n",
+			__func__, param[0]);
+		return -EINVAL;
+	}
+	if ((param[1] < 0) || (param[1] > 255)) {
+		dev_err(component->dev, "%s: register data 0x%02X out of range\n",
+			__func__, param[1]);
+		return -EINVAL;
+	}
+	if (rc == 0)
+	{
+		rc = cnt;
+		dev_info(component->dev, "%s: reg[0x%04X]=0x%02X\n",
+			__func__, param[0], param[1]);
+		snd_soc_component_write(component, param[0], param[1]);
+	} else {
+		dev_err(component->dev, "%s: write to register addr=0x%04X failed\n",
+			__func__, param[0]);
+	}
+	return rc;
+}
+
+static ssize_t debugfs_csra66x0_reg_show(struct csra66x0_priv *csra66x0,
+		char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int i, reg_val, len;
+	int addr_min, addr_max;
+	ssize_t total = 0;
+	char tmp_buf[20];
+	struct snd_soc_component *component = csra66x0->component;
+
+	if (!ubuf || !ppos || !component || *ppos < 0)
+		return -EINVAL;
+
+	if (csra66x0_addr_is_in_range(csra66x0->sysfs_reg_addr,
+		CSRA66X0_COEFF_BASE, CSRA66X0_MAX_COEFF_ADDR)) {
+		addr_min = CSRA66X0_COEFF_BASE;
+		addr_max = CSRA66X0_MAX_COEFF_ADDR;
+		csra66x0->sysfs_reg_addr = CSRA66X0_BASE;
+	} else {
+		addr_min = CSRA66X0_BASE;
+		addr_max = CSRA66X0_MAX_REGISTER_ADDR;
+	}
+
+	for (i = ((int) *ppos + addr_min);
+		i <= addr_max; i++) {
+		reg_val = snd_soc_component_read32(component, i);
+		len = snprintf(tmp_buf, 20, "0x%04X: 0x%02X\n", i, (reg_val & 0xFF));
+		if ((total + len) >= count - 1)
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			dev_err(component->dev, "%s: fail to copy reg dump\n",
+				__func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		*ppos += len;
+		total += len;
+	}
+
+copy_err:
+	return total;
+}
+
+static ssize_t debugfs_codec_read_op(struct file *filp,
+		char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	struct csra66x0_priv *csra66x0 =
+		(struct csra66x0_priv *) filp->private_data;
+	ssize_t ret_cnt;
+
+	if (!filp || !ppos || !ubuf || *ppos < 0)
+		return -EINVAL;
+	ret_cnt = debugfs_csra66x0_reg_show(csra66x0, ubuf, cnt, ppos);
+	return ret_cnt;
+}
+
+static const struct file_operations debugfs_codec_ops = {
+	.open = debugfs_codec_open_op,
+	.write = debugfs_codec_write_op,
+	.read = debugfs_codec_read_op,
+};
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * CSRA66X0 Controls
+ */
+static const DECLARE_TLV_DB_SCALE(csra66x0_volume_tlv, -9000, 25, 0);
+static const DECLARE_TLV_DB_RANGE(csra66x0_bass_treble_tlv,
+		0,  0, TLV_DB_SCALE_ITEM(0,   0, 0),
+		1, 15, TLV_DB_SCALE_ITEM(-1500, 100, 0),
+		16, 30, TLV_DB_SCALE_ITEM(100, 100, 0)
+);
+
+static int csra66x0_get_volume(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+			(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	unsigned int reg_l = mc->reg;
+	unsigned int reg_r = mc->rreg;
+	unsigned int val_l, val_r;
+
+	val_l = (snd_soc_component_read32(component, reg_l) & 0xff) |
+			((snd_soc_component_read32(component,
+			CSRA66X0_CH1_VOLUME_1_FA) & (0x01)) << 8);
+	val_r = (snd_soc_component_read32(component, reg_r) & 0xff) |
+			((snd_soc_component_read32(component,
+			CSRA66X0_CH2_VOLUME_1_FA) & (0x01)) << 8);
+	ucontrol->value.integer.value[0] = val_l;
+	ucontrol->value.integer.value[1] = val_r;
+	return 0;
+}
+
+static int csra66x0_set_volume(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+			(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct csra66x0_priv *csra66x0 =
+			snd_soc_component_get_drvdata(component);
+	unsigned int reg_l = mc->reg;
+	unsigned int reg_r = mc->rreg;
+	unsigned int val_l[2];
+	unsigned int val_r[2];
+
+	csra66x0->spk_volume_ch1 = (ucontrol->value.integer.value[0]);
+	csra66x0->spk_volume_ch2 = (ucontrol->value.integer.value[1]);
+	val_l[0] = csra66x0->spk_volume_ch1 & SPK_VOLUME_LSB_MSK;
+	val_l[1] = (csra66x0->spk_volume_ch1 & SPK_VOLUME_MSB_MSK) ? 1 : 0;
+	val_r[0] = csra66x0->spk_volume_ch2 & SPK_VOLUME_LSB_MSK;
+	val_r[1] = (csra66x0->spk_volume_ch2 & SPK_VOLUME_MSB_MSK) ? 1 : 0;
+	snd_soc_component_write(component, reg_l, val_l[0]);
+	snd_soc_component_write(component, reg_r, val_r[0]);
+	snd_soc_component_write(component, CSRA66X0_CH1_VOLUME_1_FA, val_l[1]);
+	snd_soc_component_write(component, CSRA66X0_CH2_VOLUME_1_FA, val_r[1]);
+	return 0;
+}
+
+/* enumerated controls */
+static const char * const csra66x0_mute_output_text[] = {"PLAY", "MUTE"};
+static const char * const csra66x0_output_invert_text[] = {
+		"UNCHANGED", "INVERTED"};
+static const char * const csra66x0_deemp_config_text[] = {
+		"DISABLED", "ENABLED"};
+
+SOC_ENUM_SINGLE_DECL(csra66x0_mute_output_enum,
+			CSRA66X0_MISC_CONTROL_STATUS_1_FA, 2,
+			csra66x0_mute_output_text);
+SOC_ENUM_SINGLE_DECL(csra66x0_ch1_output_invert_enum,
+			CSRA66X0_CH1_OUTPUT_INVERT_EN, 0,
+			csra66x0_output_invert_text);
+SOC_ENUM_SINGLE_DECL(csra66x0_ch2_output_invert_enum,
+			CSRA66X0_CH2_OUTPUT_INVERT_EN, 0,
+			csra66x0_output_invert_text);
+SOC_ENUM_DOUBLE_DECL(csra66x0_deemp_config_enum,
+			CSRA66X0_DEEMP_CONFIG_FA, 0, 1,
+			csra66x0_deemp_config_text);
+
+static const struct snd_kcontrol_new csra66x0_snd_controls[] = {
+	/* volume */
+	SOC_DOUBLE_R_EXT_TLV("PA VOLUME", CSRA66X0_CH1_VOLUME_0_FA,
+			CSRA66X0_CH2_VOLUME_0_FA, 0, 0x1C9, 0,
+			csra66x0_get_volume, csra66x0_set_volume,
+			csra66x0_volume_tlv),
+
+	/* bass treble */
+	SOC_DOUBLE_R_TLV("PA BASS GAIN", CSRA66X0_CH1_BASS_GAIN_CTRL_FA,
+			CSRA66X0_CH2_BASS_GAIN_CTRL_FA, 0, 0x1E, 0,
+			csra66x0_bass_treble_tlv),
+	SOC_DOUBLE_R_TLV("PA TREBLE GAIN", CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA,
+			CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA, 0, 0x1E, 0,
+			csra66x0_bass_treble_tlv),
+	SOC_DOUBLE_R("PA BASS_XOVER FREQ", CSRA66X0_CH1_BASS_FC_CTRL_FA,
+			CSRA66X0_CH2_BASS_FC_CTRL_FA, 0, 2, 0),
+	SOC_DOUBLE_R("PA TREBLE_XOVER FREQ", CSRA66X0_CH1_TREBLE_FC_CTRL_FA,
+			CSRA66X0_CH2_TREBLE_FC_CTRL_FA, 0, 2, 0),
+
+	/* switch */
+	SOC_ENUM("PA MUTE_OUTPUT SWITCH", csra66x0_mute_output_enum),
+	SOC_ENUM("PA DE-EMPHASIS SWITCH", csra66x0_deemp_config_enum),
+};
+
+static const struct snd_kcontrol_new csra_mix_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_soc_dapm_widget csra66x0_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("IN"),
+	SND_SOC_DAPM_MIXER("MIXER", SND_SOC_NOPM, 0, 0,
+			csra_mix_switch, ARRAY_SIZE(csra_mix_switch)),
+	SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUTPUT("SPKR"),
+};
+
+static const struct snd_soc_dapm_route csra66x0_dapm_routes[] = {
+	{"MIXER", "Switch", "IN"},
+	{"DAC", NULL, "MIXER"},
+	{"PGA", NULL, "DAC"},
+	{"SPKR", NULL, "PGA"},
+};
+/*
+ * csra66x0_hw_free_mute - Update csra66x0 mute register
+ *
+ * @component - csra66x0 component
+ *
+ */
+void csra66x0_hw_free_mute(struct snd_soc_component *component)
+{
+	int val = 0;
+
+	if (component == NULL)
+		return;
+
+	val = snd_soc_component_read32(component,
+			CSRA66X0_MISC_CONTROL_STATUS_1_FA);
+	snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_1_FA,
+			val | 0x04);
+}
+EXPORT_SYMBOL(csra66x0_hw_free_mute);
+
+static int csra66x0_wait_for_config_state(struct snd_soc_component *component)
+{
+	u16 val;
+	int cntdwn = WAIT_FOR_CONFIG_STATE_TIMEOUT_MS;
+
+	do {
+		/* wait >= 100ms to check if HW has moved to config state */
+		msleep(100);
+		val = snd_soc_component_read32(component,
+				CSRA66X0_CHIP_STATE_STATUS_FA);
+		if (val == CONFIG_STATE_ID)
+			break;
+
+		cntdwn = cntdwn - 100;
+	} while (cntdwn > 0);
+	if (cntdwn <= 0)
+		return -EFAULT;
+
+	return 0;
+}
+
+static int csra66x0_allow_run(struct csra66x0_priv *csra66x0)
+{
+	struct snd_soc_component *component = csra66x0->component;
+	int i;
+
+	/* csra66x0 is not in cluster */
+	if (!csra66x0->in_cluster) {
+		/* enable interrupts */
+		if (csra66x0->irq) {
+			snd_soc_component_write(component,
+				CSRA66X0_PIO0_SELECT, 0x1);
+			if (csra66x0->irq_active_low)
+				snd_soc_component_write(component,
+					CSRA66X0_IRQ_OUTPUT_POLARITY, 0x0);
+			else
+				snd_soc_component_write(component,
+					CSRA66X0_IRQ_OUTPUT_POLARITY, 0x1);
+
+			snd_soc_component_write(component,
+				CSRA66X0_IRQ_OUTPUT_ENABLE, 0x01);
+		} else {
+			snd_soc_component_write(component,
+				CSRA66X0_IRQ_OUTPUT_ENABLE, 0x00);
+		}
+		/* allow run */
+		snd_soc_component_write(component,
+			CSRA66X0_CHIP_STATE_CTRL_FA, SET_RUN_STATE);
+		return 0;
+	}
+
+	/* csra66x0 is part of cluster */
+	/* get number of probed cluster devices */
+	csra66x0->num_cluster_devices = 0;
+	for (i = 0; i < component->card->num_aux_devs; i++) {
+		if (i >= csra66x0->max_num_cluster_devices)
+			break;
+		if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+			continue;
+		if (csra_clust_dev_tbl[i].csra66x0_ptr->is_probed)
+			csra66x0->num_cluster_devices++;
+	}
+
+	/* check if all cluster devices are probed */
+	if (csra66x0->num_cluster_devices
+		== component->card->num_aux_devs) {
+		/* allow run of all slave components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				continue;
+			snd_soc_component_write(
+				csra_clust_dev_tbl[i].csra66x0_ptr->component,
+				CSRA66X0_CHIP_STATE_CTRL_FA, SET_RUN_STATE);
+		}
+		/* allow run of all master components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (!csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				continue;
+
+			/* enable interrupts */
+			if (csra66x0->irq) {
+				snd_soc_component_write(component,
+					CSRA66X0_PIO0_SELECT, 0x1);
+				if (csra66x0->irq_active_low)
+					snd_soc_component_write(component,
+						CSRA66X0_IRQ_OUTPUT_POLARITY,
+						0x0);
+				else
+					snd_soc_component_write(component,
+						CSRA66X0_IRQ_OUTPUT_POLARITY,
+						0x1);
+
+				snd_soc_component_write(component,
+					CSRA66X0_IRQ_OUTPUT_ENABLE, 0x01);
+			} else {
+				snd_soc_component_write(component,
+					CSRA66X0_IRQ_OUTPUT_ENABLE, 0x00);
+			}
+			/* allow run */
+			snd_soc_component_write(
+				csra_clust_dev_tbl[i].csra66x0_ptr->component,
+				CSRA66X0_CHIP_STATE_CTRL_FA, SET_RUN_STATE);
+		}
+	}
+	return 0;
+}
+
+static int csra66x0_init(struct csra66x0_priv *csra66x0)
+{
+	struct snd_soc_component *component = csra66x0->component;
+	int ret;
+
+	dev_dbg(component->dev, "%s: initialize %s\n",
+		__func__, component->name);
+	csra66x0->sysfs_reg_addr = CSRA66X0_BASE;
+	/* config */
+	snd_soc_component_write(component, CSRA66X0_CHIP_STATE_CTRL_FA,
+				SET_CONFIG_STATE);
+	/* wait until HW is in config state before proceeding */
+	ret = csra66x0_wait_for_config_state(component);
+	if (ret) {
+		dev_err(component->dev, "%s: timeout while %s is waiting for config state\n",
+			__func__, component->name);
+	}
+
+	/* setup */
+	snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_0,
+				0x09);
+	snd_soc_component_write(component, CSRA66X0_TEMP_PROT_BACKOFF, 0x0C);
+	snd_soc_component_write(component, CSRA66X0_EXT_PA_PROTECT_POLARITY,
+				0x03);
+	snd_soc_component_write(component, CSRA66X0_PWM_OUTPUT_CONFIG, 0xC8);
+	csra66x0->spk_volume_ch1 = SPK_VOLUME_M20DB;
+	csra66x0->spk_volume_ch2 = SPK_VOLUME_M20DB;
+	snd_soc_component_write(component, CSRA66X0_CH1_VOLUME_0_FA,
+				SPK_VOLUME_M20DB_LSB);
+	snd_soc_component_write(component, CSRA66X0_CH2_VOLUME_0_FA,
+				SPK_VOLUME_M20DB_LSB);
+	snd_soc_component_write(component, CSRA66X0_CH1_VOLUME_1_FA,
+				SPK_VOLUME_M20DB_MSB);
+	snd_soc_component_write(component, CSRA66X0_CH2_VOLUME_1_FA,
+				SPK_VOLUME_M20DB_MSB);
+
+	/* disable volume ramping */
+	snd_soc_component_write(component, CSRA66X0_VOLUME_CONFIG_FA, 0x27);
+
+	snd_soc_component_write(component, CSRA66X0_DEAD_TIME_CTRL, 0x0);
+	snd_soc_component_write(component, CSRA66X0_DEAD_TIME_THRESHOLD_0,
+				0xE7);
+	snd_soc_component_write(component, CSRA66X0_DEAD_TIME_THRESHOLD_1,
+				0x26);
+	snd_soc_component_write(component, CSRA66X0_DEAD_TIME_THRESHOLD_2,
+				0x40);
+
+	snd_soc_component_write(component, CSRA66X0_MIN_MODULATION_PULSE_WIDTH,
+				0x7A);
+	snd_soc_component_write(component, CSRA66X0_CH1_HARD_CLIP_THRESH, 0x00);
+	snd_soc_component_write(component, CSRA66X0_CH2_HARD_CLIP_THRESH, 0x00);
+
+	snd_soc_component_write(component, CSRA66X0_CH1_DCA_THRESH, 0x40);
+	snd_soc_component_write(component, CSRA66X0_CH2_DCA_THRESH, 0x40);
+	snd_soc_component_write(component, CSRA66X0_DCA_ATTACK_RATE, 0x00);
+	snd_soc_component_write(component, CSRA66X0_DCA_RELEASE_RATE, 0x00);
+
+	csra66x0_allow_run(csra66x0);
+	return 0;
+}
+
+static int csra66x0_reset(struct csra66x0_priv *csra66x0)
+{
+	struct snd_soc_component *component = csra66x0->component;
+	u16 val;
+
+	val = snd_soc_component_read32(component, CSRA66X0_FAULT_STATUS_FA);
+	if (val & FAULT_STATUS_INTERNAL)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_INTERNAL 0x%X\n",
+			__func__, val);
+	if (val & FAULT_STATUS_OTP_INTEGRITY)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_OTP_INTEGRITY 0x%X\n",
+			__func__, val);
+	if (val & FAULT_STATUS_PADS2)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_PADS2 0x%X\n",
+			__func__, val);
+	if (val & FAULT_STATUS_SMPS)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_SMPS 0x%X\n",
+			__func__, val);
+	if (val & FAULT_STATUS_TEMP)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_TEMP 0x%X\n",
+			__func__, val);
+	if (val & FAULT_STATUS_PROTECT)
+		dev_dbg(component->dev, "%s: FAULT_STATUS_PROTECT 0x%X\n",
+			__func__, val);
+
+	dev_dbg(component->dev, "%s: reset %s\n",
+		__func__, component->name);
+	/* clear fault state and re-init */
+	snd_soc_component_write(component, CSRA66X0_FAULT_STATUS_FA, 0x00);
+	snd_soc_component_write(component, CSRA66X0_IRQ_OUTPUT_STATUS_FA, 0x00);
+	/* apply reset to CSRA66X0 */
+	val = snd_soc_component_read32(component,
+			CSRA66X0_MISC_CONTROL_STATUS_1_FA);
+	snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_1_FA,
+			val | 0x08);
+	/* wait 500ms after reset to recover CSRA66X0 */
+	msleep(500);
+	return 0;
+}
+
+static int csra66x0_msconfig(struct csra66x0_priv *csra66x0)
+{
+	struct snd_soc_component *component = csra66x0->component;
+	int ret;
+
+	dev_dbg(component->dev, "%s: configure %s\n",
+		__func__, component->name);
+	/* config */
+	snd_soc_component_write(component, CSRA66X0_CHIP_STATE_CTRL_FA,
+		SET_CONFIG_STATE);
+	/* wait until HW is in config state before proceeding */
+	ret = csra66x0_wait_for_config_state(component);
+	if (ret) {
+		dev_err(component->dev, "%s: timeout while %s is waiting for config state\n",
+			__func__, component->name);
+		return ret;
+	}
+	snd_soc_component_write(component, CSRA66X0_PIO7_SELECT, 0x04);
+	snd_soc_component_write(component, CSRA66X0_PIO8_SELECT, 0x04);
+	if (csra66x0->is_master) {
+		/* Master specific config */
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_EN0, 0xFF);
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_DIR0, 0x80);
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_EN1, 0x01);
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_DIR1, 0x01);
+	} else {
+		/* Slave specific config */
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_EN0, 0x7F);
+		snd_soc_component_write(component,
+				CSRA66X0_PIO_PULL_EN1, 0x00);
+	}
+	snd_soc_component_write(component, CSRA66X0_DCA_CTRL, 0x05);
+	return 0;
+}
+
+static int csra66x0_soc_probe(struct snd_soc_component *component)
+{
+	struct csra66x0_priv *csra66x0 =
+				snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm;
+	char name[50];
+	unsigned int i;
+
+	csra66x0->component = component;
+	if (csra66x0->in_cluster) {
+		dapm = snd_soc_component_get_dapm(component);
+		dev_dbg(component->dev, "%s: assign prefix %s to component device %s\n",
+			__func__, component->name_prefix,
+			component->name);
+
+		/* add device to cluster table */
+		csra66x0->max_num_cluster_devices =
+			ARRAY_SIZE(csra_clust_dev_tbl);
+		for (i = 0; i < csra66x0->max_num_cluster_devices; i++) {
+			if (!strncmp(component->name_prefix,
+				csra_clust_dev_tbl[i].csra66x0_prefix,
+				strnlen(
+				csra_clust_dev_tbl[i].csra66x0_prefix,
+				sizeof(
+				csra_clust_dev_tbl[i].csra66x0_prefix)))) {
+				csra_clust_dev_tbl[i].csra66x0_ptr = csra66x0;
+				break;
+			}
+			if (i == csra66x0->max_num_cluster_devices - 1)
+				dev_warn(component->dev,
+					"%s: Unknown prefix %s of cluster device %s\n",
+					__func__, component->name_prefix,
+					component->name);
+		}
+
+		/* master slave config */
+		csra66x0_msconfig(csra66x0);
+		if (dapm->component) {
+			strlcpy(name, dapm->component->name_prefix,
+					sizeof(name));
+			strlcat(name, " IN", sizeof(name));
+			snd_soc_dapm_ignore_suspend(dapm, name);
+			strlcpy(name, dapm->component->name_prefix,
+					sizeof(name));
+			strlcat(name, " SPKR", sizeof(name));
+			snd_soc_dapm_ignore_suspend(dapm, name);
+		}
+	}
+
+	/* common initialization */
+	csra66x0->is_probed = 1;
+	csra66x0_init(csra66x0);
+	return 0;
+}
+
+static void csra66x0_soc_remove(struct snd_soc_component *component)
+{
+	snd_soc_component_write(component, CSRA66X0_CHIP_STATE_CTRL_FA,
+				SET_STDBY_STATE);
+	return;
+}
+
+static const struct snd_soc_component_driver soc_codec_drv_csra66x0 = {
+	.name = DRV_NAME,
+	.probe  = csra66x0_soc_probe,
+	.remove = csra66x0_soc_remove,
+	.controls = csra66x0_snd_controls,
+	.num_controls = ARRAY_SIZE(csra66x0_snd_controls),
+	.dapm_widgets = csra66x0_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(csra66x0_dapm_widgets),
+	.dapm_routes = csra66x0_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(csra66x0_dapm_routes),
+};
+
+static struct regmap_config csra66x0_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = csra66x0_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(csra66x0_reg_defaults),
+	.max_register = CSRA66X0_MAX_COEFF_ADDR,
+	.volatile_reg = csra66x0_volatile_register,
+	.writeable_reg = csra66x0_writeable_registers,
+	.readable_reg = csra66x0_readable_registers,
+};
+
+static irqreturn_t csra66x0_irq(int irq, void *data)
+{
+	struct csra66x0_priv *csra66x0 = (struct csra66x0_priv *) data;
+	struct snd_soc_component  *component = csra66x0->component;
+	u16    val;
+	unsigned int i;
+
+	/* Treat interrupt before component is initialized as spurious */
+	if (component == NULL)
+		return IRQ_NONE;
+
+	dev_dbg(component->dev, "%s: csra66x0_interrupt triggered by %s\n",
+		__func__, component->name);
+
+	/* fault  indication */
+	val = snd_soc_component_read32(component, CSRA66X0_IRQ_OUTPUT_STATUS_FA)
+		& 0x1;
+	if (!val)
+		return IRQ_HANDLED;
+
+	if (csra66x0->in_cluster) {
+		/* reset all slave components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				continue;
+			csra66x0_reset(csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+		/* reset all master components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				csra66x0_reset(
+					csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+		/* recover all components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			csra66x0_msconfig(csra_clust_dev_tbl[i].csra66x0_ptr);
+			csra66x0_init(csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+	} else {
+		csra66x0_reset(csra66x0);
+		csra66x0_init(csra66x0);
+	}
+	return IRQ_HANDLED;
+};
+
+static const struct of_device_id csra66x0_of_match[] = {
+	{ .compatible = "qcom,csra66x0", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, csra66x0_of_match);
+
+static ssize_t csra66x0_sysfs_write2reg_addr_value(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	u32 param[2]; /*reg_addr, reg_value */
+	char lbuf[CSRA66X0_SYSFS_ENTRY_MAX_LEN];
+	struct csra66x0_priv *csra66x0 = dev_get_drvdata(dev);
+	struct snd_soc_component *component = csra66x0->component;
+
+	if (!csra66x0) {
+		dev_err(component->dev, "%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (count > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	ret = strlcpy(lbuf, buf, count);
+	if (ret != count) {
+		dev_err(component->dev, "%s: copy input from user space failed. ret=%d\n",
+			__func__, ret);
+		ret = -EFAULT;
+		goto end;
+	}
+
+	lbuf[count] = '\0';
+	ret = sysfs_get_param(lbuf, param, 2);
+	if (ret) {
+		dev_err(component->dev, "%s: get sysfs parameter failed. ret=%d\n",
+			__func__, ret);
+		goto end;
+	}
+
+	if (!(csra66x0_addr_is_in_range(param[0],
+		CSRA66X0_BASE, CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(param[0],
+		CSRA66X0_COEFF_BASE, CSRA66X0_MAX_COEFF_ADDR))) {
+		dev_err(component->dev, "%s: register address 0x%04X out of range\n",
+			__func__, param[0]);
+		ret = -EINVAL;
+		goto end;
+	}
+
+	if ((param[1] < 0) || (param[1] > 255)) {
+		dev_err(component->dev, "%s: register data 0x%02X out of range\n",
+			__func__, param[1]);
+		ret = -EINVAL;
+		goto end;
+	}
+
+	snd_soccomponent_component_write(component, param[0], param[1]);
+	ret = count;
+
+end:
+	return ret;
+}
+
+static ssize_t csra66x0_sysfs_read2reg_addr_set(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	u32 reg_addr;
+	char lbuf[CSRA66X0_SYSFS_ENTRY_MAX_LEN];
+	struct csra66x0_priv *csra66x0 = dev_get_drvdata(dev);
+
+	if (!csra66x0) {
+		dev_err(dev, "%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (count > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	ret = strlcpy(lbuf, buf, count);
+	if (ret != count) {
+		dev_err(dev, "%s: copy input from user space failed. ret=%d\n",
+			__func__, ret);
+		ret = -EFAULT;
+		goto end;
+	}
+
+	lbuf[count] = '\0';
+	ret = sysfs_get_param(lbuf, &reg_addr, 1);
+	if (ret) {
+		dev_err(dev, "%s: get sysfs parameter failed. ret=%d\n",
+			__func__, ret);
+		goto end;
+	}
+
+	if (!(csra66x0_addr_is_in_range(reg_addr,
+		CSRA66X0_BASE, CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(reg_addr,
+		CSRA66X0_COEFF_BASE, CSRA66X0_MAX_COEFF_ADDR))) {
+		dev_err(dev, "%s: register address 0x%04X out of range\n",
+			__func__, reg_addr);
+		ret = -EINVAL;
+		goto end;
+	}
+
+	csra66x0->sysfs_reg_addr = reg_addr;
+	ret = count;
+
+end:
+	return ret;
+}
+
+static ssize_t csra66x0_sysfs_read2reg_addr_get(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int ret;
+	u32 reg_addr;
+	struct csra66x0_priv *csra66x0 = dev_get_drvdata(dev);
+
+	if (!csra66x0) {
+		dev_err(dev, "%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	reg_addr = csra66x0->sysfs_reg_addr;
+
+	ret = snprintf(buf, CSRA66X0_SYSFS_ENTRY_MAX_LEN,
+		"0x%04X\n", reg_addr);
+	pr_debug("%s: 0x%04X\n", __func__, reg_addr);
+
+	return ret;
+}
+
+static ssize_t csra66x0_sysfs_read2reg_value(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int ret;
+	u32 reg_val, reg_addr;
+	struct csra66x0_priv *csra66x0 = dev_get_drvdata(dev);
+	struct snd_soc_component *component = csra66x0->component;
+
+	if (!csra66x0) {
+		dev_err(dev, "%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	reg_addr = csra66x0->sysfs_reg_addr;
+	if (!(csra66x0_addr_is_in_range(reg_addr,
+		CSRA66X0_BASE, CSRA66X0_MAX_REGISTER_ADDR)
+		|| csra66x0_addr_is_in_range(reg_addr,
+		CSRA66X0_COEFF_BASE, CSRA66X0_MAX_COEFF_ADDR))) {
+		pr_debug("%s: 0x%04X: register address out of range\n",
+			__func__, reg_addr);
+		ret = snprintf(buf, CSRA66X0_SYSFS_ENTRY_MAX_LEN,
+			"0x%04X: register address out of range\n", reg_addr);
+		goto end;
+	}
+
+	reg_val = snd_soc_component_read32(component, csra66x0->sysfs_reg_addr);
+	ret = snprintf(buf, CSRA66X0_SYSFS_ENTRY_MAX_LEN,
+		"0x%04X:	0x%02X\n", csra66x0->sysfs_reg_addr, reg_val);
+	pr_debug("%s: 0x%04X: 0x%02X\n", __func__,
+		csra66x0->sysfs_reg_addr, reg_val);
+
+end:
+	return ret;
+}
+
+static ssize_t csra66x0_sysfs_reset(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int val, rc;
+	struct csra66x0_priv *csra66x0 = dev_get_drvdata(dev);
+	struct snd_soc_component *component = csra66x0->component;
+	unsigned int i;
+
+	if (!csra66x0) {
+		dev_err(dev, "%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if (val != SYSFS_RESET) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	pr_debug("%s: reset device\n", __func__);
+	if (csra66x0->in_cluster) {
+		/* reset all slave components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				continue;
+			csra66x0_reset(csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+		/* reset all master components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr->is_master)
+				csra66x0_reset(
+					csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+		/* recover all components */
+		for (i = 0; i < component->card->num_aux_devs; i++) {
+			if (i >= csra66x0->max_num_cluster_devices)
+				break;
+			if (csra_clust_dev_tbl[i].csra66x0_ptr == NULL)
+				continue;
+			csra66x0_msconfig(csra_clust_dev_tbl[i].csra66x0_ptr);
+			csra66x0_init(csra_clust_dev_tbl[i].csra66x0_ptr);
+		}
+	} else {
+		csra66x0_reset(csra66x0);
+		csra66x0_init(csra66x0);
+	}
+
+	rc = strnlen(buf, CSRA66X0_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static DEVICE_ATTR(write2reg_addr_value, 0200, NULL,
+	csra66x0_sysfs_write2reg_addr_value);
+static DEVICE_ATTR(read2reg_addr, 0644, csra66x0_sysfs_read2reg_addr_get,
+	csra66x0_sysfs_read2reg_addr_set);
+static DEVICE_ATTR(read2reg_value, 0444, csra66x0_sysfs_read2reg_value, NULL);
+static DEVICE_ATTR(reset, 0200, NULL, csra66x0_sysfs_reset);
+
+static struct attribute *csra66x0_fs_attrs[] = {
+	&dev_attr_write2reg_addr_value.attr,
+	&dev_attr_read2reg_addr.attr,
+	&dev_attr_read2reg_value.attr,
+	&dev_attr_reset.attr,
+	NULL,
+};
+
+static struct attribute_group csra66x0_fs_attrs_group = {
+	.attrs = csra66x0_fs_attrs,
+};
+
+static int csra66x0_sysfs_create(struct i2c_client *client,
+	struct csra66x0_priv *csra66x0)
+{
+	int rc;
+
+	rc = sysfs_create_group(&client->dev.kobj, &csra66x0_fs_attrs_group);
+	return rc;
+}
+
+static void csra66x0_sysfs_remove(struct i2c_client *client,
+	struct csra66x0_priv *csra66x0)
+{
+	sysfs_remove_group(&client->dev.kobj, &csra66x0_fs_attrs_group);
+}
+
+#if IS_ENABLED(CONFIG_I2C)
+static int csra66x0_i2c_probe(struct i2c_client *client_i2c,
+			const struct i2c_device_id *id)
+{
+	struct csra66x0_priv *csra66x0;
+	int ret, irq_trigger;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	char debugfs_dir_name[32];
+#endif
+
+	csra66x0 = devm_kzalloc(&client_i2c->dev, sizeof(struct csra66x0_priv),
+			GFP_KERNEL);
+	if (csra66x0 == NULL)
+		return -ENOMEM;
+
+	csra66x0->regmap = devm_regmap_init_i2c(client_i2c,
+			&csra66x0_regmap_config);
+	if (IS_ERR(csra66x0->regmap)) {
+		ret = PTR_ERR(csra66x0->regmap);
+		dev_err(&client_i2c->dev,
+				"%s %d: Failed to allocate register map for I2C device: %d\n",
+				__func__, __LINE__, ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(client_i2c, csra66x0);
+
+	/* get data from device tree */
+	if (client_i2c->dev.of_node) {
+		/* cluster of multiple devices */
+		ret = of_property_read_u32(
+			client_i2c->dev.of_node, "qcom,csra-cluster",
+			&csra66x0->in_cluster);
+		if (ret) {
+			dev_info(&client_i2c->dev,
+			"%s: qcom,csra-cluster property not defined in DT\n", __func__);
+			csra66x0->in_cluster = 0;
+		}
+		/* master or slave device */
+		ret = of_property_read_u32(
+			client_i2c->dev.of_node, "qcom,csra-cluster-master",
+			&csra66x0->is_master);
+		if (ret) {
+			dev_info(&client_i2c->dev,
+			"%s: qcom,csra-cluster-master property not defined in DT, slave assumed\n",
+			__func__);
+			csra66x0->is_master = 0;
+		}
+
+		/* gpio setup for vreg */
+		csra66x0->vreg_gpio = of_get_named_gpio(client_i2c->dev.of_node,
+			"qcom,csra-vreg-en-gpio", 0);
+		if (!gpio_is_valid(csra66x0->vreg_gpio)) {
+			dev_err(&client_i2c->dev, "%s: %s property is not found %d\n",
+					__func__, "qcom,csra-vreg-en-gpio",
+					csra66x0->vreg_gpio);
+			return -ENODEV;
+		}
+		dev_dbg(&client_i2c->dev, "%s: vreg_en gpio %d\n", __func__,
+			csra66x0->vreg_gpio);
+		ret = gpio_request(csra66x0->vreg_gpio, dev_name(&client_i2c->dev));
+		if (ret) {
+			if (ret == -EBUSY) {
+				/* GPIO was already requested */
+				dev_dbg(&client_i2c->dev,
+				"%s: gpio %d is already set\n",
+				__func__, csra66x0->vreg_gpio);
+			} else {
+				dev_err(&client_i2c->dev, "%s: Failed to request gpio %d, err: %d\n",
+					__func__, csra66x0->vreg_gpio, ret);
+			}
+		} else {
+			gpio_direction_output(csra66x0->vreg_gpio, 1);
+			gpio_set_value(csra66x0->vreg_gpio, 0);
+		}
+
+		/* register interrupt handle */
+		if (client_i2c->irq) {
+			csra66x0->irq = client_i2c->irq;
+			/* interrupt polarity */
+			ret = of_property_read_u32(
+				client_i2c->dev.of_node, "irq-active-low",
+				&csra66x0->irq_active_low);
+			if (ret) {
+				dev_info(&client_i2c->dev,
+				"%s: irq-active-low property not defined in DT\n", __func__);
+				csra66x0->irq_active_low = 0;
+			}
+			if (csra66x0->irq_active_low)
+				irq_trigger = IRQF_TRIGGER_LOW;
+			else
+				irq_trigger = IRQF_TRIGGER_HIGH;
+
+			ret = devm_request_threaded_irq(&client_i2c->dev,
+					csra66x0->irq, NULL, csra66x0_irq,
+					irq_trigger | IRQF_ONESHOT,
+					"csra66x0_irq", csra66x0);
+			if (ret) {
+				dev_err(&client_i2c->dev,
+				"%s: Failed to request IRQ %d: %d\n",
+				__func__, csra66x0->irq, ret);
+				csra66x0->irq = 0;
+			}
+		}
+	}
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	/* debugfs interface */
+	snprintf(debugfs_dir_name, sizeof(debugfs_dir_name), "%s-%s",
+		client_i2c->name, dev_name(&client_i2c->dev));
+	csra66x0->debugfs_dir = debugfs_create_dir(debugfs_dir_name, NULL);
+	if (!csra66x0->debugfs_dir) {
+		dev_dbg(&client_i2c->dev,
+			"%s: Failed to create /sys/kernel/debug/%s for debugfs\n",
+			__func__, debugfs_dir_name);
+		ret = -ENOMEM;
+		goto err_debugfs;
+	}
+	csra66x0->debugfs_file_wo = debugfs_create_file(
+		"write_reg_val", S_IFREG | S_IRUGO, csra66x0->debugfs_dir,
+		(void *) csra66x0,
+		&debugfs_codec_ops);
+	if (!csra66x0->debugfs_file_wo) {
+		dev_dbg(&client_i2c->dev,
+			"%s: Failed to create /sys/kernel/debug/%s/write_reg_val\n",
+			__func__, debugfs_dir_name);
+		ret = -ENOMEM;
+		goto err_debugfs;
+	}
+	csra66x0->debugfs_file_ro = debugfs_create_file(
+		"show_reg_dump", S_IFREG | S_IRUGO, csra66x0->debugfs_dir,
+		(void *) csra66x0,
+		&debugfs_codec_ops);
+	if (!csra66x0->debugfs_file_ro) {
+		dev_dbg(&client_i2c->dev,
+			"%s: Failed to create /sys/kernel/debug/%s/show_reg_dump\n",
+			__func__, debugfs_dir_name);
+		ret = -ENOMEM;
+		goto err_debugfs;
+	}
+#endif /* CONFIG_DEBUG_FS */
+
+	/* register component */
+	ret = snd_soc_register_component(&client_i2c->dev,
+			&soc_codec_drv_csra66x0, NULL, 0);
+	if (ret != 0) {
+		dev_err(&client_i2c->dev, "%s %d: Failed to register component: %d\n",
+			__func__, __LINE__, ret);
+		if (gpio_is_valid(csra66x0->vreg_gpio)) {
+			gpio_set_value(csra66x0->vreg_gpio, 0);
+			gpio_free(csra66x0->vreg_gpio);
+		}
+		return ret;
+	}
+
+	ret = csra66x0_sysfs_create(client_i2c, csra66x0);
+	if (ret) {
+		dev_err(&client_i2c->dev, "%s: sysfs creation failed ret=%d\n",
+			__func__, ret);
+		goto err_sysfs;
+	}
+
+	return 0;
+
+err_sysfs:
+	snd_soc_unregister_component(&client_i2c->dev);
+	return ret;
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+err_debugfs:
+	debugfs_remove_recursive(csra66x0->debugfs_dir);
+	return ret;
+#endif
+}
+
+static int csra66x0_i2c_remove(struct i2c_client *client_i2c)
+{
+	struct csra66x0_priv *csra66x0 = i2c_get_clientdata(client_i2c);
+
+	if (csra66x0) {
+		if (gpio_is_valid(csra66x0->vreg_gpio)) {
+			gpio_set_value(csra66x0->vreg_gpio, 0);
+			gpio_free(csra66x0->vreg_gpio);
+		}
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+		debugfs_remove_recursive(csra66x0->debugfs_dir);
+#endif
+	}
+
+	csra66x0_sysfs_remove(client_i2c, csra66x0);
+	snd_soc_unregister_component(&i2c_client->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id csra66x0_i2c_id[] = {
+	{ "csra66x0", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, csra66x0_i2c_id);
+
+static struct i2c_driver csra66x0_i2c_driver = {
+	.probe =    csra66x0_i2c_probe,
+	.remove =   csra66x0_i2c_remove,
+	.id_table = csra66x0_i2c_id,
+	.driver = {
+		.name = "csra66x0",
+		.owner = THIS_MODULE,
+		.of_match_table = csra66x0_of_match
+	},
+};
+#endif
+
+static int __init csra66x0_codec_init(void)
+{
+	int ret = 0;
+#if IS_ENABLED(CONFIG_I2C)
+	ret = i2c_add_driver(&csra66x0_i2c_driver);
+	if (ret != 0)
+		pr_err("%s: Failed to register CSRA66X0 I2C driver, ret = %d\n",
+			__func__, ret);
+#endif
+	return ret;
+}
+module_init(csra66x0_codec_init);
+
+static void __exit csra66x0_codec_exit(void)
+{
+#if IS_ENABLED(CONFIG_I2C)
+	i2c_del_driver(&csra66x0_i2c_driver);
+#endif
+}
+module_exit(csra66x0_codec_exit);
+
+MODULE_DESCRIPTION("CSRA66X0 Codec driver");
+MODULE_LICENSE("GPL v2");

+ 231 - 0
qcom/opensource/audio-kernel/asoc/codecs/csra66x0/csra66x0.h

@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _CSRA66X0_H
+#define _CSRA66X0_H
+
+/* CSRA66X0 register addresses */
+#define CSRA66X0_BASE 0x7000
+
+#define CSRA66X0_AUDIO_IF_RX_CONFIG1            (CSRA66X0_BASE+0x0000)
+#define CSRA66X0_AUDIO_IF_RX_CONFIG2            (CSRA66X0_BASE+0x0001)
+#define CSRA66X0_AUDIO_IF_RX_CONFIG3            (CSRA66X0_BASE+0x0002)
+#define CSRA66X0_AUDIO_IF_TX_EN                 (CSRA66X0_BASE+0x0003)
+#define CSRA66X0_AUDIO_IF_TX_CONFIG1            (CSRA66X0_BASE+0x0004)
+#define CSRA66X0_AUDIO_IF_TX_CONFIG2            (CSRA66X0_BASE+0x0005)
+#define CSRA66X0_I2C_DEVICE_ADDRESS             (CSRA66X0_BASE+0x0006)
+#define CSRA66X0_CHIP_ID_FA                     (CSRA66X0_BASE+0x0007)
+#define CSRA66X0_ROM_VER_FA                     (CSRA66X0_BASE+0x0008)
+#define CSRA66X0_CHIP_REV_0_FA                  (CSRA66X0_BASE+0x0009)
+#define CSRA66X0_CHIP_REV_1_FA                  (CSRA66X0_BASE+0x000A)
+#define CSRA66X0_CH1_MIX_SEL                    (CSRA66X0_BASE+0x000B)
+#define CSRA66X0_CH2_MIX_SEL                    (CSRA66X0_BASE+0x000C)
+#define CSRA66X0_CH1_SAMPLE1_SCALE_0            (CSRA66X0_BASE+0x000D)
+#define CSRA66X0_CH1_SAMPLE1_SCALE_1            (CSRA66X0_BASE+0x000E)
+#define CSRA66X0_CH1_SAMPLE3_SCALE_0            (CSRA66X0_BASE+0x000F)
+#define CSRA66X0_CH1_SAMPLE3_SCALE_1            (CSRA66X0_BASE+0x0010)
+#define CSRA66X0_CH1_SAMPLE5_SCALE_0            (CSRA66X0_BASE+0x0011)
+#define CSRA66X0_CH1_SAMPLE5_SCALE_1            (CSRA66X0_BASE+0x0012)
+#define CSRA66X0_CH1_SAMPLE7_SCALE_0            (CSRA66X0_BASE+0x0013)
+#define CSRA66X0_CH1_SAMPLE7_SCALE_1            (CSRA66X0_BASE+0x0014)
+#define CSRA66X0_CH1_SAMPLE2_SCALE_0            (CSRA66X0_BASE+0x0015)
+#define CSRA66X0_CH1_SAMPLE2_SCALE_1            (CSRA66X0_BASE+0x0016)
+#define CSRA66X0_CH1_SAMPLE4_SCALE_0            (CSRA66X0_BASE+0x0017)
+#define CSRA66X0_CH1_SAMPLE4_SCALE_1            (CSRA66X0_BASE+0x0018)
+#define CSRA66X0_CH1_SAMPLE6_SCALE_0            (CSRA66X0_BASE+0x0019)
+#define CSRA66X0_CH1_SAMPLE6_SCALE_1            (CSRA66X0_BASE+0x001A)
+#define CSRA66X0_CH1_SAMPLE8_SCALE_0            (CSRA66X0_BASE+0x001B)
+#define CSRA66X0_CH1_SAMPLE8_SCALE_1            (CSRA66X0_BASE+0x001C)
+#define CSRA66X0_CH2_SAMPLE1_SCALE_0            (CSRA66X0_BASE+0x001D)
+#define CSRA66X0_CH2_SAMPLE1_SCALE_1            (CSRA66X0_BASE+0x001E)
+#define CSRA66X0_CH2_SAMPLE3_SCALE_0            (CSRA66X0_BASE+0x001F)
+#define CSRA66X0_CH2_SAMPLE3_SCALE_1            (CSRA66X0_BASE+0x0020)
+#define CSRA66X0_CH2_SAMPLE5_SCALE_0            (CSRA66X0_BASE+0x0021)
+#define CSRA66X0_CH2_SAMPLE5_SCALE_1            (CSRA66X0_BASE+0x0022)
+#define CSRA66X0_CH2_SAMPLE7_SCALE_0            (CSRA66X0_BASE+0x0023)
+#define CSRA66X0_CH2_SAMPLE7_SCALE_1            (CSRA66X0_BASE+0x0024)
+#define CSRA66X0_CH2_SAMPLE2_SCALE_0            (CSRA66X0_BASE+0x0025)
+#define CSRA66X0_CH2_SAMPLE2_SCALE_1            (CSRA66X0_BASE+0x0026)
+#define CSRA66X0_CH2_SAMPLE4_SCALE_0            (CSRA66X0_BASE+0x0027)
+#define CSRA66X0_CH2_SAMPLE4_SCALE_1            (CSRA66X0_BASE+0x0028)
+#define CSRA66X0_CH2_SAMPLE6_SCALE_0            (CSRA66X0_BASE+0x0029)
+#define CSRA66X0_CH2_SAMPLE6_SCALE_1            (CSRA66X0_BASE+0x002A)
+#define CSRA66X0_CH2_SAMPLE8_SCALE_0            (CSRA66X0_BASE+0x002B)
+#define CSRA66X0_CH2_SAMPLE8_SCALE_1            (CSRA66X0_BASE+0x002C)
+#define CSRA66X0_VOLUME_CONFIG_FA               (CSRA66X0_BASE+0x002D)
+#define CSRA66X0_STARTUP_DELAY_FA               (CSRA66X0_BASE+0x002E)
+#define CSRA66X0_CH1_VOLUME_0_FA                (CSRA66X0_BASE+0x002F)
+#define CSRA66X0_CH1_VOLUME_1_FA                (CSRA66X0_BASE+0x0030)
+#define CSRA66X0_CH2_VOLUME_0_FA                (CSRA66X0_BASE+0x0031)
+#define CSRA66X0_CH2_VOLUME_1_FA                (CSRA66X0_BASE+0x0032)
+#define CSRA66X0_QUAD_ENC_COUNT_0_FA            (CSRA66X0_BASE+0x0033)
+#define CSRA66X0_QUAD_ENC_COUNT_1_FA            (CSRA66X0_BASE+0x0034)
+#define CSRA66X0_SOFT_CLIP_CONFIG               (CSRA66X0_BASE+0x0035)
+#define CSRA66X0_CH1_HARD_CLIP_THRESH           (CSRA66X0_BASE+0x0036)
+#define CSRA66X0_CH2_HARD_CLIP_THRESH           (CSRA66X0_BASE+0x0037)
+#define CSRA66X0_SOFT_CLIP_THRESH               (CSRA66X0_BASE+0x0038)
+#define CSRA66X0_DS_ENABLE_THRESH_0             (CSRA66X0_BASE+0x0039)
+#define CSRA66X0_DS_ENABLE_THRESH_1             (CSRA66X0_BASE+0x003A)
+#define CSRA66X0_DS_TARGET_COUNT_0              (CSRA66X0_BASE+0x003B)
+#define CSRA66X0_DS_TARGET_COUNT_1              (CSRA66X0_BASE+0x003C)
+#define CSRA66X0_DS_TARGET_COUNT_2              (CSRA66X0_BASE+0x003D)
+#define CSRA66X0_DS_DISABLE_THRESH_0            (CSRA66X0_BASE+0x003E)
+#define CSRA66X0_DS_DISABLE_THRESH_1            (CSRA66X0_BASE+0x003F)
+#define CSRA66X0_DCA_CTRL                       (CSRA66X0_BASE+0x0040)
+#define CSRA66X0_CH1_DCA_THRESH                 (CSRA66X0_BASE+0x0041)
+#define CSRA66X0_CH2_DCA_THRESH                 (CSRA66X0_BASE+0x0042)
+#define CSRA66X0_DCA_ATTACK_RATE                (CSRA66X0_BASE+0x0043)
+#define CSRA66X0_DCA_RELEASE_RATE               (CSRA66X0_BASE+0x0044)
+#define CSRA66X0_CH1_OUTPUT_INVERT_EN           (CSRA66X0_BASE+0x0045)
+#define CSRA66X0_CH2_OUTPUT_INVERT_EN           (CSRA66X0_BASE+0x0046)
+#define CSRA66X0_CH1_176P4K_DELAY               (CSRA66X0_BASE+0x0047)
+#define CSRA66X0_CH2_176P4K_DELAY               (CSRA66X0_BASE+0x0048)
+#define CSRA66X0_CH1_192K_DELAY                 (CSRA66X0_BASE+0x0049)
+#define CSRA66X0_CH2_192K_DELAY                 (CSRA66X0_BASE+0x004A)
+#define CSRA66X0_DEEMP_CONFIG_FA                (CSRA66X0_BASE+0x004B)
+#define CSRA66X0_CH1_TREBLE_GAIN_CTRL_FA        (CSRA66X0_BASE+0x004C)
+#define CSRA66X0_CH2_TREBLE_GAIN_CTRL_FA        (CSRA66X0_BASE+0x004D)
+#define CSRA66X0_CH1_TREBLE_FC_CTRL_FA          (CSRA66X0_BASE+0x004E)
+#define CSRA66X0_CH2_TREBLE_FC_CTRL_FA          (CSRA66X0_BASE+0x004F)
+#define CSRA66X0_CH1_BASS_GAIN_CTRL_FA          (CSRA66X0_BASE+0x0050)
+#define CSRA66X0_CH2_BASS_GAIN_CTRL_FA          (CSRA66X0_BASE+0x0051)
+#define CSRA66X0_CH1_BASS_FC_CTRL_FA            (CSRA66X0_BASE+0x0052)
+#define CSRA66X0_CH2_BASS_FC_CTRL_FA            (CSRA66X0_BASE+0x0053)
+#define CSRA66X0_FILTER_SEL_8K                  (CSRA66X0_BASE+0x0054)
+#define CSRA66X0_FILTER_SEL_11P025K             (CSRA66X0_BASE+0x0055)
+#define CSRA66X0_FILTER_SEL_16K                 (CSRA66X0_BASE+0x0056)
+#define CSRA66X0_FILTER_SEL_22P05K              (CSRA66X0_BASE+0x0057)
+#define CSRA66X0_FILTER_SEL_32K                 (CSRA66X0_BASE+0x0058)
+#define CSRA66X0_FILTER_SEL_44P1K_48K           (CSRA66X0_BASE+0x0059)
+#define CSRA66X0_FILTER_SEL_88P2K_96K           (CSRA66X0_BASE+0x005A)
+#define CSRA66X0_FILTER_SEL_176P4K_192K         (CSRA66X0_BASE+0x005B)
+/* RESERVED (CSRA66X0_BASE+0x005C) */
+#define CSRA66X0_USER_DSP_CTRL                  (CSRA66X0_BASE+0x005D)
+#define CSRA66X0_TEST_TONE_CTRL                 (CSRA66X0_BASE+0x005E)
+#define CSRA66X0_TEST_TONE_FREQ_0               (CSRA66X0_BASE+0x005F)
+#define CSRA66X0_TEST_TONE_FREQ_1               (CSRA66X0_BASE+0x0060)
+#define CSRA66X0_TEST_TONE_FREQ_2               (CSRA66X0_BASE+0x0061)
+#define CSRA66X0_AUDIO_RATE_CTRL_FA             (CSRA66X0_BASE+0x0062)
+#define CSRA66X0_MODULATION_INDEX_CTRL          (CSRA66X0_BASE+0x0063)
+#define CSRA66X0_MODULATION_INDEX_COUNT         (CSRA66X0_BASE+0x0064)
+#define CSRA66X0_MIN_MODULATION_PULSE_WIDTH     (CSRA66X0_BASE+0x0065)
+#define CSRA66X0_DEAD_TIME_CTRL                 (CSRA66X0_BASE+0x0066)
+#define CSRA66X0_DEAD_TIME_THRESHOLD_0          (CSRA66X0_BASE+0x0067)
+#define CSRA66X0_DEAD_TIME_THRESHOLD_1          (CSRA66X0_BASE+0x0068)
+#define CSRA66X0_DEAD_TIME_THRESHOLD_2          (CSRA66X0_BASE+0x0069)
+#define CSRA66X0_CH1_LOW_SIDE_DLY               (CSRA66X0_BASE+0x006A)
+#define CSRA66X0_CH2_LOW_SIDE_DLY               (CSRA66X0_BASE+0x006B)
+#define CSRA66X0_SPECTRUM_CTRL                  (CSRA66X0_BASE+0x006C)
+/* RESERVED (CSRA66X0_BASE+0x006D) */
+#define CSRA66X0_SPECTRUM_SPREAD_CTRL           (CSRA66X0_BASE+0x006E)
+/* RESERVED (CSRA66X0_BASE+0x006F) */
+/* ... */
+/* RESERVED (CSRA66X0_BASE+0x007C) */
+#define CSRA66X0_EXT_PA_PROTECT_POLARITY        (CSRA66X0_BASE+0x007D)
+#define CSRA66X0_TEMP0_BACKOFF_COMP_VALUE       (CSRA66X0_BASE+0x007E)
+#define CSRA66X0_TEMP0_SHUTDOWN_COMP_VALUE      (CSRA66X0_BASE+0x007F)
+#define CSRA66X0_TEMP1_BACKOFF_COMP_VALUE       (CSRA66X0_BASE+0x0080)
+#define CSRA66X0_TEMP1_SHUTDOWN_COMP_VALUE      (CSRA66X0_BASE+0x0081)
+#define CSRA66X0_TEMP_PROT_BACKOFF              (CSRA66X0_BASE+0x0082)
+#define CSRA66X0_TEMP_READ0_FA                  (CSRA66X0_BASE+0x0083)
+#define CSRA66X0_TEMP_READ1_FA                  (CSRA66X0_BASE+0x0084)
+#define CSRA66X0_CHIP_STATE_CTRL_FA             (CSRA66X0_BASE+0x0085)
+/* RESERVED (CSRA66X0_BASE+0x0086) */
+#define CSRA66X0_PWM_OUTPUT_CONFIG              (CSRA66X0_BASE+0x0087)
+#define CSRA66X0_MISC_CONTROL_STATUS_0          (CSRA66X0_BASE+0x0088)
+#define CSRA66X0_MISC_CONTROL_STATUS_1_FA       (CSRA66X0_BASE+0x0089)
+#define CSRA66X0_PIO0_SELECT                    (CSRA66X0_BASE+0x008A)
+#define CSRA66X0_PIO1_SELECT                    (CSRA66X0_BASE+0x008B)
+#define CSRA66X0_PIO2_SELECT                    (CSRA66X0_BASE+0x008C)
+#define CSRA66X0_PIO3_SELECT                    (CSRA66X0_BASE+0x008D)
+#define CSRA66X0_PIO4_SELECT                    (CSRA66X0_BASE+0x008E)
+#define CSRA66X0_PIO5_SELECT                    (CSRA66X0_BASE+0x008F)
+#define CSRA66X0_PIO6_SELECT                    (CSRA66X0_BASE+0x0090)
+#define CSRA66X0_PIO7_SELECT                    (CSRA66X0_BASE+0x0091)
+#define CSRA66X0_PIO8_SELECT                    (CSRA66X0_BASE+0x0092)
+#define CSRA66X0_PIO_DIRN0                      (CSRA66X0_BASE+0x0093)
+#define CSRA66X0_PIO_DIRN1                      (CSRA66X0_BASE+0x0094)
+#define CSRA66X0_PIO_PULL_EN0                   (CSRA66X0_BASE+0x0095)
+#define CSRA66X0_PIO_PULL_EN1                   (CSRA66X0_BASE+0x0096)
+#define CSRA66X0_PIO_PULL_DIR0                  (CSRA66X0_BASE+0x0097)
+#define CSRA66X0_PIO_PULL_DIR1                  (CSRA66X0_BASE+0x0098)
+#define CSRA66X0_PIO_DRIVE_OUT0_FA              (CSRA66X0_BASE+0x0099)
+#define CSRA66X0_PIO_DRIVE_OUT1_FA              (CSRA66X0_BASE+0x009A)
+#define CSRA66X0_PIO_STATUS_IN0_FA              (CSRA66X0_BASE+0x009B)
+#define CSRA66X0_PIO_STATUS_IN1_FA              (CSRA66X0_BASE+0x009C)
+/* RESERVED (CSRA66X0_BASE+0x009D) */
+#define CSRA66X0_IRQ_OUTPUT_ENABLE              (CSRA66X0_BASE+0x009E)
+#define CSRA66X0_IRQ_OUTPUT_POLARITY            (CSRA66X0_BASE+0x009F)
+#define CSRA66X0_IRQ_OUTPUT_STATUS_FA           (CSRA66X0_BASE+0x00A0)
+#define CSRA66X0_CLIP_DCA_STATUS_FA             (CSRA66X0_BASE+0x00A1)
+#define CSRA66X0_CHIP_STATE_STATUS_FA           (CSRA66X0_BASE+0x00A2)
+#define CSRA66X0_FAULT_STATUS_FA                (CSRA66X0_BASE+0x00A3)
+#define CSRA66X0_OTP_STATUS_FA                  (CSRA66X0_BASE+0x00A4)
+#define CSRA66X0_AUDIO_IF_STATUS_FA             (CSRA66X0_BASE+0x00A5)
+/* RESERVED (CSRA66X0_BASE+0x00A6) */
+#define CSRA66X0_DSP_SATURATION_STATUS_FA       (CSRA66X0_BASE+0x00A7)
+#define CSRA66X0_AUDIO_RATE_STATUS_FA           (CSRA66X0_BASE+0x00A8)
+/* RESERVED (CSRA66X0_BASE+0x00A9) */
+/* ... */
+/* RESERVED (CSRA66X0_BASE+0x00AB) */
+#define CSRA66X0_DISABLE_PWM_OUTPUT             (CSRA66X0_BASE+0x00AC)
+/* RESERVED (CSRA66X0_BASE+0x00AD) */
+/* ... */
+/* RESERVED (CSRA66X0_BASE+0x00B0) */
+#define CSRA66X0_OTP_VER_FA                     (CSRA66X0_BASE+0x00B1)
+#define CSRA66X0_RAM_VER_FA                     (CSRA66X0_BASE+0x00B2)
+/* RESERVED (CSRA66X0_BASE+0x00B3) */
+#define CSRA66X0_AUDIO_SATURATION_FLAGS_FA      (CSRA66X0_BASE+0x00B4)
+#define CSRA66X0_DCOFFSET_CHAN_1_01_FA          (CSRA66X0_BASE+0x00B5)
+#define CSRA66X0_DCOFFSET_CHAN_1_02_FA          (CSRA66X0_BASE+0x00B6)
+#define CSRA66X0_DCOFFSET_CHAN_1_03_FA          (CSRA66X0_BASE+0x00B7)
+#define CSRA66X0_DCOFFSET_CHAN_2_01_FA          (CSRA66X0_BASE+0x00B8)
+#define CSRA66X0_DCOFFSET_CHAN_2_02_FA          (CSRA66X0_BASE+0x00B9)
+#define CSRA66X0_DCOFFSET_CHAN_2_03_FA          (CSRA66X0_BASE+0x00BA)
+#define CSRA66X0_FORCED_PA_SWITCHING_CTRL       (CSRA66X0_BASE+0x00BB)
+#define CSRA66X0_PA_FORCE_PULSE_WIDTH           (CSRA66X0_BASE+0x00BC)
+#define CSRA66X0_PA_HIGH_MODULATION_CTRL_CH1    (CSRA66X0_BASE+0x00BD)
+/* RESERVED (CSRA66X0_BASE+0x00BE) */
+/* RESERVED (CSRA66X0_BASE+0x00BF) */
+#define CSRA66X0_HIGH_MODULATION_THRESHOLD_LOW  (CSRA66X0_BASE+0x00C0)
+#define CSRA66X0_HIGH_MODULATION_THRESHOLD_HIGH (CSRA66X0_BASE+0x00C1)
+/* RESERVED (CSRA66X0_BASE+0x00C2) */
+/* RESERVED (CSRA66X0_BASE+0x00C3) */
+#define CSRA66X0_PA_FREEZE_CTRL                 (CSRA66X0_BASE+0x00C4)
+#define CSRA66X0_DCA_FREEZE_CTRL                (CSRA66X0_BASE+0x00C5)
+/* RESERVED (CSRA66X0_BASE+0x00C6) */
+/* ... */
+/* RESERVED (CSRA66X0_BASE+0x00FF) */
+#define CSRA66X0_MAX_REGISTER_ADDR CSRA66X0_DCA_FREEZE_CTRL
+
+#define CSRA66X0_COEFF_BASE     0xD000
+#define CSRA66X0_MAX_COEFF_ADDR 0xD6DF
+
+#define EXPECTED_CSRA66X0_CHIP_ID 0x39
+
+#define SPK_VOLUME_M20DB 0x119
+#define SPK_VOLUME_M20DB_LSB (SPK_VOLUME_M20DB & 0x0FF)
+#define SPK_VOLUME_M20DB_MSB ((SPK_VOLUME_M20DB & 0x100)>>8)
+#define SPK_VOLUME_LSB_MSK 0x00FF
+#define SPK_VOLUME_MSB_MSK 0x0100
+
+#define SET_CONFIG_STATE    0x0
+#define SET_RUN_STATE       0x1
+#define SET_STDBY_STATE     0x2
+
+#define CONFIG_STATE_ID 0x3
+#define WAIT_FOR_CONFIG_STATE_TIMEOUT_MS 2000
+#define SYSFS_RESET 1
+
+#define FAULT_STATUS_INTERNAL       0x01
+#define FAULT_STATUS_OTP_INTEGRITY  0x02
+#define FAULT_STATUS_PADS2          0x04
+#define FAULT_STATUS_SMPS           0x08
+#define FAULT_STATUS_TEMP           0x10
+#define FAULT_STATUS_PROTECT        0x20
+
+
+void csra66x0_hw_free_mute(struct snd_soc_component *component);
+#endif /* _CSRA66X0_H */

+ 106 - 0
qcom/opensource/audio-kernel/asoc/codecs/ep92/Kbuild

@@ -0,0 +1,106 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ EP92 ############
+
+# for EP92 Codec
+ifdef CONFIG_SND_SOC_EP92
+	EP92_OBJS += ep92.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+#EXTRA_CFLAGS += $(INCS)
+ccflags-y += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+#EXTRA_CFLAGS += -Wmaybe-uninitialized
+ccflags-y += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+#EXTRA_CFLAGS += -Wheader-guard
+ccflags-y += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_EP92) += ep92_dlkm.o
+ep92_dlkm-y := $(EP92_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 2002 - 0
qcom/opensource/audio-kernel/asoc/codecs/ep92/ep92.c

@@ -0,0 +1,2002 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <linux/workqueue.h>
+#include "ep92.h"
+
+#define DRV_NAME "ep92_codec"
+
+#define EP92_POLL_INTERVAL_OFF_MSEC 200
+#define EP92_POLL_INTERVAL_ON_MSEC  20
+#define EP92_POLL_RUNOUT_MSEC       5000
+#define EP92_SYSFS_ENTRY_MAX_LEN 64
+#define EP92_HYST_CNT 5
+
+#define EP92_RATES (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 EP92_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static const unsigned int ep92_samp_freq_table[8] = {
+	32000, 44100, 48000, 88200, 96000, 176400, 192000, 768000
+};
+
+static const unsigned int ep92_dsd_freq_table[4] = {
+	64, 128, 256, 0
+};
+
+/* EP92 register default values */
+static struct reg_default ep92_reg_defaults[] = {
+	{EP92_BI_VENDOR_ID_0,                   0x17},
+	{EP92_BI_VENDOR_ID_1,                   0x7A},
+	{EP92_BI_DEVICE_ID_0,                   0x94},
+	{EP92_BI_DEVICE_ID_1,                   0xA3},
+	{EP92_BI_VERSION_NUM,                   0x10},
+	{EP92_BI_VERSION_YEAR,                  0x09},
+	{EP92_BI_VERSION_MONTH,                 0x07},
+	{EP92_BI_VERSION_DATE,                  0x06},
+	{EP92_BI_GENERAL_INFO_0,                0x00},
+	{EP92_BI_GENERAL_INFO_1,                0x00},
+	{EP92_BI_GENERAL_INFO_2,                0x00},
+	{EP92_BI_GENERAL_INFO_3,                0x00},
+	{EP92_BI_GENERAL_INFO_4,                0x00},
+	{EP92_BI_GENERAL_INFO_5,                0x00},
+	{EP92_BI_GENERAL_INFO_6,                0x00},
+	{EP92_ISP_MODE_ENTER_ISP,               0x00},
+	{EP92_GENERAL_CONTROL_0,                0x20},
+	{EP92_GENERAL_CONTROL_1,                0x00},
+	{EP92_GENERAL_CONTROL_2,                0x00},
+	{EP92_GENERAL_CONTROL_3,                0x10},
+	{EP92_GENERAL_CONTROL_4,                0x00},
+	{EP92_CEC_EVENT_CODE,                   0x00},
+	{EP92_CEC_EVENT_PARAM_1,                0x00},
+	{EP92_CEC_EVENT_PARAM_2,                0x00},
+	{EP92_CEC_EVENT_PARAM_3,                0x00},
+	{EP92_CEC_EVENT_PARAM_4,                0x00},
+	{EP92_AUDIO_INFO_SYSTEM_STATUS_0,       0x00},
+	{EP92_AUDIO_INFO_SYSTEM_STATUS_1,       0x00},
+	{EP92_AUDIO_INFO_AUDIO_STATUS,          0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_0,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_1,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_2,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_3,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_4,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_0,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_1,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_2,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_3,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_4,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_5,      0x00},
+	{EP92_OTHER_PACKETS_HDMI_VS_0,          0x00},
+	{EP92_OTHER_PACKETS_HDMI_VS_1,          0x00},
+	{EP92_OTHER_PACKETS_ACP_PACKET,         0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_0,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_1,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_2,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_3,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_4,   0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_0,        0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_1,        0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_2,        0x00},
+};
+
+static bool ep92_volatile_register(struct device *dev, unsigned int reg)
+{
+	/* do not cache register state in regmap */
+	return true;
+}
+
+static bool ep92_writeable_registers(struct device *dev, unsigned int reg)
+{
+	if (reg >= EP92_ISP_MODE_ENTER_ISP && reg <= EP92_GENERAL_CONTROL_4)
+		return true;
+
+	return false;
+}
+
+static bool ep92_readable_registers(struct device *dev, unsigned int reg)
+{
+	if (reg >= EP92_BI_VENDOR_ID_0 && reg <= EP92_MAX_REGISTER_ADDR)
+		return true;
+
+	return false;
+}
+
+/* codec private data */
+struct ep92_pdata {
+	struct regmap        *regmap;
+	struct snd_soc_component *component;
+	struct timer_list    timer;
+	struct work_struct   read_status_worker;
+	int                  irq;
+	int                  poll_trig;
+	int                  poll_rem;
+	int                  force_inactive;
+
+	int                  hyst_tx_plug;
+	int                  hyst_link_on0;
+	int                  hyst_link_on1;
+	int                  hyst_link_on2;
+	int                  filt_tx_plug;
+	int                  filt_link_on0;
+	int                  filt_link_on1;
+	int                  filt_link_on2;
+	struct {
+		u8 tx_info;
+		u8 video_latency;
+	} gi; /* General Info block */
+
+	struct {
+		u8 ctl;
+		u8 rx_sel;
+		u8 ctl2;
+		u8 cec_volume;
+		u8 link;
+	} gc; /* General Control block */
+
+	struct {
+		u8 system_status_0;
+		u8 system_status_1;
+		u8 audio_status;
+		u8 cs[5];
+		u8 cc;
+		u8 ca;
+	} ai; /* Audio Info block */
+
+	u8 old_mode;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	struct dentry *debugfs_dir;
+	struct dentry *debugfs_file_wo;
+	struct dentry *debugfs_file_ro;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+struct ep92_mclk_cfg_info {
+	uint32_t in_sample_rate;
+	uint32_t out_mclk_freq;
+	uint8_t mul_val;
+};
+
+#define EP92_MCLK_MUL_512		0x3
+#define EP92_MCLK_MUL_384		0x2
+#define EP92_MCLK_MUL_256		0x1
+#define EP92_MCLK_MUL_128		0x0
+#define EP92_MCLK_MUL_MASK		0x3
+
+/**
+ * ep92_set_ext_mclk - Configure the mclk based on sample freq
+ *
+ * @codec: handle pointer to ep92 codec
+ * @mclk_freq: mclk frequency to be set
+ *
+ * Returns 0 for sucess or appropriate negative error code
+ */
+int ep92_set_ext_mclk(struct snd_soc_codec *codec, uint32_t mclk_freq)
+{
+	unsigned int samp_freq = 0;
+	struct ep92_pdata *ep92 = NULL;
+	uint8_t value = 0;
+	int ret = 0;
+
+	if (!codec)
+		return -EINVAL;
+
+	ep92 = snd_soc_codec_get_drvdata(codec);
+
+	samp_freq = ep92_samp_freq_table[(ep92->ai.audio_status) &
+						EP92_AI_RATE_MASK];
+
+	if (!mclk_freq || (mclk_freq % samp_freq)) {
+		pr_err("%s incompatbile mclk:%u and sample freq:%u\n",
+				__func__, mclk_freq, samp_freq);
+		return -EINVAL;
+	}
+
+	switch (mclk_freq / samp_freq) {
+	case 512:
+		value = EP92_MCLK_MUL_512;
+		break;
+	case 384:
+		value = EP92_MCLK_MUL_384;
+		break;
+	case 256:
+		value = EP92_MCLK_MUL_256;
+		break;
+	case 128:
+		value = EP92_MCLK_MUL_128;
+		break;
+	default:
+		dev_err(codec->dev, "unsupported mclk:%u for sample freq:%u\n",
+					mclk_freq, samp_freq);
+		return -EINVAL;
+	}
+
+	pr_debug("%s mclk:%u, in sample freq:%u, write reg:0x%02x val:0x%02x\n",
+		__func__, mclk_freq, samp_freq,
+		EP92_GENERAL_CONTROL_2, EP92_MCLK_MUL_MASK & value);
+
+	ret = snd_soc_update_bits(codec, EP92_GENERAL_CONTROL_2,
+					EP92_MCLK_MUL_MASK, value);
+
+	return (((ret == 0) || (ret == 1)) ? 0 : ret);
+}
+EXPORT_SYMBOL(ep92_set_ext_mclk);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static int debugfs_codec_open_op(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int debugfs_get_parameters(char *buf, u32 *param1, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtou32(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else {
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static ssize_t debugfs_codec_write_op(struct file *filp,
+		const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	struct ep92_pdata *ep92 = (struct ep92_pdata *) filp->private_data;
+	struct snd_soc_component *component = ep92->component;
+	char lbuf[32];
+	int rc;
+	u32 param[2];
+
+	if (!component)
+		return -ENODEV;
+
+	if (!filp || !ppos || !ubuf)
+		return -EINVAL;
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+	lbuf[cnt] = '\0';
+	rc = debugfs_get_parameters(lbuf, param, 2);
+	if ((param[0] < EP92_ISP_MODE_ENTER_ISP)
+		|| (param[0] > EP92_GENERAL_CONTROL_4)) {
+		dev_err(component->dev, "%s: reg address 0x%02X out of range\n",
+			__func__, param[0]);
+		return -EINVAL;
+	}
+	if ((param[1] < 0) || (param[1] > 255)) {
+		dev_err(component->dev, "%s: reg data 0x%02X out of range\n",
+			__func__, param[1]);
+		return -EINVAL;
+	}
+	if (rc == 0) {
+		rc = cnt;
+		dev_info(component->dev, "%s: reg[0x%02X]=0x%02X\n",
+			__func__, param[0], param[1]);
+		snd_soc_component_write(component, param[0], param[1]);
+	} else {
+		dev_err(component->dev, "%s: write to register addr=0x%02X failed\n",
+			__func__, param[0]);
+	}
+	return rc;
+}
+
+static ssize_t debugfs_ep92_reg_show(struct snd_soc_component *component,
+		char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int i, reg_val, len;
+	ssize_t total = 0;
+	char tmp_buf[20];
+
+	if (!ubuf || !ppos || !component || *ppos < 0)
+		return -EINVAL;
+
+	for (i = (int) *ppos / 11; i <= EP92_MAX_REGISTER_ADDR; i++) {
+		reg_val = snd_soc_component_read32(component, i);
+		len = snprintf(tmp_buf, 20, "0x%02X: 0x%02X\n", i,
+			(reg_val & 0xFF));
+		if ((total + len) > count)
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			dev_err(component->dev, "%s: fail to copy reg dump\n",
+				__func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		*ppos += len;
+		total += len;
+	}
+
+copy_err:
+	return total;
+}
+
+static ssize_t debugfs_codec_read_op(struct file *filp,
+		char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	struct ep92_pdata *ep92 = (struct ep92_pdata *) filp->private_data;
+	struct snd_soc_component *component = ep92->component;
+	ssize_t ret_cnt;
+
+	if (!component)
+		return -ENODEV;
+
+	if (!filp || !ppos || !ubuf || *ppos < 0)
+		return -EINVAL;
+	ret_cnt = debugfs_ep92_reg_show(component, ubuf, cnt, ppos);
+	return ret_cnt;
+}
+
+static const struct file_operations debugfs_codec_ops = {
+	.open = debugfs_codec_open_op,
+	.write = debugfs_codec_write_op,
+	.read = debugfs_codec_read_op,
+};
+#endif /* CONFIG_DEBUG_FS */
+
+static int ep92_send_uevent(struct ep92_pdata *ep92, char *event)
+{
+	char *env[] = { event, NULL };
+
+	if (!event || !ep92)
+		return -EINVAL;
+
+	if (!ep92->component)
+		return -ENODEV;
+	return kobject_uevent_env(&ep92->component->dev->kobj,
+			KOBJ_CHANGE, env);
+}
+
+static int ep92_startup(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	return 0;
+}
+
+static void ep92_shutdown(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+}
+
+static int ep92_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	return 0;
+}
+
+static struct snd_soc_dai_ops ep92_dai_ops = {
+	.startup = ep92_startup,
+	.shutdown = ep92_shutdown,
+	.hw_params = ep92_hw_params,
+};
+
+static struct snd_soc_dai_driver ep92_dai[] = {
+	{
+		.name = "ep92-hdmi",
+		.id = 1,
+		.capture = {
+			.stream_name = "HDMI Capture",
+			.rate_max = 192000,
+			.rate_min = 32000,
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = EP92_RATES,
+			.formats = EP92_FORMATS,
+		},
+		.ops = &ep92_dai_ops, /* callbacks */
+	},
+	{
+		.name = "ep92-arc",
+		.id = 2,
+		.capture = {
+			.stream_name = "ARC Capture",
+			.rate_max = 192000,
+			.rate_min = 32000,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = EP92_RATES,
+			.formats = EP92_FORMATS,
+		},
+		.ops = &ep92_dai_ops, /* callbacks */
+	},
+};
+
+static void ep92_read_general_control(struct snd_soc_component *component,
+	struct ep92_pdata *ep92)
+{
+	u8 old, change;
+	int val;
+
+	old = ep92->gi.tx_info;
+	ep92->gi.tx_info = snd_soc_component_read32(component,
+				EP92_BI_GENERAL_INFO_0);
+	if (ep92->gi.tx_info == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_BI_GENERAL_INFO_0 read 0xff\n");
+		ep92->gi.tx_info = old;
+	}
+	/* implement hysteresis to prevent events on glitches */
+	if (ep92->gi.tx_info & EP92_GI_TX_HOT_PLUG_MASK) {
+		if (ep92->hyst_tx_plug < EP92_HYST_CNT) {
+			ep92->hyst_tx_plug++;
+			if ((ep92->hyst_tx_plug == EP92_HYST_CNT) &&
+			    (ep92->filt_tx_plug == 0)) {
+				ep92->filt_tx_plug = 1;
+				dev_dbg(component->dev, "ep92 out_plug changed to 1\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_OUT_PLUG=CONNECTED");
+			}
+		}
+	} else {
+		if (ep92->hyst_tx_plug > 0) {
+			ep92->hyst_tx_plug--;
+			if ((ep92->hyst_tx_plug == 0) &&
+			    (ep92->filt_tx_plug == 1)) {
+				ep92->filt_tx_plug = 0;
+				dev_dbg(component->dev, "ep92 out_plug changed to 0\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_OUT_PLUG=DISCONNECTED");
+			}
+		}
+	}
+
+	old = ep92->gi.video_latency;
+	ep92->gi.video_latency = snd_soc_component_read32(component,
+					EP92_BI_GENERAL_INFO_4);
+	if (ep92->gi.video_latency == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_BI_GENERAL_INFO_4 read 0xff\n");
+		ep92->gi.video_latency = old;
+	}
+	change = ep92->gi.video_latency ^ old;
+	if (change & EP92_GI_VIDEO_LATENCY_MASK) {
+		val = ep92->gi.video_latency;
+		if (val > 0)
+			val = (val - 1) * 2;
+		dev_dbg(component->dev, "ep92 video latency changed to %d\n", val);
+		ep92_send_uevent(ep92, "EP92EVT_VIDEO_LATENCY=CHANGED");
+	}
+
+	old = ep92->gc.ctl;
+	ep92->gc.ctl = snd_soc_component_read32(component,
+			EP92_GENERAL_CONTROL_0);
+	if (ep92->gc.ctl == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_GENERAL_CONTROL_0 read 0xff\n");
+		ep92->gc.ctl = old;
+	}
+	change = ep92->gc.ctl ^ old;
+	if (change & EP92_GC_POWER_MASK) {
+		val = (ep92->gc.ctl >> EP92_GC_POWER_SHIFT) &
+			EP92_2CHOICE_MASK;
+		dev_dbg(component->dev, "ep92 power changed to %d\n", val);
+		if (val)
+			ep92_send_uevent(ep92, "EP92EVT_POWER=ON");
+		else
+			ep92_send_uevent(ep92, "EP92EVT_POWER=OFF");
+	}
+	if (change & EP92_GC_AUDIO_PATH_MASK) {
+		val = (ep92->gc.ctl >> EP92_GC_AUDIO_PATH_SHIFT) &
+			EP92_2CHOICE_MASK;
+		dev_dbg(component->dev, "ep92 audio_path changed to %d\n", val);
+		if (val)
+			ep92_send_uevent(ep92, "EP92EVT_AUDIO_PATH=TV");
+		else
+			ep92_send_uevent(ep92, "EP92EVT_AUDIO_PATH=SPEAKER");
+	}
+	if (change & EP92_GC_CEC_MUTE_MASK) {
+		val = (ep92->gc.ctl >> EP92_GC_CEC_MUTE_SHIFT) &
+			EP92_2CHOICE_MASK;
+		dev_dbg(component->dev, "ep92 cec_mute changed to %d\n", val);
+		if (val)
+			ep92_send_uevent(ep92, "EP92EVT_CEC_MUTE=NORMAL");
+		else
+			ep92_send_uevent(ep92, "EP92EVT_CEC_MUTE=MUTED");
+	}
+	if (change & EP92_GC_ARC_EN_MASK) {
+		val = ep92->gc.ctl & EP92_2CHOICE_MASK;
+		dev_dbg(component->dev, "ep92 arc_en changed to %d\n", val);
+		if (val)
+			ep92_send_uevent(ep92, "EP92EVT_ARC_EN=ON");
+		else
+			ep92_send_uevent(ep92, "EP92EVT_ARC_EN=OFF");
+	}
+
+	old = ep92->gc.rx_sel;
+	ep92->gc.rx_sel = snd_soc_component_read32(component,
+				EP92_GENERAL_CONTROL_1);
+	if (ep92->gc.rx_sel == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_GENERAL_CONTROL_1 read 0xff\n");
+		ep92->gc.rx_sel = old;
+	}
+	change = ep92->gc.rx_sel ^ old;
+	if (change & EP92_GC_RX_SEL_MASK) {
+		val = ep92->gc.rx_sel & EP92_GC_RX_SEL_MASK;
+		dev_dbg(component->dev, "ep92 rx_sel changed to %d\n", val);
+		ep92_send_uevent(ep92, "EP92EVT_SRC_SEL=CHANGED");
+	}
+
+	old = ep92->gc.cec_volume;
+	ep92->gc.cec_volume = snd_soc_component_read32(component,
+				EP92_GENERAL_CONTROL_3);
+	if (ep92->gc.cec_volume == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_GENERAL_CONTROL_3 read 0xff\n");
+		ep92->gc.cec_volume = old;
+	}
+	change = ep92->gc.cec_volume ^ old;
+	if (change & EP92_GC_CEC_VOLUME_MASK) {
+		val = ep92->gc.cec_volume & EP92_GC_CEC_VOLUME_MASK;
+		dev_dbg(component->dev, "ep92 cec_volume changed to %d\n", val);
+		ep92_send_uevent(ep92, "EP92EVT_CEC_VOLUME=CHANGED");
+	}
+
+	old = ep92->gc.link;
+	ep92->gc.link = snd_soc_component_read32(component,
+				EP92_GENERAL_CONTROL_4);
+	if (ep92->gc.link == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_GENERAL_CONTROL_4 read 0xff\n");
+		ep92->gc.link = old;
+	}
+
+	/* implement hysteresis to prevent events on glitches */
+	if (ep92->gc.link & EP92_GC_LINK_ON0_MASK) {
+		if (ep92->hyst_link_on0 < EP92_HYST_CNT) {
+			ep92->hyst_link_on0++;
+			if ((ep92->hyst_link_on0 == EP92_HYST_CNT) &&
+			    (ep92->filt_link_on0 == 0)) {
+				ep92->filt_link_on0 = 1;
+				dev_dbg(component->dev, "ep92 link_on0 changed to 1\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON0=CONNECTED");
+			}
+		}
+	} else {
+		if (ep92->hyst_link_on0 > 0) {
+			ep92->hyst_link_on0--;
+			if ((ep92->hyst_link_on0 == 0) &&
+			    (ep92->filt_link_on0 == 1)) {
+				ep92->filt_link_on0 = 0;
+				dev_dbg(component->dev, "ep92 link_on0 changed to 0\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON0=DISCONNECTED");
+			}
+		}
+	}
+
+	/* implement hysteresis to prevent events on glitches */
+	if (ep92->gc.link & EP92_GC_LINK_ON1_MASK) {
+		if (ep92->hyst_link_on1 < EP92_HYST_CNT) {
+			ep92->hyst_link_on1++;
+			if ((ep92->hyst_link_on1 == EP92_HYST_CNT) &&
+			    (ep92->filt_link_on1 == 0)) {
+				ep92->filt_link_on1 = 1;
+				dev_dbg(component->dev, "ep92 link_on1 changed to 1\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON1=CONNECTED");
+			}
+		}
+	} else {
+		if (ep92->hyst_link_on1 > 0) {
+			ep92->hyst_link_on1--;
+			if ((ep92->hyst_link_on1 == 0) &&
+			    (ep92->filt_link_on1 == 1)) {
+				ep92->filt_link_on1 = 0;
+				dev_dbg(component->dev, "ep92 link_on1 changed to 0\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON1=DISCONNECTED");
+			}
+		}
+	}
+
+	/* implement hysteresis to prevent events on glitches */
+	if (ep92->gc.link & EP92_GC_LINK_ON2_MASK) {
+		if (ep92->hyst_link_on2 < EP92_HYST_CNT) {
+			ep92->hyst_link_on2++;
+			if ((ep92->hyst_link_on2 == EP92_HYST_CNT) &&
+			    (ep92->filt_link_on2 == 0)) {
+				ep92->filt_link_on2 = 1;
+				dev_dbg(component->dev, "ep92 link_on2 changed to 1\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON2=CONNECTED");
+			}
+		}
+	} else {
+		if (ep92->hyst_link_on2 > 0) {
+			ep92->hyst_link_on2--;
+			if ((ep92->hyst_link_on2 == 0) &&
+			    (ep92->filt_link_on2 == 1)) {
+				ep92->filt_link_on2 = 0;
+				dev_dbg(component->dev, "ep92 link_on2 changed to 0\n");
+				ep92_send_uevent(ep92,
+					"EP92EVT_LINK_ON2=DISCONNECTED");
+			}
+		}
+	}
+}
+
+static void ep92_read_audio_info(struct snd_soc_component *component,
+	struct ep92_pdata *ep92)
+{
+	u8 old, change;
+	u8 new_mode;
+	bool send_uevent = false;
+
+	old = ep92->ai.system_status_0;
+	ep92->ai.system_status_0 = snd_soc_component_read32(component,
+		EP92_AUDIO_INFO_SYSTEM_STATUS_0);
+	if (ep92->ai.system_status_0 == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_AUDIO_INFO_SYSTEM_STATUS_0 read 0xff\n");
+		ep92->ai.system_status_0 = old;
+	}
+	change = ep92->ai.system_status_0 ^ old;
+	if (change & EP92_AI_MCLK_ON_MASK) {
+		dev_dbg(component->dev, "ep92 status changed to %d\n",
+			(ep92->ai.system_status_0 >> EP92_AI_MCLK_ON_SHIFT) &
+			EP92_2CHOICE_MASK);
+		send_uevent = true;
+	}
+	if (change & EP92_AI_AVMUTE_MASK) {
+		dev_dbg(component->dev, "ep92 avmute changed to %d\n",
+			(ep92->ai.system_status_0 >> EP92_AI_AVMUTE_SHIFT) &
+			EP92_2CHOICE_MASK);
+		send_uevent = true;
+	}
+	if (change & EP92_AI_LAYOUT_MASK) {
+		dev_dbg(component->dev, "ep92 layout changed to %d\n",
+			(ep92->ai.system_status_0) & EP92_2CHOICE_MASK);
+		send_uevent = true;
+	}
+
+	old = ep92->ai.system_status_1;
+	ep92->ai.system_status_1 = snd_soc_read(codec,
+		EP92_AUDIO_INFO_SYSTEM_STATUS_1);
+	if (ep92->ai.system_status_1 == 0xff) {
+		dev_dbg(codec->dev,
+			"ep92 EP92_AUDIO_INFO_SYSTEM_STATUS_1 read 0xff\n");
+		ep92->ai.system_status_1 = old;
+	}
+	change = ep92->ai.system_status_1 ^ old;
+	if (change & EP92_AI_DSD_RATE_MASK) {
+		dev_dbg(codec->dev, "ep92 dsd rate changed to %d\n",
+			ep92_dsd_freq_table[(ep92->ai.system_status_1 &
+				EP92_AI_DSD_RATE_MASK)
+				>> EP92_AI_DSD_RATE_SHIFT]);
+		send_uevent = true;
+	}
+
+	old = ep92->ai.audio_status;
+	ep92->ai.audio_status = snd_soc_component_read32(component,
+		EP92_AUDIO_INFO_AUDIO_STATUS);
+	if (ep92->ai.audio_status == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_AUDIO_INFO_AUDIO_STATUS read 0xff\n");
+		ep92->ai.audio_status = old;
+	}
+	change = ep92->ai.audio_status ^ old;
+	if (change & EP92_AI_RATE_MASK) {
+		dev_dbg(component->dev, "ep92 rate changed to %d\n",
+			ep92_samp_freq_table[(ep92->ai.audio_status) &
+			EP92_AI_RATE_MASK]);
+		send_uevent = true;
+	}
+
+	old = ep92->ai.cs[0];
+	ep92->ai.cs[0] = snd_soc_component_read32(component,
+		EP92_AUDIO_INFO_CHANNEL_STATUS_0);
+	if (ep92->ai.cs[0] == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_AUDIO_INFO_CHANNEL_STATUS_0 read 0xff\n");
+		ep92->ai.cs[0] = old;
+	}
+	change = ep92->ai.cs[0] ^ old;
+	if (change & EP92_AI_PREEMPH_MASK) {
+		dev_dbg(component->dev, "ep92 preemph changed to %d\n",
+			(ep92->ai.cs[0] & EP92_AI_PREEMPH_MASK) >>
+			EP92_AI_PREEMPH_SHIFT);
+		send_uevent = true;
+	}
+
+	new_mode = ep92->old_mode;
+	if (ep92->ai.audio_status & EP92_AI_DSD_ADO_MASK)
+		new_mode = 2; /* One bit audio */
+	else if (ep92->ai.audio_status & EP92_AI_STD_ADO_MASK) {
+		if (ep92->ai.cs[0] & EP92_AI_NPCM_MASK)
+			new_mode = 1; /* Compr */
+		else
+			new_mode = 0; /* LPCM */
+	} else if (ep92->ai.audio_status & EP92_AI_HBR_ADO_MASK)
+		new_mode = 1; /* Compr */
+
+	if (ep92->old_mode != new_mode) {
+		dev_dbg(component->dev, "ep92 mode changed to %d\n", new_mode);
+		send_uevent = true;
+	}
+	ep92->old_mode = new_mode;
+
+	old = ep92->ai.cc;
+	ep92->ai.cc = snd_soc_component_read32(component,
+				EP92_AUDIO_INFO_ADO_INFO_FRAME_1);
+	if (ep92->ai.cc == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_AUDIO_INFO_ADO_INFO_FRAME_1 read 0xff\n");
+		ep92->ai.cc = old;
+	}
+	change = ep92->ai.cc ^ old;
+	if (change & EP92_AI_CH_COUNT_MASK) {
+		dev_dbg(component->dev, "ep92 ch_count changed to %d (%d)\n",
+			ep92->ai.cc & EP92_AI_CH_COUNT_MASK,
+			(ep92->ai.cc & EP92_AI_CH_COUNT_MASK) == 0 ? 0 :
+			(ep92->ai.cc & EP92_AI_CH_COUNT_MASK) + 1);
+		send_uevent = true;
+	}
+
+	old = ep92->ai.ca;
+	ep92->ai.ca = snd_soc_component_read32(component,
+				EP92_AUDIO_INFO_ADO_INFO_FRAME_4);
+	if (ep92->ai.ca == 0xff) {
+		dev_dbg(component->dev, "ep92 EP92_AUDIO_INFO_ADO_INFO_FRAME_4 read 0xff\n");
+		ep92->ai.ca = old;
+	}
+	change = ep92->ai.ca ^ old;
+	if (change & EP92_AI_CH_ALLOC_MASK) {
+		dev_dbg(component->dev, "ep92 ch_alloc changed to 0x%02x\n",
+			(ep92->ai.ca) & EP92_AI_CH_ALLOC_MASK);
+		send_uevent = true;
+	}
+
+	if (send_uevent)
+		ep92_send_uevent(ep92, "EP92EVT_AUDIO=MEDIA_CONFIG_CHANGE");
+}
+
+static void ep92_init(struct snd_soc_component *component,
+		      struct ep92_pdata *ep92)
+{
+	int reg0 = 0;
+	int reg1 = 0;
+	int reg2 = 0;
+	int reg3 = 0;
+
+	if (!ep92 || !component)
+		return;
+
+	reg0 = snd_soc_component_read32(component, EP92_BI_VERSION_YEAR);
+	reg1 = snd_soc_component_read32(component, EP92_BI_VERSION_MONTH);
+	reg2 = snd_soc_component_read32(component, EP92_BI_VERSION_DATE);
+	reg3 = snd_soc_component_read32(component, EP92_BI_VERSION_NUM);
+
+	dev_info(compoent->dev, "ep92 version info %02d/%02d/%02d %d\n",
+		reg0, reg1, reg2, reg3);
+
+	/* update the format information in mixer controls */
+	ep92_read_general_control(component, ep92);
+	ep92_read_audio_info(component, ep92);
+}
+
+static int ep92_probe(struct snd_soc_component *component)
+{
+	struct ep92_pdata *ep92 = snd_soc_component_get_drvdata(component);
+
+	ep92->component = component;
+	ep92_init(component, ep92);
+
+	/* start polling when codec is registered */
+	mod_timer(&ep92->timer, jiffies +
+		msecs_to_jiffies(EP92_POLL_INTERVAL_OFF_MSEC));
+
+	return 0;
+}
+
+static void ep92_remove(struct snd_soc_component *component)
+{
+	return;
+}
+
+static const struct snd_soc_component_driver soc_codec_drv_ep92 = {
+	.name = DRV_NAME,
+	.probe  = ep92_probe,
+	.remove = ep92_remove,
+};
+
+static struct regmap_config ep92_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = ep92_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(ep92_reg_defaults),
+	.max_register = EP92_MAX_REGISTER_ADDR,
+	.volatile_reg = ep92_volatile_register,
+	.writeable_reg = ep92_writeable_registers,
+	.readable_reg = ep92_readable_registers,
+};
+
+void ep92_read_status(struct work_struct *work)
+{
+	struct ep92_pdata *ep92 = container_of(work, struct ep92_pdata,
+		read_status_worker);
+	struct snd_soc_component *component = ep92->component;
+	u8 val;
+
+	/* No polling before component is initialized */
+	if (component == NULL)
+		return;
+
+	if (ep92->force_inactive)
+		return;
+
+	/* check ADO_CHF that is set when audio format has changed */
+	val = snd_soc_component_read32(component, EP92_BI_GENERAL_INFO_1);
+	if (val == 0xff) {
+		/* workaround for Nak'ed first read */
+		val = snd_soc_component_read32(component,
+				EP92_BI_GENERAL_INFO_1);
+		if (val == 0xff)
+			return;	/* assume device not present */
+	}
+
+	if (val & EP92_GI_ADO_CHF_MASK)
+		dev_dbg(component->dev, "ep92 audio mode change trigger.\n");
+
+	if (val & EP92_GI_CEC_ECF_MASK)
+		dev_dbg(component->dev, "ep92 CEC change trigger.\n");
+
+	/* check for general control changes */
+	ep92_read_general_control(component, ep92);
+
+	/* update the format information in mixer controls */
+	ep92_read_audio_info(component, ep92);
+}
+
+static irqreturn_t ep92_irq(int irq, void *data)
+{
+	struct ep92_pdata *ep92 = data;
+	struct snd_soc_component *component = ep92->component;
+
+	/* Treat interrupt before component is initialized as spurious */
+	if (component == NULL)
+		return IRQ_NONE;
+
+	dev_dbg(component->dev, "ep92_interrupt\n");
+
+	ep92->poll_trig = 1;
+	mod_timer(&ep92->timer, jiffies +
+		msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
+
+	schedule_work(&ep92->read_status_worker);
+
+	return IRQ_HANDLED;
+};
+
+void ep92_poll_status(struct timer_list *t)
+{
+	struct ep92_pdata *ep92 = from_timer(ep92, t, timer);
+	struct snd_soc_component *component = ep92->component;
+
+	if (ep92->force_inactive)
+		return;
+
+	/* if no IRQ is configured, always keep on polling */
+	if (ep92->irq == 0)
+		ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
+
+	/* on interrupt, start polling for some time */
+	if (ep92->poll_trig) {
+		if (ep92->poll_rem == 0)
+			dev_info(component->dev, "status checking activated\n");
+
+		ep92->poll_trig = 0;
+		ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
+	}
+
+	/*
+	 * If power_on == 0, poll only until poll_rem reaches zero and stop.
+	 * This allows to system to go to low power sleep mode.
+	 * Otherwise (power_on == 1) always re-arm timer to keep on polling.
+	 */
+	if ((ep92->gc.ctl & EP92_GC_POWER_MASK) == 0) {
+		if (ep92->poll_rem) {
+			mod_timer(&ep92->timer, jiffies +
+				msecs_to_jiffies(EP92_POLL_INTERVAL_OFF_MSEC));
+			if (ep92->poll_rem > EP92_POLL_INTERVAL_OFF_MSEC) {
+				ep92->poll_rem -= EP92_POLL_INTERVAL_OFF_MSEC;
+			} else {
+				dev_info(component->dev, "status checking stopped\n");
+				ep92->poll_rem = 0;
+			}
+		}
+	} else {
+		ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
+		mod_timer(&ep92->timer, jiffies +
+			msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
+	}
+
+	schedule_work(&ep92->read_status_worker);
+}
+
+static const struct of_device_id ep92_of_match[] = {
+	{ .compatible = "explore,ep92a6", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ep92_of_match);
+
+static ssize_t ep92_sysfs_rda_chipid(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int reg0 = 0;
+	int reg1 = 0;
+	int reg2 = 0;
+	int reg3 = 0;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	reg0 = snd_soc_component_read32(ep92->component, EP92_BI_VENDOR_ID_0);
+	reg1 = snd_soc_component_read32(ep92->component, EP92_BI_VENDOR_ID_1);
+	reg2 = snd_soc_component_read32(ep92->component, EP92_BI_DEVICE_ID_0);
+	reg3 = snd_soc_component_read32(ep92->component, EP92_BI_DEVICE_ID_1);
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%02x%02x/%02x%02x\n",
+		reg0, reg1, reg2, reg3);
+	dev_dbg(dev, "%s: '%s'\n", __func__, buf);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_version(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int reg0 = 0;
+	int reg1 = 0;
+	int reg2 = 0;
+	int reg3 = 0;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	reg0 = snd_soc_component_read32(ep92->component,
+				EP92_BI_VERSION_YEAR);
+	reg1 = snd_soc_component_read32(ep92->component,
+				EP92_BI_VERSION_MONTH);
+	reg2 = snd_soc_component_read32(ep92->component,
+				EP92_BI_VERSION_DATE);
+	reg3 = snd_soc_component_read32(ep92->component,
+				EP92_BI_VERSION_NUM);
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%02d/%02d/%02d %d\n",
+		reg0, reg1, reg2, reg3);
+	dev_dbg(dev, "%s: '%s'\n", __func__, buf);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_state(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->ai.system_status_0 & EP92_AI_MCLK_ON_MASK) >>
+		EP92_AI_MCLK_ON_SHIFT;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_format(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->old_mode;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_dsd_rate(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->codec) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92_dsd_freq_table[(ep92->ai.system_status_1 &
+			EP92_AI_DSD_RATE_MASK) >> EP92_AI_DSD_RATE_SHIFT];
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_rate(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92_samp_freq_table[(ep92->ai.audio_status) &
+				   EP92_AI_RATE_MASK];
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_layout(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->ai.system_status_0 & EP92_AI_LAYOUT_MASK) >>
+		EP92_AI_LAYOUT_SHIFT;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_ch_count(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->ai.cc & EP92_AI_CH_COUNT_MASK;
+	/* mapping is ch_count = reg_val + 1, with exception: 0 = unknown */
+	if (val > 0)
+		val += 1;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_ch_alloc(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->ai.ca & EP92_AI_CH_ALLOC_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_audio_preemph(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->ai.cs[0] & EP92_AI_PREEMPH_MASK) >>
+		EP92_AI_PREEMPH_SHIFT;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_avmute(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->ai.system_status_0 >> EP92_AI_AVMUTE_SHIFT) &
+		EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_link_on0(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->filt_link_on0;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_link_on1(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->filt_link_on1;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_link_on2(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->filt_link_on2;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_out_plug(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->filt_tx_plug;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_video_latency(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->gi.video_latency & EP92_GI_VIDEO_LATENCY_MASK;
+	if (val > 0)
+		val = (val - 1) * 2;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_arc_disable(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.ctl2 >> EP92_GC_ARC_DIS_SHIFT) &
+		EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_arc_disable(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component,
+			EP92_GENERAL_CONTROL_2);
+	reg &= ~EP92_GC_ARC_DIS_MASK;
+	reg |= ((val << EP92_GC_ARC_DIS_SHIFT) & EP92_GC_ARC_DIS_MASK);
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_2, reg);
+	ep92->gc.ctl2 &= ~EP92_GC_ARC_DIS_MASK;
+	ep92->gc.ctl2 |= (val << EP92_GC_ARC_DIS_SHIFT) & EP92_GC_ARC_DIS_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_power(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.ctl >> EP92_GC_POWER_SHIFT) & EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_power(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component, EP92_GENERAL_CONTROL_0);
+	reg &= ~EP92_GC_POWER_MASK;
+	reg |= (val << EP92_GC_POWER_SHIFT) & EP92_GC_POWER_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_0, reg);
+	ep92->gc.ctl &= ~EP92_GC_POWER_MASK;
+	ep92->gc.ctl |= (val << EP92_GC_POWER_SHIFT) & EP92_GC_POWER_MASK;
+
+	if (val == 1) {
+		ep92->poll_trig = 1;
+		mod_timer(&ep92->timer, jiffies +
+			msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
+	}
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_audio_path(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.ctl >> EP92_GC_AUDIO_PATH_SHIFT) & EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_audio_path(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component,
+			EP92_GENERAL_CONTROL_0);
+	reg &= ~EP92_GC_AUDIO_PATH_MASK;
+	reg |= (val << EP92_GC_AUDIO_PATH_SHIFT) & EP92_GC_AUDIO_PATH_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_0, reg);
+	ep92->gc.ctl &= ~EP92_GC_AUDIO_PATH_MASK;
+	ep92->gc.ctl |= (val << EP92_GC_AUDIO_PATH_SHIFT) &
+		EP92_GC_AUDIO_PATH_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_src_sel(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->gc.rx_sel & EP92_GC_RX_SEL_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_src_sel(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 7)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component,
+			EP92_GENERAL_CONTROL_1);
+	reg &= ~EP92_GC_RX_SEL_MASK;
+	reg |= (val << EP92_GC_RX_SEL_SHIFT) & EP92_GC_RX_SEL_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_1, reg);
+	ep92->gc.rx_sel &= ~EP92_GC_RX_SEL_MASK;
+	ep92->gc.rx_sel |= (val << EP92_GC_RX_SEL_SHIFT) & EP92_GC_RX_SEL_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_arc_enable(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.ctl >> EP92_GC_ARC_EN_SHIFT) & EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_arc_enable(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component, EP92_GENERAL_CONTROL_0);
+	reg &= ~EP92_GC_ARC_EN_MASK;
+	reg |= (val << EP92_GC_ARC_EN_SHIFT) & EP92_GC_ARC_EN_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_0, reg);
+	ep92->gc.ctl &= ~EP92_GC_ARC_EN_MASK;
+	ep92->gc.ctl |= (val << EP92_GC_ARC_EN_SHIFT) &
+		EP92_GC_ARC_EN_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_cec_mute(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.ctl >> EP92_GC_CEC_MUTE_SHIFT) & EP92_2CHOICE_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_cec_mute(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = snd_soc_component_read32(ep92->component, EP92_GENERAL_CONTROL_0);
+	reg &= ~EP92_GC_CEC_MUTE_MASK;
+	reg |= (val << EP92_GC_CEC_MUTE_SHIFT) & EP92_GC_CEC_MUTE_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_0, reg);
+	ep92->gc.ctl &= ~EP92_GC_CEC_MUTE_MASK;
+	ep92->gc.ctl |= (val << EP92_GC_CEC_MUTE_SHIFT) &
+		EP92_GC_CEC_MUTE_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_cec_volume(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = (ep92->gc.cec_volume >> EP92_GC_CEC_VOLUME_SHIFT) &
+		EP92_GC_CEC_VOLUME_MASK;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_cec_volume(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int reg, val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > EP92_GC_CEC_VOLUME_MAX)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	reg = val & EP92_GC_CEC_VOLUME_MASK;
+	snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_3, reg);
+	ep92->gc.cec_volume = val & EP92_GC_CEC_VOLUME_MASK;
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static ssize_t ep92_sysfs_rda_runout(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->poll_rem;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_rda_force_inactive(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	int val;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	val = ep92->force_inactive;
+
+	ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
+	dev_dbg(dev, "%s: '%d'\n", __func__, val);
+
+	return ret;
+}
+
+static ssize_t ep92_sysfs_wta_force_inactive(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int val, rc;
+	struct ep92_pdata *ep92 = dev_get_drvdata(dev);
+
+	if (!ep92 || !ep92->component) {
+		dev_err(dev, "%s: device error\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = kstrtoint(buf, 10, &val);
+	if (rc) {
+		dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		goto end;
+	}
+	if ((val < 0) || (val > 1)) {
+		dev_err(dev, "%s: value out of range.\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (val == 0) {
+		ep92->force_inactive = 0;
+		ep92->poll_trig = 1;
+		mod_timer(&ep92->timer, jiffies +
+			msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
+	} else {
+		ep92->force_inactive = 1;
+		ep92->poll_rem = 0;
+	}
+
+	rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
+end:
+	return rc;
+}
+
+static DEVICE_ATTR(chipid, 0444, ep92_sysfs_rda_chipid, NULL);
+static DEVICE_ATTR(version, 0444, ep92_sysfs_rda_version, NULL);
+static DEVICE_ATTR(audio_state, 0444, ep92_sysfs_rda_audio_state, NULL);
+static DEVICE_ATTR(audio_format, 0444, ep92_sysfs_rda_audio_format, NULL);
+static DEVICE_ATTR(audio_rate, 0444, ep92_sysfs_rda_audio_rate, NULL);
+static DEVICE_ATTR(audio_layout, 0444, ep92_sysfs_rda_audio_layout, NULL);
+static DEVICE_ATTR(audio_ch_count, 0444, ep92_sysfs_rda_audio_ch_count, NULL);
+static DEVICE_ATTR(audio_ch_alloc, 0444, ep92_sysfs_rda_audio_ch_alloc, NULL);
+static DEVICE_ATTR(audio_preemph, 0444, ep92_sysfs_rda_audio_preemph, NULL);
+static DEVICE_ATTR(audio_avmute, 0444, ep92_sysfs_rda_avmute, NULL);
+static DEVICE_ATTR(link_on0, 0444, ep92_sysfs_rda_link_on0, NULL);
+static DEVICE_ATTR(link_on1, 0444, ep92_sysfs_rda_link_on1, NULL);
+static DEVICE_ATTR(link_on2, 0444, ep92_sysfs_rda_link_on2, NULL);
+static DEVICE_ATTR(out_plug, 0444, ep92_sysfs_rda_out_plug, NULL);
+static DEVICE_ATTR(video_latency, 0444, ep92_sysfs_rda_video_latency, NULL);
+static DEVICE_ATTR(arc_disable, 0644, ep92_sysfs_rda_arc_disable,
+	ep92_sysfs_wta_arc_disable);
+static DEVICE_ATTR(power_on, 0644, ep92_sysfs_rda_power, ep92_sysfs_wta_power);
+static DEVICE_ATTR(audio_path, 0644, ep92_sysfs_rda_audio_path,
+	ep92_sysfs_wta_audio_path);
+static DEVICE_ATTR(src_sel, 0644, ep92_sysfs_rda_src_sel,
+	ep92_sysfs_wta_src_sel);
+static DEVICE_ATTR(arc_enable, 0644, ep92_sysfs_rda_arc_enable,
+	ep92_sysfs_wta_arc_enable);
+static DEVICE_ATTR(cec_mute, 0644, ep92_sysfs_rda_cec_mute,
+	ep92_sysfs_wta_cec_mute);
+static DEVICE_ATTR(cec_volume, 0644, ep92_sysfs_rda_cec_volume,
+	ep92_sysfs_wta_cec_volume);
+static DEVICE_ATTR(runout, 0444, ep92_sysfs_rda_runout, NULL);
+static DEVICE_ATTR(force_inactive, 0644, ep92_sysfs_rda_force_inactive,
+	ep92_sysfs_wta_force_inactive);
+static DEVICE_ATTR(dsd_rate, 0444, ep92_sysfs_rda_dsd_rate, NULL);
+
+static struct attribute *ep92_fs_attrs[] = {
+	&dev_attr_chipid.attr,
+	&dev_attr_version.attr,
+	&dev_attr_audio_state.attr,
+	&dev_attr_audio_format.attr,
+	&dev_attr_audio_rate.attr,
+	&dev_attr_audio_layout.attr,
+	&dev_attr_audio_ch_count.attr,
+	&dev_attr_audio_ch_alloc.attr,
+	&dev_attr_audio_preemph.attr,
+	&dev_attr_audio_avmute.attr,
+	&dev_attr_link_on0.attr,
+	&dev_attr_link_on1.attr,
+	&dev_attr_link_on2.attr,
+	&dev_attr_out_plug.attr,
+	&dev_attr_video_latency.attr,
+	&dev_attr_arc_disable.attr,
+	&dev_attr_power_on.attr,
+	&dev_attr_audio_path.attr,
+	&dev_attr_src_sel.attr,
+	&dev_attr_arc_enable.attr,
+	&dev_attr_cec_mute.attr,
+	&dev_attr_cec_volume.attr,
+	&dev_attr_runout.attr,
+	&dev_attr_force_inactive.attr,
+	&dev_attr_dsd_rate.attr,
+	NULL,
+};
+
+static struct attribute_group ep92_fs_attrs_group = {
+	.attrs = ep92_fs_attrs,
+};
+
+static int ep92_sysfs_create(struct i2c_client *client,
+	struct ep92_pdata *ep92)
+{
+	int rc;
+
+	rc = sysfs_create_group(&client->dev.kobj, &ep92_fs_attrs_group);
+
+	return rc;
+}
+
+static void ep92_sysfs_remove(struct i2c_client *client,
+	struct ep92_pdata *ep92)
+{
+	sysfs_remove_group(&client->dev.kobj, &ep92_fs_attrs_group);
+}
+
+static int ep92_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	struct ep92_pdata *ep92;
+	int ret;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	char debugfs_dir_name[32];
+#endif
+
+	ep92 = devm_kzalloc(&client->dev, sizeof(struct ep92_pdata),
+		GFP_KERNEL);
+	if (ep92 == NULL)
+		return -ENOMEM;
+
+	ep92->regmap = devm_regmap_init_i2c(client, &ep92_regmap_config);
+	if (IS_ERR(ep92->regmap)) {
+		ret = PTR_ERR(ep92->regmap);
+		dev_err(&client->dev,
+			"%s: Failed to allocate regmap for I2C device: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(client, ep92);
+
+	/* register interrupt handler */
+	INIT_WORK(&ep92->read_status_worker, ep92_read_status);
+	ep92->irq = client->irq;
+	if (ep92->irq) {
+		ret = devm_request_threaded_irq(&client->dev, ep92->irq,
+			NULL, ep92_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			"ep92_irq", ep92);
+		if (ret) {
+			dev_err(&client->dev,
+				"%s: Failed to request IRQ %d: %d\n",
+				__func__, ep92->irq, ret);
+			ep92->irq = 0;
+		}
+	}
+	/* prepare timer */
+	timer_setup(&ep92->timer, ep92_poll_status, 0);
+	ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	/* debugfs interface */
+	snprintf(debugfs_dir_name, sizeof(debugfs_dir_name), "%s-%s",
+		client->name, dev_name(&client->dev));
+	ep92->debugfs_dir = debugfs_create_dir(debugfs_dir_name, NULL);
+	if (!ep92->debugfs_dir) {
+		dev_dbg(&client->dev,
+			"%s: Failed to create /sys/kernel/debug/%s for debugfs\n",
+			__func__, debugfs_dir_name);
+		return -ENOMEM;
+	}
+	ep92->debugfs_file_wo = debugfs_create_file(
+		"write_reg_val", S_IFREG | 0444, ep92->debugfs_dir,
+		(void *) ep92,
+		&debugfs_codec_ops);
+	if (!ep92->debugfs_file_wo) {
+		dev_dbg(&client->dev,
+			"%s: Failed to create /sys/kernel/debug/%s/write_reg_val\n",
+			__func__, debugfs_dir_name);
+		return -ENOMEM;
+	}
+	ep92->debugfs_file_ro = debugfs_create_file(
+		"show_reg_dump", S_IFREG | 0444, ep92->debugfs_dir,
+		(void *) ep92,
+		&debugfs_codec_ops);
+	if (!ep92->debugfs_file_ro) {
+		dev_dbg(&client->dev,
+			"%s: Failed to create /sys/kernel/debug/%s/show_reg_dump\n",
+			__func__, debugfs_dir_name);
+		return -ENOMEM;
+	}
+#endif /* CONFIG_DEBUG_FS */
+
+	/* register component */
+	ret = snd_soc_register_component(&client->dev, &soc_codec_drv_ep92,
+		ep92_dai, ARRAY_SIZE(ep92_dai));
+	if (ret) {
+		dev_err(&client->dev, "%s %d: Failed to register CODEC: %d\n",
+			__func__, __LINE__, ret);
+		goto err_reg;
+	}
+
+	ret = ep92_sysfs_create(client, ep92);
+	if (ret) {
+		dev_err(&client->dev, "%s: sysfs creation failed ret=%d\n",
+			__func__, ret);
+		goto err_sysfs;
+	}
+
+	return 0;
+
+err_sysfs:
+	snd_soc_unregister_component(&client->dev);
+err_reg:
+	del_timer(&ep92->timer);
+
+	return ret;
+}
+
+static int ep92_i2c_remove(struct i2c_client *client)
+{
+	struct ep92_pdata *ep92;
+
+	ep92 = i2c_get_clientdata(client);
+	if (ep92) {
+		del_timer(&ep92->timer);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+		debugfs_remove_recursive(ep92->debugfs_dir);
+#endif
+	}
+	snd_soc_unregister_component(&client->dev);
+
+	ep92_sysfs_remove(client, ep92);
+
+	return 0;
+}
+
+static const struct i2c_device_id ep92_i2c_id[] = {
+	{ "ep92-dev", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ep92_i2c_id);
+
+static struct i2c_driver ep92_i2c_driver = {
+	.probe =    ep92_i2c_probe,
+	.remove =   ep92_i2c_remove,
+	.id_table = ep92_i2c_id,
+	.driver = {
+		.name = "ep92",
+		.owner = THIS_MODULE,
+		.of_match_table = ep92_of_match
+	},
+};
+
+static int __init ep92_codec_init(void)
+{
+	int ret = 0;
+
+	ret = i2c_add_driver(&ep92_i2c_driver);
+	if (ret)
+		pr_err("Failed to register EP92 I2C driver: %d\n", ret);
+
+	return ret;
+}
+module_init(ep92_codec_init);
+
+static void __exit ep92_codec_exit(void)
+{
+	i2c_del_driver(&ep92_i2c_driver);
+}
+module_exit(ep92_codec_exit);
+
+MODULE_DESCRIPTION("EP92 HDMI repeater/switch driver");
+MODULE_LICENSE("GPL v2");

+ 159 - 0
qcom/opensource/audio-kernel/asoc/codecs/ep92/ep92.h

@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __EP92_H__
+#define __EP92_H__
+
+/* EP92 register addresses */
+/* BI = Basic Info */
+#define   EP92_BI_VENDOR_ID_0                   0x00
+#define   EP92_BI_VENDOR_ID_1                   0x01
+#define   EP92_BI_DEVICE_ID_0                   0x02
+#define   EP92_BI_DEVICE_ID_1                   0x03
+#define   EP92_BI_VERSION_NUM                   0x04
+#define   EP92_BI_VERSION_YEAR                  0x05
+#define   EP92_BI_VERSION_MONTH                 0x06
+#define   EP92_BI_VERSION_DATE                  0x07
+#define   EP92_BI_GENERAL_INFO_0                0x08
+#define   EP92_BI_GENERAL_INFO_1                0x09
+#define   EP92_BI_GENERAL_INFO_2                0x0A
+#define   EP92_BI_GENERAL_INFO_3                0x0B
+#define   EP92_BI_GENERAL_INFO_4                0x0C
+#define   EP92_BI_GENERAL_INFO_5                0x0D
+#define   EP92_BI_GENERAL_INFO_6                0x0E
+
+#define   EP92_ISP_MODE_ENTER_ISP               0x0F
+
+#define   EP92_GENERAL_CONTROL_0                0x10
+#define   EP92_GENERAL_CONTROL_1                0x11
+#define   EP92_GENERAL_CONTROL_2                0x12
+#define   EP92_GENERAL_CONTROL_3                0x13
+#define   EP92_GENERAL_CONTROL_4                0x14
+
+#define   EP92_CEC_EVENT_CODE                   0x15
+#define   EP92_CEC_EVENT_PARAM_1                0x16
+#define   EP92_CEC_EVENT_PARAM_2                0x17
+#define   EP92_CEC_EVENT_PARAM_3                0x18
+#define   EP92_CEC_EVENT_PARAM_4                0x19
+/*        RESERVED                              0x1A */
+/*        ...                                   ...  */
+/*        RESERVED                              0x1F */
+#define   EP92_AUDIO_INFO_SYSTEM_STATUS_0       0x20
+#define   EP92_AUDIO_INFO_SYSTEM_STATUS_1       0x21
+#define   EP92_AUDIO_INFO_AUDIO_STATUS          0x22
+#define   EP92_AUDIO_INFO_CHANNEL_STATUS_0      0x23
+#define   EP92_AUDIO_INFO_CHANNEL_STATUS_1      0x24
+#define   EP92_AUDIO_INFO_CHANNEL_STATUS_2      0x25
+#define   EP92_AUDIO_INFO_CHANNEL_STATUS_3      0x26
+#define   EP92_AUDIO_INFO_CHANNEL_STATUS_4      0x27
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_0      0x28
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_1      0x29
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_2      0x2A
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_3      0x2B
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_4      0x2C
+#define   EP92_AUDIO_INFO_ADO_INFO_FRAME_5      0x2D
+
+#define   EP92_OTHER_PACKETS_HDMI_VS_0          0x2E
+#define   EP92_OTHER_PACKETS_HDMI_VS_1          0x2F
+#define   EP92_OTHER_PACKETS_ACP_PACKET         0x30
+#define   EP92_OTHER_PACKETS_AVI_INFO_FRAME_0   0x31
+#define   EP92_OTHER_PACKETS_AVI_INFO_FRAME_1   0x32
+#define   EP92_OTHER_PACKETS_AVI_INFO_FRAME_2   0x33
+#define   EP92_OTHER_PACKETS_AVI_INFO_FRAME_3   0x34
+#define   EP92_OTHER_PACKETS_AVI_INFO_FRAME_4   0x35
+#define   EP92_OTHER_PACKETS_GC_PACKET_0        0x36
+#define   EP92_OTHER_PACKETS_GC_PACKET_1        0x37
+#define   EP92_OTHER_PACKETS_GC_PACKET_2        0x38
+
+#define   EP92_MAX_REGISTER_ADDR                EP92_OTHER_PACKETS_GC_PACKET_2
+
+/* shift/masks for register bits
+ * GI = General Info
+ * GC = General Control
+ * AI = Audio Info
+ */
+#define EP92_GI_ADO_CHF_MASK        0x01
+#define EP92_GI_CEC_ECF_MASK        0x02
+#define EP92_GI_TX_HOT_PLUG_SHIFT   7
+#define EP92_GI_TX_HOT_PLUG_MASK    0x80
+#define EP92_GI_VIDEO_LATENCY_SHIFT 0
+#define EP92_GI_VIDEO_LATENCY_MASK  0xff
+
+#define EP92_GC_POWER_SHIFT      7
+#define EP92_GC_POWER_MASK       0x80
+#define EP92_GC_AUDIO_PATH_SHIFT 5
+#define EP92_GC_AUDIO_PATH_MASK  0x20
+#define EP92_GC_CEC_MUTE_SHIFT   1
+#define EP92_GC_CEC_MUTE_MASK    0x02
+#define EP92_GC_ARC_EN_SHIFT     0
+#define EP92_GC_ARC_EN_MASK      0x01
+#define EP92_GC_ARC_DIS_SHIFT    6
+#define EP92_GC_ARC_DIS_MASK     0x40
+#define EP92_GC_RX_SEL_SHIFT     0
+#define EP92_GC_RX_SEL_MASK      0x07
+#define EP92_GC_CEC_VOLUME_SHIFT 0
+#define EP92_GC_CEC_VOLUME_MASK  0xff
+#define EP92_GC_LINK_ON0_SHIFT   0
+#define EP92_GC_LINK_ON0_MASK    0x01
+#define EP92_GC_LINK_ON1_SHIFT   1
+#define EP92_GC_LINK_ON1_MASK    0x02
+#define EP92_GC_LINK_ON2_SHIFT   2
+#define EP92_GC_LINK_ON2_MASK    0x04
+
+#define EP92_AI_MCLK_ON_SHIFT    6
+#define EP92_AI_MCLK_ON_MASK     0x40
+#define EP92_AI_AVMUTE_SHIFT     5
+#define EP92_AI_AVMUTE_MASK      0x20
+#define EP92_AI_LAYOUT_SHIFT     0
+#define EP92_AI_LAYOUT_MASK      0x01
+#define EP92_AI_HBR_ADO_SHIFT    5
+#define EP92_AI_HBR_ADO_MASK     0x20
+#define EP92_AI_STD_ADO_SHIFT    3
+#define EP92_AI_STD_ADO_MASK     0x08
+#define EP92_AI_RATE_MASK        0x07
+#define EP92_AI_NPCM_MASK        0x02
+#define EP92_AI_PREEMPH_SHIFT    3
+#define EP92_AI_PREEMPH_MASK     0x38
+#define EP92_AI_CH_COUNT_MASK    0x07
+#define EP92_AI_CH_ALLOC_MASK    0xff
+#define EP92_AI_DSD_ADO_SHIFT    4
+#define EP92_AI_DSD_ADO_MASK     0x10
+#define EP92_AI_DSD_RATE_SHIFT   4
+#define EP92_AI_DSD_RATE_MASK    0x30
+
+#define EP92_2CHOICE_MASK        1
+#define EP92_GC_CEC_VOLUME_MIN   0
+#define EP92_GC_CEC_VOLUME_MAX   100
+#define EP92_AI_RATE_MIN         0
+#define EP92_AI_RATE_MAX         768000
+#define EP92_AI_CH_COUNT_MIN     0
+#define EP92_AI_CH_COUNT_MAX     8
+#define EP92_AI_CH_ALLOC_MIN     0
+#define EP92_AI_CH_ALLOC_MAX     0xff
+
+#define EP92_STATUS_NO_SIGNAL           0
+#define EP92_STATUS_AUDIO_ACTIVE        1
+
+/* kcontrol storage indices */
+enum {
+	EP92_KCTL_POWER = 0,
+	EP92_KCTL_AUDIO_PATH,
+	EP92_KCTL_CEC_MUTE,
+	EP92_KCTL_ARC_EN,
+	EP92_KCTL_RX_SEL,
+	EP92_KCTL_CEC_VOLUME,
+	EP92_KCTL_STATE,
+	EP92_KCTL_AVMUTE,
+	EP92_KCTL_LAYOUT,
+	EP92_KCTL_MODE,
+	EP92_KCTL_RATE,
+	EP92_KCTL_CH_COUNT,
+	EP92_KCTL_CH_ALLOC,
+	EP92_KCTL_MAX
+};
+
+int ep92_set_ext_mclk(struct snd_soc_codec *codec, uint32_t mclk_freq);
+
+#endif /* __EP92_H__ */

+ 672 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-bt-swr.c

@@ -0,0 +1,672 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <soc/swr-common.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+#include <soc/swr-wcd.h>
+#include <soc/snd_event.h>
+
+#define DRV_NAME "lpass-bt-swr"
+
+/* pm runtime auto suspend timer in msecs */
+#define LPASS_BT_SWR_AUTO_SUSPEND_DELAY          100 /* delay in msec */
+
+#define LPASS_BT_SWR_STRING_LEN 80
+
+#define LPASS_BT_SWR_CHILD_DEVICES_MAX 1
+
+/* Hold instance to soundwire platform device */
+struct lpass_bt_swr_ctrl_data {
+	struct platform_device *lpass_bt_swr_pdev;
+};
+
+struct lpass_bt_swr_ctrl_platform_data {
+	void *handle; /* holds parent private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+struct lpass_bt_swr_priv {
+	struct device *dev;
+	struct mutex vote_lock;
+	struct mutex swr_clk_lock;
+	struct mutex ssr_lock;
+	bool dev_up;
+	bool initial_boot;
+
+	struct clk *lpass_core_hw_vote;
+	struct clk *lpass_audio_hw_vote;
+	int core_hw_vote_count;
+	int core_audio_vote_count;
+	int swr_clk_users;
+	struct clk *clk_handle;
+	struct clk *clk_handle_2x;
+
+	struct lpass_bt_swr_ctrl_data *swr_ctrl_data;
+	struct lpass_bt_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct lpass_bt_swr_add_child_devices_work;
+	struct platform_device *pdev_child_devices
+			[LPASS_BT_SWR_CHILD_DEVICES_MAX];
+	int child_count;
+
+	struct device_node *bt_swr_gpio_p;
+
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+
+	struct blocking_notifier_head notifier;
+	struct device *clk_dev;
+};
+
+static struct lpass_bt_swr_priv *lpass_bt_priv;
+
+static void lpass_bt_swr_add_child_devices(struct work_struct *work)
+{
+	struct lpass_bt_swr_priv *priv;
+	struct platform_device *pdev;
+	struct device_node *node;
+	struct lpass_bt_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
+	int ret;
+	u16 count = 0, ctrl_num = 0;
+	struct lpass_bt_swr_ctrl_platform_data *platdata;
+	char plat_dev_name[LPASS_BT_SWR_STRING_LEN];
+
+	priv = container_of(work, struct lpass_bt_swr_priv,
+			     lpass_bt_swr_add_child_devices_work);
+	if (!priv) {
+		pr_err("%s: Memory for priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!priv->dev || !priv->dev->of_node) {
+		dev_err(priv->dev,
+			"%s: DT node for priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &priv->swr_plat_data;
+	priv->child_count = 0;
+
+	for_each_available_child_of_node(priv->dev->of_node, node) {
+		if (strnstr(node->name, "bt_swr_mstr",
+				strlen("bt_swr_mstr")) != NULL)
+			strscpy(plat_dev_name, "bt_swr_mstr",
+				(LPASS_BT_SWR_STRING_LEN - 1));
+		else
+			continue;
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			return;
+		}
+		pdev->dev.parent = priv->dev;
+		pdev->dev.of_node = node;
+
+		ret = platform_device_add_data(pdev, platdata,
+					       sizeof(*platdata));
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: cannot add plat data ctrl:%d\n",
+				__func__, ctrl_num);
+			goto fail_pdev_add;
+		}
+
+		temp = krealloc(swr_ctrl_data,
+				(ctrl_num + 1) * sizeof(
+				struct lpass_bt_swr_ctrl_data),
+				GFP_KERNEL);
+		if (!temp) {
+			dev_err(&pdev->dev, "out of memory\n");
+			ret = -ENOMEM;
+			goto fail_pdev_add;
+		}
+		swr_ctrl_data = temp;
+		swr_ctrl_data[ctrl_num].lpass_bt_swr_pdev = pdev;
+		ctrl_num++;
+
+		dev_dbg(&pdev->dev, "%s: Adding soundwire ctrl device(s)\n",
+			__func__);
+		priv->swr_ctrl_data = swr_ctrl_data;
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (priv->child_count < LPASS_BT_SWR_CHILD_DEVICES_MAX)
+			priv->pdev_child_devices[
+					priv->child_count++] = pdev;
+		else
+			return;
+	}
+
+	return;
+fail_pdev_add:
+	for (count = 0; count < priv->child_count; count++)
+		platform_device_put(priv->pdev_child_devices[count]);
+}
+
+
+bool lpass_bt_swr_check_core_votes(struct lpass_bt_swr_priv *priv)
+{
+	bool ret = true;
+
+	mutex_lock(&priv->vote_lock);
+	if (!priv->dev_up ||
+		(priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+		(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))
+		ret = false;
+	mutex_unlock(&priv->vote_lock);
+
+	return ret;
+}
+
+static int lpass_bt_swr_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct lpass_bt_swr_priv *priv = (struct lpass_bt_swr_priv *) handle;
+
+	if (priv == NULL) {
+		pr_err_ratelimited("%s: priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!priv->dev_up && enable) {
+		pr_err("%s: adsp is not up\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(priv->dev);
+		if (lpass_bt_swr_check_core_votes(priv))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(priv->dev);
+		pm_runtime_mark_last_busy(priv->dev);
+	}
+	return rc;
+}
+
+static int lpass_bt_swr_mclk_enable(
+				struct lpass_bt_swr_priv *priv,
+				bool mclk_enable)
+{
+	int ret = 0;
+
+	dev_dbg(priv->dev, "%s: mclk_enable = %u\n",
+		__func__, mclk_enable);
+
+	ret = lpass_bt_swr_core_vote(priv, true);
+	if (ret < 0) {
+		dev_err_ratelimited(priv->dev,
+			"%s: request core vote failed\n",
+			__func__);
+		goto exit;
+	}
+
+	if (mclk_enable) {
+		ret = clk_prepare_enable(priv->clk_handle);
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: bt_swr_clk enable failed\n", __func__);
+			goto error;
+		}
+
+		if (priv->clk_handle_2x) {
+			ret = clk_prepare_enable(priv->clk_handle_2x);
+			if (ret < 0) {
+				dev_err_ratelimited(priv->dev,
+				  "%s: bt_swr_2x_clk enable failed\n", __func__);
+				clk_disable_unprepare(priv->clk_handle);
+			}
+		}
+	} else {
+		clk_disable_unprepare(priv->clk_handle);
+		if (priv->clk_handle_2x)
+			clk_disable_unprepare(priv->clk_handle_2x);
+	}
+
+error:
+	lpass_bt_swr_core_vote(priv, false);
+exit:
+	return ret;
+}
+
+static int lpass_bt_swrm_clock(void *handle, bool enable)
+{
+	struct lpass_bt_swr_priv *priv = (struct lpass_bt_swr_priv *) handle;
+	int ret = 0;
+
+	mutex_lock(&priv->swr_clk_lock);
+
+	dev_dbg(priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(priv->dev);
+		if (priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						priv->bt_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(priv->dev,
+					"%s: bt swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(priv->dev);
+				pm_runtime_put_autosuspend(priv->dev);
+				goto exit;
+			}
+			ret = lpass_bt_swr_mclk_enable(priv, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						priv->bt_swr_gpio_p);
+				dev_err_ratelimited(priv->dev,
+					"%s: lpass bt swr request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(priv->dev);
+				pm_runtime_put_autosuspend(priv->dev);
+				goto exit;
+			}
+		}
+		priv->swr_clk_users++;
+		pm_runtime_mark_last_busy(priv->dev);
+		pm_runtime_put_autosuspend(priv->dev);
+	} else {
+		if (priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: clock already disabled\n",
+			__func__);
+			priv->swr_clk_users = 0;
+			goto exit;
+		}
+		priv->swr_clk_users--;
+		if (priv->swr_clk_users == 0) {
+			lpass_bt_swr_mclk_enable(priv, false);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						priv->bt_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(priv->dev,
+					"%s: bt swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(priv->dev, "%s: swrm clock users %d\n",
+		__func__, priv->swr_clk_users);
+exit:
+	mutex_unlock(&priv->swr_clk_lock);
+	return ret;
+}
+
+static void lpass_bt_swr_ssr_disable(struct device *dev, void *data)
+{
+	struct lpass_bt_swr_priv *priv = data;
+
+	if (!priv->dev_up) {
+		dev_err_ratelimited(priv->dev,
+				    "%s: already disabled\n", __func__);
+		return;
+	}
+
+	mutex_lock(&priv->ssr_lock);
+	priv->dev_up = false;
+	mutex_unlock(&priv->ssr_lock);
+
+	swrm_wcd_notify(priv->swr_ctrl_data->lpass_bt_swr_pdev,
+				 SWR_DEVICE_SSR_DOWN, NULL);
+
+}
+
+static int lpass_bt_swr_ssr_enable(struct device *dev, void *data)
+{
+	struct lpass_bt_swr_priv *priv = data;
+	int ret;
+
+	if (priv->initial_boot) {
+		priv->initial_boot = false;
+		return 0;
+	}
+
+	mutex_lock(&priv->ssr_lock);
+	priv->dev_up = true;
+	mutex_unlock(&priv->ssr_lock);
+
+	mutex_lock(&priv->swr_clk_lock);
+
+	dev_dbg(priv->dev, "%s: swrm clock users %d\n",
+		__func__, priv->swr_clk_users);
+
+	lpass_bt_swr_mclk_enable(priv, false);
+	ret = msm_cdc_pinctrl_select_sleep_state(
+				priv->bt_swr_gpio_p);
+	if (ret < 0) {
+		dev_err_ratelimited(priv->dev,
+			"%s: bt swr pinctrl disable failed\n",
+			__func__);
+	}
+
+	if (priv->swr_clk_users > 0) {
+		lpass_bt_swr_mclk_enable(priv, true);
+		ret = msm_cdc_pinctrl_select_active_state(
+					priv->bt_swr_gpio_p);
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: bt swr pinctrl enable failed\n",
+				__func__);
+		}
+	}
+	mutex_unlock(&priv->swr_clk_lock);
+
+	swrm_wcd_notify(priv->swr_ctrl_data->lpass_bt_swr_pdev,
+				 SWR_DEVICE_SSR_UP, NULL);
+
+	return 0;
+}
+
+static const struct snd_event_ops lpass_bt_swr_ssr_ops = {
+	.enable = lpass_bt_swr_ssr_enable,
+	.disable = lpass_bt_swr_ssr_disable,
+};
+
+static int lpass_bt_swr_probe(struct platform_device *pdev)
+{
+	struct lpass_bt_swr_priv *priv;
+	int ret;
+	struct clk *lpass_core_hw_vote = NULL;
+	struct clk *lpass_audio_hw_vote = NULL;
+	struct clk *bt_swr_clk = NULL;
+	struct clk *bt_swr_2x_clk = NULL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_bt_swr_priv),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier);
+	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->core_hw_vote_count = 0;
+	priv->core_audio_vote_count = 0;
+
+	dev_set_drvdata(&pdev->dev, priv);
+	mutex_init(&priv->vote_lock);
+	mutex_init(&priv->swr_clk_lock);
+	mutex_init(&priv->ssr_lock);
+
+	priv->bt_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,bt-swr-gpios", 0);
+	if (!priv->bt_swr_gpio_p) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(priv->bt_swr_gpio_p) < 0) {
+		dev_info(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
+	/* Register LPASS core hw vote */
+	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
+	if (IS_ERR(lpass_core_hw_vote)) {
+		ret = PTR_ERR(lpass_core_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_core_hw_vote", ret);
+		lpass_core_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_core_hw_vote = lpass_core_hw_vote;
+
+	/* Register LPASS audio hw vote */
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_audio_hw_vote = lpass_audio_hw_vote;
+
+	/* Register bt swr clk vote */
+	bt_swr_clk = devm_clk_get(&pdev->dev, "bt_swr_mclk_clk");
+	if (IS_ERR(bt_swr_clk)) {
+		ret = PTR_ERR(bt_swr_clk);
+		dev_err(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "bt_swr_clk", ret);
+		return -EINVAL;
+	}
+	priv->clk_handle = bt_swr_clk;
+
+	/* Register bt swr 2x clk vote */
+	bt_swr_2x_clk = devm_clk_get(&pdev->dev, "bt_swr_mclk_clk_2x");
+	if (IS_ERR(bt_swr_2x_clk)) {
+		ret = PTR_ERR(bt_swr_2x_clk);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "bt_swr_2x_clk", ret);
+		bt_swr_2x_clk = NULL;
+		ret = 0;
+	}
+	priv->clk_handle_2x = bt_swr_2x_clk;
+
+	/* Add soundwire child devices. */
+	INIT_WORK(&priv->lpass_bt_swr_add_child_devices_work,
+		 lpass_bt_swr_add_child_devices);
+
+	priv->swr_plat_data.handle = (void *)priv;
+	priv->swr_plat_data.read = NULL;
+	priv->swr_plat_data.write = NULL;
+	priv->swr_plat_data.bulk_write = NULL;
+	priv->swr_plat_data.clk = lpass_bt_swrm_clock;
+	priv->swr_plat_data.core_vote = lpass_bt_swr_core_vote;
+	priv->swr_plat_data.handle_irq = NULL;
+
+	lpass_bt_priv = priv;
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, LPASS_BT_SWR_AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+
+	/* call scheduler to add child devices. */
+	schedule_work(&priv->lpass_bt_swr_add_child_devices_work);
+
+	priv->initial_boot = true;
+	ret = snd_event_client_register(priv->dev, &lpass_bt_swr_ssr_ops, priv);
+	if (!ret) {
+		snd_event_notify(priv->dev, SND_EVENT_UP);
+		dev_err(&pdev->dev, "%s: Registered SSR ops\n", __func__);
+	} else {
+		dev_err(&pdev->dev,
+			"%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+	}
+
+	return 0;
+}
+
+static int lpass_bt_swr_remove(struct platform_device *pdev)
+{
+	struct lpass_bt_swr_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	of_platform_depopulate(&pdev->dev);
+	mutex_destroy(&priv->vote_lock);
+	mutex_destroy(&priv->swr_clk_lock);
+	mutex_destroy(&priv->ssr_lock);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int lpass_bt_swr_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct lpass_bt_swr_priv *priv = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	dev_dbg(dev, "%s, enter\n", __func__);
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
+		goto audio_vote;
+	}
+
+	if (priv->core_hw_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote, dev);
+		if (ret < 0) {
+			dev_err_ratelimited(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+			goto audio_vote;
+		}
+	}
+	priv->core_hw_vote_count++;
+
+audio_vote:
+	if (priv->lpass_audio_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__);
+		goto done;
+	}
+
+	if (priv->core_audio_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote, dev);
+		if (ret < 0) {
+			dev_err_ratelimited(dev, "%s:lpass audio hw enable failed\n",
+				__func__);
+			goto done;
+		}
+	}
+	priv->core_audio_vote_count++;
+
+done:
+	mutex_unlock(&priv->vote_lock);
+	dev_dbg(dev, "%s, leave, hw_vote %d, audio_vote %d\n", __func__,
+			priv->core_hw_vote_count, priv->core_audio_vote_count);
+	pm_runtime_set_autosuspend_delay(priv->dev, LPASS_BT_SWR_AUTO_SUSPEND_DELAY);
+
+	return 0;
+}
+
+int lpass_bt_swr_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct lpass_bt_swr_priv *priv = platform_get_drvdata(pdev);
+
+	dev_dbg(dev, "%s, enter\n", __func__);
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote != NULL) {
+		if (--priv->core_hw_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_core_hw_vote, dev);
+		if (priv->core_hw_vote_count < 0)
+			priv->core_hw_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n",
+			__func__);
+	}
+
+	if (priv->lpass_audio_hw_vote != NULL) {
+		if (--priv->core_audio_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_audio_hw_vote, dev);
+		if (priv->core_audio_vote_count < 0)
+			priv->core_audio_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n",
+			__func__);
+	}
+
+	mutex_unlock(&priv->vote_lock);
+	dev_dbg(dev, "%s, leave, hw_vote %d, audio_vote %d\n", __func__,
+		priv->core_hw_vote_count, priv->core_audio_vote_count);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct of_device_id lpass_bt_swr_dt_match[] = {
+	{.compatible = "qcom,lpass-bt-swr"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, lpass_bt_swr_dt_match);
+
+static const struct dev_pm_ops lpass_bt_swr_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_bt_swr_runtime_suspend,
+		lpass_bt_swr_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_bt_swr_drv = {
+	.driver = {
+		.name = "lpass-bt-swr",
+		.pm = &lpass_bt_swr_pm_ops,
+		.of_match_table = lpass_bt_swr_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_bt_swr_probe,
+	.remove = lpass_bt_swr_remove,
+};
+
+static int lpass_bt_swr_drv_init(void)
+{
+	return platform_driver_register(&lpass_bt_swr_drv);
+}
+
+static void lpass_bt_swr_drv_exit(void)
+{
+	platform_driver_unregister(&lpass_bt_swr_drv);
+}
+
+static int __init lpass_bt_swr_init(void)
+{
+	lpass_bt_swr_drv_init();
+	return 0;
+}
+module_init(lpass_bt_swr_init);
+
+static void __exit lpass_bt_swr_exit(void)
+{
+	lpass_bt_swr_drv_exit();
+}
+module_exit(lpass_bt_swr_exit);
+
+MODULE_SOFTDEP("pre: bt_fm_swr");
+MODULE_DESCRIPTION("LPASS BT SWR driver");
+MODULE_LICENSE("GPL");

+ 183 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/Kbuild

@@ -0,0 +1,183 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_TRINKET), y)
+		include $(AUDIO_ROOT)/config/sm6150auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KONA), y)
+		include $(AUDIO_ROOT)/config/konaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/konaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_WAIPIO), y)
+		include $(AUDIO_ROOT)/config/waipioauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/waipioautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_KALAMA), y)
+		include $(AUDIO_ROOT)/config/kalamaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/kalamaautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_PINEAPPLE), y)
+		include $(AUDIO_ROOT)/config/pineappleauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pineappleautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_PITTI), y)
+		include $(AUDIO_ROOT)/config/pittiauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/pittiautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_LITO), y)
+		include $(AUDIO_ROOT)/config/litoauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_BENGAL), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
+	ifeq ($(CONFIG_ARCH_QCS405), y)
+		include $(AUDIO_ROOT)/config/qcs405auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi/audio
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ LPASS_CDC ############
+
+# for LPASS_CDC Codec
+ifdef CONFIG_SND_SOC_LPASS_CDC
+	LPASS_CDC_OBJS += lpass-cdc.o
+	LPASS_CDC_OBJS += lpass-cdc-comp.o
+	LPASS_CDC_OBJS += lpass-cdc-utils.o
+	LPASS_CDC_OBJS += lpass-cdc-regmap.o
+	LPASS_CDC_OBJS += lpass-cdc-tables.o
+	LPASS_CDC_OBJS += lpass-cdc-clk-rsc.o
+endif
+
+ifdef CONFIG_LPASS_CDC_WSA2_MACRO
+	WSA2_OBJS += lpass-cdc-wsa2-macro.o
+endif
+
+ifdef CONFIG_LPASS_CDC_WSA_MACRO
+	WSA_OBJS += lpass-cdc-wsa-macro.o
+endif
+
+ifdef CONFIG_LPASS_CDC_VA_MACRO
+	VA_OBJS += lpass-cdc-va-macro.o
+endif
+
+ifdef CONFIG_LPASS_CDC_TX_MACRO
+	TX_OBJS += lpass-cdc-tx-macro.o
+endif
+
+ifdef CONFIG_LPASS_CDC_RX_MACRO
+	RX_OBJS += lpass-cdc-rx-macro.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_LPASS_CDC) += lpass_cdc_dlkm.o
+lpass_cdc_dlkm-y := $(LPASS_CDC_OBJS)
+
+obj-$(CONFIG_LPASS_CDC_WSA2_MACRO) += lpass_cdc_wsa2_macro_dlkm.o
+lpass_cdc_wsa2_macro_dlkm-y := $(WSA2_OBJS)
+
+obj-$(CONFIG_LPASS_CDC_WSA_MACRO) += lpass_cdc_wsa_macro_dlkm.o
+lpass_cdc_wsa_macro_dlkm-y := $(WSA_OBJS)
+
+obj-$(CONFIG_LPASS_CDC_VA_MACRO) += lpass_cdc_va_macro_dlkm.o
+lpass_cdc_va_macro_dlkm-y := $(VA_OBJS)
+
+obj-$(CONFIG_LPASS_CDC_TX_MACRO) += lpass_cdc_tx_macro_dlkm.o
+lpass_cdc_tx_macro_dlkm-y := $(TX_OBJS)
+
+obj-$(CONFIG_LPASS_CDC_RX_MACRO) += lpass_cdc_rx_macro_dlkm.o
+lpass_cdc_rx_macro_dlkm-y := $(RX_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 6 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/Makefile

@@ -0,0 +1,6 @@
+modules:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) VERBOSE=1
+modules_install:
+	$(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean

+ 112 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/internal.h

@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _LPASS_CDC_INTERNAL_H
+#define _LPASS_CDC_INTERNAL_H
+
+#include "lpass-cdc-registers.h"
+
+#define LPASS_CDC_CHILD_DEVICES_MAX 6
+
+/* from lpass_cdc to WCD events */
+enum {
+	LPASS_CDC_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
+	LPASS_CDC_WCD_EVT_PA_OFF_PRE_SSR,
+	LPASS_CDC_WCD_EVT_SSR_DOWN,
+	LPASS_CDC_WCD_EVT_SSR_UP,
+	LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK,
+	LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB,
+	LPASS_CDC_WCD_EVT_CLK_NOTIFY,
+};
+
+enum {
+	REG_NO_ACCESS,
+	RD_REG,
+	WR_REG,
+	RD_WR_REG
+};
+
+/* from WCD to lpass_cdc events */
+enum {
+	WCD_LPASS_CDC_EVT_RX_MUTE = 1, /* for RX mute/unmute */
+	WCD_LPASS_CDC_EVT_IMPED_TRUE,   /* for imped true */
+	WCD_LPASS_CDC_EVT_IMPED_FALSE,  /* for imped false */
+	WCD_LPASS_CDC_EVT_RX_COMPANDER_SOFT_RST,
+	WCD_LPASS_CDC_EVT_BCS_CLK_OFF,
+	WCD_LPASS_CDC_EVT_RX_PA_GAIN_UPDATE,
+	WCD_LPASS_CDC_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */
+	WCD_LPASS_CDC_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */
+};
+
+struct wcd_ctrl_platform_data {
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				 struct notifier_block *nblock,
+				 bool enable);
+};
+
+struct lpass_cdc_priv {
+	struct device *dev;
+	struct snd_soc_component *component;
+	struct regmap *regmap;
+	struct mutex macro_lock;
+	struct mutex io_lock;
+	struct mutex clk_lock;
+	struct mutex vote_lock;
+	bool va_without_decimation;
+	bool macros_supported[MAX_MACRO];
+	bool dev_up;
+	bool pre_dev_up;
+	bool initial_boot;
+	struct macro_ops macro_params[MAX_MACRO];
+	struct snd_soc_dai_driver *lpass_cdc_dais;
+	u16 num_dais;
+	u16 num_macros_registered;
+	u16 num_macros;
+	u16 current_mclk_mux_macro[MAX_MACRO];
+	struct work_struct lpass_cdc_add_child_devices_work;
+	u32 version;
+	struct clk *lpass_core_hw_vote;
+	struct clk *lpass_audio_hw_vote;
+	int core_hw_vote_count;
+	int core_audio_vote_count;
+	int core_clk_vote_count;
+
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+
+	int (*read_dev)(struct lpass_cdc_priv *priv,
+			u16 macro_id, u16 reg, u8 *val);
+	int (*write_dev)(struct lpass_cdc_priv *priv,
+			 u16 macro_id, u16 reg, u8 val);
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_CHILD_DEVICES_MAX];
+	u16 child_count;
+	struct wcd_ctrl_platform_data plat_data;
+	struct device *wcd_dev;
+	struct blocking_notifier_head notifier;
+	struct device *clk_dev;
+	rsc_clk_cb_t rsc_clk_cb;
+	s32 dmic_0_1_clk_cnt;
+	s32 dmic_2_3_clk_cnt;
+	s32 dmic_4_5_clk_cnt;
+	s32 dmic_6_7_clk_cnt;
+	u8 dmic_0_1_clk_div;
+	u8 dmic_2_3_clk_div;
+	u8 dmic_4_5_clk_div;
+	u8 dmic_6_7_clk_div;
+};
+
+struct regmap *lpass_cdc_regmap_init(struct device *dev,
+				  const struct regmap_config *config);
+int lpass_cdc_get_macro_id(bool va_no_dec_flag, u16 reg);
+
+extern const struct regmap_config lpass_cdc_regmap_config;
+extern u8 *lpass_cdc_reg_access[MAX_MACRO];
+extern const u16 macro_id_base_offset[MAX_MACRO];
+
+#endif

+ 785 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.c

@@ -0,0 +1,785 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-clk-rsc.h"
+
+#define DRV_NAME "lpass-cdc-clk-rsc"
+#define LPASS_CDC_CLK_NAME_LENGTH 30
+#define NPL_CLK_OFFSET (TX_NPL_CLK  - TX_CORE_CLK)
+
+static char clk_src_name[MAX_CLK][LPASS_CDC_CLK_NAME_LENGTH] = {
+	"tx_core_clk",
+	"rx_core_clk",
+	"wsa_core_clk",
+	"va_core_clk",
+	"wsa2_core_clk",
+	"rx_tx_core_clk",
+	"wsa_tx_core_clk",
+	"wsa2_tx_core_clk",
+	"tx_npl_clk",
+	"rx_npl_clk",
+	"wsa_npl_clk",
+	"va_npl_clk",
+};
+
+struct lpass_cdc_clk_rsc {
+	struct device *dev;
+	struct mutex rsc_clk_lock;
+	struct mutex fs_gen_lock;
+	struct clk *clk[MAX_CLK];
+	int clk_cnt[MAX_CLK];
+	int reg_seq_en_cnt;
+	int va_tx_clk_cnt;
+	bool dev_up;
+	bool dev_up_gfmux;
+	u32 num_fs_reg;
+	u32 *fs_gen_seq;
+	int default_clk_id[MAX_CLK];
+	struct regmap *regmap;
+	char __iomem *rx_clk_muxsel;
+	char __iomem *wsa_clk_muxsel;
+	char __iomem *va_clk_muxsel;
+};
+
+static int lpass_cdc_clk_rsc_cb(struct device *dev, u16 event)
+{
+	struct lpass_cdc_clk_rsc *priv;
+
+	if (!dev) {
+		pr_err("%s: Invalid device pointer\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		pr_err("%s: Invalid clk rsc priviate data\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&priv->rsc_clk_lock);
+	if (event == LPASS_CDC_MACRO_EVT_SSR_UP) {
+		priv->dev_up = true;
+	} else if (event == LPASS_CDC_MACRO_EVT_SSR_DOWN) {
+		priv->dev_up = false;
+		priv->dev_up_gfmux = false;
+	} else if (event == LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP) {
+		priv->dev_up_gfmux = true;
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+
+	return 0;
+}
+
+static char __iomem *lpass_cdc_clk_rsc_get_clk_muxsel(struct lpass_cdc_clk_rsc *priv,
+						 int clk_id)
+{
+	switch (clk_id) {
+	case RX_CORE_CLK:
+		return priv->rx_clk_muxsel;
+	case WSA_CORE_CLK:
+	case WSA2_CORE_CLK:
+		return priv->wsa_clk_muxsel;
+	case VA_CORE_CLK:
+		return priv->va_clk_muxsel;
+	case TX_CORE_CLK:
+	case RX_TX_CORE_CLK:
+	case WSA_TX_CORE_CLK:
+	case WSA2_TX_CORE_CLK:
+	default:
+		dev_err_ratelimited(priv->dev, "%s: Invalid case\n", __func__);
+		break;
+	}
+
+	return NULL;
+}
+
+int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	struct device *clk_dev = NULL;
+	struct lpass_cdc_clk_rsc *priv = NULL;
+	int count = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_BOLERO_VER_2P1
+	if (clk_id < 0 || clk_id >= MAX_CLK - NPL_CLK_OFFSET) {
+#else
+	if (clk_id < 0 || clk_id >= MAX_CLK) {
+#endif
+		pr_err("%s: Invalid clk_id: %d\n",
+			__func__, clk_id);
+		return -EINVAL;
+	}
+
+	clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return -EINVAL;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return -EINVAL;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+	while (__clk_is_enabled(priv->clk[clk_id])) {
+#ifdef CONFIG_BOLERO_VER_2P1
+		clk_disable_unprepare(priv->clk[clk_id + NPL_CLK_OFFSET]);
+#endif
+		clk_disable_unprepare(priv->clk[clk_id]);
+		count++;
+	}
+	dev_dbg(priv->dev,
+		"%s: clock reset after ssr, count %d\n", __func__, count);
+
+	while (count--) {
+		clk_prepare_enable(priv->clk[clk_id]);
+#ifdef CONFIG_BOLERO_VER_2P1
+		clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]);
+#endif
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_rsc_clk_reset);
+
+void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev, bool enable)
+{
+	struct device *clk_dev = NULL;
+	struct lpass_cdc_clk_rsc *priv = NULL;
+	int i = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+
+	clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk private data\n", __func__);
+		return;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+#ifdef CONFIG_BOLERO_VER_2P1
+	for (i = 0; i < MAX_CLK - NPL_CLK_OFFSET; i++) {
+#else
+	for (i = 0; i < MAX_CLK; i++) {
+#endif
+		if (enable) {
+			if (priv->clk[i])
+				clk_prepare_enable(priv->clk[i]);
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[i + NPL_CLK_OFFSET])
+				clk_prepare_enable(
+					priv->clk[i + NPL_CLK_OFFSET]);
+#endif
+		} else {
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[i + NPL_CLK_OFFSET] &&
+					__clk_is_enabled(priv->clk[i + NPL_CLK_OFFSET]))
+				clk_disable_unprepare(
+					priv->clk[i + NPL_CLK_OFFSET]);
+#endif
+			if (priv->clk[i] && __clk_is_enabled(priv->clk[i]))
+				clk_disable_unprepare(priv->clk[i]);
+		}
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return;
+}
+EXPORT_SYMBOL(lpass_cdc_clk_rsc_enable_all_clocks);
+
+static int lpass_cdc_clk_rsc_mux0_clk_request(struct lpass_cdc_clk_rsc *priv,
+					   int clk_id,
+					   bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		/* Enable Requested Core clk */
+		if (priv->clk_cnt[clk_id] == 0) {
+			ret = clk_prepare_enable(priv->clk[clk_id]);
+			if (ret < 0) {
+				dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+							__func__, clk_id);
+				goto done;
+			}
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[clk_id + NPL_CLK_OFFSET]) {
+				ret = clk_prepare_enable(
+						priv->clk[clk_id + NPL_CLK_OFFSET]);
+				if (ret < 0) {
+					dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+							__func__, clk_id + NPL_CLK_OFFSET);
+					goto err;
+				}
+			}
+#endif
+		}
+		priv->clk_cnt[clk_id]++;
+	} else {
+		if (priv->clk_cnt[clk_id] <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n",
+					__func__, clk_id);
+			priv->clk_cnt[clk_id] = 0;
+			goto done;
+		}
+		priv->clk_cnt[clk_id]--;
+		if (priv->clk_cnt[clk_id] == 0) {
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[clk_id + NPL_CLK_OFFSET])
+				clk_disable_unprepare(
+						priv->clk[clk_id + NPL_CLK_OFFSET]);
+#endif
+			clk_disable_unprepare(priv->clk[clk_id]);
+		}
+	}
+return ret;
+#ifdef CONFIG_BOLERO_VER_2P1
+err:
+	clk_disable_unprepare(priv->clk[clk_id]);
+#endif
+done:
+	return ret;
+}
+
+static int lpass_cdc_clk_rsc_mux1_clk_request(struct lpass_cdc_clk_rsc *priv,
+					   int clk_id,
+					   bool enable)
+{
+	char __iomem *clk_muxsel = NULL;
+	int ret = 0;
+	int default_clk_id = priv->default_clk_id[clk_id];
+	u32 muxsel = 0;
+
+	clk_muxsel = lpass_cdc_clk_rsc_get_clk_muxsel(priv, clk_id);
+	if (!clk_muxsel) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (enable) {
+		if (priv->clk_cnt[clk_id] == 0) {
+			if (clk_id != VA_CORE_CLK) {
+				ret = lpass_cdc_clk_rsc_mux0_clk_request(priv,
+							default_clk_id,
+							true);
+				if (ret < 0)
+					goto done;
+			}
+
+			ret = clk_prepare_enable(priv->clk[clk_id]);
+			if (ret < 0) {
+				dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+					__func__, clk_id);
+				goto err_clk;
+			}
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[clk_id + NPL_CLK_OFFSET]) {
+				ret = clk_prepare_enable(
+						priv->clk[clk_id + NPL_CLK_OFFSET]);
+				if (ret < 0) {
+					dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n",
+							__func__, clk_id + NPL_CLK_OFFSET);
+					goto err_npl_clk;
+				}
+			}
+#endif
+			/*
+			 * Temp SW workaround to address a glitch issue of
+			 * VA GFMux instance responsible for switching from
+			 * TX MCLK to VA MCLK. This configuration would be taken
+			 * care in DSP itself
+			 */
+			if (clk_id != VA_CORE_CLK) {
+				if (priv->dev_up_gfmux) {
+					iowrite32(0x1, clk_muxsel);
+					muxsel = ioread32(clk_muxsel);
+				}
+				lpass_cdc_clk_rsc_mux0_clk_request(priv, default_clk_id,
+							   false);
+			}
+		}
+		priv->clk_cnt[clk_id]++;
+	} else {
+		if (priv->clk_cnt[clk_id] <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n",
+				__func__, clk_id);
+			priv->clk_cnt[clk_id] = 0;
+			goto done;
+		}
+		priv->clk_cnt[clk_id]--;
+		if (priv->clk_cnt[clk_id] == 0) {
+			/*
+			 * Temp SW workaround to address a glitch issue
+			 * of VA GFMux instance responsible for
+			 * switching from TX MCLK to VA MCLK.
+			 * This configuration would be taken
+			 * care in DSP itself.
+			 */
+			if (clk_id != VA_CORE_CLK) {
+				ret = lpass_cdc_clk_rsc_mux0_clk_request(priv,
+						default_clk_id, true);
+				if (!ret && priv->dev_up_gfmux) {
+					iowrite32(0x0, clk_muxsel);
+					muxsel = ioread32(clk_muxsel);
+				}
+			}
+#ifdef CONFIG_BOLERO_VER_2P1
+			if (priv->clk[clk_id + NPL_CLK_OFFSET])
+				clk_disable_unprepare(priv->clk[clk_id + NPL_CLK_OFFSET]);
+#endif
+			clk_disable_unprepare(priv->clk[clk_id]);
+			if (clk_id != VA_CORE_CLK && !ret)
+				lpass_cdc_clk_rsc_mux0_clk_request(priv,
+						default_clk_id, false);
+		}
+	}
+	return ret;
+#ifdef CONFIG_BOLERO_VER_2P1
+err_npl_clk:
+	clk_disable_unprepare(priv->clk[clk_id]);
+#endif
+err_clk:
+	if (clk_id != VA_CORE_CLK)
+		lpass_cdc_clk_rsc_mux0_clk_request(priv, default_clk_id, false);
+done:
+	return ret;
+}
+
+static int lpass_cdc_clk_rsc_check_and_update_va_clk(struct lpass_cdc_clk_rsc *priv,
+						  bool mux_switch,
+						  int clk_id,
+						  bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		if (clk_id == VA_CORE_CLK && mux_switch) {
+			/*
+			 * Handle the following usecase scenarios during enable
+			 * 1. VA only, Active clk is VA_CORE_CLK
+			 * 2. record -> record + VA, Active clk is TX_CORE_CLK
+			 */
+			if (priv->clk_cnt[TX_CORE_CLK] == 0) {
+				ret = lpass_cdc_clk_rsc_mux1_clk_request(priv,
+							 VA_CORE_CLK, enable);
+				if (ret < 0)
+					goto err;
+			} else {
+				ret = lpass_cdc_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, enable);
+				if (ret < 0)
+					goto err;
+				priv->va_tx_clk_cnt++;
+			}
+		} else if ((priv->clk_cnt[TX_CORE_CLK] > 0) &&
+			   (priv->clk_cnt[VA_CORE_CLK] > 0)) {
+			/*
+			 * Handle following concurrency scenario during enable
+			 * 1. VA-> Record+VA, Increment TX CLK and Disable VA
+			 * 2. VA-> Playback+VA, Increment TX CLK and Disable VA
+			 */
+			while (priv->clk_cnt[VA_CORE_CLK] > 0) {
+				ret = lpass_cdc_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, true);
+				if (ret < 0)
+					goto err;
+
+				lpass_cdc_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, false);
+				priv->va_tx_clk_cnt++;
+			}
+		}
+	} else {
+		if (clk_id == VA_CORE_CLK && mux_switch) {
+			/*
+			 * Handle the following usecase scenarios during disable
+			 * 1. VA only, disable VA_CORE_CLK
+			 * 2. Record + VA -> Record, decrement TX CLK count
+			 */
+			if (priv->clk_cnt[VA_CORE_CLK]) {
+				lpass_cdc_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, enable);
+			} else if (priv->va_tx_clk_cnt) {
+				lpass_cdc_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, enable);
+				priv->va_tx_clk_cnt--;
+			}
+		} else if (priv->va_tx_clk_cnt == priv->clk_cnt[TX_CORE_CLK]) {
+			/*
+			 * Handle the following usecase scenarios during disable
+			 * Record+VA-> VA: enable VA CLK, decrement TX CLK count
+			 */
+			while (priv->va_tx_clk_cnt) {
+				ret = lpass_cdc_clk_rsc_mux1_clk_request(priv,
+							VA_CORE_CLK, true);
+				if (ret < 0)
+					goto err;
+
+				lpass_cdc_clk_rsc_mux0_clk_request(priv,
+							TX_CORE_CLK, false);
+				priv->va_tx_clk_cnt--;
+			}
+		}
+	}
+
+err:
+	return ret;
+}
+
+/**
+ * lpass_cdc_clk_rsc_fs_gen_request - request to enable/disable fs generation
+ * sequence
+ *
+ * @dev: Macro device pointer
+ * @enable: enable or disable flag
+ */
+void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev, bool enable)
+{
+	int i;
+	struct regmap *regmap;
+	struct device *clk_dev = NULL;
+	struct lpass_cdc_clk_rsc *priv = NULL;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+	clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return;
+	}
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return;
+	}
+	regmap = dev_get_regmap(priv->dev->parent, NULL);
+	if (!regmap) {
+		pr_err("%s: regmap is null\n", __func__);
+		return;
+	}
+	mutex_lock(&priv->fs_gen_lock);
+	if (enable) {
+		if (priv->reg_seq_en_cnt++ == 0) {
+			for (i = 0; i < (priv->num_fs_reg * 3); i += 3) {
+				dev_dbg(priv->dev, "%s: Register: %d, mask: %d, value: %d\n",
+					__func__, priv->fs_gen_seq[i],
+					priv->fs_gen_seq[i + 1],
+					priv->fs_gen_seq[i + 2]);
+				regmap_update_bits(regmap,
+						   priv->fs_gen_seq[i],
+						   priv->fs_gen_seq[i + 1],
+						   priv->fs_gen_seq[i + 2]);
+			}
+		}
+	} else {
+		if (priv->reg_seq_en_cnt <= 0) {
+			dev_err_ratelimited(priv->dev, "%s: req_seq_cnt: %d is already disabled\n",
+				__func__, priv->reg_seq_en_cnt);
+			priv->reg_seq_en_cnt = 0;
+			mutex_unlock(&priv->fs_gen_lock);
+			return;
+		}
+		if (--priv->reg_seq_en_cnt == 0) {
+			for (i = ((priv->num_fs_reg - 1) * 3); i >= 0; i -= 3) {
+				dev_dbg(priv->dev, "%s: Register: %d, mask: %d\n",
+					__func__, priv->fs_gen_seq[i],
+					priv->fs_gen_seq[i + 1]);
+				regmap_update_bits(regmap, priv->fs_gen_seq[i],
+						priv->fs_gen_seq[i + 1], 0x0);
+			}
+		}
+	}
+	mutex_unlock(&priv->fs_gen_lock);
+}
+EXPORT_SYMBOL(lpass_cdc_clk_rsc_fs_gen_request);
+
+/**
+ * lpass_cdc_clk_rsc_request_clock - request for clock to
+ * enable/disable
+ *
+ * @dev: Macro device pointer.
+ * @default_clk_id: mux0 Core clock ID input.
+ * @clk_id_req: Core clock ID requested to enable/disable
+ * @enable: enable or disable clock flag
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int lpass_cdc_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable)
+{
+	int ret = 0;
+	struct device *clk_dev = NULL;
+	struct lpass_cdc_clk_rsc *priv = NULL;
+	bool mux_switch = false;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if ((clk_id_req < 0 || clk_id_req >= MAX_CLK) &&
+		(default_clk_id < 0 || default_clk_id >= MAX_CLK)) {
+		pr_err("%s: Invalid clk_id_req: %d or default_clk_id: %d\n",
+				__func__, clk_id_req, default_clk_id);
+		return -EINVAL;
+	}
+	clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&priv->rsc_clk_lock);
+	if (!priv->dev_up && enable) {
+		dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	priv->default_clk_id[clk_id_req] = default_clk_id;
+	if (default_clk_id != clk_id_req)
+		mux_switch = true;
+
+	if (mux_switch) {
+		if (clk_id_req != VA_CORE_CLK) {
+			ret = lpass_cdc_clk_rsc_mux1_clk_request(priv, clk_id_req,
+							enable);
+			if (ret < 0)
+				goto err;
+		}
+	} else {
+		ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, clk_id_req, enable);
+		if (ret < 0)
+			goto err;
+	}
+
+	ret = lpass_cdc_clk_rsc_check_and_update_va_clk(priv, mux_switch,
+						 clk_id_req,
+						 enable);
+	if (ret < 0)
+		goto err;
+
+	dev_dbg(priv->dev, "%s: clk_cnt: %d for requested clk: %d, enable: %d\n",
+		__func__,  priv->clk_cnt[clk_id_req], clk_id_req,
+		enable);
+
+	mutex_unlock(&priv->rsc_clk_lock);
+
+	return 0;
+
+err:
+	mutex_unlock(&priv->rsc_clk_lock);
+	return ret;
+}
+EXPORT_SYMBOL(lpass_cdc_clk_rsc_request_clock);
+
+
+static int lpass_cdc_clk_rsc_probe(struct platform_device *pdev)
+{
+	int ret = 0, fs_gen_size, i, j;
+	const char **clk_name_array;
+	int clk_cnt;
+	struct clk *clk;
+	struct lpass_cdc_clk_rsc *priv = NULL;
+	u32 muxsel = 0;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_clk_rsc),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* Get clk fs gen sequence from device tree */
+	if (!of_find_property(pdev->dev.of_node, "qcom,fs-gen-sequence",
+						  &fs_gen_size)) {
+		dev_err(&pdev->dev, "%s: unable to find qcom,fs-gen-sequence property\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	priv->num_fs_reg = fs_gen_size/(3 * sizeof(u32));
+	priv->fs_gen_seq = devm_kzalloc(&pdev->dev, fs_gen_size, GFP_KERNEL);
+	if (!priv->fs_gen_seq) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	dev_dbg(&pdev->dev, "%s: num_fs_reg %d\n", __func__, priv->num_fs_reg);
+	/* Parse fs-gen-sequence */
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+					 "qcom,fs-gen-sequence",
+					 priv->fs_gen_seq,
+					 priv->num_fs_reg * 3);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: unable to parse fs-gen-sequence, ret = %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* Get clk details from device tree */
+	clk_cnt = of_property_count_strings(pdev->dev.of_node, "clock-names");
+	if (clk_cnt <= 0 || clk_cnt > MAX_CLK) {
+		dev_err(&pdev->dev, "%s: Invalid number of clocks %d",
+				__func__, clk_cnt);
+		ret = -EINVAL;
+		goto err;
+	}
+	clk_name_array = devm_kzalloc(&pdev->dev, clk_cnt * sizeof(char *),
+					  GFP_KERNEL);
+	if (!clk_name_array) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = of_property_read_string_array(pdev->dev.of_node, "clock-names",
+					clk_name_array, clk_cnt);
+
+	for (i = 0; i < MAX_CLK; i++) {
+		priv->clk[i] = NULL;
+		for (j = 0; j < clk_cnt; j++) {
+			if (!strcmp(clk_src_name[i], clk_name_array[j])) {
+				clk = devm_clk_get(&pdev->dev, clk_src_name[i]);
+				if (IS_ERR(clk)) {
+					ret = PTR_ERR(clk);
+					dev_err(&pdev->dev, "%s: clk get failed for %s with ret %d\n",
+						__func__, clk_src_name[i], ret);
+					goto err;
+				}
+				priv->clk[i] = clk;
+				dev_dbg(&pdev->dev, "%s: clk get success for clk name %s\n",
+						__func__, clk_src_name[i]);
+				break;
+			}
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				 "qcom,rx_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,rx_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->rx_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->rx_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for rx muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,wsa_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,wsa_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->wsa_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->wsa_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for wsa muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+	ret = of_property_read_u32(pdev->dev.of_node,
+				 "qcom,va_mclk_mode_muxsel", &muxsel);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find qcom,va_mclk_mode_muxsel entry in dt\n",
+			__func__);
+	} else {
+		priv->va_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4);
+		if (!priv->va_clk_muxsel) {
+			dev_err(&pdev->dev, "%s: ioremap failed for va muxsel\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
+
+	ret = lpass_cdc_register_res_clk(&pdev->dev, lpass_cdc_clk_rsc_cb);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: Failed to register cb %d",
+				__func__, ret);
+		goto err;
+	}
+	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->dev_up_gfmux = true;
+	mutex_init(&priv->rsc_clk_lock);
+	mutex_init(&priv->fs_gen_lock);
+	dev_set_drvdata(&pdev->dev, priv);
+
+err:
+	return ret;
+}
+
+static int lpass_cdc_clk_rsc_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_clk_rsc *priv = dev_get_drvdata(&pdev->dev);
+
+	lpass_cdc_unregister_res_clk(&pdev->dev);
+	of_platform_depopulate(&pdev->dev);
+	if (!priv)
+		return -EINVAL;
+	mutex_destroy(&priv->rsc_clk_lock);
+	mutex_destroy(&priv->fs_gen_lock);
+
+	return 0;
+}
+
+static const struct of_device_id lpass_cdc_clk_rsc_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-clk-rsc-mngr"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, lpass_cdc_clk_rsc_dt_match);
+
+static struct platform_driver lpass_cdc_clk_rsc_mgr = {
+	.driver = {
+		.name = "lpass-cdc-clk-rsc-mngr",
+		.owner = THIS_MODULE,
+		.of_match_table = lpass_cdc_clk_rsc_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_clk_rsc_probe,
+	.remove = lpass_cdc_clk_rsc_remove,
+};
+
+int lpass_cdc_clk_rsc_mgr_init(void)
+{
+	return platform_driver_register(&lpass_cdc_clk_rsc_mgr);
+}
+
+void lpass_cdc_clk_rsc_mgr_exit(void)
+{
+	platform_driver_unregister(&lpass_cdc_clk_rsc_mgr);
+}
+MODULE_DESCRIPTION("LPASS codec clock resource manager driver");
+MODULE_LICENSE("GPL v2");

+ 52 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.h

@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef LPASS_CDC_CLK_RSC_H
+#define LPASS_CDC_CLK_RSC_H
+
+#include <linux/regmap.h>
+#include <bindings/qcom,lpass-cdc-clk-rsc.h>
+
+#if IS_ENABLED(CONFIG_SND_SOC_LPASS_CDC)
+int lpass_cdc_clk_rsc_mgr_init(void);
+void lpass_cdc_clk_rsc_mgr_exit(void);
+void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev,
+						bool enable);
+int lpass_cdc_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable);
+int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id);
+void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev, bool enable);
+#else
+static inline void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev,
+						bool enable)
+{
+}
+static inline int lpass_cdc_clk_rsc_mgr_init(void)
+{
+	return 0;
+}
+static inline void lpass_cdc_clk_rsc_mgr_exit(void)
+{
+}
+static inline int lpass_cdc_clk_rsc_request_clock(struct device *dev,
+				int default_clk_id,
+				int clk_id_req,
+				bool enable)
+{
+	return 0;
+}
+static inline int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	return 0;
+}
+static inline void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev,
+						    bool enable)
+{
+	return;
+}
+#endif /* CONFIG_SND_SOC_LPASS_CDC */
+#endif /* LPASS_CDC_CLK_RSC_H */

+ 117 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-comp.c

@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ */
+#include "lpass-cdc-comp.h"
+
+int lpass_cdc_load_compander_coeff(struct snd_soc_component *component,
+				   u16 lsb_reg, u16 msb_reg,
+				   struct comp_coeff_val *comp_coeff_table,
+				   u16 arr_size)
+{
+	int i = 0;
+
+	/* Load Compander Coeff */
+	for (i = 0; i < arr_size; i++) {
+		snd_soc_component_write(component, lsb_reg,
+				comp_coeff_table[i].lsb);
+		snd_soc_component_write(component, msb_reg,
+				comp_coeff_table[i].msb);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_load_compander_coeff);
+
+int lpass_cdc_update_compander_setting(struct snd_soc_component *component,
+				u16 start_addr,
+				struct lpass_cdc_comp_setting *comp_setting)
+{
+	int zone2_rms, zone3_rms, zone4_rms, zone5_rms, zone6_rms;
+	int path_gain;
+	int max_attn;
+	int zone1_rms = 6;
+	int upper_gain_int = comp_setting->upper_gain_int;
+	int lower_gain_int = comp_setting->lower_gain_int;
+	int ana_addr_map = comp_setting->ana_addr_map;
+	int upper_gain_dig_int = upper_gain_int - lower_gain_int;
+
+	/* skip comp_ctl8, comp_ctl9 default settings is fine */
+
+	/* apply zone settings */
+	snd_soc_component_write(component,
+				start_addr + 8,
+				zone1_rms);
+
+	if (upper_gain_dig_int >= 24)
+		zone2_rms = 18;
+	else if (upper_gain_dig_int >= 18)
+		zone2_rms = 12;
+	else
+		zone2_rms = upper_gain_dig_int;
+	snd_soc_component_write(component,
+				start_addr + 0xC,
+				zone2_rms);
+
+	if (upper_gain_dig_int >= 66)
+		zone3_rms = 33;
+	else if (upper_gain_dig_int >= 36)
+		zone3_rms = 30;
+	else if (upper_gain_dig_int >= 30)
+		zone3_rms = 24;
+	else
+		zone3_rms = upper_gain_dig_int;
+	snd_soc_component_write(component,
+				start_addr + 0x10,
+				zone3_rms);
+
+	if (upper_gain_dig_int >= 66)
+		zone4_rms = 48;
+	else if (upper_gain_dig_int >= 48)
+		zone4_rms = 42;
+	else if (upper_gain_dig_int >= 42)
+		zone4_rms = 36;
+	else
+		zone4_rms = upper_gain_dig_int;
+	snd_soc_component_write(component,
+				start_addr + 0x14,
+				zone4_rms);
+
+	if (upper_gain_dig_int >= 69)
+		zone5_rms = 63;
+	else if (upper_gain_dig_int >= 66)
+		zone5_rms = 60;
+	else if (upper_gain_dig_int >= 60)
+		zone5_rms = 54;
+	else if (upper_gain_dig_int >= 54)
+		zone5_rms = 48;
+	else
+		zone5_rms = upper_gain_dig_int;
+	snd_soc_component_write(component,
+				start_addr + 0x18,
+				zone5_rms);
+
+	zone6_rms = upper_gain_dig_int;
+	snd_soc_component_write(component,
+				start_addr + 0x1C,
+				zone6_rms);
+
+	if (lower_gain_int < 0)
+		max_attn = 256 + lower_gain_int;
+	else
+		max_attn = lower_gain_int;
+	snd_soc_component_write(component,
+				start_addr + 0x20,
+				max_attn);
+
+	path_gain = zone6_rms - abs(lower_gain_int);
+	snd_soc_component_write(component,
+				start_addr + 0x24,
+				path_gain);
+
+	snd_soc_component_write(component,
+				start_addr + 0x28,
+				ana_addr_map);
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_update_compander_setting);

+ 27 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-comp.h

@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+#ifndef LPASS_CDC_COMP_H
+#define LPASS_CDC_COMP_H
+
+#include <sound/soc.h>
+
+struct comp_coeff_val {
+	u8 lsb;
+	u8 msb;
+};
+
+struct lpass_cdc_comp_setting {
+	int upper_gain_int;
+	int lower_gain_int;
+	int ana_addr_map;
+};
+
+int lpass_cdc_load_compander_coeff(struct snd_soc_component *component,
+				   u16 lsb_reg, u16 msb_reg,
+				   struct comp_coeff_val *comp_coeff_table,
+				   u16 arr_size);
+int lpass_cdc_update_compander_setting(struct snd_soc_component *component,
+				u16 start_addr,
+				struct lpass_cdc_comp_setting *comp_setting);
+#endif

+ 1426 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-registers.h

@@ -0,0 +1,1426 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _LPASS_CDC_REGISTERS_H
+#define _LPASS_CDC_REGISTERS_H
+
+#define TX_START_OFFSET 0x0000
+
+#define LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (TX_START_OFFSET + 0x0000)
+#define LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (TX_START_OFFSET + 0x0004)
+#define LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL	(TX_START_OFFSET + 0x0008)
+#define LPASS_CDC_TX_TOP_CSR_TOP_CFG0		(TX_START_OFFSET + 0x0080)
+#define LPASS_CDC_TX_TOP_CSR_ANC_CFG		(TX_START_OFFSET + 0x0084)
+#define LPASS_CDC_TX_TOP_CSR_SWR_CTRL		(TX_START_OFFSET + 0x0088)
+#define LPASS_CDC_TX_TOP_CSR_FREQ_MCLK		(TX_START_OFFSET + 0x0090)
+#define LPASS_CDC_TX_TOP_CSR_DEBUG_BUS		(TX_START_OFFSET + 0x0094)
+#define LPASS_CDC_TX_TOP_CSR_DEBUG_EN		(TX_START_OFFSET + 0x0098)
+#define LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL		(TX_START_OFFSET + 0x00A4)
+#define LPASS_CDC_TX_TOP_CSR_I2S_CLK		(TX_START_OFFSET + 0x00A8)
+#define LPASS_CDC_TX_TOP_CSR_I2S_RESET		(TX_START_OFFSET + 0x00AC)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL	(TX_START_OFFSET + 0x00C0)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL	(TX_START_OFFSET + 0x00C4)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL	(TX_START_OFFSET + 0x00C8)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL	(TX_START_OFFSET + 0x00CC)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL	(TX_START_OFFSET + 0x00D0)
+#define LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL	(TX_START_OFFSET + 0x00D4)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0	(TX_START_OFFSET + 0x0100)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1	(TX_START_OFFSET + 0x0104)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0	(TX_START_OFFSET + 0x0108)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1	(TX_START_OFFSET + 0x010C)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0	(TX_START_OFFSET + 0x0110)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1	(TX_START_OFFSET + 0x0114)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0	(TX_START_OFFSET + 0x0118)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1	(TX_START_OFFSET + 0x011C)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0	(TX_START_OFFSET + 0x0120)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1	(TX_START_OFFSET + 0x0124)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0	(TX_START_OFFSET + 0x0128)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1	(TX_START_OFFSET + 0x012C)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0	(TX_START_OFFSET + 0x0130)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1	(TX_START_OFFSET + 0x0134)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0	(TX_START_OFFSET + 0x0138)
+#define LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1	(TX_START_OFFSET + 0x013C)
+#define LPASS_CDC_TX_ANC0_CLK_RESET_CTL		(TX_START_OFFSET + 0x0200)
+#define LPASS_CDC_TX_ANC0_MODE_1_CTL		(TX_START_OFFSET + 0x0204)
+#define LPASS_CDC_TX_ANC0_MODE_2_CTL		(TX_START_OFFSET + 0x0208)
+#define LPASS_CDC_TX_ANC0_FF_SHIFT		(TX_START_OFFSET + 0x020C)
+#define LPASS_CDC_TX_ANC0_FB_SHIFT		(TX_START_OFFSET + 0x0210)
+#define LPASS_CDC_TX_ANC0_LPF_FF_A_CTL		(TX_START_OFFSET + 0x0214)
+#define LPASS_CDC_TX_ANC0_LPF_FF_B_CTL		(TX_START_OFFSET + 0x0218)
+#define LPASS_CDC_TX_ANC0_LPF_FB_CTL		(TX_START_OFFSET + 0x021C)
+#define LPASS_CDC_TX_ANC0_SMLPF_CTL		(TX_START_OFFSET + 0x0220)
+#define LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL	(TX_START_OFFSET + 0x0224)
+#define LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL		(TX_START_OFFSET + 0x0228)
+#define LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL	(TX_START_OFFSET + 0x022C)
+#define LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL	(TX_START_OFFSET + 0x0230)
+#define LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL		(TX_START_OFFSET + 0x0234)
+#define LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL		(TX_START_OFFSET + 0x0238)
+#define LPASS_CDC_TX_ANC0_FB_GAIN_CTL		(TX_START_OFFSET + 0x023C)
+#define LPASS_CDC_TX0_TX_PATH_CTL	(TX_START_OFFSET + 0x0400)
+#define LPASS_CDC_TX0_TX_PATH_CFG0	(TX_START_OFFSET + 0x0404)
+#define LPASS_CDC_TX0_TX_PATH_CFG1	(TX_START_OFFSET + 0x0408)
+#define LPASS_CDC_TX0_TX_VOL_CTL	(TX_START_OFFSET + 0x040C)
+#define LPASS_CDC_TX0_TX_PATH_SEC0	(TX_START_OFFSET + 0x0410)
+#define LPASS_CDC_TX0_TX_PATH_SEC1	(TX_START_OFFSET + 0x0414)
+#define LPASS_CDC_TX0_TX_PATH_SEC2	(TX_START_OFFSET + 0x0418)
+#define LPASS_CDC_TX0_TX_PATH_SEC3	(TX_START_OFFSET + 0x041C)
+#define LPASS_CDC_TX0_TX_PATH_SEC4	(TX_START_OFFSET + 0x0420)
+#define LPASS_CDC_TX0_TX_PATH_SEC5	(TX_START_OFFSET + 0x0424)
+#define LPASS_CDC_TX0_TX_PATH_SEC6	(TX_START_OFFSET + 0x0428)
+#define LPASS_CDC_TX0_TX_PATH_SEC7	(TX_START_OFFSET + 0x042C)
+#define LPASS_CDC_TX1_TX_PATH_CTL	(TX_START_OFFSET + 0x0480)
+#define LPASS_CDC_TX1_TX_PATH_CFG0	(TX_START_OFFSET + 0x0484)
+#define LPASS_CDC_TX1_TX_PATH_CFG1	(TX_START_OFFSET + 0x0488)
+#define LPASS_CDC_TX1_TX_VOL_CTL	(TX_START_OFFSET + 0x048C)
+#define LPASS_CDC_TX1_TX_PATH_SEC0	(TX_START_OFFSET + 0x0490)
+#define LPASS_CDC_TX1_TX_PATH_SEC1	(TX_START_OFFSET + 0x0494)
+#define LPASS_CDC_TX1_TX_PATH_SEC2	(TX_START_OFFSET + 0x0498)
+#define LPASS_CDC_TX1_TX_PATH_SEC3	(TX_START_OFFSET + 0x049C)
+#define LPASS_CDC_TX1_TX_PATH_SEC4	(TX_START_OFFSET + 0x04A0)
+#define LPASS_CDC_TX1_TX_PATH_SEC5	(TX_START_OFFSET + 0x04A4)
+#define LPASS_CDC_TX1_TX_PATH_SEC6	(TX_START_OFFSET + 0x04A8)
+#define LPASS_CDC_TX2_TX_PATH_CTL	(TX_START_OFFSET + 0x0500)
+#define LPASS_CDC_TX2_TX_PATH_CFG0	(TX_START_OFFSET + 0x0504)
+#define LPASS_CDC_TX2_TX_PATH_CFG1	(TX_START_OFFSET + 0x0508)
+#define LPASS_CDC_TX2_TX_VOL_CTL	(TX_START_OFFSET + 0x050C)
+#define LPASS_CDC_TX2_TX_PATH_SEC0	(TX_START_OFFSET + 0x0510)
+#define LPASS_CDC_TX2_TX_PATH_SEC1	(TX_START_OFFSET + 0x0514)
+#define LPASS_CDC_TX2_TX_PATH_SEC2	(TX_START_OFFSET + 0x0518)
+#define LPASS_CDC_TX2_TX_PATH_SEC3	(TX_START_OFFSET + 0x051C)
+#define LPASS_CDC_TX2_TX_PATH_SEC4	(TX_START_OFFSET + 0x0520)
+#define LPASS_CDC_TX2_TX_PATH_SEC5	(TX_START_OFFSET + 0x0524)
+#define LPASS_CDC_TX2_TX_PATH_SEC6	(TX_START_OFFSET + 0x0528)
+#define LPASS_CDC_TX3_TX_PATH_CTL	(TX_START_OFFSET + 0x0580)
+#define LPASS_CDC_TX3_TX_PATH_CFG0	(TX_START_OFFSET + 0x0584)
+#define LPASS_CDC_TX3_TX_PATH_CFG1	(TX_START_OFFSET + 0x0588)
+#define LPASS_CDC_TX3_TX_VOL_CTL	(TX_START_OFFSET + 0x058C)
+#define LPASS_CDC_TX3_TX_PATH_SEC0	(TX_START_OFFSET + 0x0590)
+#define LPASS_CDC_TX3_TX_PATH_SEC1	(TX_START_OFFSET + 0x0594)
+#define LPASS_CDC_TX3_TX_PATH_SEC2	(TX_START_OFFSET + 0x0598)
+#define LPASS_CDC_TX3_TX_PATH_SEC3	(TX_START_OFFSET + 0x059C)
+#define LPASS_CDC_TX3_TX_PATH_SEC4	(TX_START_OFFSET + 0x05A0)
+#define LPASS_CDC_TX3_TX_PATH_SEC5	(TX_START_OFFSET + 0x05A4)
+#define LPASS_CDC_TX3_TX_PATH_SEC6	(TX_START_OFFSET + 0x05A8)
+#define LPASS_CDC_TX4_TX_PATH_CTL	(TX_START_OFFSET + 0x0600)
+#define LPASS_CDC_TX4_TX_PATH_CFG0	(TX_START_OFFSET + 0x0604)
+#define LPASS_CDC_TX4_TX_PATH_CFG1	(TX_START_OFFSET + 0x0608)
+#define LPASS_CDC_TX4_TX_VOL_CTL	(TX_START_OFFSET + 0x060C)
+#define LPASS_CDC_TX4_TX_PATH_SEC0	(TX_START_OFFSET + 0x0610)
+#define LPASS_CDC_TX4_TX_PATH_SEC1	(TX_START_OFFSET + 0x0614)
+#define LPASS_CDC_TX4_TX_PATH_SEC2	(TX_START_OFFSET + 0x0618)
+#define LPASS_CDC_TX4_TX_PATH_SEC3	(TX_START_OFFSET + 0x061C)
+#define LPASS_CDC_TX4_TX_PATH_SEC4	(TX_START_OFFSET + 0x0620)
+#define LPASS_CDC_TX4_TX_PATH_SEC5	(TX_START_OFFSET + 0x0624)
+#define LPASS_CDC_TX4_TX_PATH_SEC6	(TX_START_OFFSET + 0x0628)
+#define LPASS_CDC_TX5_TX_PATH_CTL	(TX_START_OFFSET + 0x0680)
+#define LPASS_CDC_TX5_TX_PATH_CFG0	(TX_START_OFFSET + 0x0684)
+#define LPASS_CDC_TX5_TX_PATH_CFG1	(TX_START_OFFSET + 0x0688)
+#define LPASS_CDC_TX5_TX_VOL_CTL	(TX_START_OFFSET + 0x068C)
+#define LPASS_CDC_TX5_TX_PATH_SEC0	(TX_START_OFFSET + 0x0690)
+#define LPASS_CDC_TX5_TX_PATH_SEC1	(TX_START_OFFSET + 0x0694)
+#define LPASS_CDC_TX5_TX_PATH_SEC2	(TX_START_OFFSET + 0x0698)
+#define LPASS_CDC_TX5_TX_PATH_SEC3	(TX_START_OFFSET + 0x069C)
+#define LPASS_CDC_TX5_TX_PATH_SEC4	(TX_START_OFFSET + 0x06A0)
+#define LPASS_CDC_TX5_TX_PATH_SEC5	(TX_START_OFFSET + 0x06A4)
+#define LPASS_CDC_TX5_TX_PATH_SEC6	(TX_START_OFFSET + 0x06A8)
+#define LPASS_CDC_TX6_TX_PATH_CTL	(TX_START_OFFSET + 0x0700)
+#define LPASS_CDC_TX6_TX_PATH_CFG0	(TX_START_OFFSET + 0x0704)
+#define LPASS_CDC_TX6_TX_PATH_CFG1	(TX_START_OFFSET + 0x0708)
+#define LPASS_CDC_TX6_TX_VOL_CTL	(TX_START_OFFSET + 0x070C)
+#define LPASS_CDC_TX6_TX_PATH_SEC0	(TX_START_OFFSET + 0x0710)
+#define LPASS_CDC_TX6_TX_PATH_SEC1	(TX_START_OFFSET + 0x0714)
+#define LPASS_CDC_TX6_TX_PATH_SEC2	(TX_START_OFFSET + 0x0718)
+#define LPASS_CDC_TX6_TX_PATH_SEC3	(TX_START_OFFSET + 0x071C)
+#define LPASS_CDC_TX6_TX_PATH_SEC4	(TX_START_OFFSET + 0x0720)
+#define LPASS_CDC_TX6_TX_PATH_SEC5	(TX_START_OFFSET + 0x0724)
+#define LPASS_CDC_TX6_TX_PATH_SEC6	(TX_START_OFFSET + 0x0728)
+#define LPASS_CDC_TX7_TX_PATH_CTL	(TX_START_OFFSET + 0x0780)
+#define LPASS_CDC_TX7_TX_PATH_CFG0	(TX_START_OFFSET + 0x0784)
+#define LPASS_CDC_TX7_TX_PATH_CFG1	(TX_START_OFFSET + 0x0788)
+#define LPASS_CDC_TX7_TX_VOL_CTL	(TX_START_OFFSET + 0x078C)
+#define LPASS_CDC_TX7_TX_PATH_SEC0	(TX_START_OFFSET + 0x0790)
+#define LPASS_CDC_TX7_TX_PATH_SEC1	(TX_START_OFFSET + 0x0794)
+#define LPASS_CDC_TX7_TX_PATH_SEC2	(TX_START_OFFSET + 0x0798)
+#define LPASS_CDC_TX7_TX_PATH_SEC3	(TX_START_OFFSET + 0x079C)
+#define LPASS_CDC_TX7_TX_PATH_SEC4	(TX_START_OFFSET + 0x07A0)
+#define LPASS_CDC_TX7_TX_PATH_SEC5	(TX_START_OFFSET + 0x07A4)
+#define LPASS_CDC_TX7_TX_PATH_SEC6	(TX_START_OFFSET + 0x07A8)
+#define TX_MAX_OFFSET			(TX_START_OFFSET + 0x07A8)
+
+#define LPASS_CDC_TX_MACRO_MAX 0x1EB /* 7A8/4 = 1EA + 1 */
+
+#define RX_START_OFFSET				0x1000
+#define LPASS_CDC_RX_TOP_TOP_CFG0		(RX_START_OFFSET + 0x0000)
+#define LPASS_CDC_RX_TOP_TOP_CFG1		(RX_START_OFFSET + 0x0004)
+#define LPASS_CDC_RX_TOP_SWR_CTRL		(RX_START_OFFSET + 0x0008)
+#define LPASS_CDC_RX_TOP_DEBUG			(RX_START_OFFSET + 0x000C)
+#define LPASS_CDC_RX_TOP_DEBUG_BUS		(RX_START_OFFSET + 0x0010)
+#define LPASS_CDC_RX_TOP_DEBUG_EN0		(RX_START_OFFSET + 0x0014)
+#define LPASS_CDC_RX_TOP_DEBUG_EN1		(RX_START_OFFSET + 0x0018)
+#define LPASS_CDC_RX_TOP_DEBUG_EN2		(RX_START_OFFSET + 0x001C)
+#define LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB	(RX_START_OFFSET + 0x0020)
+#define LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB	(RX_START_OFFSET + 0x0024)
+#define LPASS_CDC_RX_TOP_HPHL_COMP_LUT		(RX_START_OFFSET + 0x0028)
+#define LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB	(RX_START_OFFSET + 0x002C)
+#define LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB	(RX_START_OFFSET + 0x0030)
+#define LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB	(RX_START_OFFSET + 0x0034)
+#define LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB	(RX_START_OFFSET + 0x0038)
+#define LPASS_CDC_RX_TOP_HPHR_COMP_LUT		(RX_START_OFFSET + 0x003C)
+#define LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB	(RX_START_OFFSET + 0x0040)
+#define LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB	(RX_START_OFFSET + 0x0044)
+#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0	(RX_START_OFFSET + 0x0070)
+#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1	(RX_START_OFFSET + 0x0074)
+#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2	(RX_START_OFFSET + 0x0078)
+#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3	(RX_START_OFFSET + 0x007C)
+#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0	(RX_START_OFFSET + 0x0080)
+#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1	(RX_START_OFFSET + 0x0084)
+#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2	(RX_START_OFFSET + 0x0088)
+#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3	(RX_START_OFFSET + 0x008C)
+#define LPASS_CDC_RX_TOP_RX_I2S_CTL		(RX_START_OFFSET + 0x0090)
+#define LPASS_CDC_RX_TOP_TX_I2S2_CTL		(RX_START_OFFSET + 0x0094)
+#define LPASS_CDC_RX_TOP_I2S_CLK		(RX_START_OFFSET + 0x0098)
+#define LPASS_CDC_RX_TOP_I2S_RESET		(RX_START_OFFSET + 0x009C)
+#define LPASS_CDC_RX_TOP_I2S_MUX		(RX_START_OFFSET + 0x00A0)
+#define LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL	(RX_START_OFFSET + 0x0100)
+#define LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(RX_START_OFFSET + 0x0104)
+#define LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL	(RX_START_OFFSET + 0x0108)
+#define LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL	(RX_START_OFFSET + 0x010C)
+#define LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL \
+						(RX_START_OFFSET + 0x0110)
+#define LPASS_CDC_RX_SOFTCLIP_CRC		(RX_START_OFFSET + 0x0140)
+#define LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL	(RX_START_OFFSET + 0x0144)
+#define LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0	(RX_START_OFFSET + 0x0180)
+#define LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1	(RX_START_OFFSET + 0x0184)
+#define LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0	(RX_START_OFFSET + 0x0188)
+#define LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1	(RX_START_OFFSET + 0x018C)
+#define LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0	(RX_START_OFFSET + 0x0190)
+#define LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1	(RX_START_OFFSET + 0x0194)
+#define LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4	(RX_START_OFFSET + 0x0198)
+#define LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5	(RX_START_OFFSET + 0x019C)
+#define LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0	(RX_START_OFFSET + 0x01A0)
+#define LPASS_CDC_RX_CLSH_CRC			(RX_START_OFFSET + 0x0200)
+#define LPASS_CDC_RX_CLSH_DLY_CTRL		(RX_START_OFFSET + 0x0204)
+#define LPASS_CDC_RX_CLSH_DECAY_CTRL		(RX_START_OFFSET + 0x0208)
+#define LPASS_CDC_RX_CLSH_HPH_V_PA		(RX_START_OFFSET + 0x020C)
+#define LPASS_CDC_RX_CLSH_EAR_V_PA		(RX_START_OFFSET + 0x0210)
+#define LPASS_CDC_RX_CLSH_HPH_V_HD		(RX_START_OFFSET + 0x0214)
+#define LPASS_CDC_RX_CLSH_EAR_V_HD		(RX_START_OFFSET + 0x0218)
+#define LPASS_CDC_RX_CLSH_K1_MSB		(RX_START_OFFSET + 0x021C)
+#define LPASS_CDC_RX_CLSH_K1_LSB		(RX_START_OFFSET + 0x0220)
+#define LPASS_CDC_RX_CLSH_K2_MSB		(RX_START_OFFSET + 0x0224)
+#define LPASS_CDC_RX_CLSH_K2_LSB		(RX_START_OFFSET + 0x0228)
+#define LPASS_CDC_RX_CLSH_IDLE_CTRL		(RX_START_OFFSET + 0x022C)
+#define LPASS_CDC_RX_CLSH_IDLE_HPH		(RX_START_OFFSET + 0x0230)
+#define LPASS_CDC_RX_CLSH_IDLE_EAR		(RX_START_OFFSET + 0x0234)
+#define LPASS_CDC_RX_CLSH_TEST0		(RX_START_OFFSET + 0x0238)
+#define LPASS_CDC_RX_CLSH_TEST1		(RX_START_OFFSET + 0x023C)
+#define LPASS_CDC_RX_CLSH_OVR_VREF		(RX_START_OFFSET + 0x0240)
+#define LPASS_CDC_RX_CLSH_CLSG_CTL		(RX_START_OFFSET + 0x0244)
+#define LPASS_CDC_RX_CLSH_CLSG_CFG1		(RX_START_OFFSET + 0x0248)
+#define LPASS_CDC_RX_CLSH_CLSG_CFG2		(RX_START_OFFSET + 0x024C)
+#define LPASS_CDC_RX_BCL_VBAT_PATH_CTL		(RX_START_OFFSET + 0x0280)
+#define LPASS_CDC_RX_BCL_VBAT_CFG		(RX_START_OFFSET + 0x0284)
+#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL1		(RX_START_OFFSET + 0x0288)
+#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL2		(RX_START_OFFSET + 0x028C)
+#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL3		(RX_START_OFFSET + 0x0290)
+#define LPASS_CDC_RX_BCL_VBAT_PK_EST1		(RX_START_OFFSET + 0x0294)
+#define LPASS_CDC_RX_BCL_VBAT_PK_EST2		(RX_START_OFFSET + 0x0298)
+#define LPASS_CDC_RX_BCL_VBAT_PK_EST3		(RX_START_OFFSET + 0x029C)
+#define LPASS_CDC_RX_BCL_VBAT_RF_PROC1		(RX_START_OFFSET + 0x02A0)
+#define LPASS_CDC_RX_BCL_VBAT_RF_PROC2		(RX_START_OFFSET + 0x02A4)
+#define LPASS_CDC_RX_BCL_VBAT_TAC1		(RX_START_OFFSET + 0x02A8)
+#define LPASS_CDC_RX_BCL_VBAT_TAC2		(RX_START_OFFSET + 0x02AC)
+#define LPASS_CDC_RX_BCL_VBAT_TAC3		(RX_START_OFFSET + 0x02B0)
+#define LPASS_CDC_RX_BCL_VBAT_TAC4		(RX_START_OFFSET + 0x02B4)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1	(RX_START_OFFSET + 0x02B8)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2	(RX_START_OFFSET + 0x02BC)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3	(RX_START_OFFSET + 0x02C0)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4	(RX_START_OFFSET + 0x02C4)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5	(RX_START_OFFSET + 0x02C8)
+#define LPASS_CDC_RX_BCL_VBAT_DEBUG1		(RX_START_OFFSET + 0x02CC)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON	(RX_START_OFFSET + 0x02D0)
+#define LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL	(RX_START_OFFSET + 0x02D4)
+#define LPASS_CDC_RX_BCL_VBAT_BAN		(RX_START_OFFSET + 0x02D8)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1	(RX_START_OFFSET + 0x02DC)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2	(RX_START_OFFSET + 0x02E0)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3	(RX_START_OFFSET + 0x02E4)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4	(RX_START_OFFSET + 0x02E8)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5	(RX_START_OFFSET + 0x02EC)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6	(RX_START_OFFSET + 0x02F0)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7	(RX_START_OFFSET + 0x02F4)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8	(RX_START_OFFSET + 0x02F8)
+#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9	(RX_START_OFFSET + 0x02FC)
+#define LPASS_CDC_RX_BCL_VBAT_ATTN1		(RX_START_OFFSET + 0x0300)
+#define LPASS_CDC_RX_BCL_VBAT_ATTN2		(RX_START_OFFSET + 0x0304)
+#define LPASS_CDC_RX_BCL_VBAT_ATTN3		(RX_START_OFFSET + 0x0308)
+#define LPASS_CDC_RX_INTR_CTRL_CFG		(RX_START_OFFSET + 0x0340)
+#define LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT	(RX_START_OFFSET + 0x0344)
+#define LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0	(RX_START_OFFSET + 0x0360)
+#define LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0	(RX_START_OFFSET + 0x0368)
+#define LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0	(RX_START_OFFSET + 0x0370)
+#define LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0	(RX_START_OFFSET + 0x0380)
+#define LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0	(RX_START_OFFSET + 0x0388)
+#define LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0	(RX_START_OFFSET + 0x0390)
+#define LPASS_CDC_RX_INTR_CTRL_LEVEL0		(RX_START_OFFSET + 0x03C0)
+#define LPASS_CDC_RX_INTR_CTRL_BYPASS0		(RX_START_OFFSET + 0x03C8)
+#define LPASS_CDC_RX_INTR_CTRL_SET0		(RX_START_OFFSET + 0x03D0)
+#define LPASS_CDC_RX_RX0_RX_PATH_CTL		(RX_START_OFFSET + 0x0400)
+#define LPASS_CDC_RX_RX0_RX_PATH_CFG0		(RX_START_OFFSET + 0x0404)
+#define LPASS_CDC_RX_RX0_RX_PATH_CFG1		(RX_START_OFFSET + 0x0408)
+#define LPASS_CDC_RX_RX0_RX_PATH_CFG2		(RX_START_OFFSET + 0x040C)
+#define LPASS_CDC_RX_RX0_RX_PATH_CFG3		(RX_START_OFFSET + 0x0410)
+#define LPASS_CDC_RX_RX0_RX_VOL_CTL		(RX_START_OFFSET + 0x0414)
+#define LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0418)
+#define LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x041C)
+#define LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x0420)
+#define LPASS_CDC_RX_RX0_RX_PATH_SEC1		(RX_START_OFFSET + 0x0424)
+#define LPASS_CDC_RX_RX0_RX_PATH_SEC2		(RX_START_OFFSET + 0x0428)
+#define LPASS_CDC_RX_RX0_RX_PATH_SEC3		(RX_START_OFFSET + 0x042C)
+#define LPASS_CDC_RX_RX0_RX_PATH_SEC4		(RX_START_OFFSET + 0x0430)
+#define LPASS_CDC_RX_RX0_RX_PATH_SEC7		(RX_START_OFFSET + 0x0434)
+#define LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x0438)
+#define LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x043C)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x0440)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1	(RX_START_OFFSET + 0x0444)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2	(RX_START_OFFSET + 0x0448)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3	(RX_START_OFFSET + 0x044C)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4	(RX_START_OFFSET + 0x0450)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5	(RX_START_OFFSET + 0x0454)
+#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6	(RX_START_OFFSET + 0x0458)
+#define LPASS_CDC_RX_IDLE_DETECT_PATH_CTL	(RX_START_OFFSET + 0x0780)
+#define LPASS_CDC_RX_IDLE_DETECT_CFG0		(RX_START_OFFSET + 0x0784)
+#define LPASS_CDC_RX_IDLE_DETECT_CFG1		(RX_START_OFFSET + 0x0788)
+#define LPASS_CDC_RX_IDLE_DETECT_CFG2		(RX_START_OFFSET + 0x078C)
+#define LPASS_CDC_RX_IDLE_DETECT_CFG3		(RX_START_OFFSET + 0x0790)
+#define LPASS_CDC_RX_COMPANDER0_CTL0		(RX_START_OFFSET + 0x0800)
+#define LPASS_CDC_RX_COMPANDER0_CTL1		(RX_START_OFFSET + 0x0804)
+#define LPASS_CDC_RX_COMPANDER0_CTL2		(RX_START_OFFSET + 0x0808)
+#define LPASS_CDC_RX_COMPANDER0_CTL3		(RX_START_OFFSET + 0x080C)
+#define LPASS_CDC_RX_COMPANDER0_CTL4		(RX_START_OFFSET + 0x0810)
+#define LPASS_CDC_RX_COMPANDER0_CTL5		(RX_START_OFFSET + 0x0814)
+#define LPASS_CDC_RX_COMPANDER0_CTL6		(RX_START_OFFSET + 0x0818)
+#define LPASS_CDC_RX_COMPANDER0_CTL7		(RX_START_OFFSET + 0x081C)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL \
+						(RX_START_OFFSET + 0x0A00)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL \
+						(RX_START_OFFSET + 0x0A04)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL \
+						(RX_START_OFFSET + 0x0A08)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL \
+						(RX_START_OFFSET + 0x0A0C)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL \
+						(RX_START_OFFSET + 0x0A10)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL \
+						(RX_START_OFFSET + 0x0A14)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL \
+						(RX_START_OFFSET + 0x0A18)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL \
+						(RX_START_OFFSET + 0x0A1C)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL \
+						(RX_START_OFFSET + 0x0A20)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL	(RX_START_OFFSET + 0x0A24)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL \
+						(RX_START_OFFSET + 0x0A28)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL \
+						(RX_START_OFFSET + 0x0A2C)
+#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL \
+						(RX_START_OFFSET + 0x0A30)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL \
+						(RX_START_OFFSET + 0x0A80)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL \
+						(RX_START_OFFSET + 0x0A84)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL \
+						(RX_START_OFFSET + 0x0A88)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL \
+						(RX_START_OFFSET + 0x0A8C)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL \
+						(RX_START_OFFSET + 0x0A90)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL \
+						(RX_START_OFFSET + 0x0A94)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL \
+						(RX_START_OFFSET + 0x0A98)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL \
+						(RX_START_OFFSET + 0x0A9C)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL \
+						(RX_START_OFFSET + 0x0AA0)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL	(RX_START_OFFSET + 0x0AA4)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL \
+						(RX_START_OFFSET + 0x0AA8)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL \
+						(RX_START_OFFSET + 0x0AAC)
+#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL \
+						(RX_START_OFFSET + 0x0AB0)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0	(RX_START_OFFSET + 0x0B00)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1	(RX_START_OFFSET + 0x0B04)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2	(RX_START_OFFSET + 0x0B08)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3	(RX_START_OFFSET + 0x0B0C)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0	(RX_START_OFFSET + 0x0B10)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1	(RX_START_OFFSET + 0x0B14)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2	(RX_START_OFFSET + 0x0B18)
+#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3	(RX_START_OFFSET + 0x0B1C)
+#define LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL \
+						(RX_START_OFFSET + 0x0B40)
+#define LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1 \
+						(RX_START_OFFSET + 0x0B44)
+#define LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL \
+						(RX_START_OFFSET + 0x0B50)
+#define LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1 \
+						(RX_START_OFFSET + 0x0B54)
+#define LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C00)
+#define LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C04)
+#define LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C40)
+#define LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C44)
+#define LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL \
+						(RX_START_OFFSET + 0x0C80)
+#define LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0	(RX_START_OFFSET + 0x0C84)
+#define LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL	(RX_START_OFFSET + 0x0D00)
+#define LPASS_CDC_RX_EC_ASRC0_CTL0		(RX_START_OFFSET + 0x0D04)
+#define LPASS_CDC_RX_EC_ASRC0_CTL1		(RX_START_OFFSET + 0x0D08)
+#define LPASS_CDC_RX_EC_ASRC0_FIFO_CTL		(RX_START_OFFSET + 0x0D0C)
+#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D10)
+#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D14)
+#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D18)
+#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D1C)
+#define LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO	(RX_START_OFFSET + 0x0D20)
+#define LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL	(RX_START_OFFSET + 0x0D40)
+#define LPASS_CDC_RX_EC_ASRC1_CTL0		(RX_START_OFFSET + 0x0D44)
+#define LPASS_CDC_RX_EC_ASRC1_CTL1		(RX_START_OFFSET + 0x0D48)
+#define LPASS_CDC_RX_EC_ASRC1_FIFO_CTL		(RX_START_OFFSET + 0x0D4C)
+#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D50)
+#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D54)
+#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D58)
+#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D5C)
+#define LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO	(RX_START_OFFSET + 0x0D60)
+#define LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL	(RX_START_OFFSET + 0x0D80)
+#define LPASS_CDC_RX_EC_ASRC2_CTL0		(RX_START_OFFSET + 0x0D84)
+#define LPASS_CDC_RX_EC_ASRC2_CTL1		(RX_START_OFFSET + 0x0D88)
+#define LPASS_CDC_RX_EC_ASRC2_FIFO_CTL		(RX_START_OFFSET + 0x0D8C)
+#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D90)
+#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D94)
+#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB \
+						(RX_START_OFFSET + 0x0D98)
+#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB \
+						(RX_START_OFFSET + 0x0D9C)
+#define LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO	(RX_START_OFFSET + 0x0DA0)
+#define LPASS_CDC_RX_DSD0_PATH_CTL		(RX_START_OFFSET + 0x0F00)
+#define LPASS_CDC_RX_DSD0_CFG0			(RX_START_OFFSET + 0x0F04)
+#define LPASS_CDC_RX_DSD0_CFG1			(RX_START_OFFSET + 0x0F08)
+#define LPASS_CDC_RX_DSD0_CFG2			(RX_START_OFFSET + 0x0F0C)
+#define LPASS_CDC_RX_DSD1_PATH_CTL		(RX_START_OFFSET + 0x0F80)
+#define LPASS_CDC_RX_DSD1_CFG0			(RX_START_OFFSET + 0x0F84)
+#define LPASS_CDC_RX_DSD1_CFG1			(RX_START_OFFSET + 0x0F88)
+#define LPASS_CDC_RX_DSD1_CFG2			(RX_START_OFFSET + 0x0F8C)
+
+#ifdef CONFIG_BOLERO_VER_2P6
+#define LPASS_CDC_RX_RX0_RX_FIR_CTL		(RX_START_OFFSET + 0x045C)
+#define LPASS_CDC_RX_RX0_RX_FIR_CFG		(RX_START_OFFSET + 0x0460)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_ADDR	(RX_START_OFFSET + 0x0464)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA0	(RX_START_OFFSET + 0x0468)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA1	(RX_START_OFFSET + 0x046C)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA2	(RX_START_OFFSET + 0x0470)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA3	(RX_START_OFFSET + 0x0474)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA4	(RX_START_OFFSET + 0x0478)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA5	(RX_START_OFFSET + 0x047C)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA6	(RX_START_OFFSET + 0x0480)
+#define LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA7	(RX_START_OFFSET + 0x0484)
+#define LPASS_CDC_RX_RX1_RX_PATH_CTL		(RX_START_OFFSET + 0x04C0)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG0		(RX_START_OFFSET + 0x04C4)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG1		(RX_START_OFFSET + 0x04C8)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG2		(RX_START_OFFSET + 0x04CC)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG3		(RX_START_OFFSET + 0x04D0)
+#define LPASS_CDC_RX_RX1_RX_VOL_CTL		(RX_START_OFFSET + 0x04D4)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x04D8)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x04DC)
+#define LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x04E0)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC1		(RX_START_OFFSET + 0x04E4)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC2		(RX_START_OFFSET + 0x04E8)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC3		(RX_START_OFFSET + 0x04EC)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC4		(RX_START_OFFSET + 0x04F0)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC7		(RX_START_OFFSET + 0x04F4)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x04F8)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x04FC)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x0500)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1	(RX_START_OFFSET + 0x0504)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2	(RX_START_OFFSET + 0x0508)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3	(RX_START_OFFSET + 0x050C)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4	(RX_START_OFFSET + 0x0510)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5	(RX_START_OFFSET + 0x0514)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6	(RX_START_OFFSET + 0x0518)
+#define LPASS_CDC_RX_RX1_RX_FIR_CTL		(RX_START_OFFSET + 0x051C)
+#define LPASS_CDC_RX_RX1_RX_FIR_CFG		(RX_START_OFFSET + 0x0520)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_ADDR	(RX_START_OFFSET + 0x0524)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA0	(RX_START_OFFSET + 0x0528)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA1	(RX_START_OFFSET + 0x052C)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA2	(RX_START_OFFSET + 0x0530)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA3	(RX_START_OFFSET + 0x0534)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA4	(RX_START_OFFSET + 0x0538)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA5	(RX_START_OFFSET + 0x053C)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA6	(RX_START_OFFSET + 0x0540)
+#define LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA7	(RX_START_OFFSET + 0x0544)
+#define LPASS_CDC_RX_RX2_RX_PATH_CTL		(RX_START_OFFSET + 0x0580)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG0		(RX_START_OFFSET + 0x0584)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG1		(RX_START_OFFSET + 0x0588)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG2		(RX_START_OFFSET + 0x058C)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG3		(RX_START_OFFSET + 0x0590)
+#define LPASS_CDC_RX_RX2_RX_VOL_CTL		(RX_START_OFFSET + 0x0594)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0598)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x059C)
+#define LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x05A0)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC0		(RX_START_OFFSET + 0x05A4)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC1		(RX_START_OFFSET + 0x05A8)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC2		(RX_START_OFFSET + 0x05AC)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC3		(RX_START_OFFSET + 0x05B0)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC4		(RX_START_OFFSET + 0x05B4)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC5		(RX_START_OFFSET + 0x05B8)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC6		(RX_START_OFFSET + 0x05BC)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC7		(RX_START_OFFSET + 0x05C0)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x05C4)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x05C8)
+#define LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x05CC)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL1	(RX_START_OFFSET + 0x0600)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL2	(RX_START_OFFSET + 0x0604)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL3	(RX_START_OFFSET + 0x0608)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG1	(RX_START_OFFSET + 0x060C)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG2	(RX_START_OFFSET + 0x0610)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG3	(RX_START_OFFSET + 0x0614)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG4	(RX_START_OFFSET + 0x0618)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG5	(RX_START_OFFSET + 0x061C)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG6	(RX_START_OFFSET + 0x0620)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG7	(RX_START_OFFSET + 0x0624)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG8	(RX_START_OFFSET + 0x0628)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST1	(RX_START_OFFSET + 0x062C)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST2	(RX_START_OFFSET + 0x0630)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST3	(RX_START_OFFSET + 0x0634)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST4	(RX_START_OFFSET + 0x0638)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST1	(RX_START_OFFSET + 0x063C)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST2	(RX_START_OFFSET + 0x0640)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST3	(RX_START_OFFSET + 0x0644)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST4	(RX_START_OFFSET + 0x0648)
+#define LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST5	(RX_START_OFFSET + 0x064C)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_PATH_CTL	(RX_START_OFFSET + 0x0680)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_CFG		(RX_START_OFFSET + 0x0684)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL1	(RX_START_OFFSET + 0x0688)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL2	(RX_START_OFFSET + 0x068C)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL3	(RX_START_OFFSET + 0x0690)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST1	(RX_START_OFFSET + 0x0694)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST2	(RX_START_OFFSET + 0x0698)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST3	(RX_START_OFFSET + 0x069C)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC1	(RX_START_OFFSET + 0x06A0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC2	(RX_START_OFFSET + 0x06A4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC1	(RX_START_OFFSET + 0x06A8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC2	(RX_START_OFFSET + 0x06AC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC3	(RX_START_OFFSET + 0x06B0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC4	(RX_START_OFFSET + 0x06B4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD1	(RX_START_OFFSET + 0x06B8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD2	(RX_START_OFFSET + 0x06BC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD3	(RX_START_OFFSET + 0x06C0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD4	(RX_START_OFFSET + 0x06C4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD5	(RX_START_OFFSET + 0x06C8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_DEBUG1	(RX_START_OFFSET + 0x06CC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD_MON \
+						(RX_START_OFFSET + 0x06D0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_MON_VAL \
+						(RX_START_OFFSET + 0x06D4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BAN		(RX_START_OFFSET + 0x06D8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD1 \
+						(RX_START_OFFSET + 0x06DC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD2 \
+						(RX_START_OFFSET + 0x06E0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD3 \
+						(RX_START_OFFSET + 0x06E4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD4 \
+						(RX_START_OFFSET + 0x06E8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD5 \
+						(RX_START_OFFSET + 0x06EC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD6 \
+						(RX_START_OFFSET + 0x06F0)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD7 \
+						(RX_START_OFFSET + 0x06F4)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD8 \
+						(RX_START_OFFSET + 0x06F8)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD9 \
+						(RX_START_OFFSET + 0x06FC)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN1	(RX_START_OFFSET + 0x0700)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN2	(RX_START_OFFSET + 0x0704)
+#define LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN3	(RX_START_OFFSET + 0x0708)
+
+#define LPASS_CDC_RX_COMPANDER0_CTL8		(RX_START_OFFSET + 0x0820)
+#define LPASS_CDC_RX_COMPANDER0_CTL9		(RX_START_OFFSET + 0x0824)
+#define LPASS_CDC_RX_COMPANDER0_CTL10		(RX_START_OFFSET + 0x0828)
+#define LPASS_CDC_RX_COMPANDER0_CTL11		(RX_START_OFFSET + 0x082C)
+#define LPASS_CDC_RX_COMPANDER0_CTL12		(RX_START_OFFSET + 0x0830)
+#define LPASS_CDC_RX_COMPANDER0_CTL13		(RX_START_OFFSET + 0x0834)
+#define LPASS_CDC_RX_COMPANDER0_CTL14		(RX_START_OFFSET + 0x0838)
+#define LPASS_CDC_RX_COMPANDER0_CTL15		(RX_START_OFFSET + 0x083C)
+#define LPASS_CDC_RX_COMPANDER0_CTL16		(RX_START_OFFSET + 0x0840)
+#define LPASS_CDC_RX_COMPANDER0_CTL17		(RX_START_OFFSET + 0x0844)
+#define LPASS_CDC_RX_COMPANDER0_CTL18		(RX_START_OFFSET + 0x0848)
+#define LPASS_CDC_RX_COMPANDER0_CTL19		(RX_START_OFFSET + 0x084C)
+#define LPASS_CDC_RX_COMPANDER1_CTL0		(RX_START_OFFSET + 0x0860)
+#define LPASS_CDC_RX_COMPANDER1_CTL1		(RX_START_OFFSET + 0x0864)
+#define LPASS_CDC_RX_COMPANDER1_CTL2		(RX_START_OFFSET + 0x0868)
+#define LPASS_CDC_RX_COMPANDER1_CTL3		(RX_START_OFFSET + 0x086C)
+#define LPASS_CDC_RX_COMPANDER1_CTL4		(RX_START_OFFSET + 0x0870)
+#define LPASS_CDC_RX_COMPANDER1_CTL5		(RX_START_OFFSET + 0x0874)
+#define LPASS_CDC_RX_COMPANDER1_CTL6		(RX_START_OFFSET + 0x0878)
+#define LPASS_CDC_RX_COMPANDER1_CTL7		(RX_START_OFFSET + 0x087C)
+#define LPASS_CDC_RX_COMPANDER1_CTL8		(RX_START_OFFSET + 0x0880)
+#define LPASS_CDC_RX_COMPANDER1_CTL9		(RX_START_OFFSET + 0x0884)
+#define LPASS_CDC_RX_COMPANDER1_CTL10		(RX_START_OFFSET + 0x0888)
+#define LPASS_CDC_RX_COMPANDER1_CTL11		(RX_START_OFFSET + 0x088C)
+#define LPASS_CDC_RX_COMPANDER1_CTL12		(RX_START_OFFSET + 0x0890)
+#define LPASS_CDC_RX_COMPANDER1_CTL13		(RX_START_OFFSET + 0x0894)
+#define LPASS_CDC_RX_COMPANDER1_CTL14		(RX_START_OFFSET + 0x0898)
+#define LPASS_CDC_RX_COMPANDER1_CTL15		(RX_START_OFFSET + 0x089C)
+#define LPASS_CDC_RX_COMPANDER1_CTL16		(RX_START_OFFSET + 0x08A0)
+#define LPASS_CDC_RX_COMPANDER1_CTL17		(RX_START_OFFSET + 0x08A4)
+#define LPASS_CDC_RX_COMPANDER1_CTL18		(RX_START_OFFSET + 0x08A8)
+#define LPASS_CDC_RX_COMPANDER1_CTL19		(RX_START_OFFSET + 0x08AC)
+#else
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1	(RX_START_OFFSET + 0x030C)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2	(RX_START_OFFSET + 0x0310)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1	(RX_START_OFFSET + 0x0314)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2	(RX_START_OFFSET + 0x0318)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3	(RX_START_OFFSET + 0x031C)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4	(RX_START_OFFSET + 0x0320)
+#define LPASS_CDC_RX_BCL_VBAT_DECODE_ST		(RX_START_OFFSET + 0x0324)
+#define LPASS_CDC_RX_RX1_RX_PATH_CTL		(RX_START_OFFSET + 0x0480)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG0		(RX_START_OFFSET + 0x0484)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG1		(RX_START_OFFSET + 0x0488)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG2		(RX_START_OFFSET + 0x048C)
+#define LPASS_CDC_RX_RX1_RX_PATH_CFG3		(RX_START_OFFSET + 0x0490)
+#define LPASS_CDC_RX_RX1_RX_VOL_CTL		(RX_START_OFFSET + 0x0494)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0498)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x049C)
+#define LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x04A0)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC1		(RX_START_OFFSET + 0x04A4)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC2		(RX_START_OFFSET + 0x04A8)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC3		(RX_START_OFFSET + 0x04AC)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC4		(RX_START_OFFSET + 0x04B0)
+#define LPASS_CDC_RX_RX1_RX_PATH_SEC7		(RX_START_OFFSET + 0x04B4)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x04B8)
+#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x04BC)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x04C0)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1	(RX_START_OFFSET + 0x04C4)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2	(RX_START_OFFSET + 0x04C8)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3	(RX_START_OFFSET + 0x04CC)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4	(RX_START_OFFSET + 0x04D0)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5	(RX_START_OFFSET + 0x04D4)
+#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6	(RX_START_OFFSET + 0x04D8)
+#define LPASS_CDC_RX_RX2_RX_PATH_CTL		(RX_START_OFFSET + 0x0500)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG0		(RX_START_OFFSET + 0x0504)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG1		(RX_START_OFFSET + 0x0508)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG2		(RX_START_OFFSET + 0x050C)
+#define LPASS_CDC_RX_RX2_RX_PATH_CFG3		(RX_START_OFFSET + 0x0510)
+#define LPASS_CDC_RX_RX2_RX_VOL_CTL		(RX_START_OFFSET + 0x0514)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL	(RX_START_OFFSET + 0x0518)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG	(RX_START_OFFSET + 0x051C)
+#define LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL	(RX_START_OFFSET + 0x0520)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC0		(RX_START_OFFSET + 0x0524)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC1		(RX_START_OFFSET + 0x0528)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC2		(RX_START_OFFSET + 0x052C)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC3		(RX_START_OFFSET + 0x0530)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC4		(RX_START_OFFSET + 0x0534)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC5		(RX_START_OFFSET + 0x0538)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC6		(RX_START_OFFSET + 0x053C)
+#define LPASS_CDC_RX_RX2_RX_PATH_SEC7		(RX_START_OFFSET + 0x0540)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0	(RX_START_OFFSET + 0x0544)
+#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1	(RX_START_OFFSET + 0x0548)
+#define LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL	(RX_START_OFFSET + 0x054C)
+#define LPASS_CDC_RX_COMPANDER1_CTL0		(RX_START_OFFSET + 0x0840)
+#define LPASS_CDC_RX_COMPANDER1_CTL1		(RX_START_OFFSET + 0x0844)
+#define LPASS_CDC_RX_COMPANDER1_CTL2		(RX_START_OFFSET + 0x0848)
+#define LPASS_CDC_RX_COMPANDER1_CTL3		(RX_START_OFFSET + 0x084C)
+#define LPASS_CDC_RX_COMPANDER1_CTL4		(RX_START_OFFSET + 0x0850)
+#define LPASS_CDC_RX_COMPANDER1_CTL5		(RX_START_OFFSET + 0x0854)
+#define LPASS_CDC_RX_COMPANDER1_CTL6		(RX_START_OFFSET + 0x0858)
+#define LPASS_CDC_RX_COMPANDER1_CTL7		(RX_START_OFFSET + 0x085C)
+#endif
+#define RX_MAX_OFFSET				(RX_START_OFFSET + 0x0F8C)
+
+#define LPASS_CDC_RX_MACRO_MAX 0x3E4 /* F8C/4 = 3E3 + 1 */
+
+/* WSA - macro#2 */
+#define WSA_START_OFFSET			0x2000
+#define LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL \
+						(WSA_START_OFFSET + 0x0000)
+#define LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(WSA_START_OFFSET + 0x0004)
+#define LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL	(WSA_START_OFFSET + 0x0008)
+#define LPASS_CDC_WSA_TOP_TOP_CFG0		(WSA_START_OFFSET + 0x0080)
+#define LPASS_CDC_WSA_TOP_TOP_CFG1		(WSA_START_OFFSET + 0x0084)
+#define LPASS_CDC_WSA_TOP_FREQ_MCLK		(WSA_START_OFFSET + 0x0088)
+#define LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL	(WSA_START_OFFSET + 0x008C)
+#define LPASS_CDC_WSA_TOP_DEBUG_EN0		(WSA_START_OFFSET + 0x0090)
+#define LPASS_CDC_WSA_TOP_DEBUG_EN1		(WSA_START_OFFSET + 0x0094)
+#define LPASS_CDC_WSA_TOP_DEBUG_DSM_LB		(WSA_START_OFFSET + 0x0098)
+#define LPASS_CDC_WSA_TOP_RX_I2S_CTL		(WSA_START_OFFSET + 0x009C)
+#define LPASS_CDC_WSA_TOP_TX_I2S_CTL		(WSA_START_OFFSET + 0x00A0)
+#define LPASS_CDC_WSA_TOP_I2S_CLK		(WSA_START_OFFSET + 0x00A4)
+#define LPASS_CDC_WSA_TOP_I2S_RESET		(WSA_START_OFFSET + 0x00A8)
+#define LPASS_CDC_WSA_TOP_FS_UNGATE		(WSA_START_OFFSET + 0x00AC)
+#define LPASS_CDC_WSA_TOP_GRP_SEL		(WSA_START_OFFSET + 0x00B0)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_LSB	(WSA_START_OFFSET + 0x00B4)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_MSB	(WSA_START_OFFSET + 0x00B8)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP7_LUT	(WSA_START_OFFSET + 0x00BC)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_LSB	(WSA_START_OFFSET + 0x00C0)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_MSB	(WSA_START_OFFSET + 0x00C4)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_LSB	(WSA_START_OFFSET + 0x00C8)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_MSB	(WSA_START_OFFSET + 0x00CC)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP8_LUT	(WSA_START_OFFSET + 0x00D0)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_LSB	(WSA_START_OFFSET + 0x00D4)
+#define LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_MSB	(WSA_START_OFFSET + 0x00D8)
+#define LPASS_CDC_WSA_TOP_FS_UNGATE2		(WSA_START_OFFSET + 0x00DC)
+#define LPASS_CDC_WSA_TOP_SEQ_CTL0		(WSA_START_OFFSET + 0x00E0)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0	(WSA_START_OFFSET + 0x0100)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1	(WSA_START_OFFSET + 0x0104)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0	(WSA_START_OFFSET + 0x0108)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1	(WSA_START_OFFSET + 0x010C)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0	(WSA_START_OFFSET + 0x0110)
+#define LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0	(WSA_START_OFFSET + 0x0114)
+#define LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0	(WSA_START_OFFSET + 0x0118)
+/* VBAT registers  */
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL	(WSA_START_OFFSET + 0x0180)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG	(WSA_START_OFFSET + 0x0184)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1	(WSA_START_OFFSET + 0x0188)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2	(WSA_START_OFFSET + 0x018C)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3	(WSA_START_OFFSET + 0x0190)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1	(WSA_START_OFFSET + 0x0194)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2	(WSA_START_OFFSET + 0x0198)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3	(WSA_START_OFFSET + 0x019C)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1	(WSA_START_OFFSET + 0x01A0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2	(WSA_START_OFFSET + 0x01A4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1	(WSA_START_OFFSET + 0x01A8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2	(WSA_START_OFFSET + 0x01AC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3	(WSA_START_OFFSET + 0x01B0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4	(WSA_START_OFFSET + 0x01B4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1	(WSA_START_OFFSET + 0x01B8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2	(WSA_START_OFFSET + 0x01BC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3	(WSA_START_OFFSET + 0x01C0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4	(WSA_START_OFFSET + 0x01C4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5	(WSA_START_OFFSET + 0x01C8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1	(WSA_START_OFFSET + 0x01CC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON \
+						(WSA_START_OFFSET + 0x01D0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL \
+						(WSA_START_OFFSET + 0x01D4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN	(WSA_START_OFFSET + 0x01D8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1 \
+						(WSA_START_OFFSET + 0x01DC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2 \
+						(WSA_START_OFFSET + 0x01E0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3 \
+						(WSA_START_OFFSET + 0x01E4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4 \
+						(WSA_START_OFFSET + 0x01E8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5 \
+						(WSA_START_OFFSET + 0x01EC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6 \
+						(WSA_START_OFFSET + 0x01F0)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7 \
+						(WSA_START_OFFSET + 0x01F4)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8 \
+						(WSA_START_OFFSET + 0x01F8)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9 \
+						(WSA_START_OFFSET + 0x01FC)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1	(WSA_START_OFFSET + 0x0200)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2	(WSA_START_OFFSET + 0x0204)
+#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3	(WSA_START_OFFSET + 0x0208)
+#define LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0244)
+#define LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0248)
+#define LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0264)
+#define LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0268)
+#define LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x0284)
+#define LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x0288)
+#define LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL	(WSA_START_OFFSET + 0x02A4)
+#define LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0	(WSA_START_OFFSET + 0x02A8)
+#define LPASS_CDC_WSA_INTR_CTRL_CFG		(WSA_START_OFFSET + 0x0340)
+#define LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT	(WSA_START_OFFSET + 0x0344)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0	(WSA_START_OFFSET + 0x0360)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0	(WSA_START_OFFSET + 0x0368)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0	(WSA_START_OFFSET + 0x0370)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0	(WSA_START_OFFSET + 0x0380)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0	(WSA_START_OFFSET + 0x0388)
+#define LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0	(WSA_START_OFFSET + 0x0390)
+#define LPASS_CDC_WSA_INTR_CTRL_LEVEL0		(WSA_START_OFFSET + 0x03C0)
+#define LPASS_CDC_WSA_INTR_CTRL_BYPASS0	(WSA_START_OFFSET + 0x03C8)
+#define LPASS_CDC_WSA_INTR_CTRL_SET0		(WSA_START_OFFSET + 0x03D0)
+#define LPASS_CDC_WSA_RX0_RX_PATH_CTL		(WSA_START_OFFSET + 0x0400)
+#define LPASS_CDC_WSA_RX0_RX_PATH_CFG0		(WSA_START_OFFSET + 0x0404)
+#define LPASS_CDC_WSA_RX0_RX_PATH_CFG1		(WSA_START_OFFSET + 0x0408)
+#define LPASS_CDC_WSA_RX0_RX_PATH_CFG2		(WSA_START_OFFSET + 0x040C)
+#define LPASS_CDC_WSA_RX0_RX_PATH_CFG3		(WSA_START_OFFSET + 0x0410)
+#define LPASS_CDC_WSA_RX0_RX_VOL_CTL		(WSA_START_OFFSET + 0x0414)
+#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL	(WSA_START_OFFSET + 0x0418)
+#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG	(WSA_START_OFFSET + 0x041C)
+#define LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL	(WSA_START_OFFSET + 0x0420)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC0		(WSA_START_OFFSET + 0x0424)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC1		(WSA_START_OFFSET + 0x0428)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC2		(WSA_START_OFFSET + 0x042C)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC3		(WSA_START_OFFSET + 0x0430)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC5		(WSA_START_OFFSET + 0x0438)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC6		(WSA_START_OFFSET + 0x043C)
+#define LPASS_CDC_WSA_RX0_RX_PATH_SEC7		(WSA_START_OFFSET + 0x0440)
+#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0	(WSA_START_OFFSET + 0x0444)
+#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1	(WSA_START_OFFSET + 0x0448)
+#define LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL	(WSA_START_OFFSET + 0x044C)
+#define LPASS_CDC_WSA_RX1_RX_PATH_CTL		(WSA_START_OFFSET + 0x0480)
+#define LPASS_CDC_WSA_RX1_RX_PATH_CFG0		(WSA_START_OFFSET + 0x0484)
+#define LPASS_CDC_WSA_RX1_RX_PATH_CFG1		(WSA_START_OFFSET + 0x0488)
+#define LPASS_CDC_WSA_RX1_RX_PATH_CFG2		(WSA_START_OFFSET + 0x048C)
+#define LPASS_CDC_WSA_RX1_RX_PATH_CFG3		(WSA_START_OFFSET + 0x0490)
+#define LPASS_CDC_WSA_RX1_RX_VOL_CTL		(WSA_START_OFFSET + 0x0494)
+#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL	(WSA_START_OFFSET + 0x0498)
+#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG	(WSA_START_OFFSET + 0x049C)
+#define LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL	(WSA_START_OFFSET + 0x04A0)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC0		(WSA_START_OFFSET + 0x04A4)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC1		(WSA_START_OFFSET + 0x04A8)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC2		(WSA_START_OFFSET + 0x04AC)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC3		(WSA_START_OFFSET + 0x04B0)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC5		(WSA_START_OFFSET + 0x04B8)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC6		(WSA_START_OFFSET + 0x04BC)
+#define LPASS_CDC_WSA_RX1_RX_PATH_SEC7		(WSA_START_OFFSET + 0x04C0)
+#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0	(WSA_START_OFFSET + 0x04C4)
+#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1	(WSA_START_OFFSET + 0x04C8)
+#define LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL	(WSA_START_OFFSET + 0x04CC)
+#define LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL	(WSA_START_OFFSET + 0x0500)
+#define LPASS_CDC_WSA_BOOST0_BOOST_CTL		(WSA_START_OFFSET + 0x0504)
+#define LPASS_CDC_WSA_BOOST0_BOOST_CFG1	(WSA_START_OFFSET + 0x0508)
+#define LPASS_CDC_WSA_BOOST0_BOOST_CFG2	(WSA_START_OFFSET + 0x050C)
+#define LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL	(WSA_START_OFFSET + 0x0540)
+#define LPASS_CDC_WSA_BOOST1_BOOST_CTL		(WSA_START_OFFSET + 0x0544)
+#define LPASS_CDC_WSA_BOOST1_BOOST_CFG1	(WSA_START_OFFSET + 0x0548)
+#define LPASS_CDC_WSA_BOOST1_BOOST_CFG2	(WSA_START_OFFSET + 0x054C)
+#define LPASS_CDC_WSA_COMPANDER0_CTL0		(WSA_START_OFFSET + 0x0580)
+#define LPASS_CDC_WSA_COMPANDER0_CTL1		(WSA_START_OFFSET + 0x0584)
+#define LPASS_CDC_WSA_COMPANDER0_CTL2		(WSA_START_OFFSET + 0x0588)
+#define LPASS_CDC_WSA_COMPANDER0_CTL3		(WSA_START_OFFSET + 0x058C)
+#define LPASS_CDC_WSA_COMPANDER0_CTL4		(WSA_START_OFFSET + 0x0590)
+#define LPASS_CDC_WSA_COMPANDER0_CTL5		(WSA_START_OFFSET + 0x0594)
+#define LPASS_CDC_WSA_COMPANDER0_CTL6		(WSA_START_OFFSET + 0x0598)
+#define LPASS_CDC_WSA_COMPANDER0_CTL7		(WSA_START_OFFSET + 0x059C)
+#define LPASS_CDC_WSA_COMPANDER0_CTL8		(WSA_START_OFFSET + 0x05A0)
+#define LPASS_CDC_WSA_COMPANDER0_CTL9		(WSA_START_OFFSET + 0x05A4)
+#define LPASS_CDC_WSA_COMPANDER0_CTL10		(WSA_START_OFFSET + 0x05A8)
+#define LPASS_CDC_WSA_COMPANDER0_CTL11		(WSA_START_OFFSET + 0x05AC)
+#define LPASS_CDC_WSA_COMPANDER0_CTL12		(WSA_START_OFFSET + 0x05B0)
+#define LPASS_CDC_WSA_COMPANDER0_CTL13		(WSA_START_OFFSET + 0x05B4)
+#define LPASS_CDC_WSA_COMPANDER0_CTL14		(WSA_START_OFFSET + 0x05B8)
+#define LPASS_CDC_WSA_COMPANDER0_CTL15		(WSA_START_OFFSET + 0x05BC)
+#define LPASS_CDC_WSA_COMPANDER0_CTL16		(WSA_START_OFFSET + 0x05C0)
+#define LPASS_CDC_WSA_COMPANDER0_CTL17		(WSA_START_OFFSET + 0x05C4)
+#define LPASS_CDC_WSA_COMPANDER0_CTL18		(WSA_START_OFFSET + 0x05C8)
+#define LPASS_CDC_WSA_COMPANDER0_CTL19		(WSA_START_OFFSET + 0x05CC)
+#define LPASS_CDC_WSA_COMPANDER1_CTL0		(WSA_START_OFFSET + 0x05E0)
+#define LPASS_CDC_WSA_COMPANDER1_CTL1		(WSA_START_OFFSET + 0x05E4)
+#define LPASS_CDC_WSA_COMPANDER1_CTL2		(WSA_START_OFFSET + 0x05E8)
+#define LPASS_CDC_WSA_COMPANDER1_CTL3		(WSA_START_OFFSET + 0x05EC)
+#define LPASS_CDC_WSA_COMPANDER1_CTL4		(WSA_START_OFFSET + 0x05F0)
+#define LPASS_CDC_WSA_COMPANDER1_CTL5		(WSA_START_OFFSET + 0x05F4)
+#define LPASS_CDC_WSA_COMPANDER1_CTL6		(WSA_START_OFFSET + 0x05F8)
+#define LPASS_CDC_WSA_COMPANDER1_CTL7		(WSA_START_OFFSET + 0x05FC)
+#define LPASS_CDC_WSA_COMPANDER1_CTL8		(WSA_START_OFFSET + 0x0600)
+#define LPASS_CDC_WSA_COMPANDER1_CTL9		(WSA_START_OFFSET + 0x0604)
+#define LPASS_CDC_WSA_COMPANDER1_CTL10		(WSA_START_OFFSET + 0x0608)
+#define LPASS_CDC_WSA_COMPANDER1_CTL11		(WSA_START_OFFSET + 0x060C)
+#define LPASS_CDC_WSA_COMPANDER1_CTL12		(WSA_START_OFFSET + 0x0610)
+#define LPASS_CDC_WSA_COMPANDER1_CTL13		(WSA_START_OFFSET + 0x0614)
+#define LPASS_CDC_WSA_COMPANDER1_CTL14		(WSA_START_OFFSET + 0x0618)
+#define LPASS_CDC_WSA_COMPANDER1_CTL15		(WSA_START_OFFSET + 0x061C)
+#define LPASS_CDC_WSA_COMPANDER1_CTL16		(WSA_START_OFFSET + 0x0620)
+#define LPASS_CDC_WSA_COMPANDER1_CTL17		(WSA_START_OFFSET + 0x0624)
+#define LPASS_CDC_WSA_COMPANDER1_CTL18		(WSA_START_OFFSET + 0x0628)
+#define LPASS_CDC_WSA_COMPANDER1_CTL19		(WSA_START_OFFSET + 0x062C)
+#define LPASS_CDC_WSA_SOFTCLIP0_CRC		(WSA_START_OFFSET + 0x0640)
+#define LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL	(WSA_START_OFFSET + 0x0644)
+#define LPASS_CDC_WSA_SOFTCLIP1_CRC		(WSA_START_OFFSET + 0x0660)
+#define LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL	(WSA_START_OFFSET + 0x0664)
+#define LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL \
+						(WSA_START_OFFSET + 0x0680)
+#define LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0	(WSA_START_OFFSET + 0x0684)
+#define LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL \
+						(WSA_START_OFFSET + 0x06C0)
+#define LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0	(WSA_START_OFFSET + 0x06C4)
+#define LPASS_CDC_WSA_IDLE_DETECT_PATH_CTL	(WSA_START_OFFSET + 0x0780)
+#define LPASS_CDC_WSA_IDLE_DETECT_CFG0		(WSA_START_OFFSET + 0x0784)
+#define LPASS_CDC_WSA_IDLE_DETECT_CFG1		(WSA_START_OFFSET + 0x0788)
+#define LPASS_CDC_WSA_IDLE_DETECT_CFG2		(WSA_START_OFFSET + 0x078C)
+#define LPASS_CDC_WSA_IDLE_DETECT_CFG3		(WSA_START_OFFSET + 0x0790)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL1	(WSA_START_OFFSET + 0x0900)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL2	(WSA_START_OFFSET + 0x0904)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL3	(WSA_START_OFFSET + 0x0908)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG1	(WSA_START_OFFSET + 0x090C)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG2	(WSA_START_OFFSET + 0x0910)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG3	(WSA_START_OFFSET + 0x0914)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG4	(WSA_START_OFFSET + 0x0918)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG5	(WSA_START_OFFSET + 0x091C)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG6	(WSA_START_OFFSET + 0x0920)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG7	(WSA_START_OFFSET + 0x0924)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG8	(WSA_START_OFFSET + 0x0928)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST1 \
+						(WSA_START_OFFSET + 0x092C)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST2 \
+						(WSA_START_OFFSET + 0x0930)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST3 \
+						(WSA_START_OFFSET + 0x0934)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST4 \
+						(WSA_START_OFFSET + 0x0938)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST1	(WSA_START_OFFSET + 0x093C)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST2	(WSA_START_OFFSET + 0x0940)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST3	(WSA_START_OFFSET + 0x0944)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST4	(WSA_START_OFFSET + 0x0948)
+#define LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST5	(WSA_START_OFFSET + 0x094C)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_PATH_CTL	(WSA_START_OFFSET + 0x0980)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_CFG	(WSA_START_OFFSET + 0x0984)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL1	(WSA_START_OFFSET + 0x0988)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL2	(WSA_START_OFFSET + 0x098C)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL3	(WSA_START_OFFSET + 0x0990)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST1	(WSA_START_OFFSET + 0x0994)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST2	(WSA_START_OFFSET + 0x0998)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST3	(WSA_START_OFFSET + 0x099C)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC1	(WSA_START_OFFSET + 0x09A0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC2	(WSA_START_OFFSET + 0x09A4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC1	(WSA_START_OFFSET + 0x09A8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC2	(WSA_START_OFFSET + 0x09AC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC3	(WSA_START_OFFSET + 0x09B0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC4	(WSA_START_OFFSET + 0x09B4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD1	(WSA_START_OFFSET + 0x09B8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD2	(WSA_START_OFFSET + 0x09BC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD3	(WSA_START_OFFSET + 0x09C0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD4	(WSA_START_OFFSET + 0x09C4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD5	(WSA_START_OFFSET + 0x09C8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_DEBUG1	(WSA_START_OFFSET + 0x09CC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD_MON \
+						(WSA_START_OFFSET + 0x09D0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_MON_VAL \
+						(WSA_START_OFFSET + 0x09D4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BAN	(WSA_START_OFFSET + 0x09D8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD1 \
+						(WSA_START_OFFSET + 0x09DC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD2 \
+						(WSA_START_OFFSET + 0x09E0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD3 \
+						(WSA_START_OFFSET + 0x09E4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD4 \
+						(WSA_START_OFFSET + 0x09E8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD5 \
+						(WSA_START_OFFSET + 0x09EC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD6 \
+						(WSA_START_OFFSET + 0x09F0)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD7 \
+						(WSA_START_OFFSET + 0x09F4)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD8 \
+						(WSA_START_OFFSET + 0x09F8)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD9 \
+						(WSA_START_OFFSET + 0x09FC)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN1	(WSA_START_OFFSET + 0x0A00)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN2	(WSA_START_OFFSET + 0x0A04)
+#define LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN3	(WSA_START_OFFSET + 0x0A08)
+/* lpass 2.6 new registers */
+#define LPASS_CDC_WSA_PBR_PATH_CTL	(WSA_START_OFFSET + 0xB00)
+#define LPASS_CDC_WSA_LA_CFG	(WSA_START_OFFSET + 0xB04)
+#define LPASS_CDC_WSA_PBR_CFG1	(WSA_START_OFFSET + 0xB08)
+#define LPASS_CDC_WSA_PBR_CFG2	(WSA_START_OFFSET + 0xB0C)
+#define LPASS_CDC_WSA_PBR_CFG3	(WSA_START_OFFSET + 0xB10)
+#define LPASS_CDC_WSA_PBR_CFG4	(WSA_START_OFFSET + 0xB14)
+#define LPASS_CDC_WSA_PBR_CFG5	(WSA_START_OFFSET + 0xB18)
+#define LPASS_CDC_WSA_PBR_CFG6	(WSA_START_OFFSET + 0xB1C)
+#define LPASS_CDC_WSA_PBR_CFG7	(WSA_START_OFFSET + 0xB20)
+#define LPASS_CDC_WSA_PBR_CFG8	(WSA_START_OFFSET + 0xB24)
+#define LPASS_CDC_WSA_PBR_CFG9	(WSA_START_OFFSET + 0xB28)
+#define LPASS_CDC_WSA_PBR_CFG10	(WSA_START_OFFSET + 0xB2C)
+#define LPASS_CDC_WSA_PBR_CFG11	(WSA_START_OFFSET + 0xB30)
+#define LPASS_CDC_WSA_PBR_CFG12	(WSA_START_OFFSET + 0xB34)
+#define LPASS_CDC_WSA_PBR_CFG13	(WSA_START_OFFSET + 0xB38)
+#define LPASS_CDC_WSA_PBR_CFG14	(WSA_START_OFFSET + 0xB3C)
+#define LPASS_CDC_WSA_PBR_CFG15	(WSA_START_OFFSET + 0xB40)
+#define LPASS_CDC_WSA_PBR_CFG16	(WSA_START_OFFSET + 0xB44)
+#define LPASS_CDC_WSA_PBR_CFG17	(WSA_START_OFFSET + 0xB48)
+#define LPASS_CDC_WSA_ILIM_CFG0	(WSA_START_OFFSET + 0xB4C)
+#define LPASS_CDC_WSA_ILIM_CFG1	(WSA_START_OFFSET + 0xB50)
+#define LPASS_CDC_WSA_ILIM_CFG2	(WSA_START_OFFSET + 0xB54)
+#define LPASS_CDC_WSA_ILIM_CFG3	(WSA_START_OFFSET + 0xB58)
+#define LPASS_CDC_WSA_ILIM_CFG4	(WSA_START_OFFSET + 0xB5C)
+#define LPASS_CDC_WSA_ILIM_CFG5	(WSA_START_OFFSET + 0xB60)
+#define LPASS_CDC_WSA_ILIM_CFG6	(WSA_START_OFFSET + 0xB64)
+#define LPASS_CDC_WSA_ILIM_CFG7	(WSA_START_OFFSET + 0xB68)
+#define LPASS_CDC_WSA_ILIM_CFG8	(WSA_START_OFFSET + 0xB6C)
+#define LPASS_CDC_WSA_LA_CFG_1	(WSA_START_OFFSET + 0xB70)
+#define LPASS_CDC_WSA_PBR_CFG1_1	(WSA_START_OFFSET + 0xB74)
+#define LPASS_CDC_WSA_PBR_CFG2_1	(WSA_START_OFFSET + 0xB78)
+#define LPASS_CDC_WSA_PBR_CFG3_1	(WSA_START_OFFSET + 0xB7C)
+#define LPASS_CDC_WSA_PBR_CFG4_1	(WSA_START_OFFSET + 0xB80)
+#define LPASS_CDC_WSA_PBR_CFG5_1	(WSA_START_OFFSET + 0xB84)
+#define LPASS_CDC_WSA_PBR_CFG6_1	(WSA_START_OFFSET + 0xB88)
+#define LPASS_CDC_WSA_PBR_CFG7_1	(WSA_START_OFFSET + 0xB8C)
+#define LPASS_CDC_WSA_PBR_CFG8_1	(WSA_START_OFFSET + 0xB90)
+#define LPASS_CDC_WSA_PBR_CFG9_1	(WSA_START_OFFSET + 0xB94)
+#define LPASS_CDC_WSA_PBR_CFG10_1	(WSA_START_OFFSET + 0xB98)
+#define LPASS_CDC_WSA_PBR_CFG11_1	(WSA_START_OFFSET + 0xB9C)
+#define LPASS_CDC_WSA_PBR_CFG12_1	(WSA_START_OFFSET + 0xBA0)
+#define LPASS_CDC_WSA_PBR_CFG13_1	(WSA_START_OFFSET + 0xBA4)
+#define LPASS_CDC_WSA_PBR_CFG14_1	(WSA_START_OFFSET + 0xBA8)
+#define LPASS_CDC_WSA_PBR_CFG15_1	(WSA_START_OFFSET + 0xBAC)
+#define LPASS_CDC_WSA_PBR_CFG16_1	(WSA_START_OFFSET + 0xBB0)
+#define LPASS_CDC_WSA_ILIM_CFG0_1	(WSA_START_OFFSET + 0xBB4)
+#define LPASS_CDC_WSA_ILIM_CFG1_1	(WSA_START_OFFSET + 0xBB8)
+#define LPASS_CDC_WSA_ILIM_CFG2_1	(WSA_START_OFFSET + 0xBBC)
+#define LPASS_CDC_WSA_ILIM_CFG5_1	(WSA_START_OFFSET + 0xBC0)
+#define LPASS_CDC_WSA_ILIM_CFG9	(WSA_START_OFFSET + 0xBC4)
+#define LPASS_CDC_WSA_ILIM_CFG6_1	(WSA_START_OFFSET + 0xBC8)
+#define LPASS_CDC_WSA_PBR_CFG18	(WSA_START_OFFSET + 0xBCC)
+#define LPASS_CDC_WSA_PBR_CFG18_1	(WSA_START_OFFSET + 0xBD0)
+#define LPASS_CDC_WSA_PBR_CFG19	(WSA_START_OFFSET + 0xBD4)
+#define LPASS_CDC_WSA_PBR_CFG20	(WSA_START_OFFSET + 0xBD8)
+#define LPASS_CDC_WSA_PBR_CFG21	(WSA_START_OFFSET + 0xBDC)
+#define LPASS_CDC_WSA_PBR_CFG22	(WSA_START_OFFSET + 0xBE0)
+#define LPASS_CDC_WSA_PBR_CFG23	(WSA_START_OFFSET + 0xBE4)
+#define WSA_MAX_OFFSET				(WSA_START_OFFSET + 0xBE4)
+
+#define LPASS_CDC_WSA_MACRO_MAX 0x2FA /* 0xBE4/4 = 0x2F9 + 1 registers */
+
+/* VA macro registers */
+#define VA_START_OFFSET				0x3000
+#define LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL	(VA_START_OFFSET + 0x0000)
+#define LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(VA_START_OFFSET + 0x0004)
+#define LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL	(VA_START_OFFSET + 0x0008)
+#define LPASS_CDC_VA_TOP_CSR_TOP_CFG0		(VA_START_OFFSET + 0x0080)
+#define LPASS_CDC_VA_TOP_CSR_DMIC0_CTL		(VA_START_OFFSET + 0x0084)
+#define LPASS_CDC_VA_TOP_CSR_DMIC1_CTL		(VA_START_OFFSET + 0x0088)
+#define LPASS_CDC_VA_TOP_CSR_DMIC2_CTL		(VA_START_OFFSET + 0x008C)
+#define LPASS_CDC_VA_TOP_CSR_DMIC3_CTL		(VA_START_OFFSET + 0x0090)
+#define LPASS_CDC_VA_TOP_CSR_DMIC_CFG		(VA_START_OFFSET + 0x0094)
+#define LPASS_CDC_VA_TOP_CSR_VAD_MUX		(VA_START_OFFSET + 0x0098)
+#define LPASS_CDC_VA_TOP_CSR_DEBUG_BUS		(VA_START_OFFSET + 0x009C)
+#define LPASS_CDC_VA_TOP_CSR_DEBUG_EN		(VA_START_OFFSET + 0x00A0)
+#define LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL		(VA_START_OFFSET + 0x00A4)
+#define LPASS_CDC_VA_TOP_CSR_I2S_CLK		(VA_START_OFFSET + 0x00A8)
+#define LPASS_CDC_VA_TOP_CSR_I2S_RESET		(VA_START_OFFSET + 0x00AC)
+#define LPASS_CDC_VA_TOP_CSR_DEBUG_CLK		(VA_START_OFFSET + 0x00B0)
+#define LPASS_CDC_VA_TOP_CSR_CORE_ID_0		(VA_START_OFFSET + 0x00C0)
+#define LPASS_CDC_VA_TOP_CSR_CORE_ID_1		(VA_START_OFFSET + 0x00C4)
+#define LPASS_CDC_VA_TOP_CSR_CORE_ID_2		(VA_START_OFFSET + 0x00C8)
+#define LPASS_CDC_VA_TOP_CSR_CORE_ID_3		(VA_START_OFFSET + 0x00CC)
+#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0	(VA_START_OFFSET + 0x00D0)
+#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1	(VA_START_OFFSET + 0x00D4)
+#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2	(VA_START_OFFSET + 0x00D8)
+#define LPASS_CDC_VA_TOP_CSR_SWR_CTRL		(VA_START_OFFSET + 0x00DC)
+#define LPASS_CDC_VA_TOP_CSR_SEQ_CTL0		(VA_START_OFFSET + 0x00E0)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0	(VA_START_OFFSET + 0x0100)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1	(VA_START_OFFSET + 0x0104)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0	(VA_START_OFFSET + 0x0108)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1	(VA_START_OFFSET + 0x010C)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0	(VA_START_OFFSET + 0x0110)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1	(VA_START_OFFSET + 0x0114)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0	(VA_START_OFFSET + 0x0118)
+#define LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1	(VA_START_OFFSET + 0x011C)
+#define LPASS_CDC_VA_TX0_TX_PATH_CTL	(VA_START_OFFSET + 0x0400)
+#define LPASS_CDC_VA_TX0_TX_PATH_CFG0	(VA_START_OFFSET + 0x0404)
+#define LPASS_CDC_VA_TX0_TX_PATH_CFG1	(VA_START_OFFSET + 0x0408)
+#define LPASS_CDC_VA_TX0_TX_VOL_CTL	(VA_START_OFFSET + 0x040C)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC0	(VA_START_OFFSET + 0x0410)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC1	(VA_START_OFFSET + 0x0414)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC2	(VA_START_OFFSET + 0x0418)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC3	(VA_START_OFFSET + 0x041C)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC4	(VA_START_OFFSET + 0x0420)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC5	(VA_START_OFFSET + 0x0424)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC6	(VA_START_OFFSET + 0x0428)
+#define LPASS_CDC_VA_TX0_TX_PATH_SEC7	(VA_START_OFFSET + 0x042C)
+#define LPASS_CDC_VA_TX1_TX_PATH_CTL	(VA_START_OFFSET + 0x0480)
+#define LPASS_CDC_VA_TX1_TX_PATH_CFG0	(VA_START_OFFSET + 0x0484)
+#define LPASS_CDC_VA_TX1_TX_PATH_CFG1	(VA_START_OFFSET + 0x0488)
+#define LPASS_CDC_VA_TX1_TX_VOL_CTL	(VA_START_OFFSET + 0x048C)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC0	(VA_START_OFFSET + 0x0490)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC1	(VA_START_OFFSET + 0x0494)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC2	(VA_START_OFFSET + 0x0498)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC3	(VA_START_OFFSET + 0x049C)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC4	(VA_START_OFFSET + 0x04A0)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC5	(VA_START_OFFSET + 0x04A4)
+#define LPASS_CDC_VA_TX1_TX_PATH_SEC6	(VA_START_OFFSET + 0x04A8)
+#define LPASS_CDC_VA_TX2_TX_PATH_CTL	(VA_START_OFFSET + 0x0500)
+#define LPASS_CDC_VA_TX2_TX_PATH_CFG0	(VA_START_OFFSET + 0x0504)
+#define LPASS_CDC_VA_TX2_TX_PATH_CFG1	(VA_START_OFFSET + 0x0508)
+#define LPASS_CDC_VA_TX2_TX_VOL_CTL	(VA_START_OFFSET + 0x050C)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC0	(VA_START_OFFSET + 0x0510)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC1	(VA_START_OFFSET + 0x0514)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC2	(VA_START_OFFSET + 0x0518)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC3	(VA_START_OFFSET + 0x051C)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC4	(VA_START_OFFSET + 0x0520)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC5	(VA_START_OFFSET + 0x0524)
+#define LPASS_CDC_VA_TX2_TX_PATH_SEC6	(VA_START_OFFSET + 0x0528)
+#define LPASS_CDC_VA_TX3_TX_PATH_CTL	(VA_START_OFFSET + 0x0580)
+#define LPASS_CDC_VA_TX3_TX_PATH_CFG0	(VA_START_OFFSET + 0x0584)
+#define LPASS_CDC_VA_TX3_TX_PATH_CFG1	(VA_START_OFFSET + 0x0588)
+#define LPASS_CDC_VA_TX3_TX_VOL_CTL	(VA_START_OFFSET + 0x058C)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC0	(VA_START_OFFSET + 0x0590)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC1	(VA_START_OFFSET + 0x0594)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC2	(VA_START_OFFSET + 0x0598)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC3	(VA_START_OFFSET + 0x059C)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC4	(VA_START_OFFSET + 0x05A0)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC5	(VA_START_OFFSET + 0x05A4)
+#define LPASS_CDC_VA_TX3_TX_PATH_SEC6	(VA_START_OFFSET + 0x05A8)
+#define VA_MAX_OFFSET			(VA_START_OFFSET + 0x05A8)
+
+#define LPASS_CDC_VA_MACRO_MAX 0x16B /* 5A8/4 = 16A + 1 = 16B */
+
+/* WSA2 - macro#5 */
+#define WSA2_START_OFFSET			0x4000
+#define LPASS_CDC_WSA2_CLK_RST_CTRL_MCLK_CONTROL \
+						(WSA2_START_OFFSET + 0x0000)
+#define LPASS_CDC_WSA2_CLK_RST_CTRL_FS_CNT_CONTROL \
+						(WSA2_START_OFFSET + 0x0004)
+#define LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL	(WSA2_START_OFFSET + 0x0008)
+#define LPASS_CDC_WSA2_TOP_TOP_CFG0		(WSA2_START_OFFSET + 0x0080)
+#define LPASS_CDC_WSA2_TOP_TOP_CFG1		(WSA2_START_OFFSET + 0x0084)
+#define LPASS_CDC_WSA2_TOP_FREQ_MCLK		(WSA2_START_OFFSET + 0x0088)
+#define LPASS_CDC_WSA2_TOP_DEBUG_BUS_SEL	(WSA2_START_OFFSET + 0x008C)
+#define LPASS_CDC_WSA2_TOP_DEBUG_EN0		(WSA2_START_OFFSET + 0x0090)
+#define LPASS_CDC_WSA2_TOP_DEBUG_EN1		(WSA2_START_OFFSET + 0x0094)
+#define LPASS_CDC_WSA2_TOP_DEBUG_DSM_LB		(WSA2_START_OFFSET + 0x0098)
+#define LPASS_CDC_WSA2_TOP_RX_I2S_CTL		(WSA2_START_OFFSET + 0x009C)
+#define LPASS_CDC_WSA2_TOP_TX_I2S_CTL		(WSA2_START_OFFSET + 0x00A0)
+#define LPASS_CDC_WSA2_TOP_I2S_CLK		(WSA2_START_OFFSET + 0x00A4)
+#define LPASS_CDC_WSA2_TOP_I2S_RESET		(WSA2_START_OFFSET + 0x00A8)
+#define LPASS_CDC_WSA2_TOP_FS_UNGATE		(WSA2_START_OFFSET + 0x00AC)
+#define LPASS_CDC_WSA2_TOP_GRP_SEL		(WSA2_START_OFFSET + 0x00B0)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_LSB	(WSA2_START_OFFSET + 0x00B4)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_MSB	(WSA2_START_OFFSET + 0x00B8)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP7_LUT	(WSA2_START_OFFSET + 0x00BC)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_LSB	(WSA2_START_OFFSET + 0x00C0)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_MSB	(WSA2_START_OFFSET + 0x00C4)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_LSB	(WSA2_START_OFFSET + 0x00C8)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_MSB	(WSA2_START_OFFSET + 0x00CC)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP8_LUT	(WSA2_START_OFFSET + 0x00D0)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_LSB	(WSA2_START_OFFSET + 0x00D4)
+#define LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_MSB	(WSA2_START_OFFSET + 0x00D8)
+#define LPASS_CDC_WSA2_TOP_FS_UNGATE2		(WSA2_START_OFFSET + 0x00DC)
+#define LPASS_CDC_WSA2_TOP_SEQ_CTL0		(WSA2_START_OFFSET + 0x00E0)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0	(WSA2_START_OFFSET + 0x0100)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1	(WSA2_START_OFFSET + 0x0104)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0	(WSA2_START_OFFSET + 0x0108)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1	(WSA2_START_OFFSET + 0x010C)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0	(WSA2_START_OFFSET + 0x0110)
+#define LPASS_CDC_WSA2_RX_INP_MUX_RX_EC_CFG0	(WSA2_START_OFFSET + 0x0114)
+#define LPASS_CDC_WSA2_RX_INP_MUX_SOFTCLIP_CFG0	(WSA2_START_OFFSET + 0x0118)
+/* VBAT registers  */
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_PATH_CTL	(WSA2_START_OFFSET + 0x0180)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG	(WSA2_START_OFFSET + 0x0184)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL1	(WSA2_START_OFFSET + 0x0188)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL2	(WSA2_START_OFFSET + 0x018C)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL3	(WSA2_START_OFFSET + 0x0190)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST1	(WSA2_START_OFFSET + 0x0194)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST2	(WSA2_START_OFFSET + 0x0198)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST3	(WSA2_START_OFFSET + 0x019C)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC1	(WSA2_START_OFFSET + 0x01A0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC2	(WSA2_START_OFFSET + 0x01A4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC1	(WSA2_START_OFFSET + 0x01A8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC2	(WSA2_START_OFFSET + 0x01AC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC3	(WSA2_START_OFFSET + 0x01B0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC4	(WSA2_START_OFFSET + 0x01B4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD1	(WSA2_START_OFFSET + 0x01B8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD2	(WSA2_START_OFFSET + 0x01BC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD3	(WSA2_START_OFFSET + 0x01C0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD4	(WSA2_START_OFFSET + 0x01C4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD5	(WSA2_START_OFFSET + 0x01C8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_DEBUG1	(WSA2_START_OFFSET + 0x01CC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD_MON \
+						(WSA2_START_OFFSET + 0x01D0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_MON_VAL \
+						(WSA2_START_OFFSET + 0x01D4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BAN	(WSA2_START_OFFSET + 0x01D8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD1 \
+						(WSA2_START_OFFSET + 0x01DC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD2 \
+						(WSA2_START_OFFSET + 0x01E0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD3 \
+						(WSA2_START_OFFSET + 0x01E4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD4 \
+						(WSA2_START_OFFSET + 0x01E8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD5 \
+						(WSA2_START_OFFSET + 0x01EC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD6 \
+						(WSA2_START_OFFSET + 0x01F0)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD7 \
+						(WSA2_START_OFFSET + 0x01F4)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD8 \
+						(WSA2_START_OFFSET + 0x01F8)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9 \
+						(WSA2_START_OFFSET + 0x01FC)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN1	(WSA2_START_OFFSET + 0x0200)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN2	(WSA2_START_OFFSET + 0x0204)
+#define LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN3	(WSA2_START_OFFSET + 0x0208)
+#define LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL	(WSA2_START_OFFSET + 0x0244)
+#define LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CFG0	(WSA2_START_OFFSET + 0x0248)
+#define LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL	(WSA2_START_OFFSET + 0x0264)
+#define LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0	(WSA2_START_OFFSET + 0x0268)
+#define LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL	(WSA2_START_OFFSET + 0x0284)
+#define LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0	(WSA2_START_OFFSET + 0x0288)
+#define LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL	(WSA2_START_OFFSET + 0x02A4)
+#define LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0	(WSA2_START_OFFSET + 0x02A8)
+#define LPASS_CDC_WSA2_INTR_CTRL_CFG		(WSA2_START_OFFSET + 0x0340)
+#define LPASS_CDC_WSA2_INTR_CTRL_CLR_COMMIT	(WSA2_START_OFFSET + 0x0344)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN1_MASK0	(WSA2_START_OFFSET + 0x0360)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN1_STATUS0	(WSA2_START_OFFSET + 0x0368)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN1_CLEAR0	(WSA2_START_OFFSET + 0x0370)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN2_MASK0	(WSA2_START_OFFSET + 0x0380)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN2_STATUS0	(WSA2_START_OFFSET + 0x0388)
+#define LPASS_CDC_WSA2_INTR_CTRL_PIN2_CLEAR0	(WSA2_START_OFFSET + 0x0390)
+#define LPASS_CDC_WSA2_INTR_CTRL_LEVEL0		(WSA2_START_OFFSET + 0x03C0)
+#define LPASS_CDC_WSA2_INTR_CTRL_BYPASS0	(WSA2_START_OFFSET + 0x03C8)
+#define LPASS_CDC_WSA2_INTR_CTRL_SET0		(WSA2_START_OFFSET + 0x03D0)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_CTL		(WSA2_START_OFFSET + 0x0400)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_CFG0		(WSA2_START_OFFSET + 0x0404)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_CFG1		(WSA2_START_OFFSET + 0x0408)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_CFG2		(WSA2_START_OFFSET + 0x040C)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_CFG3		(WSA2_START_OFFSET + 0x0410)
+#define LPASS_CDC_WSA2_RX0_RX_VOL_CTL		(WSA2_START_OFFSET + 0x0414)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL	(WSA2_START_OFFSET + 0x0418)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG	(WSA2_START_OFFSET + 0x041C)
+#define LPASS_CDC_WSA2_RX0_RX_VOL_MIX_CTL	(WSA2_START_OFFSET + 0x0420)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC0		(WSA2_START_OFFSET + 0x0424)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC1		(WSA2_START_OFFSET + 0x0428)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC2		(WSA2_START_OFFSET + 0x042C)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC3		(WSA2_START_OFFSET + 0x0430)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC5		(WSA2_START_OFFSET + 0x0438)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC6		(WSA2_START_OFFSET + 0x043C)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_SEC7		(WSA2_START_OFFSET + 0x0440)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC0	(WSA2_START_OFFSET + 0x0444)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC1	(WSA2_START_OFFSET + 0x0448)
+#define LPASS_CDC_WSA2_RX0_RX_PATH_DSMDEM_CTL	(WSA2_START_OFFSET + 0x044C)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_CTL		(WSA2_START_OFFSET + 0x0480)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_CFG0		(WSA2_START_OFFSET + 0x0484)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_CFG1		(WSA2_START_OFFSET + 0x0488)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_CFG2		(WSA2_START_OFFSET + 0x048C)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_CFG3		(WSA2_START_OFFSET + 0x0490)
+#define LPASS_CDC_WSA2_RX1_RX_VOL_CTL		(WSA2_START_OFFSET + 0x0494)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CTL	(WSA2_START_OFFSET + 0x0498)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG	(WSA2_START_OFFSET + 0x049C)
+#define LPASS_CDC_WSA2_RX1_RX_VOL_MIX_CTL	(WSA2_START_OFFSET + 0x04A0)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC0		(WSA2_START_OFFSET + 0x04A4)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC1		(WSA2_START_OFFSET + 0x04A8)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC2		(WSA2_START_OFFSET + 0x04AC)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC3		(WSA2_START_OFFSET + 0x04B0)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC5		(WSA2_START_OFFSET + 0x04B8)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC6		(WSA2_START_OFFSET + 0x04BC)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_SEC7		(WSA2_START_OFFSET + 0x04C0)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC0	(WSA2_START_OFFSET + 0x04C4)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC1	(WSA2_START_OFFSET + 0x04C8)
+#define LPASS_CDC_WSA2_RX1_RX_PATH_DSMDEM_CTL	(WSA2_START_OFFSET + 0x04CC)
+#define LPASS_CDC_WSA2_BOOST0_BOOST_PATH_CTL	(WSA2_START_OFFSET + 0x0500)
+#define LPASS_CDC_WSA2_BOOST0_BOOST_CTL		(WSA2_START_OFFSET + 0x0504)
+#define LPASS_CDC_WSA2_BOOST0_BOOST_CFG1	(WSA2_START_OFFSET + 0x0508)
+#define LPASS_CDC_WSA2_BOOST0_BOOST_CFG2	(WSA2_START_OFFSET + 0x050C)
+#define LPASS_CDC_WSA2_BOOST1_BOOST_PATH_CTL	(WSA2_START_OFFSET + 0x0540)
+#define LPASS_CDC_WSA2_BOOST1_BOOST_CTL		(WSA2_START_OFFSET + 0x0544)
+#define LPASS_CDC_WSA2_BOOST1_BOOST_CFG1	(WSA2_START_OFFSET + 0x0548)
+#define LPASS_CDC_WSA2_BOOST1_BOOST_CFG2	(WSA2_START_OFFSET + 0x054C)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL0		(WSA2_START_OFFSET + 0x0580)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL1		(WSA2_START_OFFSET + 0x0584)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL2		(WSA2_START_OFFSET + 0x0588)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL3		(WSA2_START_OFFSET + 0x058C)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL4		(WSA2_START_OFFSET + 0x0590)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL5		(WSA2_START_OFFSET + 0x0594)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL6		(WSA2_START_OFFSET + 0x0598)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL7		(WSA2_START_OFFSET + 0x059C)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL8		(WSA2_START_OFFSET + 0x05A0)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL9		(WSA2_START_OFFSET + 0x05A4)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL10		(WSA2_START_OFFSET + 0x05A8)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL11		(WSA2_START_OFFSET + 0x05AC)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL12		(WSA2_START_OFFSET + 0x05B0)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL13		(WSA2_START_OFFSET + 0x05B4)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL14		(WSA2_START_OFFSET + 0x05B8)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL15		(WSA2_START_OFFSET + 0x05BC)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL16		(WSA2_START_OFFSET + 0x05C0)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL17		(WSA2_START_OFFSET + 0x05C4)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL18		(WSA2_START_OFFSET + 0x05C8)
+#define LPASS_CDC_WSA2_COMPANDER0_CTL19		(WSA2_START_OFFSET + 0x05CC)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL0		(WSA2_START_OFFSET + 0x05E0)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL1		(WSA2_START_OFFSET + 0x05E4)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL2		(WSA2_START_OFFSET + 0x05E8)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL3		(WSA2_START_OFFSET + 0x05EC)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL4		(WSA2_START_OFFSET + 0x05F0)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL5		(WSA2_START_OFFSET + 0x05F4)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL6		(WSA2_START_OFFSET + 0x05F8)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL7		(WSA2_START_OFFSET + 0x05FC)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL8		(WSA2_START_OFFSET + 0x0600)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL9		(WSA2_START_OFFSET + 0x0604)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL10		(WSA2_START_OFFSET + 0x0608)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL11		(WSA2_START_OFFSET + 0x060C)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL12		(WSA2_START_OFFSET + 0x0610)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL13		(WSA2_START_OFFSET + 0x0614)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL14		(WSA2_START_OFFSET + 0x0618)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL15		(WSA2_START_OFFSET + 0x061C)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL16		(WSA2_START_OFFSET + 0x0620)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL17		(WSA2_START_OFFSET + 0x0624)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL18		(WSA2_START_OFFSET + 0x0628)
+#define LPASS_CDC_WSA2_COMPANDER1_CTL19		(WSA2_START_OFFSET + 0x062C)
+#define LPASS_CDC_WSA2_SOFTCLIP0_CRC		(WSA2_START_OFFSET + 0x0640)
+#define LPASS_CDC_WSA2_SOFTCLIP0_SOFTCLIP_CTRL	(WSA2_START_OFFSET + 0x0644)
+#define LPASS_CDC_WSA2_SOFTCLIP1_CRC		(WSA2_START_OFFSET + 0x0660)
+#define LPASS_CDC_WSA2_SOFTCLIP1_SOFTCLIP_CTRL	(WSA2_START_OFFSET + 0x0664)
+#define LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_PATH_CTL \
+						(WSA2_START_OFFSET + 0x0680)
+#define LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_CFG0	(WSA2_START_OFFSET + 0x0684)
+#define LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_PATH_CTL \
+						(WSA2_START_OFFSET + 0x06C0)
+#define LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_CFG0	(WSA2_START_OFFSET + 0x06C4)
+#define LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL	(WSA2_START_OFFSET + 0x0780)
+#define LPASS_CDC_WSA2_IDLE_DETECT_CFG0		(WSA2_START_OFFSET + 0x0784)
+#define LPASS_CDC_WSA2_IDLE_DETECT_CFG1		(WSA2_START_OFFSET + 0x0788)
+#define LPASS_CDC_WSA2_IDLE_DETECT_CFG2		(WSA2_START_OFFSET + 0x078C)
+#define LPASS_CDC_WSA2_IDLE_DETECT_CFG3		(WSA2_START_OFFSET + 0x0790)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1	(WSA2_START_OFFSET + 0x0900)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2	(WSA2_START_OFFSET + 0x0904)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3	(WSA2_START_OFFSET + 0x0908)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG1	(WSA2_START_OFFSET + 0x090C)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG2	(WSA2_START_OFFSET + 0x0910)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG3	(WSA2_START_OFFSET + 0x0914)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG4	(WSA2_START_OFFSET + 0x0918)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG5	(WSA2_START_OFFSET + 0x091C)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG6	(WSA2_START_OFFSET + 0x0920)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG7	(WSA2_START_OFFSET + 0x0924)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG8	(WSA2_START_OFFSET + 0x0928)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST1 \
+						(WSA2_START_OFFSET + 0x092C)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST2 \
+						(WSA2_START_OFFSET + 0x0930)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST3 \
+						(WSA2_START_OFFSET + 0x0934)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST4 \
+						(WSA2_START_OFFSET + 0x0938)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST1	(WSA2_START_OFFSET + 0x093C)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST2	(WSA2_START_OFFSET + 0x0940)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST3	(WSA2_START_OFFSET + 0x0944)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST4	(WSA2_START_OFFSET + 0x0948)
+#define LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST5	(WSA2_START_OFFSET + 0x094C)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PATH_CTL	(WSA2_START_OFFSET + 0x0980)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_CFG	(WSA2_START_OFFSET + 0x0984)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL1	(WSA2_START_OFFSET + 0x0988)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL2	(WSA2_START_OFFSET + 0x098C)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL3	(WSA2_START_OFFSET + 0x0990)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST1	(WSA2_START_OFFSET + 0x0994)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST2	(WSA2_START_OFFSET + 0x0998)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST3	(WSA2_START_OFFSET + 0x099C)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC1	(WSA2_START_OFFSET + 0x09A0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC2	(WSA2_START_OFFSET + 0x09A4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC1	(WSA2_START_OFFSET + 0x09A8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC2	(WSA2_START_OFFSET + 0x09AC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC3	(WSA2_START_OFFSET + 0x09B0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC4	(WSA2_START_OFFSET + 0x09B4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD1	(WSA2_START_OFFSET + 0x09B8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD2	(WSA2_START_OFFSET + 0x09BC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD3	(WSA2_START_OFFSET + 0x09C0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD4	(WSA2_START_OFFSET + 0x09C4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD5	(WSA2_START_OFFSET + 0x09C8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_DEBUG1	(WSA2_START_OFFSET + 0x09CC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD_MON \
+						(WSA2_START_OFFSET + 0x09D0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_MON_VAL \
+						(WSA2_START_OFFSET + 0x09D4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BAN	(WSA2_START_OFFSET + 0x09D8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD1 \
+						(WSA2_START_OFFSET + 0x09DC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD2 \
+						(WSA2_START_OFFSET + 0x09E0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD3 \
+						(WSA2_START_OFFSET + 0x09E4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD4 \
+						(WSA2_START_OFFSET + 0x09E8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD5 \
+						(WSA2_START_OFFSET + 0x09EC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD6 \
+						(WSA2_START_OFFSET + 0x09F0)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD7 \
+						(WSA2_START_OFFSET + 0x09F4)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD8 \
+						(WSA2_START_OFFSET + 0x09F8)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD9 \
+						(WSA2_START_OFFSET + 0x09FC)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN1	(WSA2_START_OFFSET + 0x0A00)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN2	(WSA2_START_OFFSET + 0x0A04)
+#define LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN3	(WSA2_START_OFFSET + 0x0A08)
+/* lpass 2.6 new registers */
+#define LPASS_CDC_WSA2_PBR_PATH_CTL	(WSA2_START_OFFSET + 0xB00)
+#define LPASS_CDC_WSA2_LA_CFG	(WSA2_START_OFFSET + 0xB04)
+#define LPASS_CDC_WSA2_PBR_CFG1	(WSA2_START_OFFSET + 0xB08)
+#define LPASS_CDC_WSA2_PBR_CFG2	(WSA2_START_OFFSET + 0xB0C)
+#define LPASS_CDC_WSA2_PBR_CFG3	(WSA2_START_OFFSET + 0xB10)
+#define LPASS_CDC_WSA2_PBR_CFG4	(WSA2_START_OFFSET + 0xB14)
+#define LPASS_CDC_WSA2_PBR_CFG5	(WSA2_START_OFFSET + 0xB18)
+#define LPASS_CDC_WSA2_PBR_CFG6	(WSA2_START_OFFSET + 0xB1C)
+#define LPASS_CDC_WSA2_PBR_CFG7	(WSA2_START_OFFSET + 0xB20)
+#define LPASS_CDC_WSA2_PBR_CFG8	(WSA2_START_OFFSET + 0xB24)
+#define LPASS_CDC_WSA2_PBR_CFG9	(WSA2_START_OFFSET + 0xB28)
+#define LPASS_CDC_WSA2_PBR_CFG10	(WSA2_START_OFFSET + 0xB2C)
+#define LPASS_CDC_WSA2_PBR_CFG11	(WSA2_START_OFFSET + 0xB30)
+#define LPASS_CDC_WSA2_PBR_CFG12	(WSA2_START_OFFSET + 0xB34)
+#define LPASS_CDC_WSA2_PBR_CFG13	(WSA2_START_OFFSET + 0xB38)
+#define LPASS_CDC_WSA2_PBR_CFG14	(WSA2_START_OFFSET + 0xB3C)
+#define LPASS_CDC_WSA2_PBR_CFG15	(WSA2_START_OFFSET + 0xB40)
+#define LPASS_CDC_WSA2_PBR_CFG16	(WSA2_START_OFFSET + 0xB44)
+#define LPASS_CDC_WSA2_PBR_CFG17	(WSA2_START_OFFSET + 0xB48)
+#define LPASS_CDC_WSA2_ILIM_CFG0	(WSA2_START_OFFSET + 0xB4C)
+#define LPASS_CDC_WSA2_ILIM_CFG1	(WSA2_START_OFFSET + 0xB50)
+#define LPASS_CDC_WSA2_ILIM_CFG2	(WSA2_START_OFFSET + 0xB54)
+#define LPASS_CDC_WSA2_ILIM_CFG3	(WSA2_START_OFFSET + 0xB58)
+#define LPASS_CDC_WSA2_ILIM_CFG4	(WSA2_START_OFFSET + 0xB5C)
+#define LPASS_CDC_WSA2_ILIM_CFG5	(WSA2_START_OFFSET + 0xB60)
+#define LPASS_CDC_WSA2_ILIM_CFG6	(WSA2_START_OFFSET + 0xB64)
+#define LPASS_CDC_WSA2_ILIM_CFG7	(WSA2_START_OFFSET + 0xB68)
+#define LPASS_CDC_WSA2_ILIM_CFG8	(WSA2_START_OFFSET + 0xB6C)
+#define LPASS_CDC_WSA2_LA_CFG_1	(WSA2_START_OFFSET + 0xB70)
+#define LPASS_CDC_WSA2_PBR_CFG1_1	(WSA2_START_OFFSET + 0xB74)
+#define LPASS_CDC_WSA2_PBR_CFG2_1	(WSA2_START_OFFSET + 0xB78)
+#define LPASS_CDC_WSA2_PBR_CFG3_1	(WSA2_START_OFFSET + 0xB7C)
+#define LPASS_CDC_WSA2_PBR_CFG4_1	(WSA2_START_OFFSET + 0xB80)
+#define LPASS_CDC_WSA2_PBR_CFG5_1	(WSA2_START_OFFSET + 0xB84)
+#define LPASS_CDC_WSA2_PBR_CFG6_1	(WSA2_START_OFFSET + 0xB88)
+#define LPASS_CDC_WSA2_PBR_CFG7_1	(WSA2_START_OFFSET + 0xB8C)
+#define LPASS_CDC_WSA2_PBR_CFG8_1	(WSA2_START_OFFSET + 0xB90)
+#define LPASS_CDC_WSA2_PBR_CFG9_1	(WSA2_START_OFFSET + 0xB94)
+#define LPASS_CDC_WSA2_PBR_CFG10_1	(WSA2_START_OFFSET + 0xB98)
+#define LPASS_CDC_WSA2_PBR_CFG11_1	(WSA2_START_OFFSET + 0xB9C)
+#define LPASS_CDC_WSA2_PBR_CFG12_1	(WSA2_START_OFFSET + 0xBA0)
+#define LPASS_CDC_WSA2_PBR_CFG13_1	(WSA2_START_OFFSET + 0xBA4)
+#define LPASS_CDC_WSA2_PBR_CFG14_1	(WSA2_START_OFFSET + 0xBA8)
+#define LPASS_CDC_WSA2_PBR_CFG15_1	(WSA2_START_OFFSET + 0xBAC)
+#define LPASS_CDC_WSA2_PBR_CFG16_1	(WSA2_START_OFFSET + 0xBB0)
+#define LPASS_CDC_WSA2_ILIM_CFG0_1	(WSA2_START_OFFSET + 0xBB4)
+#define LPASS_CDC_WSA2_ILIM_CFG1_1	(WSA2_START_OFFSET + 0xBB8)
+#define LPASS_CDC_WSA2_ILIM_CFG2_1	(WSA2_START_OFFSET + 0xBBC)
+#define LPASS_CDC_WSA2_ILIM_CFG5_1	(WSA2_START_OFFSET + 0xBC0)
+#define LPASS_CDC_WSA2_ILIM_CFG9	(WSA2_START_OFFSET + 0xBC4)
+#define LPASS_CDC_WSA2_ILIM_CFG6_1	(WSA2_START_OFFSET + 0xBC8)
+#define LPASS_CDC_WSA2_PBR_CFG18	(WSA2_START_OFFSET + 0xBCC)
+#define LPASS_CDC_WSA2_PBR_CFG18_1	(WSA2_START_OFFSET + 0xBD0)
+#define LPASS_CDC_WSA2_PBR_CFG19	(WSA2_START_OFFSET + 0xBD4)
+#define LPASS_CDC_WSA2_PBR_CFG20	(WSA2_START_OFFSET + 0xBD8)
+#define LPASS_CDC_WSA2_PBR_CFG21	(WSA2_START_OFFSET + 0xBDC)
+#define LPASS_CDC_WSA2_PBR_CFG22	(WSA2_START_OFFSET + 0xBE0)
+#define LPASS_CDC_WSA2_PBR_CFG23	(WSA2_START_OFFSET + 0xBE4)
+
+#define WSA2_MAX_OFFSET				(WSA2_START_OFFSET + 0xBE4)
+
+#define LPASS_CDC_WSA2_MACRO_MAX 0x2FA /* 0xBE4/4 = 0x2F9 + 1 registers */
+
+#define LPASS_CDC_MAX_REGISTER WSA2_MAX_OFFSET
+
+#define LPASS_CDC_REG(reg)  (((reg) & 0x0FFF)/4)
+
+#endif

+ 1401 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-regmap.c

@@ -0,0 +1,1401 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include "lpass-cdc.h"
+#include "internal.h"
+
+static const struct reg_default lpass_cdc_defaults[] = {
+	/* TX Macro */
+	{ LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+	{ LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+	{ LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_TOP_CFG0, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_ANC_CFG, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_FREQ_MCLK, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_DEBUG_BUS, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_DEBUG_EN, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_TX_TOP_CSR_I2S_CLK, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_I2S_RESET, 0x00},
+
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00},
+	{ LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00},
+	{ LPASS_CDC_TX_ANC0_CLK_RESET_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_MODE_1_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_MODE_2_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_FF_SHIFT, 0x00},
+	{ LPASS_CDC_TX_ANC0_FB_SHIFT, 0x00},
+	{ LPASS_CDC_TX_ANC0_LPF_FF_A_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_LPF_FF_B_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_LPF_FB_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_SMLPF_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00},
+	{ LPASS_CDC_TX_ANC0_FB_GAIN_CTL, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX0_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX0_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX0_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX0_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX0_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX0_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX0_TX_PATH_SEC7, 0x25},
+	{ LPASS_CDC_TX1_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX1_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX1_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX1_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX1_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX1_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX1_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX1_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX1_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX1_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX1_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX2_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX2_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX2_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX2_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX2_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX2_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX2_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX2_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX2_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX2_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX2_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX3_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX3_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX3_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX3_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX3_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX3_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX3_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX3_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX3_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX3_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX3_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX4_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX4_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX4_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX4_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX4_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX4_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX4_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX4_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX4_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX4_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX4_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX5_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX5_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX5_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX5_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX5_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX5_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX5_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX5_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX5_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX5_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX5_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX6_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX6_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX6_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX6_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX6_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX6_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX6_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX6_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX6_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX6_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX6_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_TX7_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_TX7_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_TX7_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_TX7_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_TX7_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_TX7_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_TX7_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_TX7_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_TX7_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_TX7_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_TX7_TX_PATH_SEC6, 0x00},
+#ifdef CONFIG_BOLERO_VER_2P6
+	{ LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0x60},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL, 0x0E},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL, 0x0E},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL, 0x0E},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL, 0x0E},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL, 0x0E},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL, 0x0E},
+#else
+	{ LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL, 0x00},
+	{ LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL, 0x00},
+#endif
+
+	/* RX Macro */
+	{ LPASS_CDC_RX_TOP_TOP_CFG0, 0x00},
+	{ LPASS_CDC_RX_TOP_TOP_CFG1, 0x00},
+	{ LPASS_CDC_RX_TOP_SWR_CTRL, 0x00},
+	{ LPASS_CDC_RX_TOP_DEBUG, 0x00},
+	{ LPASS_CDC_RX_TOP_DEBUG_BUS, 0x00},
+	{ LPASS_CDC_RX_TOP_DEBUG_EN0, 0x00},
+	{ LPASS_CDC_RX_TOP_DEBUG_EN1, 0x00},
+	{ LPASS_CDC_RX_TOP_DEBUG_EN2, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHL_COMP_LUT, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHR_COMP_LUT, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00},
+	{ LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00},
+	{ LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11},
+	{ LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20},
+	{ LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00},
+	{ LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11},
+	{ LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20},
+	{ LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00},
+	{ LPASS_CDC_RX_TOP_RX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_RX_TOP_TX_I2S2_CTL, 0x0C},
+	{ LPASS_CDC_RX_TOP_I2S_CLK, 0x0C},
+	{ LPASS_CDC_RX_TOP_I2S_RESET, 0x00},
+	{ LPASS_CDC_RX_TOP_I2S_MUX, 0x00},
+	{ LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00},
+	{ LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08},
+	{ LPASS_CDC_RX_SOFTCLIP_CRC, 0x00},
+	{ LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00},
+	{ LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00},
+	{ LPASS_CDC_RX_CLSH_CRC, 0x00},
+	{ LPASS_CDC_RX_CLSH_DLY_CTRL, 0x03},
+	{ LPASS_CDC_RX_CLSH_DECAY_CTRL, 0x02},
+	{ LPASS_CDC_RX_CLSH_HPH_V_PA, 0x1C},
+	{ LPASS_CDC_RX_CLSH_EAR_V_PA, 0x39},
+	{ LPASS_CDC_RX_CLSH_HPH_V_HD, 0x0C},
+	{ LPASS_CDC_RX_CLSH_EAR_V_HD, 0x0C},
+	{ LPASS_CDC_RX_CLSH_K1_MSB, 0x01},
+	{ LPASS_CDC_RX_CLSH_K1_LSB, 0x00},
+	{ LPASS_CDC_RX_CLSH_K2_MSB, 0x00},
+	{ LPASS_CDC_RX_CLSH_K2_LSB, 0x80},
+	{ LPASS_CDC_RX_CLSH_IDLE_CTRL, 0x00},
+	{ LPASS_CDC_RX_CLSH_IDLE_HPH, 0x00},
+	{ LPASS_CDC_RX_CLSH_IDLE_EAR, 0x00},
+	{ LPASS_CDC_RX_CLSH_TEST0, 0x07},
+	{ LPASS_CDC_RX_CLSH_TEST1, 0x00},
+	{ LPASS_CDC_RX_CLSH_OVR_VREF, 0x00},
+	{ LPASS_CDC_RX_CLSH_CLSG_CTL, 0x02},
+	{ LPASS_CDC_RX_CLSH_CLSG_CFG1, 0x9A},
+	{ LPASS_CDC_RX_CLSH_CLSG_CFG2, 0x10},
+	{ LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_CFG, 0x10},
+	{ LPASS_CDC_RX_BCL_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_RX_BCL_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_RX_BCL_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_RX_BCL_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_RX_BCL_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_RX_BCL_VBAT_RF_PROC2, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_RX_BCL_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_RX_BCL_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_RX_BCL_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_ATTN1, 0x04},
+	{ LPASS_CDC_RX_BCL_VBAT_ATTN2, 0x08},
+	{ LPASS_CDC_RX_BCL_VBAT_ATTN3, 0x0C},
+	{ LPASS_CDC_RX_INTR_CTRL_CFG, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_LEVEL0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_BYPASS0, 0x00},
+	{ LPASS_CDC_RX_INTR_CTRL_SET0, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CTL, 0x04},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_RX_RX0_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_RX_RX0_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_SEC4, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55},
+	{ LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CTL, 0x04},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_RX_RX1_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_RX_RX1_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_SEC4, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55},
+	{ LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CTL, 0x04},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_RX_RX2_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC0, 0x04},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC4, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00},
+	{ LPASS_CDC_RX_IDLE_DETECT_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_IDLE_DETECT_CFG0, 0x07},
+	{ LPASS_CDC_RX_IDLE_DETECT_CFG1, 0x3C},
+	{ LPASS_CDC_RX_IDLE_DETECT_CFG2, 0x00},
+	{ LPASS_CDC_RX_IDLE_DETECT_CFG3, 0x00},
+	{ LPASS_CDC_RX_COMPANDER0_CTL0, 0x60},
+	{ LPASS_CDC_RX_COMPANDER0_CTL1, 0xDB},
+	{ LPASS_CDC_RX_COMPANDER0_CTL2, 0xFF},
+	{ LPASS_CDC_RX_COMPANDER0_CTL3, 0x35},
+	{ LPASS_CDC_RX_COMPANDER0_CTL4, 0xFF},
+	{ LPASS_CDC_RX_COMPANDER0_CTL5, 0x00},
+	{ LPASS_CDC_RX_COMPANDER0_CTL6, 0x01},
+	{ LPASS_CDC_RX_COMPANDER0_CTL7, 0x28},
+	{ LPASS_CDC_RX_COMPANDER1_CTL0, 0x60},
+	{ LPASS_CDC_RX_COMPANDER1_CTL1, 0xDB},
+	{ LPASS_CDC_RX_COMPANDER1_CTL2, 0xFF},
+	{ LPASS_CDC_RX_COMPANDER1_CTL3, 0x35},
+	{ LPASS_CDC_RX_COMPANDER1_CTL4, 0xFF},
+	{ LPASS_CDC_RX_COMPANDER1_CTL5, 0x00},
+	{ LPASS_CDC_RX_COMPANDER1_CTL6, 0x01},
+	{ LPASS_CDC_RX_COMPANDER1_CTL7, 0x28},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00},
+	{ LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04},
+	{ LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00},
+	{ LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04},
+	{ LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00},
+	{ LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_CTL0, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_CTL1, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8},
+	{ LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_CTL0, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_CTL1, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8},
+	{ LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_CTL0, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_CTL1, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8},
+	{ LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00},
+	{ LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00},
+	{ LPASS_CDC_RX_DSD0_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_DSD0_CFG0, 0x00},
+	{ LPASS_CDC_RX_DSD0_CFG1, 0x62},
+	{ LPASS_CDC_RX_DSD0_CFG2, 0x96},
+	{ LPASS_CDC_RX_DSD1_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_DSD1_CFG0, 0x00},
+	{ LPASS_CDC_RX_DSD1_CFG1, 0x62},
+	{ LPASS_CDC_RX_DSD1_CFG2, 0x96},
+#ifdef CONFIG_BOLERO_VER_2P6
+	{ LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x08},
+	{ LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x08},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CFG3, 0x03},
+	{ LPASS_CDC_RX_RX0_RX_FIR_CTL, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_CFG, 0x64},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_ADDR, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA0, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA1, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA2, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA3, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA4, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA5, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA6, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA7, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CFG3, 0x03},
+	{ LPASS_CDC_RX_RX1_RX_FIR_CTL, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_CFG, 0x64},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_ADDR, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA0, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA1, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA2, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA3, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA4, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA5, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA6, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA7, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CFG3, 0x03},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL1, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL2, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL3, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG1, 0x85},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG2, 0xDC},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG3, 0x85},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG4, 0xDC},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG5, 0x85},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG6, 0xDC},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG7, 0x32},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG8, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST1, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST2, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST3, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST4, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST1, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST2, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST3, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST4, 0x00},
+	{ LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST5, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_CFG, 0x10},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC1, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN1, 0x04},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN2, 0x08},
+	{ LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN3, 0x0C},
+	{ LPASS_CDC_RX_COMPANDER0_CTL8, 0x00},
+	{ LPASS_CDC_RX_COMPANDER0_CTL9, 0x00},
+	{ LPASS_CDC_RX_COMPANDER0_CTL10, 0x06},
+	{ LPASS_CDC_RX_COMPANDER0_CTL11, 0x12},
+	{ LPASS_CDC_RX_COMPANDER0_CTL12, 0x1E},
+	{ LPASS_CDC_RX_COMPANDER0_CTL13, 0x2A},
+	{ LPASS_CDC_RX_COMPANDER0_CTL14, 0x36},
+	{ LPASS_CDC_RX_COMPANDER0_CTL15, 0x3C},
+	{ LPASS_CDC_RX_COMPANDER0_CTL16, 0xC4},
+	{ LPASS_CDC_RX_COMPANDER0_CTL17, 0x00},
+	{ LPASS_CDC_RX_COMPANDER0_CTL18, 0x0C},
+	{ LPASS_CDC_RX_COMPANDER0_CTL19, 0x16},
+	{ LPASS_CDC_RX_COMPANDER1_CTL8, 0x00},
+	{ LPASS_CDC_RX_COMPANDER1_CTL9, 0x00},
+	{ LPASS_CDC_RX_COMPANDER1_CTL10, 0x06},
+	{ LPASS_CDC_RX_COMPANDER1_CTL11, 0x12},
+	{ LPASS_CDC_RX_COMPANDER1_CTL12, 0x1E},
+	{ LPASS_CDC_RX_COMPANDER1_CTL13, 0x2A},
+	{ LPASS_CDC_RX_COMPANDER1_CTL14, 0x36},
+	{ LPASS_CDC_RX_COMPANDER1_CTL15, 0x3C},
+	{ LPASS_CDC_RX_COMPANDER1_CTL16, 0xC4},
+	{ LPASS_CDC_RX_COMPANDER1_CTL17, 0x00},
+	{ LPASS_CDC_RX_COMPANDER1_CTL18, 0x0C},
+	{ LPASS_CDC_RX_COMPANDER1_CTL19, 0x16},
+#else
+	{ LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00},
+	{ LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00},
+	{ LPASS_CDC_RX_BCL_VBAT_DECODE_ST, 0x00},
+	{ LPASS_CDC_RX_RX0_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_RX_RX1_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_RX_RX2_RX_PATH_CFG3, 0x00},
+#endif
+
+	/* WSA Macro */
+	{ LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ LPASS_CDC_WSA_TOP_TOP_CFG0, 0x00},
+	{ LPASS_CDC_WSA_TOP_TOP_CFG1, 0x00},
+	{ LPASS_CDC_WSA_TOP_FREQ_MCLK, 0x00},
+	{ LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL, 0x00},
+	{ LPASS_CDC_WSA_TOP_DEBUG_EN0, 0x00},
+	{ LPASS_CDC_WSA_TOP_DEBUG_EN1, 0x00},
+	{ LPASS_CDC_WSA_TOP_DEBUG_DSM_LB, 0x88},
+	{ LPASS_CDC_WSA_TOP_RX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_WSA_TOP_TX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_WSA_TOP_I2S_CLK, 0x02},
+	{ LPASS_CDC_WSA_TOP_I2S_RESET, 0x00},
+	{ LPASS_CDC_WSA_TOP_FS_UNGATE, 0xFF},
+	{ LPASS_CDC_WSA_TOP_GRP_SEL, 0x08},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_LSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_MSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP7_LUT, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_LSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_MSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_LSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_MSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP8_LUT, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_LSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_MSB, 0x00},
+	{ LPASS_CDC_WSA_TOP_FS_UNGATE2, 0x1F},
+	{ LPASS_CDC_WSA_TOP_SEQ_CTL0, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x10},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1, 0x04},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2, 0x08},
+	{ LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3, 0x0C},
+	{ LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA_INTR_CTRL_CFG, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0, 0xFF},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_LEVEL0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_BYPASS0, 0x00},
+	{ LPASS_CDC_WSA_INTR_CTRL_SET0, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC0, 0x04},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC0, 0x04},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL, 0x00},
+	{ LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0xD0},
+	{ LPASS_CDC_WSA_BOOST0_BOOST_CFG1, 0x89},
+	{ LPASS_CDC_WSA_BOOST0_BOOST_CFG2, 0x04},
+	{ LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0xD0},
+	{ LPASS_CDC_WSA_BOOST1_BOOST_CFG1, 0x89},
+	{ LPASS_CDC_WSA_BOOST1_BOOST_CFG2, 0x04},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL0, 0x60},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL1, 0xDB},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL2, 0xFF},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL3, 0x35},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL4, 0xFF},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL5, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL6, 0x01},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL7, 0x28},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL8, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL9, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL10, 0x06},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL11, 0x12},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL12, 0x1E},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL13, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL14, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL15, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL16, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL17, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL18, 0x2A},
+	{ LPASS_CDC_WSA_COMPANDER0_CTL19, 0x16},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL0, 0x60},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL1, 0xDB},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL2, 0xFF},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL3, 0x35},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL4, 0xFF},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL5, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL6, 0x01},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL7, 0x28},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL8, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL9, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL10, 0x06},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL11, 0x12},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL12, 0x1E},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL13, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL14, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL15, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL16, 0x00},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL17, 0x24},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL18, 0x2A},
+	{ LPASS_CDC_WSA_COMPANDER1_CTL19, 0x16},
+	{ LPASS_CDC_WSA_SOFTCLIP0_CRC, 0x00},
+	{ LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38},
+	{ LPASS_CDC_WSA_SOFTCLIP1_CRC, 0x00},
+	{ LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38},
+	{ LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_WSA_IDLE_DETECT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_IDLE_DETECT_CFG0, 0x07},
+	{ LPASS_CDC_WSA_IDLE_DETECT_CFG1, 0x3C},
+	{ LPASS_CDC_WSA_IDLE_DETECT_CFG2, 0x00},
+	{ LPASS_CDC_WSA_IDLE_DETECT_CFG3, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL1, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL2, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL3, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG1, 0x85},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG2, 0xDC},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG3, 0x85},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG4, 0xDC},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG5, 0x85},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG6, 0xDC},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG7, 0x32},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG8, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST1, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST2, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST3, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST4, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST1, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST2, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST3, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST4, 0x00},
+	{ LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST5, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_CFG, 0x10},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN1, 0x04},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN2, 0x08},
+	{ LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN3, 0x0C},
+	/* lpass 2.6 new registers */
+	{ LPASS_CDC_WSA_PBR_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA_LA_CFG, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG2, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG3, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG4, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG5, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG6, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG7, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG8, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG9, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG10, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG11, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG12, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG13, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG14, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG15, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG16, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG17, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG0, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG2, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG3, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG4, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG5, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG6, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG7, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG8, 0x00},
+	{ LPASS_CDC_WSA_LA_CFG_1, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG1_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG2_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG3_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG4_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG5_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG6_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG7_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG8_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG9_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG10_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG11_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG12_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG13_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG14_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG15_1, 0xFF},
+	{ LPASS_CDC_WSA_PBR_CFG16_1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG0_1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG1_1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG2_1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG5_1, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG9, 0x00},
+	{ LPASS_CDC_WSA_ILIM_CFG6_1, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG18, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG18_1, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG19, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG20, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG21, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG22, 0x00},
+	{ LPASS_CDC_WSA_PBR_CFG23, 0x00},
+
+	/* VA macro */
+	{ LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_TOP_CFG0, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DMIC0_CTL, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DMIC1_CTL, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DMIC2_CTL, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DMIC3_CTL, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DMIC_CFG, 0x80},
+	{ LPASS_CDC_VA_TOP_CSR_VAD_MUX, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DEBUG_BUS, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_DEBUG_EN, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_VA_TOP_CSR_I2S_CLK, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_I2S_RESET, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_CORE_ID_0, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_CORE_ID_1, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_CORE_ID_2, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_CORE_ID_3, 0x00},
+	{ LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE},
+	{ LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE},
+	{ LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE},
+	{ LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x06},
+	{ LPASS_CDC_VA_TOP_CSR_SEQ_CTL0, 0x00},
+
+	/* VA core */
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00},
+	{ LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_VA_TX0_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_VA_TX0_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_VA_TX0_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_VA_TX0_TX_PATH_SEC7, 0x25},
+	{ LPASS_CDC_VA_TX1_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_VA_TX1_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_VA_TX1_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_VA_TX1_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_VA_TX1_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_VA_TX2_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_VA_TX2_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_VA_TX2_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_VA_TX2_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_VA_TX2_TX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_VA_TX3_TX_PATH_CTL, 0x04},
+	{ LPASS_CDC_VA_TX3_TX_PATH_CFG0, 0x10},
+	{ LPASS_CDC_VA_TX3_TX_PATH_CFG1, 0x0B},
+	{ LPASS_CDC_VA_TX3_TX_VOL_CTL, 0x00},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC0, 0x00},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC1, 0x00},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC2, 0x01},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC3, 0x3C},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC4, 0x20},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_VA_TX3_TX_PATH_SEC6, 0x00},
+
+	/* WSA2 Macro */
+	{ LPASS_CDC_WSA2_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
+	{ LPASS_CDC_WSA2_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ LPASS_CDC_WSA2_TOP_TOP_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_TOP_TOP_CFG1, 0x00},
+	{ LPASS_CDC_WSA2_TOP_FREQ_MCLK, 0x00},
+	{ LPASS_CDC_WSA2_TOP_DEBUG_BUS_SEL, 0x00},
+	{ LPASS_CDC_WSA2_TOP_DEBUG_EN0, 0x00},
+	{ LPASS_CDC_WSA2_TOP_DEBUG_EN1, 0x00},
+	{ LPASS_CDC_WSA2_TOP_DEBUG_DSM_LB, 0x88},
+	{ LPASS_CDC_WSA2_TOP_RX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_WSA2_TOP_TX_I2S_CTL, 0x0C},
+	{ LPASS_CDC_WSA2_TOP_I2S_CLK, 0x02},
+	{ LPASS_CDC_WSA2_TOP_I2S_RESET, 0x00},
+	{ LPASS_CDC_WSA2_TOP_FS_UNGATE, 0xFF},
+	{ LPASS_CDC_WSA2_TOP_GRP_SEL, 0x08},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_LSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_MSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP7_LUT, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_LSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_MSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_LSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_MSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP8_LUT, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_LSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_MSB, 0x00},
+	{ LPASS_CDC_WSA2_TOP_FS_UNGATE2, 0x03},
+	{ LPASS_CDC_WSA2_TOP_SEQ_CTL0, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_RX_EC_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX_INP_MUX_SOFTCLIP_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG, 0x10},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC2, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN1, 0x04},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN2, 0x08},
+	{ LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN3, 0x0C},
+	{ LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0, 0x02},
+	{ LPASS_CDC_WSA2_INTR_CTRL_CFG, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_CLR_COMMIT, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN1_MASK0, 0xFF},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN1_STATUS0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN1_CLEAR0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN2_MASK0, 0xFF},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN2_STATUS0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_PIN2_CLEAR0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_LEVEL0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_BYPASS0, 0x00},
+	{ LPASS_CDC_WSA2_INTR_CTRL_SET0, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_CTL, 0x04},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_WSA2_RX0_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC0, 0x04},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_WSA2_RX0_RX_PATH_DSMDEM_CTL, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_CFG1, 0x64},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_CFG2, 0x8F},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_CFG3, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_VOL_CTL, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CTL, 0x04},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG, 0x7E},
+	{ LPASS_CDC_WSA2_RX1_RX_VOL_MIX_CTL, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC0, 0x04},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC1, 0x08},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC2, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC3, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC5, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC6, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_SEC7, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC0, 0x08},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC1, 0x00},
+	{ LPASS_CDC_WSA2_RX1_RX_PATH_DSMDEM_CTL, 0x00},
+	{ LPASS_CDC_WSA2_BOOST0_BOOST_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_BOOST0_BOOST_CTL, 0xD0},
+	{ LPASS_CDC_WSA2_BOOST0_BOOST_CFG1, 0x89},
+	{ LPASS_CDC_WSA2_BOOST0_BOOST_CFG2, 0x04},
+	{ LPASS_CDC_WSA2_BOOST1_BOOST_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_BOOST1_BOOST_CTL, 0xD0},
+	{ LPASS_CDC_WSA2_BOOST1_BOOST_CFG1, 0x89},
+	{ LPASS_CDC_WSA2_BOOST1_BOOST_CFG2, 0x04},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL0, 0x60},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL1, 0xDB},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL2, 0xFF},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL3, 0x35},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL4, 0xFF},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL5, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL6, 0x01},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x28},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL8, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL9, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL10, 0x06},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL11, 0x12},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL12, 0x1E},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL13, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL14, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL15, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL16, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL17, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL18, 0x2A},
+	{ LPASS_CDC_WSA2_COMPANDER0_CTL19, 0x16},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL0, 0x60},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL1, 0xDB},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL2, 0xFF},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL3, 0x35},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL4, 0xFF},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL5, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL6, 0x01},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x28},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL8, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL9, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL10, 0x06},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL11, 0x12},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL12, 0x1E},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL13, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL14, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL15, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL16, 0x00},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL17, 0x24},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL18, 0x2A},
+	{ LPASS_CDC_WSA2_COMPANDER1_CTL19, 0x16},
+	{ LPASS_CDC_WSA2_SOFTCLIP0_CRC, 0x00},
+	{ LPASS_CDC_WSA2_SOFTCLIP0_SOFTCLIP_CTRL, 0x38},
+	{ LPASS_CDC_WSA2_SOFTCLIP1_CRC, 0x00},
+	{ LPASS_CDC_WSA2_SOFTCLIP1_SOFTCLIP_CTRL, 0x38},
+	{ LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_CFG0, 0x01},
+	{ LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_IDLE_DETECT_CFG0, 0x07},
+	{ LPASS_CDC_WSA2_IDLE_DETECT_CFG1, 0x3C},
+	{ LPASS_CDC_WSA2_IDLE_DETECT_CFG2, 0x00},
+	{ LPASS_CDC_WSA2_IDLE_DETECT_CFG3, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG1, 0x85},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG2, 0xDC},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG3, 0x85},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG4, 0xDC},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG5, 0x85},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG6, 0xDC},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG7, 0x32},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG8, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST1, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST2, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST3, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST4, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST1, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST2, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST3, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST4, 0x00},
+	{ LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST5, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_CFG, 0x10},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL2, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL3, 0x04},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST1, 0xE0},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST2, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST3, 0x40},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC1, 0x2A},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC2, 0x18},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC3, 0x18},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC4, 0x03},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD1, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD2, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD3, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD4, 0x64},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD5, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_DEBUG1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD_MON, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_MON_VAL, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BAN, 0x0C},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD1, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD2, 0x77},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD3, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD4, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD5, 0x4B},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD6, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD7, 0x01},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD8, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD9, 0x00},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN1, 0x04},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN2, 0x08},
+	{ LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN3, 0x0C},
+	/* lpass 2.6 new registers */
+	{ LPASS_CDC_WSA2_PBR_PATH_CTL, 0x00},
+	{ LPASS_CDC_WSA2_LA_CFG, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG2, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG3, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG4, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG5, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG6, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG7, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG8, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG9, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG10, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG11, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG12, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG13, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG14, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG15, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG16, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG17, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG0, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG2, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG3, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG4, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG5, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG6, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG7, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG8, 0x00},
+	{ LPASS_CDC_WSA2_LA_CFG_1, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG1_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG2_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG3_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG4_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG5_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG6_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG7_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG8_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG9_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG10_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG11_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG12_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG13_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG14_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG15_1, 0xFF},
+	{ LPASS_CDC_WSA2_PBR_CFG16_1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG0_1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG1_1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG2_1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG5_1, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG9, 0x00},
+	{ LPASS_CDC_WSA2_ILIM_CFG6_1, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG18, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG18_1, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG19, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG20, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG21, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG22, 0x00},
+	{ LPASS_CDC_WSA2_PBR_CFG23, 0x00},
+};
+
+static bool lpass_cdc_is_readable_register(struct device *dev,
+					unsigned int reg)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev);
+	u16 reg_offset;
+	int macro_id;
+	u8 *reg_tbl = NULL;
+
+	if (!priv)
+		return false;
+
+	macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation,
+				       reg);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return false;
+
+	reg_tbl = lpass_cdc_reg_access[macro_id];
+	reg_offset = (reg - macro_id_base_offset[macro_id])/4;
+
+	if (reg_tbl)
+		return (reg_tbl[reg_offset] & RD_REG);
+
+	return false;
+}
+
+static bool lpass_cdc_is_writeable_register(struct device *dev,
+					 unsigned int reg)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev);
+	u16 reg_offset;
+	int macro_id;
+	const u8 *reg_tbl = NULL;
+
+	if (!priv)
+		return false;
+
+	macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation,
+				       reg);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return false;
+
+	reg_tbl = lpass_cdc_reg_access[macro_id];
+	reg_offset = (reg - macro_id_base_offset[macro_id])/4;
+
+	if (reg_tbl)
+		return (reg_tbl[reg_offset] & WR_REG);
+
+	return false;
+}
+
+static bool lpass_cdc_is_volatile_register(struct device *dev,
+					unsigned int reg)
+{
+	/* Update volatile list for rx/tx macros */
+	switch (reg) {
+	case LPASS_CDC_VA_TOP_CSR_CORE_ID_0:
+	case LPASS_CDC_VA_TOP_CSR_CORE_ID_1:
+	case LPASS_CDC_VA_TOP_CSR_CORE_ID_2:
+	case LPASS_CDC_VA_TOP_CSR_CORE_ID_3:
+	case LPASS_CDC_VA_TOP_CSR_DMIC0_CTL:
+	case LPASS_CDC_VA_TOP_CSR_DMIC1_CTL:
+	case LPASS_CDC_VA_TOP_CSR_DMIC2_CTL:
+	case LPASS_CDC_VA_TOP_CSR_DMIC3_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL:
+	case LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL:
+	case LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL:
+	case LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0:
+	case LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0:
+	case LPASS_CDC_WSA_COMPANDER0_CTL6:
+	case LPASS_CDC_WSA_COMPANDER1_CTL6:
+	case LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_MON_VAL:
+	case LPASS_CDC_WSA2_INTR_CTRL_PIN1_STATUS0:
+	case LPASS_CDC_WSA2_INTR_CTRL_PIN2_STATUS0:
+	case LPASS_CDC_WSA2_COMPANDER0_CTL6:
+	case LPASS_CDC_WSA2_COMPANDER1_CTL6:
+	case LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB:
+	case LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB:
+	case LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB:
+	case LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB:
+	case LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB:
+	case LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB:
+	case LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB:
+	case LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB:
+	case LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2:
+	case LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2:
+	case LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+	case LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0:
+	case LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0:
+	case LPASS_CDC_RX_COMPANDER0_CTL6:
+	case LPASS_CDC_RX_COMPANDER1_CTL6:
+	case LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO:
+	case LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO:
+	case LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+	case LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+	case LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO:
+	case LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL:
+	case LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL:
+	case LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL:
+	case LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL:
+#ifdef CONFIG_BOLERO_VER_2P6
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_ADDR:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA0:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA1:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA2:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA3:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA4:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA5:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA6:
+	case LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA7:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_ADDR:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA0:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA1:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA2:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA3:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA4:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA5:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA6:
+	case LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA7:
+	case LPASS_CDC_RX_RX0_RX_FIR_CTL:
+	case LPASS_CDC_RX_RX1_RX_FIR_CTL:
+	case LPASS_CDC_RX_RX0_RX_PATH_CTL:
+	case LPASS_CDC_RX_RX1_RX_PATH_CTL:
+#endif
+		return true;
+	}
+	return false;
+}
+
+const struct regmap_config lpass_cdc_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.reg_stride = 4,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = lpass_cdc_defaults,
+	.num_reg_defaults = ARRAY_SIZE(lpass_cdc_defaults),
+	.max_register = LPASS_CDC_MAX_REGISTER,
+	.writeable_reg = lpass_cdc_is_writeable_register,
+	.volatile_reg = lpass_cdc_is_volatile_register,
+	.readable_reg = lpass_cdc_is_readable_register,
+};

+ 5026 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c

@@ -0,0 +1,5026 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. 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 <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+
+#include <asoc/msm-cdc-pinctrl.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-comp.h"
+#include "lpass-cdc-registers.h"
+#include "lpass-cdc-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define LPASS_CDC_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 LPASS_CDC_RX_MACRO_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+				SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
+
+#define LPASS_CDC_RX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define LPASS_CDC_RX_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_48000)
+#define LPASS_CDC_RX_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define SAMPLING_RATE_44P1KHZ   44100
+#define SAMPLING_RATE_88P2KHZ   88200
+#define SAMPLING_RATE_176P4KHZ  176400
+#define SAMPLING_RATE_352P8KHZ  352800
+
+#define LPASS_CDC_RX_MACRO_MAX_OFFSET 0x1000
+
+#define LPASS_CDC_RX_MACRO_MAX_DMA_CH_PER_PORT 2
+#define RX_SWR_STRING_LEN 80
+#define LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX 3
+
+#define LPASS_CDC_RX_MACRO_INTERP_MUX_NUM_INPUTS 3
+#define LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX 5
+#ifdef CONFIG_BOLERO_VER_2P6
+#define LPASS_CDC_RX_MACRO_FIR_COEFF_MAX 100
+#define LPASS_CDC_RX_MACRO_FIR_COEFF_ARRAY_MAX \
+	(LPASS_CDC_RX_MACRO_FIR_COEFF_MAX + 1)
+/* first value represent number of coefficients in each 100 integer group */
+#define LPASS_CDC_RX_MACRO_FIR_FILTER_BYTES \
+	(sizeof(u32) * LPASS_CDC_RX_MACRO_FIR_COEFF_ARRAY_MAX)
+#endif
+
+#define STRING(name) #name
+#define LPASS_CDC_RX_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define LPASS_CDC_RX_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+#define LPASS_CDC_RX_MACRO_RX_PATH_OFFSET \
+		(LPASS_CDC_RX_RX1_RX_PATH_CTL - LPASS_CDC_RX_RX0_RX_PATH_CTL)
+#define LPASS_CDC_RX_MACRO_COMP_OFFSET \
+		(LPASS_CDC_RX_COMPANDER1_CTL0 - LPASS_CDC_RX_COMPANDER0_CTL0)
+
+#define MAX_IMPED_PARAMS 6
+
+#define LPASS_CDC_RX_MACRO_EC_MIX_TX0_MASK 0xf0
+#define LPASS_CDC_RX_MACRO_EC_MIX_TX1_MASK 0x0f
+#define LPASS_CDC_RX_MACRO_EC_MIX_TX2_MASK 0x0f
+
+#define LPASS_CDC_RX_MACRO_GAIN_MAX_VAL 0x28
+#define LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY 0x0
+/* Define macros to increase PA Gain by half */
+#define LPASS_CDC_RX_MACRO_MOD_GAIN (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY + 6)
+
+#define COMP_MAX_COEFF 25
+
+struct wcd_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+static const struct wcd_imped_val imped_index[] = {
+	{4, 0},
+	{5, 1},
+	{6, 2},
+	{7, 3},
+	{8, 4},
+	{9, 5},
+	{10, 6},
+	{11, 7},
+	{12, 8},
+	{13, 9},
+};
+
+enum {
+	HPH_ULP,
+	HPH_LOHIFI,
+	HPH_MODE_MAX,
+};
+
+static 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},
+	},
+};
+
+enum {
+	RX_MODE_ULP,
+	RX_MODE_LOHIFI,
+	RX_MODE_EAR,
+	RX_MODE_MAX
+};
+
+#ifdef CONFIG_BOLERO_VER_2P6
+static struct lpass_cdc_comp_setting comp_setting_table[RX_MODE_MAX] =
+{
+	{12, -60, 12},
+	{0, -60, 12},
+	{12, -36, 12},
+};
+#endif
+
+struct lpass_cdc_rx_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static const struct lpass_cdc_rx_macro_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf2},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf2},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf4},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf4},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf7},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf7},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf9},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf9},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfa},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfa},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfb},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfb},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfc},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfc},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+};
+
+enum {
+	INTERP_HPHL,
+	INTERP_HPHR,
+	INTERP_AUX,
+	INTERP_MAX
+};
+
+enum {
+	LPASS_CDC_RX_MACRO_RX0,
+	LPASS_CDC_RX_MACRO_RX1,
+	LPASS_CDC_RX_MACRO_RX2,
+	LPASS_CDC_RX_MACRO_RX3,
+	LPASS_CDC_RX_MACRO_RX4,
+	LPASS_CDC_RX_MACRO_RX5,
+	LPASS_CDC_RX_MACRO_PORTS_MAX
+};
+
+enum {
+	LPASS_CDC_RX_MACRO_COMP1, /* HPH_L */
+	LPASS_CDC_RX_MACRO_COMP2, /* HPH_R */
+	LPASS_CDC_RX_MACRO_COMP_MAX
+};
+
+enum {
+	LPASS_CDC_RX_MACRO_EC0_MUX = 0,
+	LPASS_CDC_RX_MACRO_EC1_MUX,
+	LPASS_CDC_RX_MACRO_EC2_MUX,
+	LPASS_CDC_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 LPASS_CDC_RX_MACRO_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX)
+
+struct lpass_cdc_rx_macro_iir_filter_ctl {
+	unsigned int iir_idx;
+	unsigned int band_idx;
+	struct soc_bytes_ext bytes_ext;
+};
+
+#define LPASS_CDC_RX_MACRO_IIR_FILTER_CTL(xname, iidx, bidx) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = lpass_cdc_rx_macro_iir_filter_info, \
+	.get = lpass_cdc_rx_macro_iir_band_audio_mixer_get, \
+	.put = lpass_cdc_rx_macro_iir_band_audio_mixer_put, \
+	.private_value = (unsigned long)&(struct lpass_cdc_rx_macro_iir_filter_ctl) { \
+		.iir_idx = iidx, \
+		.band_idx = bidx, \
+		.bytes_ext = {.max = LPASS_CDC_RX_MACRO_IIR_FILTER_SIZE, }, \
+	} \
+}
+
+#ifdef CONFIG_BOLERO_VER_2P6
+/* Codec supports 2 FIR filters Path */
+enum {
+	RX0_PATH = 0,
+	RX1_PATH,
+	FIR_PATH_MAX,
+};
+
+/* Each RX Path has 2 group of coefficients */
+enum {
+	GRP0 = 0,
+	GRP1,
+	GRP_MAX,
+};
+
+struct lpass_cdc_rx_macro_fir_filter_ctl {
+	unsigned int path_idx;
+	unsigned int grp_idx;
+	struct soc_bytes_ext bytes_ext;
+};
+
+#define LPASS_CDC_RX_MACRO_FIR_FILTER_CTL(xname, pidx, gidx) \
+{	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	 .info = lpass_cdc_rx_macro_fir_filter_info, \
+	 .get = lpass_cdc_rx_macro_fir_audio_mixer_get, \
+	 .put = lpass_cdc_rx_macro_fir_audio_mixer_put, \
+	 .private_value = (unsigned long)&(struct lpass_cdc_rx_macro_fir_filter_ctl) { \
+		.path_idx = pidx, \
+		.grp_idx = gidx, \
+		.bytes_ext = {.max = LPASS_CDC_RX_MACRO_FIR_FILTER_BYTES, }, \
+	} \
+}
+#endif
+
+struct lpass_cdc_rx_macro_idle_detect_config {
+	u8 hph_idle_thr;
+	u8 hph_idle_detect_en;
+};
+
+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},
+};
+
+struct lpass_cdc_rx_macro_bcl_pmic_params {
+	u8 id;
+	u8 sid;
+	u8 ppid;
+};
+
+static int lpass_cdc_rx_macro_core_vote(void *handle, bool enable);
+static int lpass_cdc_rx_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+static int lpass_cdc_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);
+static int lpass_cdc_rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol);
+static int lpass_cdc_rx_macro_mux_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol);
+static int lpass_cdc_rx_macro_mux_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol);
+static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx);
+
+/* Hold instance to soundwire platform device */
+struct rx_swr_ctrl_data {
+	struct platform_device *rx_swr_pdev;
+};
+
+struct rx_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+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_AIF5_PB,
+	RX_MACRO_AIF6_PB,
+	LPASS_CDC_RX_MACRO_MAX_DAIS,
+};
+
+enum {
+	RX_MACRO_AIF1_CAP = 0,
+	RX_MACRO_AIF2_CAP,
+	RX_MACRO_AIF3_CAP,
+	LPASS_CDC_RX_MACRO_MAX_AIF_CAP_DAIS
+};
+/*
+ * @dev: rx macro device pointer
+ * @comp_enabled: compander enable mixer value set
+ * @prim_int_users: Users of interpolator
+ * @rx_mclk_users: RX MCLK users count
+ * @vi_feed_value: VI sense mask
+ * @swr_clk_lock: to lock swr master clock operations
+ * @swr_ctrl_data: SoundWire data structure
+ * @swr_plat_data: Soundwire platform data
+ * @lpass_cdc_rx_macro_add_child_devices_work: work for adding child devices
+ * @rx_swr_gpio_p: used by pinctrl API
+ * @component: codec handle
+ */
+struct lpass_cdc_rx_macro_priv {
+	struct device *dev;
+	int comp_enabled[LPASS_CDC_RX_MACRO_COMP_MAX];
+	u8 is_pcm_enabled;
+	/* Main path clock users count */
+	int main_clk_users[INTERP_MAX];
+	int rx_port_value[LPASS_CDC_RX_MACRO_PORTS_MAX];
+	u16 prim_int_users[INTERP_MAX];
+	int rx_mclk_users;
+	int swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	int clsh_users;
+	int rx_mclk_cnt;
+#ifdef CONFIG_BOLERO_VER_2P6
+	u8 fir_total_coeff_num[FIR_PATH_MAX];
+	bool is_fir_coeff_written[FIR_PATH_MAX][GRP_MAX];
+	u32 fir_coeff_array[FIR_PATH_MAX][GRP_MAX]
+		[LPASS_CDC_RX_MACRO_FIR_COEFF_MAX];
+	u32 num_fir_coeff[FIR_PATH_MAX][GRP_MAX];
+#endif
+	bool is_native_on;
+	bool is_ear_mode_on;
+	bool is_fir_filter_on;
+	bool is_fir_capable;
+	bool dev_up;
+	bool pre_dev_up;
+	bool hph_pwr_mode;
+	bool hph_hd2_mode;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct rx_swr_ctrl_data *swr_ctrl_data;
+	struct rx_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct lpass_cdc_rx_macro_add_child_devices_work;
+	struct device_node *rx_swr_gpio_p;
+	struct snd_soc_component *component;
+	unsigned long active_ch_mask[LPASS_CDC_RX_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[LPASS_CDC_RX_MACRO_MAX_DAIS];
+	u16 bit_width[LPASS_CDC_RX_MACRO_MAX_DAIS];
+	char __iomem *rx_io_base;
+	char __iomem *rx_mclk_mode_muxsel;
+	struct lpass_cdc_rx_macro_idle_detect_config idle_det_cfg;
+	u8 sidetone_coeff_array[IIR_MAX][BAND_MAX]
+		[LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX * 4];
+	/* NOT designed to always reflect the actual hardware value */
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int is_softclip_on;
+	int is_aux_hpf_on;
+	int softclip_clk_users;
+	struct lpass_cdc_rx_macro_bcl_pmic_params bcl_pmic_params;
+	u16 clk_id;
+	u16 default_clk_id;
+	struct clk *hifi_fir_clk;
+	int8_t rx0_gain_val;
+	int8_t rx1_gain_val;
+	int pcm_select_users;
+};
+
+static struct snd_soc_dai_driver lpass_cdc_rx_macro_dai[];
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+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 lpass_cdc_rx_macro_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
+};
+
+static const char *const lpass_cdc_rx_macro_ear_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum lpass_cdc_rx_macro_ear_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_ear_mode_text);
+
+static const char *const lpass_cdc_rx_macro_hph_hd2_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum lpass_cdc_rx_macro_hph_hd2_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_hph_hd2_mode_text);
+
+static const char *const lpass_cdc_rx_macro_hph_pwr_mode_text[] = {"ULP", "LOHIFI"};
+static const struct soc_enum lpass_cdc_rx_macro_hph_pwr_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_hph_pwr_mode_text);
+
+static const char * const lpass_cdc_rx_macro_vbat_bcl_gsm_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum lpass_cdc_rx_macro_vbat_bcl_gsm_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_vbat_bcl_gsm_mode_text);
+
+#ifdef CONFIG_BOLERO_VER_2P6
+static const char *const lpass_cdc_rx_macro_fir_filter_text[] = {"OFF", "ON"};
+static const struct soc_enum lpass_cdc_rx_macro_fir_filter_enum =
+	SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_fir_filter_text);
+#endif
+
+static const struct snd_kcontrol_new rx_int2_1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("RX AUX VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const char * const hph_idle_detect_text[] = {"OFF", "ON"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_2, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
+		rx_int_mix_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_2, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
+		rx_int_mix_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_2, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
+		rx_int_mix_mux_text);
+
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
+		rx_prim_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
+		rx_prim_mix_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
+		rx_sidetone_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
+		rx_sidetone_mix_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
+		rx_sidetone_mix_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp0, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp1, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp2, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp3, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp0, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp1, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp2, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
+	iir_inp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp3, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
+	iir_inp_mux_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0,
+	rx_int0_1_interp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0,
+	rx_int1_1_interp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0,
+	rx_int2_1_interp_mux_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0,
+	rx_int0_2_interp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0,
+	rx_int1_2_interp_mux_text);
+LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0,
+	rx_int2_2_interp_mux_text);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(rx_int0_dem_inp, LPASS_CDC_RX_RX0_RX_PATH_CFG1, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	lpass_cdc_rx_macro_int_dem_inp_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(rx_int1_dem_inp, LPASS_CDC_RX_RX1_RX_PATH_CFG1, 0,
+	rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
+	lpass_cdc_rx_macro_int_dem_inp_mux_put);
+
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx0, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx1, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx2, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx3, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx4, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx5, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text,
+	lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put);
+
+static const char * const rx_echo_mux_text[] = {
+	"ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2"
+};
+
+static const struct soc_enum rx_mix_tx2_mux_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4,
+			rx_echo_mux_text);
+
+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 soc_enum rx_mix_tx1_mux_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4,
+			rx_echo_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 soc_enum rx_mix_tx0_mux_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4,
+			rx_echo_mux_text);
+
+static const struct snd_kcontrol_new rx_mix_tx0_mux =
+	SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum);
+
+static struct snd_soc_dai_ops lpass_cdc_rx_macro_dai_ops = {
+	.hw_params = lpass_cdc_rx_macro_hw_params,
+	.get_channel_map = lpass_cdc_rx_macro_get_channel_map,
+};
+
+static struct snd_soc_dai_driver lpass_cdc_rx_macro_dai[] = {
+	{
+		.name = "rx_macro_rx1",
+		.id = RX_MACRO_AIF1_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF1 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx2",
+		.id = RX_MACRO_AIF2_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF2 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx3",
+		.id = RX_MACRO_AIF3_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF3 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx4",
+		.id = RX_MACRO_AIF4_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF4 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_echo",
+		.id = RX_MACRO_AIF_ECHO,
+		.capture = {
+			.stream_name = "RX_AIF_ECHO Capture",
+			.rates = LPASS_CDC_RX_MACRO_ECHO_RATES,
+			.formats = LPASS_CDC_RX_MACRO_ECHO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 3,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx5",
+		.id = RX_MACRO_AIF5_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF5 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx6",
+		.id = RX_MACRO_AIF6_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF6 Playback",
+			.rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES,
+			.formats = LPASS_CDC_RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &lpass_cdc_rx_macro_dai_ops,
+	},
+};
+
+static int get_impedance_index(int imped)
+{
+	int i = 0;
+
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than %d Ohm\n",
+			__func__, imped_index[i].imped_val);
+		i = 0;
+		goto ret;
+	}
+	if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
+		pr_debug("%s, detected impedance is greater than %d Ohm\n",
+			__func__,
+			imped_index[ARRAY_SIZE(imped_index) - 1].imped_val);
+		i = ARRAY_SIZE(imped_index) - 1;
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+/*
+ * lpass_cdc_rx_macro_wcd_clsh_imped_config -
+ * This function updates HPHL and HPHR gain settings
+ * according to the impedance value.
+ *
+ * @component: codec pointer handle
+ * @imped: impedance value of HPHL/R
+ * @reset: bool variable to reset registers when teardown
+ */
+static void lpass_cdc_rx_macro_wcd_clsh_imped_config(struct snd_soc_component *component,
+					   int imped, bool reset)
+{
+	int i;
+	int index = 0;
+	int table_size;
+
+	static const struct lpass_cdc_rx_macro_reg_mask_val
+				(*imped_table_ptr)[MAX_IMPED_PARAMS];
+
+	table_size = ARRAY_SIZE(imped_table);
+	imped_table_ptr = imped_table;
+	/* reset = 1, which means request is to reset the register values */
+	if (reset) {
+		for (i = 0; i < MAX_IMPED_PARAMS; i++)
+			snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask, 0);
+		return;
+	}
+	index = get_impedance_index(imped);
+	if (index >= (ARRAY_SIZE(imped_index) - 1)) {
+		pr_debug("%s, impedance not in range = %d\n", __func__, imped);
+		return;
+	}
+	if (index >= table_size) {
+		pr_debug("%s, impedance index not in range = %d\n", __func__,
+			index);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_component_update_bits(component,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask,
+				imped_table_ptr[index][i].val);
+}
+
+static bool lpass_cdc_rx_macro_get_data(struct snd_soc_component *component,
+			       struct device **rx_dev,
+			       struct lpass_cdc_rx_macro_priv **rx_priv,
+			       const char *func_name)
+{
+	*rx_dev = lpass_cdc_get_device_ptr(component->dev, RX_MACRO);
+
+	if (!(*rx_dev)) {
+		dev_err_ratelimited(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+
+	*rx_priv = dev_get_drvdata((*rx_dev));
+	if (!(*rx_priv)) {
+		dev_err_ratelimited(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+
+	if (!(*rx_priv)->component) {
+		dev_err_ratelimited(component->dev,
+			"%s: rx_priv component is not initialized!\n", func_name);
+		return false;
+	}
+
+	return true;
+}
+
+static int lpass_cdc_rx_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (rx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int lpass_cdc_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 int val = 0;
+	unsigned short look_ahead_dly_reg =
+				LPASS_CDC_RX_RX0_RX_PATH_CFG0;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val >= e->items)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	if (e->reg == LPASS_CDC_RX_RX0_RX_PATH_CFG1)
+		look_ahead_dly_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0;
+	else if (e->reg == LPASS_CDC_RX_RX1_RX_PATH_CFG1)
+		look_ahead_dly_reg = LPASS_CDC_RX_RX1_RX_PATH_CFG0;
+
+	/* Set Look Ahead Delay */
+	snd_soc_component_update_bits(component, look_ahead_dly_reg,
+			    0x08, (val ? 0x08 : 0x00));
+	/* Set DEM INP Select */
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int lpass_cdc_rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					    u8 rate_reg_val,
+					    u32 sample_rate)
+{
+	u8 int_1_mix1_inp = 0;
+	u32 j = 0, port = 0;
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u16 int_fs_reg = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 inp0_sel = 0, inp1_sel = 0, inp2_sel = 0;
+	struct snd_soc_component *component = dai->component;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_RX_MACRO_PORTS_MAX) {
+		int_1_mix1_inp = port;
+		if ((int_1_mix1_inp < LPASS_CDC_RX_MACRO_RX0) ||
+			(int_1_mix1_inp > LPASS_CDC_RX_MACRO_PORTS_MAX)) {
+			pr_err_ratelimited("%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg0 = LPASS_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;
+
+			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 & 0x0F;
+			inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F;
+			inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F;
+			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 = LPASS_CDC_RX_RX0_RX_PATH_CTL +
+					LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * j;
+				pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_1\n",
+					  __func__, dai->id, j);
+				pr_debug("%s: set INT%u_1 sample rate to %u\n",
+					__func__, j, sample_rate);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						0x0F, rate_reg_val);
+			}
+			int_mux_cfg0 += 8;
+		}
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					u8 rate_reg_val,
+					u32 sample_rate)
+{
+	u8 int_2_inp = 0;
+	u32 j = 0, port = 0;
+	u16 int_mux_cfg1 = 0, int_fs_reg = 0;
+	u8 int_mux_cfg1_val = 0;
+	struct snd_soc_component *component = dai->component;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_RX_MACRO_PORTS_MAX) {
+		int_2_inp = port;
+		if ((int_2_inp < LPASS_CDC_RX_MACRO_RX0) ||
+			(int_2_inp > LPASS_CDC_RX_MACRO_PORTS_MAX)) {
+			pr_err_ratelimited("%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg1 = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1;
+		for (j = 0; j < INTERP_MAX; j++) {
+			int_mux_cfg1_val = snd_soc_component_read(
+						component, int_mux_cfg1) &
+						0x0F;
+			if (int_mux_cfg1_val == int_2_inp +
+							INTn_2_INP_SEL_RX0) {
+				int_fs_reg = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL +
+					LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * j;
+				pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_2\n",
+					  __func__, dai->id, j);
+				pr_debug("%s: set INT%u_2 sample rate to %u\n",
+					__func__, j, sample_rate);
+				snd_soc_component_update_bits(
+						component, int_fs_reg,
+						0x0F, rate_reg_val);
+			}
+			int_mux_cfg1 += 8;
+		}
+	}
+	return 0;
+}
+
+static bool lpass_cdc_rx_macro_is_fractional_sample_rate(u32 sample_rate)
+{
+	switch (sample_rate) {
+	case SAMPLING_RATE_44P1KHZ:
+	case SAMPLING_RATE_88P2KHZ:
+	case SAMPLING_RATE_176P4KHZ:
+	case SAMPLING_RATE_352P8KHZ:
+		return true;
+	default:
+		return false;
+	}
+	return false;
+}
+
+static int lpass_cdc_rx_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+					  u32 sample_rate)
+{
+	struct snd_soc_component *component = dai->component;
+	int rate_val = 0;
+	int i = 0, ret = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+
+	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;
+			if (lpass_cdc_rx_macro_is_fractional_sample_rate(sample_rate))
+				rx_priv->is_native_on = true;
+			else
+				rx_priv->is_native_on = false;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
+		dev_err(component->dev, "%s: Unsupported sample rate: %d\n",
+			__func__, sample_rate);
+		return -EINVAL;
+	}
+
+	ret = lpass_cdc_rx_macro_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate);
+	if (ret)
+		return ret;
+	ret = lpass_cdc_rx_macro_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int lpass_cdc_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;
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = lpass_cdc_rx_macro_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			pr_err_ratelimited("%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		rx_priv->bit_width[dai->id] = params_width(params);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	unsigned int temp = 0, ch_mask = 0;
+	u16 val = 0, mask = 0, cnt = 0, i = 0;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	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_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_RX_MACRO_PORTS_MAX) {
+			ch_mask |= (1 << temp);
+			if (++i == LPASS_CDC_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)
+		 * Above is reflected in machine driver BE dailink
+		 */
+		if (ch_mask & 0x0C)
+			ch_mask = ch_mask >> 2;
+		if ((ch_mask & 0x10) || (ch_mask & 0x20))
+			ch_mask = 0x1;
+		*rx_slot = ch_mask;
+		*rx_num = rx_priv->active_ch_cnt[dai->id];
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n",
+			__func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]);
+		break;
+	case RX_MACRO_AIF5_PB:
+		*rx_slot = 0x1;
+		*rx_num = 0x01;
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
+			__func__, dai->id, *rx_slot, *rx_num);
+		break;
+	case RX_MACRO_AIF6_PB:
+		*rx_slot = 0x1;
+		*rx_num = 0x01;
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
+			__func__, dai->id, *rx_slot, *rx_num);
+		break;
+	case RX_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,
+			LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4);
+		if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX0_MASK) {
+			mask |= 0x1;
+			cnt++;
+		}
+		if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX1_MASK) {
+			mask |= 0x2;
+			cnt++;
+		}
+		val = snd_soc_component_read(component,
+			LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5);
+		if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX2_MASK) {
+			mask |= 0x4;
+			cnt++;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	default:
+		dev_err_ratelimited(rx_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_mclk_enable(
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(rx_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, rx_priv->rx_mclk_users);
+
+	mutex_lock(&rx_priv->mclk_lock);
+	if (mclk_enable) {
+		if (rx_priv->rx_mclk_users == 0) {
+			if (rx_priv->is_native_on)
+				rx_priv->clk_id = RX_CORE_CLK;
+			ret = lpass_cdc_rx_macro_core_vote(rx_priv, true);
+			if (ret < 0) {
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx request core vote failed\n",
+					__func__);
+				goto exit;
+			}
+			ret = lpass_cdc_clk_rsc_request_clock(rx_priv->dev,
+							   rx_priv->default_clk_id,
+							   rx_priv->clk_id,
+							   true);
+			lpass_cdc_rx_macro_core_vote(rx_priv, false);
+			if (ret < 0) {
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx request clock enable failed\n",
+					__func__);
+				goto exit;
+			}
+			lpass_cdc_clk_rsc_fs_gen_request(rx_priv->dev,
+							true);
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					RX_START_OFFSET,
+					RX_MAX_OFFSET);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		rx_priv->rx_mclk_users++;
+	} else {
+		if (rx_priv->rx_mclk_users <= 0) {
+			dev_err_ratelimited(rx_priv->dev, "%s: clock already disabled\n",
+				__func__);
+			rx_priv->rx_mclk_users = 0;
+			goto exit;
+		}
+		rx_priv->rx_mclk_users--;
+		if (rx_priv->rx_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x02, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_clk_rsc_fs_gen_request(rx_priv->dev,
+			   false);
+			ret = lpass_cdc_rx_macro_core_vote(rx_priv, true);
+			if (ret < 0) {
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx request core vote failed\n",
+					__func__);
+			}
+			lpass_cdc_clk_rsc_request_clock(rx_priv->dev,
+						 rx_priv->default_clk_id,
+						 rx_priv->clk_id,
+						 false);
+			if (!ret)
+				lpass_cdc_rx_macro_core_vote(rx_priv, false);
+			rx_priv->clk_id = rx_priv->default_clk_id;
+		}
+	}
+exit:
+	mutex_unlock(&rx_priv->mclk_lock);
+	return ret;
+}
+
+static int lpass_cdc_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);
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	int mclk_freq = MCLK_FREQ;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(rx_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (rx_priv->is_native_on)
+			mclk_freq = MCLK_FREQ_NATIVE;
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_CLK_FREQ, &mclk_freq);
+		ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 1, true);
+		if (ret)
+			rx_priv->dapm_mclk_enable = false;
+		else
+			rx_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (rx_priv->dapm_mclk_enable)
+			ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 0, true);
+		break;
+	default:
+		dev_err_ratelimited(rx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_rx_macro_event_handler(struct snd_soc_component *component,
+				  u16 event, u32 data)
+{
+	u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0, val = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case LPASS_CDC_MACRO_EVT_RX_MUTE:
+		rx_idx = data >> 0x10;
+		mute = data & 0xffff;
+		val = mute ? 0x10 : 0x00;
+		reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + (rx_idx *
+					LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+		reg_mix = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL + (rx_idx *
+					LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+		snd_soc_component_update_bits(component, reg,
+				0x10, val);
+		snd_soc_component_update_bits(component, reg_mix,
+				0x10, val);
+		break;
+	case LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST:
+		rx_idx = data >> 0x10;
+		if (rx_idx == INTERP_AUX)
+			goto done;
+		reg = LPASS_CDC_RX_COMPANDER0_CTL0 +
+				(rx_idx * LPASS_CDC_RX_MACRO_COMP_OFFSET);
+		snd_soc_component_write(component, reg,
+				snd_soc_component_read(component, reg));
+		break;
+	case LPASS_CDC_MACRO_EVT_IMPED_TRUE:
+		lpass_cdc_rx_macro_wcd_clsh_imped_config(component, data, true);
+		break;
+	case LPASS_CDC_MACRO_EVT_IMPED_FALSE:
+		lpass_cdc_rx_macro_wcd_clsh_imped_config(component, data, false);
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_DOWN:
+		rx_priv->pre_dev_up = false;
+		rx_priv->dev_up = false;
+		if (rx_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(rx_dev) ||
+		     !pm_runtime_suspended(rx_dev))) {
+			ret = lpass_cdc_runtime_suspend(rx_dev);
+			if (!ret) {
+				pm_runtime_disable(rx_dev);
+				pm_runtime_set_suspended(rx_dev);
+				pm_runtime_enable(rx_dev);
+			}
+		}
+		break;
+	case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
+		rx_priv->pre_dev_up = true;
+		ret = lpass_cdc_rx_macro_core_vote(rx_priv, true);
+		if (ret < 0) {
+			dev_err_ratelimited(rx_priv->dev,
+				"%s: rx request core vote failed\n",
+				__func__);
+			break;
+		}
+		/* enable&disable RX_CORE_CLK to reset GFMUX reg */
+		ret = lpass_cdc_clk_rsc_request_clock(rx_priv->dev,
+						rx_priv->default_clk_id,
+						RX_CORE_CLK, true);
+		if (ret < 0)
+			dev_err_ratelimited(rx_priv->dev,
+				"%s, failed to enable clk, ret:%d\n",
+				__func__, ret);
+		else
+			lpass_cdc_clk_rsc_request_clock(rx_priv->dev,
+						rx_priv->default_clk_id,
+						RX_CORE_CLK, false);
+		lpass_cdc_rx_macro_core_vote(rx_priv, false);
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_UP:
+		rx_priv->dev_up = true;
+		/* reset swr after ssr/pdr */
+		rx_priv->reset_swr = true;
+
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case LPASS_CDC_MACRO_EVT_CLK_RESET:
+		lpass_cdc_rsc_clk_reset(rx_dev, RX_CORE_CLK);
+		lpass_cdc_rsc_clk_reset(rx_dev, RX_TX_CORE_CLK);
+		break;
+	case LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE:
+		rx_priv->rx0_gain_val = snd_soc_component_read(component,
+					LPASS_CDC_RX_RX0_RX_VOL_CTL);
+		rx_priv->rx1_gain_val = snd_soc_component_read(component,
+					LPASS_CDC_RX_RX1_RX_VOL_CTL);
+		if (data) {
+			/* Reduce gain by half only if its greater than -6DB */
+			if ((rx_priv->rx0_gain_val >= LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx0_gain_val <= LPASS_CDC_RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val -
+					 LPASS_CDC_RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >= LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx1_gain_val <= LPASS_CDC_RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val -
+					 LPASS_CDC_RX_MACRO_MOD_GAIN));
+		}
+		else {
+			/* Reset gain value to default */
+			if ((rx_priv->rx0_gain_val >=
+			    (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY - LPASS_CDC_RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx0_gain_val <= (LPASS_CDC_RX_MACRO_GAIN_MAX_VAL -
+			    LPASS_CDC_RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val +
+					 LPASS_CDC_RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >=
+			    (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY - LPASS_CDC_RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx1_gain_val <= (LPASS_CDC_RX_MACRO_GAIN_MAX_VAL -
+			    LPASS_CDC_RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val +
+					 LPASS_CDC_RX_MACRO_MOD_GAIN));
+		}
+		break;
+	case LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE:
+		/* Enable hd2 config for hphl*/
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX0_RX_PATH_CFG0, 0x04, data);
+		break;
+	case LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE:
+		/* Enable hd2 config for hphr*/
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX1_RX_PATH_CFG0, 0x04, data);
+		break;
+	}
+done:
+	return ret;
+}
+
+static int lpass_cdc_rx_macro_find_playback_dai_id_for_port(int port_id,
+						  struct lpass_cdc_rx_macro_priv *rx_priv)
+{
+	int i = 0;
+
+	for (i = RX_MACRO_AIF1_PB; i < LPASS_CDC_RX_MACRO_MAX_DAIS; i++) {
+		if (test_bit(port_id, &rx_priv->active_ch_mask[i]))
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static int lpass_cdc_rx_macro_set_idle_detect_thr(struct snd_soc_component *component,
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					int interp, int path_type)
+{
+	int port_id[4] = { 0, 0, 0, 0 };
+	int *port_ptr = NULL;
+	int num_ports = 0;
+	int bit_width = 0, i = 0;
+	int mux_reg = 0, mux_reg_val = 0;
+	int dai_id = 0, idle_thr = 0;
+
+	if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
+		return 0;
+
+	if (!rx_priv->idle_det_cfg.hph_idle_detect_en)
+		return 0;
+
+	port_ptr = &port_id[0];
+	num_ports = 0;
+
+	/*
+	 * Read interpolator MUX input registers and find
+	 * which cdc_dma port is connected and store the port
+	 * numbers in port_id array.
+	 */
+	if (path_type == INTERP_MIX_PATH) {
+		mux_reg = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1 +
+						2 * interp;
+		mux_reg_val = snd_soc_component_read(component, mux_reg) &
+				0x0f;
+
+		if ((mux_reg_val >= INTn_2_INP_SEL_RX0) &&
+		   (mux_reg_val <= INTn_2_INP_SEL_RX5)) {
+			*port_ptr++ = mux_reg_val - 1;
+			num_ports++;
+		}
+	}
+
+	if (path_type == INTERP_MAIN_PATH) {
+		mux_reg = LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0 +
+			  2 * (interp - 1);
+		mux_reg_val = snd_soc_component_read(component, mux_reg) &
+				0x0f;
+		i = LPASS_CDC_RX_MACRO_INTERP_MUX_NUM_INPUTS;
+
+		while (i) {
+			if ((mux_reg_val >= INTn_1_INP_SEL_RX0) &&
+			    (mux_reg_val <= INTn_1_INP_SEL_RX5)) {
+				*port_ptr++ = mux_reg_val -
+					INTn_1_INP_SEL_RX0;
+				num_ports++;
+			}
+			mux_reg_val =
+				(snd_soc_component_read(component, mux_reg) &
+					0xf0) >> 4;
+			mux_reg += 1;
+			i--;
+		}
+	}
+
+	dev_dbg(component->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n",
+		__func__, num_ports, port_id[0], port_id[1],
+		port_id[2], port_id[3]);
+
+	i = 0;
+	while (num_ports) {
+		dai_id = lpass_cdc_rx_macro_find_playback_dai_id_for_port(port_id[i++],
+								rx_priv);
+
+		if ((dai_id >= 0) && (dai_id < LPASS_CDC_RX_MACRO_MAX_DAIS)) {
+			dev_dbg(component->dev, "%s: dai_id: %d bit_width: %d\n",
+				__func__, dai_id,
+				rx_priv->bit_width[dai_id]);
+
+			if (rx_priv->bit_width[dai_id] > bit_width)
+				bit_width = rx_priv->bit_width[dai_id];
+		}
+		num_ports--;
+	}
+
+	switch (bit_width) {
+	case 16:
+		idle_thr = 0xff; /* F16 */
+		break;
+	case 24:
+	case 32:
+		idle_thr = 0x03; /* F22 */
+		break;
+	default:
+		idle_thr = 0x00;
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
+		__func__, idle_thr, rx_priv->idle_det_cfg.hph_idle_thr);
+
+	if ((rx_priv->idle_det_cfg.hph_idle_thr == 0) ||
+	    (idle_thr < rx_priv->idle_det_cfg.hph_idle_thr)) {
+		snd_soc_component_write(component,
+			LPASS_CDC_RX_IDLE_DETECT_CFG3, idle_thr);
+		rx_priv->idle_det_cfg.hph_idle_thr = idle_thr;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_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 = 0, mix_reg = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (w->shift >= INTERP_MAX) {
+		dev_err_ratelimited(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	}
+
+	gain_reg = LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL +
+				(w->shift * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	mix_reg = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL +
+				(w->shift * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		lpass_cdc_rx_macro_set_idle_detect_thr(component, rx_priv, w->shift,
+					INTERP_MIX_PATH);
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		/* Clk Enable */
+		snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+		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, 0x20, 0x00);
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		/* Reset enable and disable */
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static bool lpass_cdc_rx_macro_adie_lb(struct snd_soc_component *component,
+			     int interp_idx)
+{
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
+
+	int_mux_cfg0 = LPASS_CDC_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;
+	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;
+
+	int_n_inp1 = int_mux_cfg0_val >> 4;
+	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;
+
+	int_n_inp2 = int_mux_cfg1_val >> 4;
+	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 lpass_cdc_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 = 0;
+	u16 reg = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (w->shift >= INTERP_MAX) {
+		dev_err_ratelimited(component->dev, "%s: Invalid Interpolator value %d for name %s\n",
+			__func__, w->shift, w->name);
+		return -EINVAL;
+	}
+
+	reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + (w->shift *
+						LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	gain_reg = LPASS_CDC_RX_RX0_RX_VOL_CTL + (w->shift *
+						LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		lpass_cdc_rx_macro_set_idle_detect_thr(component, rx_priv, w->shift,
+						INTERP_MAIN_PATH);
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		if (lpass_cdc_rx_macro_adie_lb(component, w->shift))
+			snd_soc_component_update_bits(component,
+						reg, 0x20, 0x20);
+		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:
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_droop_setting(struct snd_soc_component *component,
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					int interp_n, int event)
+{
+	u8 pcm_rate = 0, val = 0;
+	u16 rx0_path_ctl_reg = 0, rx_path_cfg3_reg = 0;
+
+	if (rx_priv->is_pcm_enabled)
+		return;
+
+	rx_path_cfg3_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG3 +
+					(interp_n * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	rx0_path_ctl_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL +
+					(interp_n * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	pcm_rate = (snd_soc_component_read(component, rx0_path_ctl_reg)
+						& 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, rx_path_cfg3_reg,
+					0x03, val);
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		snd_soc_component_update_bits(component, rx_path_cfg3_reg,
+					0x03, 0x03);
+}
+
+static int lpass_cdc_rx_macro_config_compander(struct snd_soc_component *component,
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				int interp_n, int event)
+{
+	int comp = 0;
+	u16 comp_ctl0_reg = 0, rx_path_cfg0_reg = 0;
+	u16 comp_coeff_lsb_reg = 0, comp_coeff_msb_reg = 0;
+	u16 mode = rx_priv->hph_pwr_mode;
+#ifdef CONFIG_BOLERO_VER_2P6
+	u16 comp_ctl8_reg = 0;
+#endif
+
+	/* AUX does not have compander */
+	if (interp_n == INTERP_AUX)
+		return 0;
+
+	comp = interp_n;
+	if (!rx_priv->comp_enabled[comp])
+		return 0;
+	if (rx_priv->is_pcm_enabled)
+		return 0;
+
+	if (rx_priv->is_ear_mode_on && interp_n == INTERP_HPHL)
+		mode = RX_MODE_EAR;
+
+	if (interp_n == INTERP_HPHL) {
+		comp_coeff_lsb_reg = LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB;
+		comp_coeff_msb_reg = LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB;
+	} else if (interp_n == INTERP_HPHR) {
+		comp_coeff_lsb_reg = LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB;
+		comp_coeff_msb_reg = LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB;
+	} else {
+		/* compander coefficients are loaded only for hph path */
+		return 0;
+	}
+	comp_ctl0_reg = LPASS_CDC_RX_COMPANDER0_CTL0 +
+					(comp * LPASS_CDC_RX_MACRO_COMP_OFFSET);
+#ifdef CONFIG_BOLERO_VER_2P6
+	comp_ctl8_reg = LPASS_CDC_RX_COMPANDER0_CTL8 +
+					(comp * LPASS_CDC_RX_MACRO_COMP_OFFSET);
+#endif
+	rx_path_cfg0_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0 +
+					(comp * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		lpass_cdc_load_compander_coeff(component,
+				comp_coeff_lsb_reg, comp_coeff_msb_reg,
+				comp_coeff_table[rx_priv->hph_pwr_mode],
+				COMP_MAX_COEFF);
+#ifdef CONFIG_BOLERO_VER_2P6
+		lpass_cdc_update_compander_setting(component,
+					comp_ctl8_reg,
+					&comp_setting_table[mode]);
+#endif
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x01, 0x01);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+					0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x04, 0x04);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x01, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+					0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_enable_softclip_clk(struct snd_soc_component *component,
+					 struct lpass_cdc_rx_macro_priv *rx_priv,
+					 bool enable)
+{
+	if (enable) {
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x01);
+		rx_priv->softclip_clk_users++;
+	} else {
+		rx_priv->softclip_clk_users--;
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x00);
+	}
+}
+
+static int lpass_cdc_rx_macro_config_softclip(struct snd_soc_component *component,
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				int event)
+{
+	dev_dbg(component->dev, "%s: event %d, enabled %d\n",
+		__func__, event, rx_priv->is_softclip_on);
+
+	if (!rx_priv->is_softclip_on)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock */
+		lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, true);
+		/* Enable Softclip control */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x00);
+		lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, false);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_config_aux_hpf(struct snd_soc_component *component,
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				int event)
+{
+	dev_dbg(component->dev, "%s: event %d, enabled %d\n",
+		__func__, event, rx_priv->is_aux_hpf_on);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Update Aux HPF control */
+		if (!rx_priv->is_aux_hpf_on)
+			snd_soc_component_update_bits(component,
+				LPASS_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,
+			LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04);
+	}
+
+	return 0;
+}
+
+
+static inline void
+lpass_cdc_rx_macro_enable_clsh_block(struct lpass_cdc_rx_macro_priv *rx_priv, bool enable)
+{
+	if ((enable && ++rx_priv->clsh_users == 1) ||
+	    (!enable && --rx_priv->clsh_users == 0))
+		snd_soc_component_update_bits(rx_priv->component,
+				LPASS_CDC_RX_CLSH_CRC, 0x01,
+				(u8) enable);
+	if (rx_priv->clsh_users < 0)
+		rx_priv->clsh_users = 0;
+	dev_dbg(rx_priv->dev, "%s: clsh_users %d, enable %d", __func__,
+		rx_priv->clsh_users, enable);
+}
+
+static int lpass_cdc_rx_macro_config_classh(struct snd_soc_component *component,
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				int interp_n, int event)
+{
+	if (interp_n == INTERP_AUX)
+		return 0; /* AUX does not have Class-H */
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		lpass_cdc_rx_macro_enable_clsh_block(rx_priv, false);
+		return 0;
+	}
+
+	if (!SND_SOC_DAPM_EVENT_ON(event))
+		return 0;
+
+	lpass_cdc_rx_macro_enable_clsh_block(rx_priv, 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_update_bits(component,
+					LPASS_CDC_RX_CLSH_K1_LSB,
+					0xFF, 0xC0);
+		snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_CLSH_K1_MSB,
+					0x0F, 0x00);
+	}
+	switch (interp_n) {
+	case INTERP_HPHL:
+		if (rx_priv->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x1C);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_DECAY_CTRL,
+				0x07, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX0_RX_PATH_CFG0,
+				0x40, 0x40);
+		break;
+	case INTERP_HPHR:
+		if (rx_priv->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x1C);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_CLSH_DECAY_CTRL,
+				0x07, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX1_RX_PATH_CFG0,
+				0x40, 0x40);
+		break;
+	case INTERP_AUX:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX2_RX_PATH_CFG0,
+				0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX2_RX_PATH_CFG0,
+				0x10, 0x10);
+		break;
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_hd2_control(struct snd_soc_component *component,
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					u16 interp_idx, int event)
+{
+	u16 hd2_scale_reg = 0;
+	u16 hd2_enable_reg = 0;
+
+	if (rx_priv->is_pcm_enabled)
+		return;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hd2_scale_reg = LPASS_CDC_RX_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0;
+		break;
+	case INTERP_HPHR:
+		hd2_scale_reg = LPASS_CDC_RX_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_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,
+				0x3C, 0x14);
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+				0x04, 0x04);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+				0x04, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+				0x3C, 0x00);
+	}
+}
+
+static int lpass_cdc_rx_macro_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	struct device *rx_dev = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+		rx_priv->idle_det_cfg.hph_idle_detect_en;
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	struct device *rx_dev = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->idle_det_cfg.hph_idle_detect_en =
+		ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+#ifdef CONFIG_BOLERO_VER_2P6
+static int lpass_cdc_rx_macro_get_pcm_path(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_pcm_enabled;
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_put_pcm_path(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_pcm_enabled = ucontrol->value.integer.value[0];
+	return 0;
+}
+#endif
+
+static int lpass_cdc_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->comp_enabled[comp];
+	return 0;
+}
+
+static int lpass_cdc_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		__func__, comp + 1, rx_priv->comp_enabled[comp], value);
+	rx_priv->comp_enabled[comp] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			rx_priv->rx_port_value[widget->shift];
+	return 0;
+}
+
+static int lpass_cdc_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 = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	aif_rst = rx_priv->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err_ratelimited(rx_dev, "%s:AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst > RX_MACRO_AIF4_PB) {
+			dev_err_ratelimited(rx_dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	rx_priv->rx_port_value[widget->shift] = rx_port_value;
+
+	dev_dbg(rx_dev, "%s: mux input: %d, mux output: %d, aif_rst: %d\n",
+		__func__, rx_port_value, widget->shift, aif_rst);
+
+	switch (rx_port_value) {
+	case 0:
+		if (rx_priv->active_ch_cnt[aif_rst]) {
+			clear_bit(widget->shift,
+				&rx_priv->active_ch_mask[aif_rst]);
+			rx_priv->active_ch_cnt[aif_rst]--;
+		}
+		break;
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		set_bit(widget->shift,
+			&rx_priv->active_ch_mask[rx_port_value]);
+		rx_priv->active_ch_cnt[rx_port_value]++;
+		break;
+	default:
+		dev_err_ratelimited(component->dev,
+			"%s:Invalid AIF_ID for LPASS_CDC_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 int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_ear_mode_on;
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_ear_mode_on =
+			(!ucontrol->value.integer.value[0] ? false : true);
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->hph_hd2_mode;
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->hph_hd2_mode = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->hph_pwr_mode;
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->hph_pwr_mode = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+		((snd_soc_component_read(
+			component, LPASS_CDC_RX_BCL_VBAT_CFG) & 0x04) ?
+		  1 : 0);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_BCL_VBAT_CFG,
+					0x04, 0x04);
+	else
+		snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_BCL_VBAT_CFG,
+					0x04, 0x00);
+
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_softclip_on;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_softclip_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: soft clip enable = %d\n", __func__,
+		rx_priv->is_softclip_on);
+
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_aux_hpf_on;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_aux_hpf_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: aux hpf enable = %d\n", __func__,
+		rx_priv->is_aux_hpf_on);
+
+	return 0;
+}
+
+
+static int lpass_cdc_rx_macro_enable_vbat(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 device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x80, 0x80);
+		/* Update DSM FS rate */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x02, 0x02);
+		/* Use attenuation mode */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_CFG, 0x02, 0x00);
+		/* BCL block needs softclip clock to be enabled */
+		lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, true);
+		/* Enable VBAT at channel level */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+#ifdef CONFIG_BOLERO_VER_2P6
+                /* Enable CB decode block clock */
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
+                /* Enable BCL path */
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
+                /* Request for BCL data */
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
+#endif
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+#ifdef CONFIG_BOLERO_VER_2P6
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
+                snd_soc_component_update_bits(component,
+                        LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
+#endif
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX2_RX_PATH_CFG1,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX2_RX_PATH_SEC7,
+				0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_CFG,
+				0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_RX2_RX_PATH_CFG1,
+				0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+				0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+				0xFF, 0x00);
+		lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, false);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err_ratelimited(rx_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_idle_detect_control(struct snd_soc_component *component,
+					 struct lpass_cdc_rx_macro_priv *rx_priv,
+					 int interp, int event)
+{
+	int reg = 0, mask = 0, val = 0;
+
+	if (!rx_priv->idle_det_cfg.hph_idle_detect_en)
+		return;
+
+	if (!rx_priv->is_pcm_enabled)
+		return;
+
+	if (interp == INTERP_HPHL) {
+		reg = LPASS_CDC_RX_IDLE_DETECT_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == INTERP_HPHR) {
+		reg = LPASS_CDC_RX_IDLE_DETECT_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event))
+		snd_soc_component_update_bits(component, reg, mask, val);
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		rx_priv->idle_det_cfg.hph_idle_thr = 0;
+		snd_soc_component_write(component,
+				LPASS_CDC_RX_IDLE_DETECT_CFG3, 0x0);
+	}
+}
+
+static void lpass_cdc_rx_macro_hphdelay_lutbypass(struct snd_soc_component *component,
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					u16 interp_idx, int event)
+{
+	u16 hph_lut_bypass_reg = 0;
+	u16 hph_comp_ctrl7 = 0;
+
+	if (rx_priv->is_pcm_enabled)
+		return;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hph_lut_bypass_reg = LPASS_CDC_RX_TOP_HPHL_COMP_LUT;
+		hph_comp_ctrl7 = LPASS_CDC_RX_COMPANDER0_CTL7;
+		break;
+	case INTERP_HPHR:
+		hph_lut_bypass_reg = LPASS_CDC_RX_TOP_HPHR_COMP_LUT;
+		hph_comp_ctrl7 = LPASS_CDC_RX_COMPANDER1_CTL7;
+		break;
+	default:
+		break;
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		if (interp_idx == INTERP_HPHL) {
+			if (rx_priv->is_ear_mode_on)
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX0_RX_PATH_CFG1,
+					0x02, 0x02);
+			else
+				snd_soc_component_update_bits(component,
+					hph_lut_bypass_reg,
+					0x80, 0x80);
+		} else {
+			snd_soc_component_update_bits(component,
+					hph_lut_bypass_reg,
+					0x80, 0x80);
+		}
+		if (rx_priv->hph_pwr_mode)
+			snd_soc_component_update_bits(component,
+					hph_comp_ctrl7,
+					0x20, 0x00);
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component,
+					LPASS_CDC_RX_RX0_RX_PATH_CFG1,
+					0x02, 0x00);
+		snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+					0x80, 0x00);
+		snd_soc_component_update_bits(component, hph_comp_ctrl7,
+					0x20, 0x20);
+	}
+}
+
+static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx)
+{
+	u16 main_reg = 0, dsm_reg = 0, rx_cfg2_reg = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	main_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL +
+			(interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	dsm_reg = LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL +
+			(interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+	if (interp_idx == INTERP_AUX)
+		dsm_reg = LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL;
+	rx_cfg2_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG2 +
+			(interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (rx_priv->main_clk_users[interp_idx] == 0) {
+			/* Main path PGA mute enable */
+			snd_soc_component_update_bits(component, main_reg,
+					0x10, 0x10);
+			snd_soc_component_update_bits(component, dsm_reg,
+					0x01, 0x01);
+			/* Clk Enable */
+			snd_soc_component_update_bits(component, main_reg,
+					0x20, 0x20);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+					0x03, 0x03);
+			lpass_cdc_rx_macro_idle_detect_control(component, rx_priv,
+					interp_idx, event);
+			if (rx_priv->hph_hd2_mode)
+				lpass_cdc_rx_macro_hd2_control(
+					component, rx_priv, interp_idx, event);
+			lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv,
+						    interp_idx, event);
+			lpass_cdc_rx_macro_droop_setting(component,
+						rx_priv, interp_idx, event);
+			lpass_cdc_rx_macro_config_compander(component, rx_priv,
+						interp_idx, event);
+			if (interp_idx == INTERP_AUX) {
+				lpass_cdc_rx_macro_config_softclip(component, rx_priv,
+							event);
+				lpass_cdc_rx_macro_config_aux_hpf(component, rx_priv,
+							event);
+			}
+			lpass_cdc_rx_macro_config_classh(component, rx_priv,
+						interp_idx, event);
+			/*select PCM path and swr clk is 9.6MHz*/
+			if (rx_priv->is_pcm_enabled && !rx_priv->is_native_on &&
+					interp_idx != INTERP_AUX) {
+				if (rx_priv->pcm_select_users == 0)
+					snd_soc_component_update_bits(component,
+						LPASS_CDC_RX_TOP_SWR_CTRL, 0x02, 0x02);
+				++rx_priv->pcm_select_users;
+			}
+			lpass_cdc_notify_wcd_rx_clk(rx_dev, rx_priv->is_native_on);
+		}
+		rx_priv->main_clk_users[interp_idx]++;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		rx_priv->main_clk_users[interp_idx]--;
+		if (rx_priv->main_clk_users[interp_idx] <= 0) {
+			rx_priv->main_clk_users[interp_idx] = 0;
+			/* Main path PGA mute enable */
+			snd_soc_component_update_bits(component, main_reg,
+					0x10, 0x10);
+			/*Unselect PCM path*/
+			if (rx_priv->is_pcm_enabled && !rx_priv->is_native_on &&
+					interp_idx != INTERP_AUX) {
+				if (rx_priv->pcm_select_users == 1)
+					snd_soc_component_update_bits(component,
+						LPASS_CDC_RX_TOP_SWR_CTRL, 0x02, 0x00);
+				--rx_priv->pcm_select_users;
+				if (rx_priv->pcm_select_users < 0)
+					rx_priv->pcm_select_users = 0;
+			}
+
+			/* Clk Disable */
+			snd_soc_component_update_bits(component, dsm_reg,
+						0x01, 0x00);
+			snd_soc_component_update_bits(component, main_reg,
+						0x20, 0x00);
+			/* Reset enable and disable */
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x40);
+			snd_soc_component_update_bits(component, main_reg,
+						0x40, 0x00);
+			/* Reset rate to 48K*/
+			snd_soc_component_update_bits(component, main_reg,
+						0x0F, 0x04);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+						0x03, 0x00);
+			lpass_cdc_rx_macro_config_classh(component, rx_priv,
+						interp_idx, event);
+			lpass_cdc_rx_macro_config_compander(component, rx_priv,
+						interp_idx, event);
+			if (interp_idx ==  INTERP_AUX) {
+				lpass_cdc_rx_macro_config_softclip(component, rx_priv,
+							event);
+				lpass_cdc_rx_macro_config_aux_hpf(component, rx_priv,
+				event);
+			}
+			lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv,
+						interp_idx, event);
+			if (rx_priv->hph_hd2_mode)
+				lpass_cdc_rx_macro_hd2_control(component,
+					rx_priv, interp_idx, event);
+			lpass_cdc_rx_macro_idle_detect_control(component, rx_priv,
+					interp_idx, event);
+		}
+	}
+
+	dev_dbg(component->dev, "%s event %d main_clk_users %d\n",
+		__func__,  event, rx_priv->main_clk_users[interp_idx]);
+
+	return rx_priv->main_clk_users[interp_idx];
+}
+
+static int lpass_cdc_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);
+	u16 sidetone_reg = 0, fs_reg = 0;
+
+	dev_dbg(component->dev, "%s %d %d\n", __func__, event, w->shift);
+	sidetone_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG1 +
+			LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * (w->shift);
+	fs_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL +
+			LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * (w->shift);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		snd_soc_component_update_bits(component, sidetone_reg,
+					0x10, 0x10);
+		snd_soc_component_update_bits(component, fs_reg,
+					0x20, 0x20);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, sidetone_reg,
+					0x10, 0x00);
+		lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	default:
+		break;
+	};
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_restore_iir_coeff(struct lpass_cdc_rx_macro_priv *rx_priv, int iir_idx,
+				int band_idx)
+{
+	u16 reg_add = 0, coeff_idx = 0, idx = 0;
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return;
+	}
+
+	regmap_write(regmap,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	reg_add = LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx;
+
+	/* 5 coefficients per band and 4 writes per coefficient */
+	for (coeff_idx = 0; coeff_idx < LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX;
+		coeff_idx++) {
+		/* Four 8 bit values(one 32 bit) per coefficient */
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+		regmap_write(regmap, reg_add,
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]);
+	}
+}
+
+static int lpass_cdc_rx_macro_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	/* IIR filter band registers are at integer multiples of 0x80 */
+	u16 iir_reg = LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx;
+
+	ucontrol->value.integer.value[0] = (
+				snd_soc_component_read(component, iir_reg) &
+				(1 << band_idx)) != 0;
+
+	dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	bool iir_band_en_status = 0;
+	int value = ucontrol->value.integer.value[0];
+	u16 iir_reg = LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	lpass_cdc_rx_macro_restore_iir_coeff(rx_priv, iir_idx, band_idx);
+
+	/* Mask first 5 bits, 6-8 are reserved */
+	snd_soc_component_update_bits(component, iir_reg, (1 << band_idx),
+			    (value << band_idx));
+
+	iir_band_en_status = ((snd_soc_component_read(component, iir_reg) &
+			      (1 << band_idx)) != 0);
+	dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx, iir_band_en_status);
+	return 0;
+}
+
+static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+				   int iir_idx, int band_idx,
+				   int coeff_idx)
+{
+	uint32_t value = 0;
+
+	/* Address does not automatically update if reading */
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t)) & 0x7F);
+
+	value |= snd_soc_component_read(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx));
+
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_component_read(component,
+			       (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				0x80 * iir_idx)) << 8);
+
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_component_read(component,
+			       (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				0x80 * iir_idx)) << 16);
+
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		((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,
+				(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL +
+				 0x80 * iir_idx)) & 0x3F) << 24);
+
+	return value;
+}
+
+static int lpass_cdc_rx_macro_iir_filter_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *ucontrol)
+{
+	struct lpass_cdc_rx_macro_iir_filter_ctl *ctl =
+		(struct lpass_cdc_rx_macro_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 int lpass_cdc_rx_macro_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_iir_filter_ctl *ctl =
+		(struct lpass_cdc_rx_macro_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 coeff_idx = 0;
+
+	for (coeff_idx = 0; coeff_idx < LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX;
+			coeff_idx++) {
+		coeff[coeff_idx] =
+			get_iir_band_coeff(component, iir_idx, band_idx, coeff_idx);
+	}
+
+	memcpy(ucontrol->value.bytes.data, &coeff[0], params->max);
+
+	dev_dbg(component->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx, coeff[0],
+		__func__, iir_idx, band_idx, coeff[1],
+		__func__, iir_idx, band_idx, coeff[2],
+		__func__, iir_idx, band_idx, coeff[3],
+		__func__, iir_idx, band_idx, coeff[4]);
+	return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_component *component,
+			       int iir_idx, int band_idx,
+			       uint32_t value)
+{
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value & 0xFF));
+
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 8) & 0xFF);
+
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 16) & 0xFF);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_component_write(component,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx),
+		(value >> 24) & 0x3F);
+}
+
+static int lpass_cdc_rx_macro_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_iir_filter_ctl *ctl =
+			(struct lpass_cdc_rx_macro_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 coeff_idx, idx = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	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,
+		(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	/* Store the coefficients in sidetone coeff array */
+	for (coeff_idx = 0; coeff_idx < LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX;
+		coeff_idx++) {
+		uint32_t value = coeff[coeff_idx];
+
+		set_iir_band_coeff(component, iir_idx, band_idx, value);
+
+		/* Four 8 bit values(one 32 bit) per coefficient */
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+								(value & 0xFF);
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 8) & 0xFF;
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 16) & 0xFF;
+		rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 24) & 0xFF;
+	}
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 0),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 1),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 2),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 3),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(component, iir_idx, band_idx, 4));
+	return 0;
+}
+
+static int lpass_cdc_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);
+
+	dev_dbg(component->dev, "%s: event = %d\n", __func__, event);
+
+	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,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
+		} else {
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL));
+		}
+		break;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_BOLERO_VER_2P6
+static int lpass_cdc_rx_macro_fir_filter_enable_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.bytes.data[0] = (unsigned char)rx_priv->is_fir_filter_on;
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_fir_filter_enable_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	int ret = 0;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (!rx_priv->hifi_fir_clk) {
+		dev_dbg(rx_priv->dev, "%s: Undefined HIFI FIR Clock.\n",
+				__func__);
+		return 0;
+	}
+
+	if (!rx_priv->is_fir_capable) {
+		dev_dbg(rx_priv->dev, "%s: HIFI FIR is not supported.\n",
+				__func__);
+		return 0;
+	}
+
+	rx_priv->is_fir_filter_on =
+			(!ucontrol->value.bytes.data[0] ? false : true);
+
+	dev_dbg(rx_priv->dev, "%s:is_fir_filter_on=%d\n",
+				__func__, rx_priv->is_fir_filter_on);
+
+	if (rx_priv->is_fir_filter_on) {
+		ret = clk_prepare_enable(rx_priv->hifi_fir_clk);
+		if (ret < 0) {
+			dev_err_ratelimited(rx_priv->dev, "%s:hifi_fir_clk enable failed\n",
+						__func__);
+			return ret;
+		}
+
+		snd_soc_component_write(component, LPASS_CDC_RX_RX0_RX_FIR_CFG,
+					rx_priv->fir_total_coeff_num[RX0_PATH]);
+		dev_dbg(component->dev, "%s: HIFI FIR Path:%d total coefficients"
+				" number written: %d.\n",
+				__func__, RX0_PATH,
+				rx_priv->fir_total_coeff_num[RX0_PATH]);
+		snd_soc_component_write(component, LPASS_CDC_RX_RX1_RX_FIR_CFG,
+					rx_priv->fir_total_coeff_num[RX1_PATH]);
+		dev_dbg(component->dev, "%s: HIFI FIR Path:%d total coefficients"
+				" number written: %d.\n",
+				__func__, RX1_PATH,
+				rx_priv->fir_total_coeff_num[RX1_PATH]);
+
+		/* Enable HIFI_FEAT_EN bit */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_TOP_TOP_CFG1, 0x01, 0x01);
+		/* Enable FIR_CLK_EN */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX0_RX_PATH_CTL, 0x80, 0x80);
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX1_RX_PATH_CTL, 0x80, 0x80);
+		/* Start the FIR filter */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX0_RX_FIR_CTL, 0x0D, 0x05);
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX1_RX_FIR_CTL, 0x0D, 0x05);
+	} else {
+		/* Stop the FIR filter */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX0_RX_FIR_CTL, 0x0D, 0x00);
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX1_RX_FIR_CTL, 0x0D, 0x00);
+		/* Disable FIR_CLK_EN */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX0_RX_PATH_CTL, 0x80, 0x00);
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_RX1_RX_PATH_CTL, 0x80, 0x00);
+		/* Disable HIFI_FEAT_EN bit */
+		snd_soc_component_update_bits(component, LPASS_CDC_RX_TOP_TOP_CFG1, 0x01, 0x00);
+
+		clk_disable_unprepare(rx_priv->hifi_fir_clk);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_fir_filter_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *ucontrol)
+{
+	struct lpass_cdc_rx_macro_fir_filter_ctl *ctl =
+		(struct lpass_cdc_rx_macro_fir_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 int lpass_cdc_rx_macro_fir_audio_mixer_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_fir_filter_ctl *ctl =
+		(struct lpass_cdc_rx_macro_fir_filter_ctl *)kcontrol->private_value;
+	unsigned int path_idx = ctl->path_idx;
+	unsigned int grp_idx = ctl->grp_idx;
+	u32 num_coeff_grp = 0;
+	u32 readArray[LPASS_CDC_RX_MACRO_FIR_COEFF_ARRAY_MAX];
+
+	unsigned int coeff_idx = 0, array_idx = 0;
+	unsigned int copy_size;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (path_idx >= FIR_PATH_MAX) {
+		dev_err_ratelimited(rx_priv->dev, "%s: path_idx:%d is invalid\n",
+			__func__, path_idx);
+		return -EINVAL;
+	}
+
+	if (grp_idx >= GRP_MAX) {
+		dev_err_ratelimited(rx_priv->dev, "%s: grp_idx:%d is invalid\n",
+			__func__, grp_idx);
+		return -EINVAL;
+	}
+
+	num_coeff_grp = rx_priv->num_fir_coeff[path_idx][grp_idx];
+	readArray[array_idx++] = num_coeff_grp;
+
+	for (coeff_idx = 0; coeff_idx < num_coeff_grp; coeff_idx++) {
+		readArray[array_idx++] =
+				rx_priv->fir_coeff_array[path_idx][grp_idx][coeff_idx];
+	}
+	copy_size = array_idx;
+
+	memcpy(ucontrol->value.bytes.data, &readArray[0], sizeof(readArray[0]) * copy_size);
+
+	return 0;
+}
+
+static int set_fir_filter_coeff(struct snd_soc_component *component,
+				struct lpass_cdc_rx_macro_priv *rx_priv,
+				unsigned int path_idx)
+{
+	int grp_idx = 0, coeff_idx = 0;
+	unsigned int ret = 0;
+	unsigned int max_coeff_num, num_coeff_grp;
+	unsigned int path_ctl_addr = 0, wdata0_addr = 0, coeff_addr = 0;
+	unsigned int fir_ctl_addr = 0;
+	bool all_coeff_written = true;
+
+	switch (path_idx) {
+	case RX0_PATH:
+		path_ctl_addr = LPASS_CDC_RX_RX0_RX_PATH_CTL;
+		wdata0_addr = LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA0;
+		coeff_addr = LPASS_CDC_RX_RX0_RX_FIR_COEFF_ADDR;
+		fir_ctl_addr = LPASS_CDC_RX_RX0_RX_FIR_CTL;
+		break;
+	case RX1_PATH:
+		path_ctl_addr = LPASS_CDC_RX_RX1_RX_PATH_CTL;
+		wdata0_addr = LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA0;
+		coeff_addr = LPASS_CDC_RX_RX1_RX_FIR_COEFF_ADDR;
+		fir_ctl_addr = LPASS_CDC_RX_RX1_RX_FIR_CTL;
+		break;
+	default:
+		dev_err_ratelimited(rx_priv->dev,
+			"%s: inavlid FIR ID: %d\n", __func__, path_idx);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	max_coeff_num = LPASS_CDC_RX_MACRO_FIR_COEFF_MAX;
+
+	for (grp_idx = 0; grp_idx < GRP_MAX; grp_idx++)
+		all_coeff_written = all_coeff_written &&
+				rx_priv->is_fir_coeff_written[path_idx][grp_idx];
+
+	if (all_coeff_written)
+		goto exit;
+
+	ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 1, false);
+	if (ret < 0) {
+		dev_err_ratelimited(rx_priv->dev, "%s:rx_macro_mclk enable failed\n",
+					__func__);
+		goto exit;
+	}
+
+	ret = clk_prepare_enable(rx_priv->hifi_fir_clk);
+	if (ret < 0) {
+		dev_err_ratelimited(rx_priv->dev, "%s:hifi_fir_clk enable failed\n",
+					__func__);
+		goto disable_mclk_block;
+	}
+
+	/* Enable HIFI_FEAT_EN bit */
+	snd_soc_component_update_bits(component, LPASS_CDC_RX_TOP_TOP_CFG1, 0x01, 0x01);
+	/* Enable FIR_CLK_EN, datapath reset */
+	snd_soc_component_update_bits(component, path_ctl_addr, 0xC0, 0xC0);
+	/* Enable FIR_CLK_EN, Release Reset */
+	snd_soc_component_update_bits(component, path_ctl_addr, 0xC0, 0x80);
+
+	/* wait for data ram initialization after enabling clock  */
+	usleep_range(10, 11);
+
+	for (grp_idx = 0; grp_idx < GRP_MAX; grp_idx++) {
+		unsigned int coeff_idx_start = 0, array_idx = 0;
+
+		/* Skip if this group is written and no futher update */
+		if (rx_priv->is_fir_coeff_written[path_idx][grp_idx])
+			continue;
+
+		num_coeff_grp = rx_priv->num_fir_coeff[path_idx][grp_idx];
+		if (num_coeff_grp > max_coeff_num) {
+			dev_err_ratelimited(rx_priv->dev,
+				"%s: inavlid number of RX_FIR coefficients:%d"
+				" in path:%d, group:%d\n",
+				__func__, num_coeff_grp, path_idx, grp_idx);
+			ret = -EINVAL;
+			goto disable_FIR;
+		}
+		coeff_idx_start = grp_idx * max_coeff_num;
+
+		for (coeff_idx = coeff_idx_start;
+			coeff_idx < coeff_idx_start + num_coeff_grp / 2 * 2;
+			coeff_idx += 2) {
+
+			unsigned int addr_offset = coeff_idx / 2;
+
+			/* First coefficient in pair */
+			u32 value = rx_priv->fir_coeff_array[path_idx][grp_idx][array_idx++];
+			dev_dbg(rx_priv->dev, "%s: val of coeff_idx:%d, COEFF:0x%x\n",
+						__func__, coeff_idx, value);
+			snd_soc_component_write(component, wdata0_addr,
+					value & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x4,
+					(value >> 8) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x8,
+					(value >> 16) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0xC,
+					(value >> 24) & 0xFF);
+
+			/* Second coefficient in pair */
+			value = rx_priv->fir_coeff_array[path_idx][grp_idx][array_idx++];
+			dev_dbg(rx_priv->dev, "%s: val of coeff_idx:%d, COEFF:0x%x\n",
+						__func__, coeff_idx, value);
+			snd_soc_component_write(component, wdata0_addr + 0x10,
+					value & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x14,
+					(value >> 8) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x18,
+					(value >> 16) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x1C,
+					(value >> 24) & 0xFF);
+
+			snd_soc_component_write(component, coeff_addr, addr_offset);
+			snd_soc_component_update_bits(component, fir_ctl_addr, 0x02, 0x02);
+			usleep_range(13, 15);
+			snd_soc_component_update_bits(component, fir_ctl_addr, 0x02, 0x00);
+		}
+
+		/* odd number of coefficients in this group, handle last one */
+		if (num_coeff_grp % 2 != 0) {
+			int addr_offset = coeff_idx / 2;
+
+			/* First coefficient in pair */
+			u32 value = rx_priv->fir_coeff_array[path_idx][grp_idx][array_idx++];
+			dev_dbg(rx_priv->dev, "%s: val of coeff_idx:%d, COEFF:0x%x\n",
+						__func__, coeff_idx, value);
+			snd_soc_component_write(component, wdata0_addr,
+					value & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x4,
+					(value >> 8) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0x8,
+					(value >> 16) & 0xFF);
+			snd_soc_component_write(component, wdata0_addr + 0xC,
+					(value >> 24) & 0xFF);
+
+			/* Second coefficient in pair */
+			dev_dbg(rx_priv->dev, "%s: val of coeff_idx:%d, COEFF:0x%x\n",
+						__func__, coeff_idx, 0x0);
+			snd_soc_component_write(component, wdata0_addr + 0x10, 0x0);
+			snd_soc_component_write(component, wdata0_addr + 0x14, 0x0);
+			snd_soc_component_write(component, wdata0_addr + 0x18, 0x0);
+			snd_soc_component_write(component, wdata0_addr + 0x1C, 0x0);
+
+			snd_soc_component_write(component, coeff_addr, addr_offset);
+			snd_soc_component_update_bits(component, fir_ctl_addr, 0x02, 0x02);
+			usleep_range(13, 15);
+			snd_soc_component_update_bits(component, fir_ctl_addr, 0x02, 0x00);
+		}
+
+		rx_priv->is_fir_coeff_written[path_idx][grp_idx] = true;
+		dev_dbg(component->dev, "%s: HIFI FIR Path:%d Group:%d coefficients"
+					" updated.\n",
+					__func__, path_idx, grp_idx);
+	}
+
+disable_FIR:
+	/* disable FIR_CLK_EN */
+	snd_soc_component_update_bits(component, path_ctl_addr, 0x80, 0x00);
+
+	/* Disable HIFI_FEAT_EN bit */
+	snd_soc_component_update_bits(component, LPASS_CDC_RX_TOP_TOP_CFG1, 0x01, 0x00);
+
+	clk_disable_unprepare(rx_priv->hifi_fir_clk);
+
+disable_mclk_block:
+	lpass_cdc_rx_macro_mclk_enable(rx_priv, 0, false);
+
+exit:
+	return ret;
+}
+
+static int lpass_cdc_rx_macro_fir_audio_mixer_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_rx_macro_fir_filter_ctl *ctl =
+		(struct lpass_cdc_rx_macro_fir_filter_ctl *)kcontrol->private_value;
+	unsigned int path_idx = ctl->path_idx;
+	unsigned int grp_idx = ctl->grp_idx;
+	u32 ele_size = 0, num_coeff_grp = 0;
+	u32 coeff[LPASS_CDC_RX_MACRO_FIR_COEFF_ARRAY_MAX];
+
+	int ret = 0;
+	unsigned int stored_total_num = 0;
+	unsigned int grp_iidx = 0, coeff_idx = 0, array_idx = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (path_idx >= FIR_PATH_MAX) {
+		dev_err_ratelimited(rx_priv->dev, "%s: path_idx:%d is invalid\n",
+			__func__, path_idx);
+		return -EINVAL;
+	}
+
+	if (grp_idx >= GRP_MAX) {
+		dev_err_ratelimited(rx_priv->dev, "%s: grp_idx:%d is invalid\n",
+			__func__, grp_idx);
+		return -EINVAL;
+	}
+
+	if (!rx_priv->hifi_fir_clk) {
+		dev_dbg(rx_priv->dev, "%s: Undefined HIFI FIR Clock.\n",
+				__func__);
+		return 0;
+	}
+
+	if (!rx_priv->is_fir_capable) {
+		dev_dbg(rx_priv->dev, "%s: HIFI FIR is not supported.\n",
+				__func__);
+		return 0;
+	}
+
+	ele_size = sizeof(coeff[0]);
+	memcpy(&coeff[0], ucontrol->value.bytes.data, ele_size);
+	num_coeff_grp = coeff[0];
+
+	dev_dbg(rx_priv->dev, "%s: bytes.data: path:%d, grp:%d, num_coeff_grp:%d\n",
+		__func__, path_idx, grp_idx, num_coeff_grp);
+
+	if (num_coeff_grp > LPASS_CDC_RX_MACRO_FIR_COEFF_MAX) {
+		dev_err_ratelimited(rx_priv->dev,
+			"%s: inavlid number of RX_FIR coefficients:%d in path:%d, group:%d\n",
+				 __func__, num_coeff_grp, path_idx, grp_idx);
+		rx_priv->num_fir_coeff[path_idx][grp_idx] = 0;
+		return -EINVAL;
+	} else {
+		rx_priv->num_fir_coeff[path_idx][grp_idx] = num_coeff_grp;
+	}
+
+	memcpy(&coeff[1], &(ucontrol->value.bytes.data[ele_size]), ele_size * num_coeff_grp);
+
+	/* Store the coefficients in FIR coeff array */
+	array_idx = 1;
+	for (coeff_idx = 0; coeff_idx < num_coeff_grp; coeff_idx++)
+		rx_priv->fir_coeff_array[path_idx][grp_idx][coeff_idx] = coeff[array_idx++];
+
+	/* Clear the written flag so this group is ready to be written */
+	rx_priv->is_fir_coeff_written[path_idx][grp_idx] = false;
+
+	stored_total_num = 0;
+	for (grp_iidx = 0; grp_iidx < GRP_MAX; grp_iidx++) {
+		stored_total_num += rx_priv->num_fir_coeff[path_idx][grp_iidx];
+	}
+
+	/* Only write coeffs if total num matches, otherwise delay the write */
+	if (rx_priv->fir_total_coeff_num[path_idx] == stored_total_num)
+		ret = set_fir_filter_coeff(component, rx_priv, path_idx);
+
+	return ret;
+}
+
+static int lpass_cdc_rx_macro_fir_coeff_num_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	unsigned int path_idx = ((struct soc_multi_mixer_control *)
+				kcontrol->private_value)->shift;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (path_idx >= FIR_PATH_MAX) {
+		dev_err_ratelimited(rx_priv->dev, "%s: path_idx:%d is invalid\n",
+			__func__, path_idx);
+		return -EINVAL;
+	}
+
+	ucontrol->value.bytes.data[0] = rx_priv->fir_total_coeff_num[path_idx];
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_fir_coeff_num_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	unsigned int path_idx = ((struct soc_multi_mixer_control *)
+				kcontrol->private_value)->shift;
+	u8 fir_total_coeff_num = ucontrol->value.bytes.data[0];
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	unsigned int ret = 0;
+	unsigned int grp_idx, stored_total_num;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	if (fir_total_coeff_num > LPASS_CDC_RX_MACRO_FIR_COEFF_MAX * GRP_MAX) {
+		dev_err_ratelimited(rx_priv->dev,
+			"%s: inavlid total number of RX_FIR coefficients:%d"
+			" in path:%d\n",
+			__func__, fir_total_coeff_num, path_idx);
+		rx_priv->fir_total_coeff_num[path_idx] = 0;
+		return -EINVAL;
+	} else {
+		rx_priv->fir_total_coeff_num[path_idx] = fir_total_coeff_num;
+	}
+
+	dev_dbg(component->dev, "%s: HIFI FIR Path:%d total coefficients"
+				" number updated in private data: %d.\n",
+				__func__, path_idx, fir_total_coeff_num);
+
+	stored_total_num = 0;
+	for (grp_idx = 0; grp_idx < GRP_MAX; grp_idx++)
+		stored_total_num += rx_priv->num_fir_coeff[path_idx][grp_idx];
+
+	if (fir_total_coeff_num == stored_total_num)
+		ret = set_fir_filter_coeff(component, rx_priv, path_idx);
+
+	return ret;
+}
+#endif
+
+static const struct snd_kcontrol_new lpass_cdc_rx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume",
+			  LPASS_CDC_RX_RX0_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume",
+			  LPASS_CDC_RX_RX1_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume",
+			  LPASS_CDC_RX_RX2_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume",
+			  LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume",
+			  LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume",
+			  LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, LPASS_CDC_RX_MACRO_COMP1, 1, 0,
+		lpass_cdc_rx_macro_get_compander, lpass_cdc_rx_macro_set_compander),
+	SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_RX_MACRO_COMP2, 1, 0,
+		lpass_cdc_rx_macro_get_compander, lpass_cdc_rx_macro_set_compander),
+
+#ifdef CONFIG_BOLERO_VER_2P6
+	SOC_SINGLE_EXT("RX_HPH PCM", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_rx_macro_get_pcm_path, lpass_cdc_rx_macro_put_pcm_path),
+
+	SOC_SINGLE_EXT("RX0 FIR Coeff Num", SND_SOC_NOPM, RX0_PATH,
+			(LPASS_CDC_RX_MACRO_FIR_COEFF_MAX * GRP_MAX), 0,
+			lpass_cdc_rx_macro_fir_coeff_num_get, lpass_cdc_rx_macro_fir_coeff_num_put),
+
+	SOC_SINGLE_EXT("RX1 FIR Coeff Num", SND_SOC_NOPM, RX1_PATH,
+			(LPASS_CDC_RX_MACRO_FIR_COEFF_MAX * GRP_MAX), 0,
+			lpass_cdc_rx_macro_fir_coeff_num_get, lpass_cdc_rx_macro_fir_coeff_num_put),
+	SOC_ENUM_EXT("RX_FIR Filter", lpass_cdc_rx_macro_fir_filter_enum,
+		lpass_cdc_rx_macro_fir_filter_enable_get, lpass_cdc_rx_macro_fir_filter_enable_put),
+#endif
+
+	SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
+		lpass_cdc_rx_macro_hph_idle_detect_get, lpass_cdc_rx_macro_hph_idle_detect_put),
+
+	SOC_ENUM_EXT("RX_EAR Mode", lpass_cdc_rx_macro_ear_mode_enum,
+		lpass_cdc_rx_macro_get_ear_mode, lpass_cdc_rx_macro_put_ear_mode),
+
+
+	SOC_ENUM_EXT("RX_HPH HD2 Mode", lpass_cdc_rx_macro_hph_hd2_mode_enum,
+		lpass_cdc_rx_macro_get_hph_hd2_mode, lpass_cdc_rx_macro_put_hph_hd2_mode),
+
+	SOC_ENUM_EXT("RX_HPH_PWR_MODE", lpass_cdc_rx_macro_hph_pwr_mode_enum,
+		lpass_cdc_rx_macro_get_hph_pwr_mode, lpass_cdc_rx_macro_put_hph_pwr_mode),
+
+	SOC_ENUM_EXT("RX_GSM mode Enable", lpass_cdc_rx_macro_vbat_bcl_gsm_mode_enum,
+			lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_get,
+			lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_SINGLE_EXT("RX_Softclip Enable", SND_SOC_NOPM, 0, 1, 0,
+		     lpass_cdc_rx_macro_soft_clip_enable_get,
+		     lpass_cdc_rx_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("AUX_HPF Enable", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_rx_macro_aux_hpf_mode_get,
+			lpass_cdc_rx_macro_aux_hpf_mode_put),
+
+	SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+		LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+
+	SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_get,
+		lpass_cdc_rx_macro_iir_enable_audio_mixer_put),
+
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR0 Band1", IIR0, BAND1),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR0 Band2", IIR0, BAND2),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR0 Band3", IIR0, BAND3),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR0 Band4", IIR0, BAND4),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR0 Band5", IIR0, BAND5),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4),
+	LPASS_CDC_RX_MACRO_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5),
+
+#ifdef CONFIG_BOLERO_VER_2P6
+	LPASS_CDC_RX_MACRO_FIR_FILTER_CTL("RX0 FIR Coeff Group0", RX0_PATH, GRP0),
+	LPASS_CDC_RX_MACRO_FIR_FILTER_CTL("RX0 FIR Coeff Group1", RX0_PATH, GRP1),
+	LPASS_CDC_RX_MACRO_FIR_FILTER_CTL("RX1 FIR Coeff Group0", RX1_PATH, GRP0),
+	LPASS_CDC_RX_MACRO_FIR_FILTER_CTL("RX1 FIR Coeff Group1", RX1_PATH, GRP1),
+#endif
+};
+
+static int lpass_cdc_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);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	u16 val = 0, ec_hq_reg = 0;
+	int ec_tx = 0;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(rx_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_component_read(component,
+			LPASS_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,
+			LPASS_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 >= LPASS_CDC_RX_MACRO_EC_MUX_MAX)) {
+		dev_err_ratelimited(rx_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	ec_hq_reg = LPASS_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 = LPASS_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 lpass_cdc_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_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX0 MUX", LPASS_CDC_RX_MACRO_RX0, lpass_cdc_rx_macro_rx0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX1 MUX", LPASS_CDC_RX_MACRO_RX1, lpass_cdc_rx_macro_rx1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX2 MUX", LPASS_CDC_RX_MACRO_RX2, lpass_cdc_rx_macro_rx2),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX3 MUX", LPASS_CDC_RX_MACRO_RX3, lpass_cdc_rx_macro_rx3),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX4 MUX", LPASS_CDC_RX_MACRO_RX4, lpass_cdc_rx_macro_rx4),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX5 MUX", LPASS_CDC_RX_MACRO_RX5, lpass_cdc_rx_macro_rx5),
+
+	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),
+
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3),
+
+	SND_SOC_DAPM_MUX_E("RX MIX TX0 MUX", SND_SOC_NOPM,
+			   LPASS_CDC_RX_MACRO_EC0_MUX, 0,
+			   &rx_mix_tx0_mux, lpass_cdc_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,
+			   LPASS_CDC_RX_MACRO_EC1_MUX, 0,
+			   &rx_mix_tx1_mux, lpass_cdc_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,
+			   LPASS_CDC_RX_MACRO_EC2_MUX, 0,
+			   &rx_mix_tx2_mux, lpass_cdc_rx_macro_enable_echo,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("IIR0", LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL,
+		4, 0, NULL, 0, lpass_cdc_rx_macro_set_iir_gain,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_MIXER_E("IIR1", LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL,
+		4, 0, NULL, 0, lpass_cdc_rx_macro_set_iir_gain,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_MIXER("SRC0", LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SRC1", LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp),
+
+	SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int0_2_mux, lpass_cdc_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, lpass_cdc_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, lpass_cdc_rx_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2),
+
+	SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int0_1_interp_mux, lpass_cdc_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, lpass_cdc_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, lpass_cdc_rx_macro_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp),
+	LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp),
+
+	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, lpass_cdc_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, lpass_cdc_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, lpass_cdc_rx_macro_enable_rx_path_clk,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("RX INT2_1 VBAT", SND_SOC_NOPM,
+		0, 0, rx_int2_1_vbat_mix_switch,
+		ARRAY_SIZE(rx_int2_1_vbat_mix_switch),
+		lpass_cdc_rx_macro_enable_vbat,
+		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_OUTPUT("PCM_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,
+	lpass_cdc_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 AIF6 PB", NULL, "RX_MCLK"},
+	{"PCM_OUT", NULL, "RX AIF6 PB"},
+
+	{"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_1 VBAT", "RX AUX VBAT Enable", "RX INT2_1 INTERP"},
+	{"RX INT2 SEC MIX", NULL, "RX INT2_1 VBAT"},
+
+	{"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 lpass_cdc_rx_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct lpass_cdc_rx_macro_priv *rx_priv = (struct lpass_cdc_rx_macro_priv *) handle;
+
+	if (rx_priv == NULL) {
+		pr_err_ratelimited("%s: rx priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!rx_priv->pre_dev_up && enable) {
+		pr_debug("%s: adsp is not up\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(rx_priv->dev);
+		if (lpass_cdc_check_core_votes(rx_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(rx_priv->dev);
+		pm_runtime_mark_last_busy(rx_priv->dev);
+	}
+	return rc;
+}
+
+static int rx_swrm_clock(void *handle, bool enable)
+{
+	struct lpass_cdc_rx_macro_priv *rx_priv = (struct lpass_cdc_rx_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&rx_priv->swr_clk_lock);
+
+	dev_dbg(rx_priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(rx_priv->dev);
+		if (rx_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						rx_priv->rx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(rx_priv->dev);
+				pm_runtime_put_autosuspend(rx_priv->dev);
+				goto exit;
+			}
+			ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 1, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						rx_priv->rx_swr_gpio_p);
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(rx_priv->dev);
+				pm_runtime_put_autosuspend(rx_priv->dev);
+				goto exit;
+			}
+			if (rx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (rx_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			rx_priv->reset_swr = false;
+		}
+		pm_runtime_mark_last_busy(rx_priv->dev);
+		pm_runtime_put_autosuspend(rx_priv->dev);
+		rx_priv->swr_clk_users++;
+	} else {
+		if (rx_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(rx_priv->dev,
+				"%s: rx swrm clock users already reset\n",
+				__func__);
+			rx_priv->swr_clk_users = 0;
+			goto exit;
+		}
+		rx_priv->swr_clk_users--;
+		if (rx_priv->swr_clk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_rx_macro_mclk_enable(rx_priv, 0, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						rx_priv->rx_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(rx_priv->dev,
+					"%s: rx swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(rx_priv->dev, "%s: swrm clock users %d\n",
+		__func__, rx_priv->swr_clk_users);
+exit:
+	mutex_unlock(&rx_priv->swr_clk_lock);
+	return ret;
+}
+
+#ifdef CONFIG_BOLERO_VER_2P6
+/**
+ * lpass_cdc_rx_set_fir_capability - Set RX HIFI FIR Filter capability
+ *
+ * @component: Codec component ptr.
+ * @capable: if the target have RX HIFI FIR available.
+ *
+ * Set RX HIFI FIR capability, stored the capability into RX macro private data.
+ */
+int lpass_cdc_rx_set_fir_capability(struct snd_soc_component *component, bool capable)
+{
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_fir_capable = capable;
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_rx_set_fir_capability);
+#endif
+
+static const struct lpass_cdc_rx_macro_reg_mask_val
+				lpass_cdc_rx_macro_reg_init[] = {
+	{LPASS_CDC_RX_RX0_RX_PATH_SEC7, 0x07, 0x02},
+	{LPASS_CDC_RX_RX1_RX_PATH_SEC7, 0x07, 0x02},
+	{LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x07, 0x02},
+	{LPASS_CDC_RX_RX0_RX_PATH_CFG3, 0x03, 0x02},
+	{LPASS_CDC_RX_RX1_RX_PATH_CFG3, 0x03, 0x02},
+	{LPASS_CDC_RX_RX2_RX_PATH_CFG3, 0x03, 0x02},
+};
+
+#ifdef CONFIG_BOLERO_VER_2P1
+static void lpass_cdc_rx_macro_init_bcl_pmic_reg(struct snd_soc_component *component)
+{
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!component) {
+		pr_err("%s: NULL component pointer!\n", __func__);
+		return;
+	}
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return;
+
+	switch (rx_priv->bcl_pmic_params.id) {
+	case 0:
+		/* Enable ID0 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
+		/* Update MC_SID0 */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID0 */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	case 1:
+		/* Enable ID1 to listen to respective PMIC group interrupts */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
+		/* Update MC_SID1 */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID1 */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	default:
+		dev_err(rx_dev, "%s: PMIC ID is invalid %d\n",
+		       __func__, rx_priv->bcl_pmic_params.id);
+		break;
+	}
+}
+#endif
+
+static int lpass_cdc_rx_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret = 0;
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	int i;
+
+	rx_dev = lpass_cdc_get_device_ptr(component->dev, RX_MACRO);
+	if (!rx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	rx_priv = dev_get_drvdata(rx_dev);
+	if (!rx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_rx_macro_dapm_widgets,
+					ARRAY_SIZE(lpass_cdc_rx_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add controls\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_dapm_add_routes(dapm, rx_audio_map,
+					ARRAY_SIZE(rx_audio_map));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add routes\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add widgets\n", __func__);
+		return ret;
+	}
+	ret = snd_soc_add_component_controls(component, lpass_cdc_rx_macro_snd_controls,
+				   ARRAY_SIZE(lpass_cdc_rx_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(rx_dev, "%s: failed to add snd_ctls\n", __func__);
+		return ret;
+	}
+	rx_priv->dev_up = true;
+	rx_priv->rx0_gain_val = 0;
+	rx_priv->rx1_gain_val = 0;
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "AUX_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "PCM_OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC1_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC2_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC3_INP");
+	snd_soc_dapm_sync(dapm);
+
+	for (i = 0; i < ARRAY_SIZE(lpass_cdc_rx_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				lpass_cdc_rx_macro_reg_init[i].reg,
+				lpass_cdc_rx_macro_reg_init[i].mask,
+				lpass_cdc_rx_macro_reg_init[i].val);
+
+	rx_priv->component = component;
+#ifdef CONFIG_BOLERO_VER_2P1
+	lpass_cdc_rx_macro_init_bcl_pmic_reg(component);
+#endif
+
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->component = NULL;
+
+	return 0;
+}
+
+static void lpass_cdc_rx_macro_add_child_devices(struct work_struct *work)
+{
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct rx_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct rx_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[RX_SWR_STRING_LEN] = "";
+	bool rx_swr_master_node = false;
+
+	rx_priv = container_of(work, struct lpass_cdc_rx_macro_priv,
+			     lpass_cdc_rx_macro_add_child_devices_work);
+	if (!rx_priv) {
+		pr_err("%s: Memory for rx_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!rx_priv->dev) {
+		pr_err("%s: RX device does not exist\n", __func__);
+		return;
+	}
+
+	if(!rx_priv->dev->of_node) {
+		dev_err(rx_priv->dev,
+			"%s: DT node for RX dev does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &rx_priv->swr_plat_data;
+	rx_priv->child_count = 0;
+
+	for_each_available_child_of_node(rx_priv->dev->of_node, node) {
+		rx_swr_master_node = false;
+		if (strnstr(node->name, "rx_swr_master",
+				strlen("rx_swr_master")) != NULL)
+			rx_swr_master_node = true;
+
+		if(rx_swr_master_node)
+			strlcpy(plat_dev_name, "rx_swr_ctrl",
+				(RX_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(RX_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(rx_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = rx_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (rx_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct rx_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].rx_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			rx_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (rx_priv->child_count < LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX)
+			rx_priv->pdev_child_devices[
+					rx_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < rx_priv->child_count; count++)
+		platform_device_put(rx_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static void lpass_cdc_rx_macro_init_ops(struct macro_ops *ops, char __iomem *rx_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = lpass_cdc_rx_macro_init;
+	ops->exit = lpass_cdc_rx_macro_deinit;
+	ops->io_base = rx_io_base;
+	ops->dai_ptr = lpass_cdc_rx_macro_dai;
+	ops->num_dais = ARRAY_SIZE(lpass_cdc_rx_macro_dai);
+	ops->event_handler = lpass_cdc_rx_macro_event_handler;
+	ops->set_port_map = lpass_cdc_rx_macro_set_port_map;
+}
+
+static int lpass_cdc_rx_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops = {0};
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	u32 rx_base_addr = 0, muxsel = 0;
+	char __iomem *rx_io_base = NULL, *muxsel_io = NULL;
+	int ret = 0;
+#ifdef CONFIG_BOLERO_VER_2P1
+	u8 bcl_pmic_params[3];
+#endif
+	u32 default_clk_id = 0;
+#ifdef CONFIG_BOLERO_VER_2P6
+	struct clk *hifi_fir_clk = NULL;
+#endif
+	u32 is_used_rx_swr_gpio = 1;
+	const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_rx_macro_priv),
+			    GFP_KERNEL);
+	if (!rx_priv)
+		return -ENOMEM;
+
+	rx_priv->pre_dev_up = true;
+	rx_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &rx_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,rx_mclk_mode_muxsel",
+				   &muxsel);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,default-clk-id");
+		default_clk_id = RX_CORE_CLK;
+	}
+	if (of_find_property(pdev->dev.of_node, is_used_rx_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_rx_swr_gpio_dt,
+					   &is_used_rx_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_rx_swr_gpio_dt);
+			is_used_rx_swr_gpio = 1;
+		}
+	}
+	rx_priv->rx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,rx-swr-gpios", 0);
+	if (!rx_priv->rx_swr_gpio_p && is_used_rx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(rx_priv->rx_swr_gpio_p) < 0 &&
+		is_used_rx_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				rx_priv->rx_swr_gpio_p, false);
+
+	rx_io_base = devm_ioremap(&pdev->dev, rx_base_addr,
+				  LPASS_CDC_RX_MACRO_MAX_OFFSET);
+	if (!rx_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+	rx_priv->rx_io_base = rx_io_base;
+	muxsel_io = devm_ioremap(&pdev->dev, muxsel, 0x4);
+	if (!muxsel_io) {
+		dev_err(&pdev->dev, "%s: ioremap failed for muxsel\n",
+			__func__);
+		return -ENOMEM;
+	}
+	rx_priv->rx_mclk_mode_muxsel = muxsel_io;
+	rx_priv->reset_swr = true;
+	INIT_WORK(&rx_priv->lpass_cdc_rx_macro_add_child_devices_work,
+		  lpass_cdc_rx_macro_add_child_devices);
+	rx_priv->swr_plat_data.handle = (void *) rx_priv;
+	rx_priv->swr_plat_data.read = NULL;
+	rx_priv->swr_plat_data.write = NULL;
+	rx_priv->swr_plat_data.bulk_write = NULL;
+	rx_priv->swr_plat_data.clk = rx_swrm_clock;
+	rx_priv->swr_plat_data.core_vote = lpass_cdc_rx_macro_core_vote;
+	rx_priv->swr_plat_data.handle_irq = NULL;
+
+#ifdef CONFIG_BOLERO_VER_2P1
+	ret = of_property_read_u8_array(pdev->dev.of_node,
+				"qcom,rx-bcl-pmic-params", bcl_pmic_params,
+				sizeof(bcl_pmic_params));
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,rx-bcl-pmic-params");
+	} else {
+		rx_priv->bcl_pmic_params.id = bcl_pmic_params[0];
+		rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
+		rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
+	}
+#endif
+
+	rx_priv->clk_id = default_clk_id;
+	rx_priv->default_clk_id  = default_clk_id;
+	ops.clk_id_req = rx_priv->clk_id;
+	ops.default_clk_id = default_clk_id;
+
+#ifdef CONFIG_BOLERO_VER_2P6
+	hifi_fir_clk = devm_clk_get(&pdev->dev, "rx_mclk2_2x_clk");
+	if (IS_ERR(hifi_fir_clk)) {
+		ret = PTR_ERR(hifi_fir_clk);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "rx_mclk2_2x_clk", ret);
+		hifi_fir_clk = NULL;
+	}
+	rx_priv->hifi_fir_clk = hifi_fir_clk;
+#endif
+
+	rx_priv->is_aux_hpf_on = 1;
+
+	dev_set_drvdata(&pdev->dev, rx_priv);
+	mutex_init(&rx_priv->mclk_lock);
+	mutex_init(&rx_priv->swr_clk_lock);
+	lpass_cdc_rx_macro_init_ops(&ops, rx_io_base);
+
+	ret = lpass_cdc_register_macro(&pdev->dev, RX_MACRO, &ops);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: register macro failed\n", __func__);
+		goto err_reg_macro;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	schedule_work(&rx_priv->lpass_cdc_rx_macro_add_child_devices_work);
+	return 0;
+
+err_reg_macro:
+	mutex_destroy(&rx_priv->mclk_lock);
+	mutex_destroy(&rx_priv->swr_clk_lock);
+	return ret;
+}
+
+static int lpass_cdc_rx_macro_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+	u16 count = 0;
+
+	rx_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!rx_priv)
+		return -EINVAL;
+
+	for (count = 0; count < rx_priv->child_count &&
+		count < LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(rx_priv->pdev_child_devices[count]);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	lpass_cdc_unregister_macro(&pdev->dev, RX_MACRO);
+	mutex_destroy(&rx_priv->mclk_lock);
+	mutex_destroy(&rx_priv->swr_clk_lock);
+	kfree(rx_priv->swr_ctrl_data);
+	return 0;
+}
+
+static const struct of_device_id lpass_cdc_rx_macro_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-rx-macro"},
+	{}
+};
+
+static const struct dev_pm_ops lpass_cdc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_cdc_runtime_suspend,
+		lpass_cdc_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_cdc_rx_macro_driver = {
+	.driver = {
+		.name = "lpass_cdc_rx_macro",
+		.owner = THIS_MODULE,
+		.pm = &lpass_cdc_dev_pm_ops,
+		.of_match_table = lpass_cdc_rx_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_rx_macro_probe,
+	.remove = lpass_cdc_rx_macro_remove,
+};
+
+module_platform_driver(lpass_cdc_rx_macro_driver);
+
+MODULE_DESCRIPTION("RX macro driver");
+MODULE_LICENSE("GPL v2");

+ 1245 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-tables.c

@@ -0,0 +1,1245 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include "lpass-cdc.h"
+#include "internal.h"
+
+u8 lpass_cdc_tx_reg_access[LPASS_CDC_TX_MACRO_MAX] = {
+	[LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 lpass_cdc_rx_reg_access[LPASS_CDC_RX_MACRO_MAX] = {
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_TOP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_TOP_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_SWR_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_BUS)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_RX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_TX_I2S2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_CLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_RESET)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_MUX)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SOFTCLIP_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_DLY_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_DECAY_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_HPH_V_PA)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_EAR_V_PA)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_HPH_V_HD)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_EAR_V_HD)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K1_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K1_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K2_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K2_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_HPH)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_EAR)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_TEST0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_TEST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_OVR_VREF)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_LEVEL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_BYPASS0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_SET0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] =
+								RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL)] =
+								RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_FIFO_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_FIFO_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_FIFO_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD0_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD1_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG2)] = RD_WR_REG,
+#ifdef CONFIG_BOLERO_VER_2P6
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_ADDR)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_FIR_COEFF_WDATA7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_ADDR)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_FIR_COEFF_WDATA7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CTL3)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_CFG8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_TEST4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST3)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST4)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_CB_DECODE_CB_DECODE_ST5)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_VBAT_TEMP_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL19)] = RD_WR_REG,
+#else
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_ST)] = RD_REG,
+#endif
+};
+
+u8 lpass_cdc_va_reg_access[LPASS_CDC_VA_MACRO_MAX] = {
+	[LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_VAD_MUX)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SEQ_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 lpass_cdc_wsa_reg_access[LPASS_CDC_WSA_MACRO_MAX] = {
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TOP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TOP_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_FREQ_MCLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_EN0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_EN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_DSM_LB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_RX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_I2S_CLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_I2S_RESET)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_FS_UNGATE)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_GRP_SEL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP7_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP7_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP7_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP8_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP8_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SPKR_COMP8_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_FS_UNGATE2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TOP_SEQ_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_LEVEL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_BYPASS0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_SET0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP0_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP1_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_IDLE_DETECT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_IDLE_DETECT_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_IDLE_DETECT_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_IDLE_DETECT_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_IDLE_DETECT_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL3)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CFG8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_TEST4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST3)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST4)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_CB_DECODE_CB_DECODE_ST5)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_TEMP_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	/* lpass 2.6 new registers */
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_LA_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG17)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG7)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG8)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_LA_CFG_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG1_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG2_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG3_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG4_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG5_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG6_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG7_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG8_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG9_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG10_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG11_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG12_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG13_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG14_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG15_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG16_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG0_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG1_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG2_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG5_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_ILIM_CFG6_1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG18)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG18_1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG20)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG21)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG22)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA_PBR_CFG23)] = RD_WR_REG,
+};
+
+u8 lpass_cdc_wsa2_reg_access[LPASS_CDC_WSA2_MACRO_MAX] = {
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_TOP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_TOP_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_FREQ_MCLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_DEBUG_BUS_SEL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_DEBUG_EN0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_DEBUG_EN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_DEBUG_DSM_LB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_RX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_TX_I2S_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_I2S_CLK)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_I2S_RESET)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_FS_UNGATE)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_GRP_SEL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP7_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP7_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP7_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_LSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP8_WR_MSB)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP8_LUT)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_LSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SPKR_COMP8_RD_MSB)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_FS_UNGATE2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TOP_SEQ_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_RX_EC_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX_INP_MUX_SOFTCLIP_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_CLR_COMMIT)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN1_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN1_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN2_STATUS0)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_PIN2_CLEAR0)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_LEVEL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_BYPASS0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_INTR_CTRL_SET0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX0_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_VOL_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_SEC7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_RX1_RX_PATH_DSMDEM_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST0_BOOST_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST0_BOOST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST0_BOOST_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST0_BOOST_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST1_BOOST_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST1_BOOST_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST1_BOOST_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_BOOST1_BOOST_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER0_CTL19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL17)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL18)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_COMPANDER1_CTL19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_SOFTCLIP0_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_SOFTCLIP0_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_SOFTCLIP1_CRC)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_SOFTCLIP1_SOFTCLIP_CTRL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_EC_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_IDLE_DETECT_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_IDLE_DETECT_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_IDLE_DETECT_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_IDLE_DETECT_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CFG8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_TEST4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST2)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST3)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST4)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_ST5)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_ADC_CAL3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_PK_EST3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_RF_PROC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_TAC4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_DEBUG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_UPD_MON)] = WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_GAIN_MON_VAL)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BAN)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_VBAT_TEMP_VBAT_BCL_ATTN3)] = RD_WR_REG,
+	/* lpass 2.6 new registers */
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_PATH_CTL)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_LA_CFG)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG6)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG7)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG8)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG10)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG11)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG12)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG13)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG14)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG15)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG16)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG17)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG0)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG2)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG3)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG4)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG5)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG6)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG7)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG8)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_LA_CFG_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG1_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG2_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG3_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG4_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG5_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG6_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG7_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG8_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG9_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG10_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG11_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG12_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG13_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG14_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG15_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG16_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG0_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG1_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG2_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG5_1)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG9)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_ILIM_CFG6_1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG18)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG18_1)] = RD_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG19)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG20)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG21)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG22)] = RD_WR_REG,
+	[LPASS_CDC_REG(LPASS_CDC_WSA2_PBR_CFG23)] = RD_WR_REG,
+
+};
+
+u8 *lpass_cdc_reg_access[MAX_MACRO] = {
+	[TX_MACRO] = lpass_cdc_tx_reg_access,
+	[RX_MACRO] = lpass_cdc_rx_reg_access,
+	[WSA_MACRO] = lpass_cdc_wsa_reg_access,
+	[VA_MACRO] = lpass_cdc_va_reg_access,
+	[WSA2_MACRO] = lpass_cdc_wsa2_reg_access,
+};

+ 2175 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c

@@ -0,0 +1,2175 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. 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 <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-registers.h"
+#include "lpass-cdc-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define LPASS_CDC_TX_MACRO_MAX_OFFSET 0x1000
+
+#define NUM_DECIMATORS 8
+
+#define LPASS_CDC_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 LPASS_CDC_TX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define  TX_HPF_CUT_OFF_FREQ_MASK	0x60
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+#define LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define LPASS_CDC_TX_MACRO_MCLK_FREQ 9600000
+#define LPASS_CDC_TX_MACRO_TX_PATH_OFFSET \
+	(LPASS_CDC_TX1_TX_PATH_CTL - LPASS_CDC_TX0_TX_PATH_CTL)
+#define LPASS_CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
+#define LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET 0x8
+#define LPASS_CDC_TX_MACRO_ADC_MODE_CFG0_SHIFT 1
+
+#define LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS	40
+#define LPASS_CDC_TX_MACRO_AMIC_UNMUTE_DELAY_MS	100
+#define LPASS_CDC_TX_MACRO_DMIC_HPF_DELAY_MS	300
+#define LPASS_CDC_TX_MACRO_AMIC_HPF_DELAY_MS	300
+
+static int tx_unmute_delay = LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+module_param(tx_unmute_delay, int, 0664);
+MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path");
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+static int lpass_cdc_tx_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+static int lpass_cdc_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);
+
+#define LPASS_CDC_TX_MACRO_SWR_STRING_LEN 80
+#define LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX 3
+
+enum {
+	LPASS_CDC_TX_MACRO_AIF_INVALID = 0,
+	LPASS_CDC_TX_MACRO_AIF1_CAP,
+	LPASS_CDC_TX_MACRO_AIF2_CAP,
+	LPASS_CDC_TX_MACRO_AIF3_CAP,
+	LPASS_CDC_TX_MACRO_MAX_DAIS
+};
+
+enum {
+	LPASS_CDC_TX_MACRO_DEC0,
+	LPASS_CDC_TX_MACRO_DEC1,
+	LPASS_CDC_TX_MACRO_DEC2,
+	LPASS_CDC_TX_MACRO_DEC3,
+	LPASS_CDC_TX_MACRO_DEC4,
+	LPASS_CDC_TX_MACRO_DEC5,
+	LPASS_CDC_TX_MACRO_DEC6,
+	LPASS_CDC_TX_MACRO_DEC7,
+	LPASS_CDC_TX_MACRO_DEC_MAX,
+};
+
+enum {
+	LPASS_CDC_TX_MACRO_CLK_DIV_2,
+	LPASS_CDC_TX_MACRO_CLK_DIV_3,
+	LPASS_CDC_TX_MACRO_CLK_DIV_4,
+	LPASS_CDC_TX_MACRO_CLK_DIV_6,
+	LPASS_CDC_TX_MACRO_CLK_DIV_8,
+	LPASS_CDC_TX_MACRO_CLK_DIV_16,
+};
+
+enum {
+	MSM_DMIC,
+	SWR_MIC,
+	ANC_FB_TUNE1
+};
+
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
+struct lpass_cdc_tx_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+struct tx_mute_work {
+	struct lpass_cdc_tx_macro_priv *tx_priv;
+	u32 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct lpass_cdc_tx_macro_priv *tx_priv;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+struct lpass_cdc_tx_macro_priv {
+	struct device *dev;
+	bool dec_active[NUM_DECIMATORS];
+	int tx_mclk_users;
+	bool dapm_mclk_enable;
+	struct mutex mclk_lock;
+	struct mutex wlock;
+	struct snd_soc_component *component;
+	struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+	struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS];
+	u16 dmic_clk_div;
+	u32 version;
+	unsigned long active_ch_mask[LPASS_CDC_TX_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[LPASS_CDC_TX_MACRO_MAX_DAIS];
+	char __iomem *tx_io_base;
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	bool bcs_enable;
+	int dec_mode[NUM_DECIMATORS];
+	int bcs_ch;
+	bool bcs_clk_en;
+	bool hs_slow_insert_complete;
+	int pcm_rate[NUM_DECIMATORS];
+	bool swr_dmic_enable;
+	int wlock_holders;
+};
+
+static int lpass_cdc_tx_macro_wake_enable(struct lpass_cdc_tx_macro_priv *tx_priv,
+					bool wake_enable)
+{
+	int ret = 0;
+
+	mutex_lock(&tx_priv->wlock);
+	if (wake_enable) {
+		if (tx_priv->wlock_holders++ == 0) {
+			dev_dbg(tx_priv->dev, "%s: pm wake\n", __func__);
+			pm_stay_awake(tx_priv->dev);
+		}
+	} else {
+		if (--tx_priv->wlock_holders == 0) {
+			dev_dbg(tx_priv->dev, "%s: pm release\n", __func__);
+			pm_relax(tx_priv->dev);
+		}
+		if (tx_priv->wlock_holders < 0)
+			tx_priv->wlock_holders = 0;
+	}
+	mutex_unlock(&tx_priv->wlock);
+	return ret;
+}
+
+static bool lpass_cdc_tx_macro_get_data(struct snd_soc_component *component,
+			      struct device **tx_dev,
+			      struct lpass_cdc_tx_macro_priv **tx_priv,
+			      const char *func_name)
+{
+	*tx_dev = lpass_cdc_get_device_ptr(component->dev, TX_MACRO);
+	if (!(*tx_dev)) {
+		dev_err_ratelimited(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+
+	*tx_priv = dev_get_drvdata((*tx_dev));
+	if (!(*tx_priv)) {
+		dev_err_ratelimited(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+
+	if (!(*tx_priv)->component) {
+		dev_err_ratelimited(component->dev,
+			"%s: tx_priv->component not initialized!\n", func_name);
+		return false;
+	}
+
+	return true;
+}
+
+static int lpass_cdc_tx_macro_mclk_enable(
+				struct lpass_cdc_tx_macro_priv *tx_priv,
+				bool mclk_enable)
+{
+	struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(tx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(tx_priv->dev, "%s: mclk_enable = %u,clk_users= %d\n",
+		__func__, mclk_enable, tx_priv->tx_mclk_users);
+
+	mutex_lock(&tx_priv->mclk_lock);
+	if (mclk_enable) {
+		ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev,
+						TX_CORE_CLK,
+						TX_CORE_CLK,
+						true);
+		if (ret < 0) {
+			dev_err_ratelimited(tx_priv->dev,
+				"%s: request clock enable failed\n",
+				__func__);
+			goto exit;
+		}
+		lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev,
+					true);
+		regcache_mark_dirty(regmap);
+		regcache_sync_region(regmap,
+				TX_START_OFFSET,
+				TX_MAX_OFFSET);
+		if (tx_priv->tx_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			regmap_update_bits(regmap,
+				LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		tx_priv->tx_mclk_users++;
+	} else {
+		if (tx_priv->tx_mclk_users <= 0) {
+			dev_err_ratelimited(tx_priv->dev, "%s: clock already disabled\n",
+				__func__);
+			tx_priv->tx_mclk_users = 0;
+			goto exit;
+		}
+		tx_priv->tx_mclk_users--;
+		if (tx_priv->tx_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+		}
+
+		lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev,
+				false);
+		lpass_cdc_clk_rsc_request_clock(tx_priv->dev,
+				 TX_CORE_CLK,
+				 TX_CORE_CLK,
+				 false);
+	}
+exit:
+	mutex_unlock(&tx_priv->mclk_lock);
+	return ret;
+}
+
+static int __lpass_cdc_tx_macro_mclk_enable(struct snd_soc_component *component,
+				  bool enable)
+{
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	return lpass_cdc_tx_macro_mclk_enable(tx_priv, enable);
+}
+
+static int lpass_cdc_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);
+	int ret = 0;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(tx_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = lpass_cdc_tx_macro_mclk_enable(tx_priv, 1);
+		if (ret)
+			tx_priv->dapm_mclk_enable = false;
+		else
+			tx_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (tx_priv->dapm_mclk_enable)
+			ret = lpass_cdc_tx_macro_mclk_enable(tx_priv, 0);
+		break;
+	default:
+		dev_err_ratelimited(tx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_tx_macro_event_handler(struct snd_soc_component *component,
+				u16 event, u32 data)
+{
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case LPASS_CDC_MACRO_EVT_SSR_DOWN:
+		if ((!pm_runtime_enabled(tx_dev) ||
+		     !pm_runtime_suspended(tx_dev))) {
+			ret = lpass_cdc_runtime_suspend(tx_dev);
+			if (!ret) {
+				pm_runtime_disable(tx_dev);
+				pm_runtime_set_suspended(tx_dev);
+				pm_runtime_enable(tx_dev);
+			}
+		}
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_UP:
+		break;
+	case LPASS_CDC_MACRO_EVT_CLK_RESET:
+		lpass_cdc_rsc_clk_reset(tx_dev, TX_CORE_CLK);
+		break;
+	case LPASS_CDC_MACRO_EVT_BCS_CLK_OFF:
+		if (tx_priv->bcs_clk_en)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6);
+		if (data)
+			tx_priv->hs_slow_insert_complete = true;
+		else
+			tx_priv->hs_slow_insert_complete = false;
+		break;
+	default:
+		pr_debug("%s Invalid Event\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+	u16 adc_mux_reg = 0;
+	bool ret = false;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return ret;
+
+	adc_mux_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+
+	if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+		if (!tx_priv->swr_dmic_enable)
+			return true;
+	}
+
+	return ret;
+}
+
+static void lpass_cdc_tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work = NULL;
+	struct hpf_work *hpf_work = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct snd_soc_component *component = NULL;
+	u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
+	u8 hpf_cut_off_freq = 0;
+	u16 adc_reg = 0, adc_n = 0;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	tx_priv = hpf_work->tx_priv;
+	component = tx_priv->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = LPASS_CDC_TX0_TX_PATH_CFG0 +
+			LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+	hpf_gate_reg = LPASS_CDC_TX0_TX_PATH_SEC2 +
+			LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+
+	dev_dbg(component->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
+		__func__, hpf_work->decimator, hpf_cut_off_freq);
+
+	if (is_amic_enabled(component, hpf_work->decimator)) {
+		adc_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+			LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				LPASS_CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+		/* analog mic clear TX hold */
+		lpass_cdc_clear_amic_tx_hold(component->dev, adc_n);
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x03, 0x02);
+		/* Add delay between toggle hpf gate based on sample rate */
+		switch (tx_priv->pcm_rate[hpf_work->decimator]) {
+		case 0:
+			usleep_range(125, 130);
+			break;
+		case 1:
+			usleep_range(62, 65);
+			break;
+		case 3:
+			usleep_range(31, 32);
+			break;
+		case 4:
+			usleep_range(20, 21);
+			break;
+		case 5:
+			usleep_range(10, 11);
+			break;
+		case 6:
+			usleep_range(5, 6);
+			break;
+		default:
+			usleep_range(125, 130);
+		}
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x03, 0x01);
+	} else {
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x02, 0x02);
+		/* Minimum 1 clk cycle delay is required as per HW spec */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+						0x02, 0x00);
+	}
+	lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
+}
+
+static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work)
+{
+	struct tx_mute_work *tx_mute_dwork = NULL;
+	struct snd_soc_component *component = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct delayed_work *delayed_work = NULL;
+	u16 tx_vol_ctl_reg = 0;
+	u8 decimator = 0;
+
+	delayed_work = to_delayed_work(work);
+	tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
+	tx_priv = tx_mute_dwork->tx_priv;
+	component = tx_priv->component;
+	decimator = tx_mute_dwork->decimator;
+
+	tx_vol_ctl_reg =
+		LPASS_CDC_TX0_TX_PATH_CTL +
+			LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
+	dev_dbg(tx_priv->dev, "%s: decimator %u unmute\n",
+		__func__, decimator);
+	lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
+}
+
+static int lpass_cdc_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 = 0;
+	u16 mic_sel_reg = 0;
+	u16 dmic_clk_reg = 0;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	switch (e->reg) {
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = LPASS_CDC_TX0_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = LPASS_CDC_TX1_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = LPASS_CDC_TX2_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = LPASS_CDC_TX3_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+		mic_sel_reg = LPASS_CDC_TX4_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+		mic_sel_reg = LPASS_CDC_TX5_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+		mic_sel_reg = LPASS_CDC_TX6_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+		mic_sel_reg = LPASS_CDC_TX7_TX_PATH_CFG0;
+		break;
+	default:
+		dev_err_ratelimited(component->dev, "%s: e->reg: 0x%x not expected\n",
+			__func__, e->reg);
+		return -EINVAL;
+	}
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
+		if (val != 0) {
+			if (!tx_priv->swr_dmic_enable) {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x0 << 7);
+			} else {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x1 << 7);
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+				dmic_clk_reg =
+					LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL +
+						((val - 5)/2) * 4;
+				snd_soc_component_update_bits(component,
+					dmic_clk_reg,
+					0x0E, tx_priv->dmic_clk_div << 0x1);
+			}
+		}
+	} else {
+		/* DMIC selected */
+		if (val != 0)
+			snd_soc_component_update_bits(component, mic_sel_reg,
+							1 << 7, 1 << 7);
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int lpass_cdc_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(dec_id, &tx_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int lpass_cdc_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (test_bit(dec_id, &tx_priv->active_ch_mask[dai_id])) {
+			dev_err(component->dev, "%s: channel is already enabled, dec_id = %d, dai_id = %d\n",
+					__func__, dec_id, dai_id);
+		} else {
+			set_bit(dec_id, &tx_priv->active_ch_mask[dai_id]);
+			tx_priv->active_ch_cnt[dai_id]++;
+		}
+	} else {
+		if (!test_bit(dec_id, &tx_priv->active_ch_mask[dai_id])) {
+			dev_err(component->dev, "%s: channel is already disabled, dec_id = %d, dai_id = %d\n",
+					__func__, dec_id, dai_id);
+		} else {
+			tx_priv->active_ch_cnt[dai_id]--;
+			clear_bit(dec_id, &tx_priv->active_ch_mask[dai_id]);
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+	return 0;
+}
+
+static inline int lpass_cdc_tx_macro_path_get(const char *wname,
+				    unsigned int *path_num)
+{
+	int ret = 0;
+	char *widget_name = NULL;
+	char *w_name = NULL;
+	char *path_num_char = NULL;
+	char *path_name = NULL;
+
+	widget_name = kstrndup(wname, 10, GFP_KERNEL);
+	if (!widget_name)
+		return -EINVAL;
+
+	w_name = widget_name;
+
+	path_name = strsep(&widget_name, " ");
+	if (!path_name) {
+		pr_err_ratelimited("%s: Invalid widget name = %s\n",
+			__func__, widget_name);
+		ret = -EINVAL;
+		goto err;
+	}
+	path_num_char = strpbrk(path_name, "01234567");
+	if (!path_num_char) {
+		pr_err_ratelimited("%s: tx path index not found\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = kstrtouint(path_num_char, 10, path_num);
+	if (ret < 0)
+		pr_err_ratelimited("%s: Invalid tx path = %s\n",
+			__func__, w_name);
+
+err:
+	kfree(w_name);
+	return ret;
+}
+
+static int lpass_cdc_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 lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int ret = 0;
+	int path = 0;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ret = lpass_cdc_tx_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	ucontrol->value.integer.value[0] = tx_priv->dec_mode[path];
+
+	return 0;
+}
+
+static int lpass_cdc_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);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int ret = 0;
+	int path = 0;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ret = lpass_cdc_tx_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	tx_priv->dec_mode[path] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_bcs_ch_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.enumerated.item[0] = tx_priv->bcs_ch;
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_bcs_ch_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.enumerated.item[0];
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->bcs_ch = value;
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_swr_dmic_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+	return -EINVAL;
+
+	ucontrol->value.integer.value[0] = tx_priv->swr_dmic_enable;
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_swr_dmic_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->swr_dmic_enable = value;
+
+	return 0;
+}
+
+static int lpass_cdc_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 lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+	return -EINVAL;
+
+	ucontrol->value.integer.value[0] = tx_priv->bcs_enable;
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_set_bcs(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->bcs_enable = value;
+
+	return 0;
+}
+
+static const char * const bcs_ch_sel_mux_text[] = {
+	"SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11",
+};
+
+static const struct soc_enum bcs_ch_sel_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_sel_mux_text),
+			    bcs_ch_sel_mux_text);
+
+static int lpass_cdc_tx_macro_get_bcs_ch_sel(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value = 0;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	value = (snd_soc_component_read(component,
+			LPASS_CDC_VA_TOP_CSR_SWR_CTRL)) & 0x0F;
+
+	ucontrol->value.integer.value[0] = value;
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_put_bcs_ch_sel(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	struct device *tx_dev = NULL;
+	int value;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+	    ucontrol->value.integer.value[0] > ARRAY_SIZE(bcs_ch_sel_mux_text))
+		return -EINVAL;
+
+	value = ucontrol->value.integer.value[0];
+	snd_soc_component_update_bits(component,
+			LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F, value);
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_enable_dmic(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event, u16 adc_mux0_cfg)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+	unsigned int dmic = 0;
+
+	dmic = (snd_soc_component_read(component, adc_mux0_cfg) >> 4) - 1;
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d\n",
+			__func__, event,  dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		lpass_cdc_dmic_clk_enable(component, dmic, DMIC_TX, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		lpass_cdc_dmic_clk_enable(component, dmic, DMIC_TX, false);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_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 = 0;
+	u16 tx_vol_ctl_reg = 0;
+	u16 dec_cfg_reg = 0;
+	u16 hpf_gate_reg = 0;
+	u16 tx_gain_ctl_reg = 0;
+	u16 tx_fs_reg = 0;
+	u8 hpf_cut_off_freq = 0;
+	u16 adc_mux_reg = 0;
+	u16 adc_mux0_reg = 0;
+	int hpf_delay = LPASS_CDC_TX_MACRO_DMIC_HPF_DELAY_MS;
+	int unmute_delay = LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	decimator = w->shift;
+
+	dev_dbg(component->dev, "%s(): widget = %s decimator = %u\n", __func__,
+			w->name, decimator);
+
+	tx_vol_ctl_reg = LPASS_CDC_TX0_TX_PATH_CTL +
+				LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+	hpf_gate_reg = LPASS_CDC_TX0_TX_PATH_SEC2 +
+				LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+	dec_cfg_reg = LPASS_CDC_TX0_TX_PATH_CFG0 +
+				LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+	tx_gain_ctl_reg = LPASS_CDC_TX0_TX_VOL_CTL +
+				LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+	adc_mux_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	adc_mux0_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+			LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	tx_fs_reg = LPASS_CDC_TX0_TX_PATH_CTL +
+				LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+
+	tx_priv->pcm_rate[decimator] = (snd_soc_component_read(component,
+				     tx_fs_reg) & 0x0F);
+
+	if(!is_amic_enabled(component, decimator))
+		lpass_cdc_tx_macro_enable_dmic(w, kcontrol, event, adc_mux0_reg);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, tx_priv->dec_mode[decimator] <<
+			LPASS_CDC_TX_MACRO_ADC_MODE_CFG0_SHIFT);
+		/* Enable TX PGA Mute */
+		snd_soc_component_update_bits(component,
+			tx_vol_ctl_reg, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component,
+			tx_vol_ctl_reg, 0x20, 0x20);
+		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(component, dec_cfg_reg) &
+				TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+
+		tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq =
+						hpf_cut_off_freq;
+
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						CF_MIN_3DB_150HZ << 5);
+
+		if (is_amic_enabled(component, decimator)) {
+			hpf_delay = LPASS_CDC_TX_MACRO_AMIC_HPF_DELAY_MS;
+			unmute_delay = LPASS_CDC_TX_MACRO_AMIC_UNMUTE_DELAY_MS;
+		}
+		if (tx_unmute_delay < unmute_delay)
+			tx_unmute_delay = unmute_delay;
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 1);
+		/* schedule work queue to Remove Mute */
+		queue_delayed_work(system_freezable_wq,
+				   &tx_priv->tx_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(tx_unmute_delay));
+		if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq !=
+							CF_MIN_3DB_150HZ) {
+			lpass_cdc_tx_macro_wake_enable(tx_priv, 1);
+			queue_delayed_work(system_freezable_wq,
+				&tx_priv->tx_hpf_work[decimator].dwork,
+				msecs_to_jiffies(hpf_delay));
+			snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 0x02);
+			if (!is_amic_enabled(component, decimator))
+				snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 0x00);
+			snd_soc_component_update_bits(component,
+					hpf_gate_reg, 0x03, 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_priv->bcs_enable) {
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F,
+				tx_priv->bcs_ch);
+
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					0x01, 0x01);
+			tx_priv->bcs_clk_en = true;
+			if (tx_priv->hs_slow_insert_complete)
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_TX0_TX_PATH_SEC7, 0x40,
+					0x40);
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x10, 0x10);
+		if (cancel_delayed_work_sync(
+		    &tx_priv->tx_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_update_bits(
+						component, dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						hpf_cut_off_freq << 5);
+				if (is_amic_enabled(component, decimator))
+					snd_soc_component_update_bits(component,
+							hpf_gate_reg,
+							0x03, 0x02);
+				else
+					snd_soc_component_update_bits(component,
+							hpf_gate_reg,
+							0x03, 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,
+						0x03, 0x01);
+			}
+		}
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
+		cancel_delayed_work_sync(
+				&tx_priv->tx_mute_dwork[decimator].dwork);
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
+
+		if (snd_soc_component_read(component, adc_mux_reg)
+						& SWR_MIC)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_TX_TOP_CSR_SWR_CTRL,
+				0x01, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x20, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x40, 0x40);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x40, 0x00);
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+						0x10, 0x00);
+		snd_soc_component_update_bits(component, tx_fs_reg,
+						0x0F, 0x04);
+		if (tx_priv->bcs_enable) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00);
+			tx_priv->bcs_clk_en = false;
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F,
+					0x00);
+		}
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_enable_micbias(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	return 0;
+}
+
+/* Cutoff frequency for high pass filter */
+static const char * const cf_text[] = {
+	"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
+};
+
+static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, LPASS_CDC_TX0_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, LPASS_CDC_TX1_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, LPASS_CDC_TX2_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, LPASS_CDC_TX3_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, LPASS_CDC_TX4_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, LPASS_CDC_TX5_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, LPASS_CDC_TX6_TX_PATH_CFG0, 5,
+							cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, LPASS_CDC_TX7_TX_PATH_CFG0, 5,
+							cf_text);
+
+static int lpass_cdc_tx_macro_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	int tx_fs_rate = -EINVAL;
+	struct snd_soc_component *component = dai->component;
+	u32 decimator = 0;
+	u32 sample_rate = 0;
+	u16 tx_fs_reg = 0;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	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_ratelimited(component->dev, "%s: Invalid TX sample rate: %d\n",
+			__func__, params_rate(params));
+		return -EINVAL;
+	}
+	for_each_set_bit(decimator, &tx_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_TX_MACRO_DEC_MAX) {
+		if (decimator >= 0) {
+			tx_fs_reg = LPASS_CDC_TX0_TX_PATH_CTL +
+				    LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator;
+			dev_dbg(component->dev, "%s: set DEC%u rate to %u\n",
+				__func__, decimator, sample_rate);
+			snd_soc_component_update_bits(component, tx_fs_reg,
+						0x0F, tx_fs_rate);
+		} else {
+			dev_err_ratelimited(component->dev,
+				"%s: ERROR: Invalid decimator: %d\n",
+				__func__, decimator);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int lpass_cdc_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 device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	switch (dai->id) {
+	case LPASS_CDC_TX_MACRO_AIF1_CAP:
+	case LPASS_CDC_TX_MACRO_AIF2_CAP:
+	case LPASS_CDC_TX_MACRO_AIF3_CAP:
+		*tx_slot = tx_priv->active_ch_mask[dai->id];
+		*tx_num = tx_priv->active_ch_cnt[dai->id];
+		break;
+	default:
+		dev_err_ratelimited(tx_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static struct snd_soc_dai_ops lpass_cdc_tx_macro_dai_ops = {
+	.hw_params = lpass_cdc_tx_macro_hw_params,
+	.get_channel_map = lpass_cdc_tx_macro_get_channel_map,
+};
+
+static struct snd_soc_dai_driver lpass_cdc_tx_macro_dai[] = {
+	{
+		.name = "tx_macro_tx1",
+		.id = LPASS_CDC_TX_MACRO_AIF1_CAP,
+		.capture = {
+			.stream_name = "TX_AIF1 Capture",
+			.rates = LPASS_CDC_TX_MACRO_RATES,
+			.formats = LPASS_CDC_TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_tx_macro_dai_ops,
+	},
+	{
+		.name = "tx_macro_tx2",
+		.id = LPASS_CDC_TX_MACRO_AIF2_CAP,
+		.capture = {
+			.stream_name = "TX_AIF2 Capture",
+			.rates = LPASS_CDC_TX_MACRO_RATES,
+			.formats = LPASS_CDC_TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_tx_macro_dai_ops,
+	},
+	{
+		.name = "tx_macro_tx3",
+		.id = LPASS_CDC_TX_MACRO_AIF3_CAP,
+		.capture = {
+			.stream_name = "TX_AIF3 Capture",
+			.rates = LPASS_CDC_TX_MACRO_RATES,
+			.formats = LPASS_CDC_TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_tx_macro_dai_ops,
+	},
+};
+
+#define STRING(name) #name
+#define LPASS_CDC_TX_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define LPASS_CDC_TX_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+static const char * const adc_mux_text[] = {
+	"MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1"
+};
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1,
+		   0, adc_mux_text);
+
+
+static const char * const dmic_mux_text[] = {
+	"ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
+	"DMIC4", "DMIC5", "DMIC6", "DMIC7"
+};
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+static const char * const smic_mux_text[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_tx_macro_put_dec_enum);
+
+LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_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_EXT(ARRAY_SIZE(dec_mode_mux_text),
+			    dec_mode_mux_text);
+
+static const char * const bcs_ch_enum_text[] = {
+	"CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8", "CH9",
+	"CH10", "CH11",
+};
+
+static const struct soc_enum bcs_ch_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_enum_text),
+			    bcs_ch_enum_text);
+
+static const struct snd_kcontrol_new tx_aif1_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0,
+			lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_tx_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF1_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF2_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF3_CAP, 0),
+
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		LPASS_CDC_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,
+		LPASS_CDC_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,
+		LPASS_CDC_TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)),
+
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7),
+
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6),
+	LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7),
+
+	SND_SOC_DAPM_SUPPLY("TX MIC BIAS1", SND_SOC_NOPM, 0, 0,
+		lpass_cdc_tx_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_INPUT("TX SWR_INPUT"),
+
+	SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM,
+			   LPASS_CDC_TX_MACRO_DEC0, 0,
+			   &tx_dec0_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC1, 0,
+			   &tx_dec1_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC2, 0,
+			   &tx_dec2_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC3, 0,
+			   &tx_dec3_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC4, 0,
+			   &tx_dec4_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC5, 0,
+			   &tx_dec5_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC6, 0,
+			   &tx_dec6_mux, lpass_cdc_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,
+			   LPASS_CDC_TX_MACRO_DEC7, 0,
+			   &tx_dec7_mux, lpass_cdc_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,
+	lpass_cdc_tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+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", "MSM_DMIC", "TX DMIC MUX0"},
+	{"TX DMIC MUX0", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX0", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX0", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX0", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX0", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX0", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX0", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX0", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+	{"TX SMIC MUX0", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX0", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"},
+	{"TX DMIC MUX1", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX1", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX1", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX1", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX1", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX1", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX1", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX1", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+	{"TX SMIC MUX1", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX1", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"},
+	{"TX DMIC MUX2", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX2", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX2", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX2", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX2", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX2", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX2", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX2", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+	{"TX SMIC MUX2", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX2", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"},
+	{"TX DMIC MUX3", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX3", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX3", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX3", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX3", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX3", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX3", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX3", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+	{"TX SMIC MUX3", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX3", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"},
+	{"TX DMIC MUX4", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX4", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX4", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX4", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX4", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX4", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX4", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX4", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+	{"TX SMIC MUX4", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX4", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"},
+	{"TX DMIC MUX5", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX5", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX5", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX5", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX5", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX5", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX5", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX5", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+	{"TX SMIC MUX5", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX5", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"},
+	{"TX DMIC MUX6", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX6", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX6", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX6", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX6", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX6", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX6", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX6", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+	{"TX SMIC MUX6", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX6", "SWR_MIC11", "TX SWR_INPUT"},
+
+	{"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"},
+	{"TX DMIC MUX7", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX7", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX7", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX7", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX7", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX7", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX7", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX7", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+	{"TX SMIC MUX7", "SWR_MIC0", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC1", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC2", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC3", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC4", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC5", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC6", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC7", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC8", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC9", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC10", "TX SWR_INPUT"},
+	{"TX SMIC MUX7", "SWR_MIC11", "TX SWR_INPUT"},
+};
+
+static const struct snd_kcontrol_new lpass_cdc_tx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
+			  LPASS_CDC_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
+			  LPASS_CDC_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
+			  LPASS_CDC_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
+			  LPASS_CDC_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
+			  LPASS_CDC_TX4_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
+			  LPASS_CDC_TX5_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
+			  LPASS_CDC_TX6_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
+			  LPASS_CDC_TX7_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum,
+			lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put),
+	SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
+
+	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+
+	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+
+	SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+
+	SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+
+	SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+
+	SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+
+	SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+		       lpass_cdc_tx_macro_get_bcs, lpass_cdc_tx_macro_set_bcs),
+
+	SOC_SINGLE_EXT("TX_SWR_DMIC Enable", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_tx_macro_swr_dmic_get, lpass_cdc_tx_macro_swr_dmic_put),
+
+	SOC_ENUM_EXT("BCS Channel", bcs_ch_enum,
+		     lpass_cdc_tx_macro_bcs_ch_get, lpass_cdc_tx_macro_bcs_ch_put),
+
+	SOC_ENUM_EXT("BCS CH_SEL", bcs_ch_sel_mux_enum,
+		     lpass_cdc_tx_macro_get_bcs_ch_sel, lpass_cdc_tx_macro_put_bcs_ch_sel),
+};
+
+static int lpass_cdc_tx_macro_clk_div_get(struct snd_soc_component *component)
+{
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	return (int)tx_priv->dmic_clk_div;
+}
+
+static int lpass_cdc_tx_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
+				      struct lpass_cdc_tx_macro_priv *tx_priv)
+{
+	u32 div_factor = LPASS_CDC_TX_MACRO_CLK_DIV_2;
+	u32 mclk_rate = LPASS_CDC_TX_MACRO_MCLK_FREQ;
+
+	if (dmic_sample_rate == LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
+	    mclk_rate % dmic_sample_rate != 0)
+		goto undefined_rate;
+
+	div_factor = mclk_rate / dmic_sample_rate;
+
+	switch (div_factor) {
+	case 2:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_2;
+		break;
+	case 3:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_3;
+		break;
+	case 4:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_4;
+		break;
+	case 6:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_6;
+		break;
+	case 8:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_8;
+		break;
+	case 16:
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_16;
+		break;
+	default:
+		/* Any other DIV factor is invalid */
+		goto undefined_rate;
+	}
+
+	/* Valid dmic DIV factors */
+	dev_dbg(tx_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+		__func__, div_factor, mclk_rate);
+
+	return dmic_sample_rate;
+
+undefined_rate:
+	dev_dbg(tx_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
+		 __func__, dmic_sample_rate, mclk_rate);
+	dmic_sample_rate = LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
+
+	return dmic_sample_rate;
+}
+
+static const struct lpass_cdc_tx_macro_reg_mask_val
+				lpass_cdc_tx_macro_reg_init[] = {
+	{LPASS_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x0A},
+};
+
+static int lpass_cdc_tx_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+			snd_soc_component_get_dapm(component);
+	int ret = 0, i = 0;
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	tx_dev = lpass_cdc_get_device_ptr(component->dev, TX_MACRO);
+	if (!tx_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv = dev_get_drvdata(tx_dev);
+	if (!tx_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+	tx_priv->version = lpass_cdc_get_version(tx_dev);
+	ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_tx_macro_dapm_widgets,
+				ARRAY_SIZE(lpass_cdc_tx_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(tx_dev, "%s: Failed to add controls\n",
+			__func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
+				ARRAY_SIZE(tx_audio_map));
+	if (ret < 0) {
+		dev_err(tx_dev, "%s: Failed to add routes\n",
+			__func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(tx_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component,
+			lpass_cdc_tx_macro_snd_controls,
+			ARRAY_SIZE(lpass_cdc_tx_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+			__func__);
+		return ret;
+	}
+
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF1 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF2 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF3 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_INPUT");
+	snd_soc_dapm_sync(dapm);
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx_priv->tx_hpf_work[i].tx_priv = tx_priv;
+		tx_priv->tx_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&tx_priv->tx_hpf_work[i].dwork,
+			lpass_cdc_tx_macro_tx_hpf_corner_freq_callback);
+	}
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx_priv->tx_mute_dwork[i].tx_priv = tx_priv;
+		tx_priv->tx_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&tx_priv->tx_mute_dwork[i].dwork,
+			  lpass_cdc_tx_macro_mute_update_callback);
+	}
+	tx_priv->component = component;
+
+	for (i = 0; i < ARRAY_SIZE(lpass_cdc_tx_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				lpass_cdc_tx_macro_reg_init[i].reg,
+				lpass_cdc_tx_macro_reg_init[i].mask,
+				lpass_cdc_tx_macro_reg_init[i].val);
+
+	return 0;
+}
+
+static int lpass_cdc_tx_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *tx_dev = NULL;
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->component = NULL;
+	return 0;
+}
+
+static void lpass_cdc_tx_macro_init_ops(struct macro_ops *ops,
+			       char __iomem *tx_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = lpass_cdc_tx_macro_init;
+	ops->exit = lpass_cdc_tx_macro_deinit;
+	ops->io_base = tx_io_base;
+	ops->dai_ptr = lpass_cdc_tx_macro_dai;
+	ops->num_dais = ARRAY_SIZE(lpass_cdc_tx_macro_dai);
+	ops->event_handler = lpass_cdc_tx_macro_event_handler;
+	ops->clk_div_get = lpass_cdc_tx_macro_clk_div_get;
+	ops->clk_enable = __lpass_cdc_tx_macro_mclk_enable;
+}
+
+static int lpass_cdc_tx_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops = {0};
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+	u32 tx_base_addr = 0, sample_rate = 0;
+	char __iomem *tx_io_base = NULL;
+	int ret = 0;
+	const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate";
+
+	if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_tx_macro_priv),
+			    GFP_KERNEL);
+	if (!tx_priv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, tx_priv);
+
+	tx_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &tx_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	dev_set_drvdata(&pdev->dev, tx_priv);
+
+	tx_io_base = devm_ioremap(&pdev->dev,
+				   tx_base_addr, LPASS_CDC_TX_MACRO_MAX_OFFSET);
+	if (!tx_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+	tx_priv->tx_io_base = tx_io_base;
+	tx_priv->swr_dmic_enable = false;
+	tx_priv->wlock_holders = 0;
+	ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
+				   &sample_rate);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: could not find sample_rate entry in dt\n",
+			__func__);
+		tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_2;
+	} else {
+		if (lpass_cdc_tx_macro_validate_dmic_sample_rate(
+		sample_rate, tx_priv) == LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
+			return -EINVAL;
+	}
+
+	mutex_init(&tx_priv->mclk_lock);
+	mutex_init(&tx_priv->wlock);
+	lpass_cdc_tx_macro_init_ops(&ops, tx_io_base);
+	ops.clk_id_req = TX_CORE_CLK;
+	ops.default_clk_id = TX_CORE_CLK;
+	ret = lpass_cdc_register_macro(&pdev->dev, TX_MACRO, &ops);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: register macro failed\n", __func__);
+		goto err_reg_macro;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+err_reg_macro:
+	mutex_destroy(&tx_priv->mclk_lock);
+	mutex_destroy(&tx_priv->wlock);
+	return ret;
+}
+
+static int lpass_cdc_tx_macro_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
+
+	tx_priv = platform_get_drvdata(pdev);
+
+	if (!tx_priv)
+		return -EINVAL;
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	mutex_destroy(&tx_priv->mclk_lock);
+	mutex_destroy(&tx_priv->wlock);
+	lpass_cdc_unregister_macro(&pdev->dev, TX_MACRO);
+	return 0;
+}
+
+
+static const struct of_device_id lpass_cdc_tx_macro_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-tx-macro"},
+	{}
+};
+
+static const struct dev_pm_ops lpass_cdc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_cdc_runtime_suspend,
+		lpass_cdc_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_cdc_tx_macro_driver = {
+	.driver = {
+		.name = "lpass_cdc_tx_macro",
+		.owner = THIS_MODULE,
+		.pm = &lpass_cdc_dev_pm_ops,
+		.of_match_table = lpass_cdc_tx_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_tx_macro_probe,
+	.remove = lpass_cdc_tx_macro_remove,
+};
+
+module_platform_driver(lpass_cdc_tx_macro_driver);
+
+MODULE_DESCRIPTION("TX macro driver");
+MODULE_LICENSE("GPL v2");

+ 172 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-utils.c

@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include "lpass-cdc.h"
+#include "internal.h"
+
+#define REG_BYTES 2
+#define VAL_BYTES 1
+
+const u16 macro_id_base_offset[MAX_MACRO] = {
+	TX_START_OFFSET,
+	RX_START_OFFSET,
+	WSA_START_OFFSET,
+	VA_START_OFFSET,
+	WSA2_START_OFFSET,
+};
+
+int lpass_cdc_get_macro_id(bool va_no_dec_flag, u16 reg)
+{
+	if (reg >= TX_START_OFFSET
+		&& reg <= TX_MAX_OFFSET)
+		return TX_MACRO;
+	if (reg >= RX_START_OFFSET
+		&& reg <= RX_MAX_OFFSET)
+		return RX_MACRO;
+	if (reg >= WSA_START_OFFSET
+		&& reg <= WSA_MAX_OFFSET)
+		return WSA_MACRO;
+	if (reg >= WSA2_START_OFFSET
+		&& reg <= WSA2_MAX_OFFSET)
+		return WSA2_MACRO;
+	if (reg >= VA_START_OFFSET &&
+		reg <= VA_MAX_OFFSET)
+		return VA_MACRO;
+
+	return -EINVAL;
+}
+
+static int regmap_bus_read(void *context, const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev);
+	u16 *reg_p;
+	u16 __reg;
+	int macro_id, i;
+	u8 temp = 0;
+	int ret = -EINVAL;
+
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is NULL\n", __func__);
+		return ret;
+	}
+	if (!reg || !val) {
+		dev_err_ratelimited(dev, "%s: reg or val is NULL\n", __func__);
+		return ret;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err_ratelimited(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return ret;
+	}
+
+	reg_p = (u16 *)reg;
+	macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation,
+					   reg_p[0]);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
+	mutex_lock(&priv->io_lock);
+	for (i = 0; i < val_size; i++) {
+		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
+		ret = priv->read_dev(priv, macro_id, __reg, &temp);
+		if (ret < 0) {
+			dev_err_ratelimited(dev,
+			"%s: Codec read failed (%d), reg: 0x%x, size:%zd\n",
+			__func__, ret, reg_p[0] + i * 4, val_size);
+			break;
+		}
+		((u8 *)val)[i] = temp;
+		dev_dbg(dev, "%s: Read 0x%02x from reg 0x%x\n",
+			__func__, temp, reg_p[0] + i * 4);
+	}
+	mutex_unlock(&priv->io_lock);
+
+	return ret;
+}
+
+static int regmap_bus_gather_write(void *context,
+				   const void *reg, size_t reg_size,
+				   const void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev);
+	u16 *reg_p;
+	u16 __reg;
+	int macro_id, i;
+	int ret = -EINVAL;
+
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is NULL\n", __func__);
+		return ret;
+	}
+	if (!reg || !val) {
+		dev_err_ratelimited(dev, "%s: reg or val is NULL\n", __func__);
+		return ret;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err_ratelimited(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return ret;
+	}
+
+	reg_p = (u16 *)reg;
+	macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation,
+					reg_p[0]);
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
+	mutex_lock(&priv->io_lock);
+	for (i = 0; i < val_size; i++) {
+		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
+		ret = priv->write_dev(priv, macro_id, __reg, ((u8 *)val)[i]);
+		if (ret < 0) {
+			dev_err_ratelimited(dev,
+			"%s: Codec write failed (%d), reg:0x%x, size:%zd\n",
+			__func__, ret, reg_p[0] + i * 4, val_size);
+			break;
+		}
+		dev_dbg(dev, "Write %02x to reg 0x%x\n", ((u8 *)val)[i],
+			reg_p[0] + i * 4);
+	}
+	mutex_unlock(&priv->io_lock);
+	return ret;
+}
+
+static int regmap_bus_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	if (count < REG_BYTES) {
+		dev_err_ratelimited(dev, "%s: count %zd bytes < %d, not supported\n",
+			__func__, count, REG_BYTES);
+		return -EINVAL;
+	}
+
+	return regmap_bus_gather_write(context, data, REG_BYTES,
+				       data + REG_BYTES,
+				       count - REG_BYTES);
+}
+
+static struct regmap_bus regmap_bus_config = {
+	.write = regmap_bus_write,
+	.gather_write = regmap_bus_gather_write,
+	.read = regmap_bus_read,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+struct regmap *lpass_cdc_regmap_init(struct device *dev,
+				      const struct regmap_config *config)
+{
+	return devm_regmap_init(dev, &regmap_bus_config, dev, config);
+}

+ 2677 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c

@@ -0,0 +1,2677 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. 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 <linux/regulator/consumer.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/pm_runtime.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-registers.h"
+#include "lpass-cdc-clk-rsc.h"
+
+/* pm runtime auto suspend timer in msecs */
+#define VA_AUTO_SUSPEND_DELAY          100 /* delay in msec */
+#define LPASS_CDC_VA_MACRO_MAX_OFFSET 0x1000
+
+#define LPASS_CDC_VA_MACRO_NUM_DECIMATORS 4
+
+#define LPASS_CDC_VA_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 LPASS_CDC_VA_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define  TX_HPF_CUT_OFF_FREQ_MASK	0x60
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+#define LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define LPASS_CDC_VA_MACRO_MCLK_FREQ 9600000
+#define LPASS_CDC_VA_MACRO_TX_PATH_OFFSET \
+	(LPASS_CDC_VA_TX1_TX_PATH_CTL - LPASS_CDC_VA_TX0_TX_PATH_CTL)
+#define LPASS_CDC_VA_MACRO_TX_DMIC_CLK_DIV_MASK 0x0E
+#define LPASS_CDC_VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01
+#define LPASS_CDC_VA_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
+#define LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET 0x8
+#define LPASS_CDC_VA_MACRO_ADC_MODE_CFG0_SHIFT 1
+
+#define LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS       40
+#define LPASS_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS       100
+#define LPASS_CDC_VA_TX_DMIC_HPF_DELAY_MS       300
+#define LPASS_CDC_VA_TX_AMIC_HPF_DELAY_MS       300
+#define MAX_RETRY_ATTEMPTS 500
+#define LPASS_CDC_VA_MACRO_SWR_STRING_LEN 80
+#define LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX 3
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static int va_tx_unmute_delay = LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS;
+module_param(va_tx_unmute_delay, int, 0664);
+MODULE_PARM_DESC(va_tx_unmute_delay, "delay to unmute the tx path");
+
+static int lpass_cdc_va_macro_core_vote(void *handle, bool enable);
+enum {
+	LPASS_CDC_VA_MACRO_AIF_INVALID = 0,
+	LPASS_CDC_VA_MACRO_AIF1_CAP,
+	LPASS_CDC_VA_MACRO_AIF2_CAP,
+	LPASS_CDC_VA_MACRO_AIF3_CAP,
+	LPASS_CDC_VA_MACRO_MAX_DAIS,
+};
+
+enum {
+	LPASS_CDC_VA_MACRO_DEC0,
+	LPASS_CDC_VA_MACRO_DEC1,
+	LPASS_CDC_VA_MACRO_DEC2,
+	LPASS_CDC_VA_MACRO_DEC3,
+	LPASS_CDC_VA_MACRO_DEC_MAX,
+};
+
+enum {
+	LPASS_CDC_VA_MACRO_CLK_DIV_2,
+	LPASS_CDC_VA_MACRO_CLK_DIV_3,
+	LPASS_CDC_VA_MACRO_CLK_DIV_4,
+	LPASS_CDC_VA_MACRO_CLK_DIV_6,
+	LPASS_CDC_VA_MACRO_CLK_DIV_8,
+	LPASS_CDC_VA_MACRO_CLK_DIV_16,
+};
+
+enum {
+	MSM_DMIC,
+	SWR_MIC,
+};
+
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
+struct va_mute_work {
+	struct lpass_cdc_va_macro_priv *va_priv;
+	u32 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct lpass_cdc_va_macro_priv *va_priv;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+/* Hold instance to soundwire platform device */
+struct lpass_cdc_va_macro_swr_ctrl_data {
+	struct platform_device *va_swr_pdev;
+};
+
+struct lpass_cdc_va_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+struct lpass_cdc_va_macro_priv {
+	struct device *dev;
+	bool dec_active[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
+	bool va_without_decimation;
+	struct clk *lpass_audio_hw_vote;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct mutex wlock;
+	struct snd_soc_component *component;
+	struct hpf_work va_hpf_work[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
+	struct va_mute_work va_mute_dwork[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
+	unsigned long active_ch_mask[LPASS_CDC_VA_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[LPASS_CDC_VA_MACRO_MAX_DAIS];
+	u16 dmic_clk_div;
+	u16 va_mclk_users;
+	int swr_clk_users;
+	bool reset_swr;
+	struct device_node *va_swr_gpio_p;
+	struct lpass_cdc_va_macro_swr_ctrl_data *swr_ctrl_data;
+	struct lpass_cdc_va_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct lpass_cdc_va_macro_add_child_devices_work;
+	int child_count;
+	u16 mclk_mux_sel;
+	char __iomem *va_io_base;
+	char __iomem *va_island_mode_muxsel;
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX];
+	struct regulator *micb_supply;
+	u32 micb_voltage;
+	u32 micb_current;
+	u32 version;
+	u32 is_used_va_swr_gpio;
+	int micb_users;
+	u16 default_clk_id;
+	u16 clk_id;
+	int tx_swr_clk_cnt;
+	int va_swr_clk_cnt;
+	int va_clk_status;
+	int tx_clk_status;
+	bool lpi_enable;
+	bool clk_div_switch;
+	int dec_mode[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
+	int pcm_rate[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
+	int dapm_tx_clk_status;
+	u16 current_clk_id;
+	bool dev_up;
+	bool pre_dev_up;
+	bool swr_dmic_enable;
+	bool use_lpi_mixer_control;
+	int wlock_holders;
+};
+
+
+static int lpass_cdc_va_macro_wake_enable(struct lpass_cdc_va_macro_priv *va_priv,
+				bool wake_enable)
+{
+	int ret = 0;
+
+	mutex_lock(&va_priv->wlock);
+	if (wake_enable) {
+		if (va_priv->wlock_holders++ == 0) {
+			dev_dbg(va_priv->dev, "%s: pm wake\n", __func__);
+			pm_stay_awake(va_priv->dev);
+		}
+	} else {
+		 if (--va_priv->wlock_holders == 0) {
+			dev_dbg(va_priv->dev, "%s: pm release\n", __func__);
+			pm_relax(va_priv->dev);
+		}
+		if (va_priv->wlock_holders < 0)
+			va_priv->wlock_holders = 0;
+	}
+	mutex_unlock(&va_priv->wlock);
+	return ret;
+}
+
+static bool lpass_cdc_va_macro_get_data(struct snd_soc_component *component,
+			      struct device **va_dev,
+			      struct lpass_cdc_va_macro_priv **va_priv,
+			      const char *func_name)
+{
+	*va_dev = lpass_cdc_get_device_ptr(component->dev, VA_MACRO);
+	if (!(*va_dev)) {
+		dev_err_ratelimited(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+	*va_priv = dev_get_drvdata((*va_dev));
+	if (!(*va_priv) || !(*va_priv)->component) {
+		dev_err_ratelimited(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+	return true;
+}
+
+static int lpass_cdc_va_macro_clk_div_get(struct snd_soc_component *component)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	if (va_priv->clk_div_switch &&
+	    (va_priv->dmic_clk_div == LPASS_CDC_VA_MACRO_CLK_DIV_16))
+		return LPASS_CDC_VA_MACRO_CLK_DIV_4;
+
+
+	return (int)va_priv->dmic_clk_div;
+}
+
+static int lpass_cdc_va_macro_mclk_enable(
+			struct lpass_cdc_va_macro_priv *va_priv,
+			bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(va_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, va_priv->va_mclk_users);
+
+	mutex_lock(&va_priv->mclk_lock);
+	if (mclk_enable) {
+		ret = lpass_cdc_va_macro_core_vote(va_priv, true);
+		if (ret < 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"%s: va request core vote failed\n",
+				__func__);
+			goto exit;
+		}
+		ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   va_priv->clk_id,
+						   true);
+		lpass_cdc_va_macro_core_vote(va_priv, false);
+		if (ret < 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"%s: va request clock en failed\n",
+				__func__);
+			goto exit;
+		}
+		lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev,
+					      true);
+		if (va_priv->va_mclk_users == 0) {
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					VA_START_OFFSET,
+					VA_MAX_OFFSET);
+		}
+		va_priv->va_mclk_users++;
+	} else {
+		if (va_priv->va_mclk_users <= 0) {
+			dev_err_ratelimited(va_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			va_priv->va_mclk_users = 0;
+			goto exit;
+		}
+		va_priv->va_mclk_users--;
+		lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev,
+					  false);
+		ret = lpass_cdc_va_macro_core_vote(va_priv, true);
+		if (ret < 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"%s: va request core vote failed\n",
+				__func__);
+		}
+		lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					va_priv->clk_id,
+					false);
+		if (!ret)
+			lpass_cdc_va_macro_core_vote(va_priv, false);
+	}
+exit:
+	mutex_unlock(&va_priv->mclk_lock);
+	return ret;
+}
+
+static int lpass_cdc_va_macro_event_handler(struct snd_soc_component *component,
+				  u16 event, u32 data)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	int retry_cnt = MAX_RETRY_ATTEMPTS;
+	int ret = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case LPASS_CDC_MACRO_EVT_WAIT_VA_CLK_RESET:
+		while ((va_priv->va_mclk_users != 0) && (retry_cnt != 0)) {
+			dev_dbg_ratelimited(va_dev, "%s:retry_cnt: %d\n",
+				__func__, retry_cnt);
+			/*
+			 * Userspace takes 10 seconds to close
+			 * the session when pcm_start fails due to concurrency
+			 * with PDR/SSR. Loop and check every 20ms till 10
+			 * seconds for va_mclk user count to get reset to 0
+			 * which ensures userspace teardown is done and SSR
+			 * powerup seq can proceed.
+			 */
+			msleep(20);
+			retry_cnt--;
+		}
+		if (retry_cnt == 0)
+			dev_err_ratelimited(va_dev,
+				"%s: va_mclk_users non-zero, SSR fail!!\n",
+				__func__);
+		break;
+	case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
+		va_priv->pre_dev_up = true;
+		/* enable&disable VA_CORE_CLK to reset GFMUX reg */
+		ret = lpass_cdc_va_macro_core_vote(va_priv, true);
+		if (ret < 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"%s: va request core vote failed\n",
+				__func__);
+			break;
+		}
+		ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						va_priv->default_clk_id,
+						va_priv->clk_id, true);
+		if (ret < 0)
+			dev_err_ratelimited(va_priv->dev,
+				"%s, failed to enable clk, ret:%d\n",
+				__func__, ret);
+		else
+			lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						va_priv->default_clk_id,
+						va_priv->clk_id, false);
+		lpass_cdc_va_macro_core_vote(va_priv, false);
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_UP:
+		/* reset swr after ssr/pdr */
+		va_priv->reset_swr = true;
+		va_priv->dev_up = true;
+		if (va_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case LPASS_CDC_MACRO_EVT_CLK_RESET:
+		lpass_cdc_rsc_clk_reset(va_dev, VA_CORE_CLK);
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_DOWN:
+		va_priv->pre_dev_up = false;
+		va_priv->dev_up = false;
+		if (va_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(va_dev) ||
+		     !pm_runtime_suspended(va_dev))) {
+			ret = lpass_cdc_runtime_suspend(va_dev);
+			if (!ret) {
+				pm_runtime_disable(va_dev);
+				pm_runtime_set_suspended(va_dev);
+				pm_runtime_enable(va_dev);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_va_macro_swr_clk_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 device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		va_priv->va_swr_clk_cnt++;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		va_priv->va_swr_clk_cnt--;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_va_macro_swr_pwr_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);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	bool vote_err = false;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n",__func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		dev_dbg(component->dev,
+			"%s: va_swr_clk_cnt %d, tx_swr_clk_cnt %d, tx_clk_status %d\n",
+			__func__, va_priv->va_swr_clk_cnt,
+			va_priv->tx_swr_clk_cnt, va_priv->tx_clk_status);
+		if (va_priv->current_clk_id == VA_CORE_CLK) {
+			 return 0;
+		} else if ( va_priv->va_swr_clk_cnt != 0 &&
+				va_priv->tx_clk_status)  {
+			ret = lpass_cdc_va_macro_core_vote(va_priv, true);
+			if (ret < 0) {
+				dev_err_ratelimited(va_priv->dev,
+					"%s: va request core vote failed\n",
+					__func__);
+				break;
+			}
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					true);
+			lpass_cdc_va_macro_core_vote(va_priv, false);
+			if (ret) {
+				dev_dbg(component->dev,
+					"%s: request clock VA_CLK enable failed\n",
+					__func__);
+				break;
+			}
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					TX_CORE_CLK,
+					false);
+			if (ret) {
+				dev_dbg(component->dev,
+					"%s: request clock TX_CLK disable failed\n",
+					__func__);
+				lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					false);
+				break;
+			}
+			va_priv->current_clk_id = VA_CORE_CLK;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (va_priv->current_clk_id == VA_CORE_CLK) {
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					TX_CORE_CLK,
+					true);
+			if (ret) {
+				dev_err_ratelimited(component->dev,
+					"%s: request clock TX_CLK enable failed\n",
+					__func__);
+				if (va_priv->dev_up)
+					break;
+			}
+			ret = lpass_cdc_va_macro_core_vote(va_priv, true);
+			if (ret < 0) {
+				dev_err_ratelimited(va_priv->dev,
+					"%s: va request core vote failed\n",
+					__func__);
+				if (va_priv->dev_up)
+					break;
+				vote_err = true;
+			}
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					va_priv->default_clk_id,
+					VA_CORE_CLK,
+					false);
+			if (!vote_err)
+				lpass_cdc_va_macro_core_vote(va_priv, false);
+			if (ret) {
+				dev_err_ratelimited(component->dev,
+					"%s: request clock VA_CLK disable failed\n",
+					__func__);
+				if (va_priv->dev_up)
+					lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						va_priv->default_clk_id,
+						TX_CORE_CLK,
+						false);
+				break;
+			}
+			va_priv->current_clk_id = TX_CORE_CLK;
+		}
+		break;
+	default:
+		dev_err_ratelimited(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_va_macro_tx_swr_clk_event(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++va_priv->tx_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--va_priv->tx_swr_clk_cnt;
+
+	return 0;
+}
+
+static int lpass_cdc_va_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);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   true);
+		if (!ret)
+			va_priv->dapm_tx_clk_status++;
+
+		if (!va_priv->use_lpi_mixer_control) {
+			ret = lpass_cdc_va_macro_mclk_enable(va_priv, 1, true);
+		} else {
+			if (va_priv->lpi_enable)
+				ret = lpass_cdc_va_macro_mclk_enable(va_priv, 1, true);
+			else
+				ret = lpass_cdc_tx_mclk_enable(component, 1);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (!va_priv->use_lpi_mixer_control) {
+			lpass_cdc_va_macro_mclk_enable(va_priv, 0, true);
+		} else {
+			if (va_priv->lpi_enable)
+				lpass_cdc_va_macro_mclk_enable(va_priv, 0, true);
+			else
+				lpass_cdc_tx_mclk_enable(component, 0);
+		}
+
+		if (va_priv->dapm_tx_clk_status > 0) {
+			lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+					   va_priv->default_clk_id,
+					   TX_CORE_CLK,
+					   false);
+			va_priv->dapm_tx_clk_status--;
+		}
+		break;
+	default:
+		dev_err_ratelimited(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_va_macro_tx_va_mclk_enable(
+				struct lpass_cdc_va_macro_priv *va_priv,
+				struct regmap *regmap, int clk_type,
+				bool enable)
+{
+	int ret = 0, clk_tx_ret = 0;
+
+	dev_dbg(va_priv->dev,
+		"%s: clock type %s, enable: %s tx_mclk_users: %d\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"), va_priv->va_mclk_users);
+
+	if (enable) {
+		if (va_priv->swr_clk_users == 0) {
+			msm_cdc_pinctrl_select_active_state(
+						va_priv->va_swr_gpio_p);
+			msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, false);
+		}
+		clk_tx_ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		if (clk_type == TX_MCLK) {
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+			lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev,
+						  true);
+		}
+		if (clk_type == VA_MCLK) {
+			ret = lpass_cdc_va_macro_mclk_enable(va_priv, 1, true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: request clock enable failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (va_priv->swr_clk_users == 0) {
+			dev_dbg(va_priv->dev, "%s: reset_swr: %d\n",
+				__func__, va_priv->reset_swr);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			va_priv->reset_swr = false;
+		}
+		if (!clk_tx_ret)
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		va_priv->swr_clk_users++;
+	} else {
+		if (va_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"va swrm clock users already 0\n");
+			va_priv->swr_clk_users = 0;
+			return 0;
+		}
+		clk_tx_ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		va_priv->swr_clk_users--;
+		if (va_priv->swr_clk_users == 0)
+			regmap_update_bits(regmap,
+				LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+		if (clk_type == VA_MCLK)
+			lpass_cdc_va_macro_mclk_enable(va_priv, 0, true);
+		if (clk_type == TX_MCLK) {
+			lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev,
+						  false);
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0) {
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				}
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (!clk_tx_ret)
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		if (va_priv->swr_clk_users == 0) {
+			msm_cdc_pinctrl_select_sleep_state(
+						va_priv->va_swr_gpio_p);
+			msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, true);
+		}
+	}
+	return 0;
+
+done:
+	if (!clk_tx_ret)
+		lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+	return ret;
+}
+
+static int lpass_cdc_va_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct lpass_cdc_va_macro_priv *va_priv =
+					(struct lpass_cdc_va_macro_priv *) handle;
+
+	if (va_priv == NULL) {
+		pr_err_ratelimited("%s: va priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!va_priv->pre_dev_up && enable) {
+		pr_err("%s: adsp is not up\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (lpass_cdc_check_core_votes(va_priv->dev)) {
+			rc = 0;
+		} else {
+			rc = -ENOTSYNC;
+		}
+	} else {
+		pm_runtime_put_autosuspend(va_priv->dev);
+		pm_runtime_mark_last_busy(va_priv->dev);
+	}
+	return rc;
+}
+
+static int lpass_cdc_va_macro_swrm_clock(void *handle, bool enable)
+{
+	struct lpass_cdc_va_macro_priv *va_priv =
+					(struct lpass_cdc_va_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&va_priv->swr_clk_lock);
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		va_priv->tx_swr_clk_cnt, va_priv->va_swr_clk_cnt);
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (va_priv->va_swr_clk_cnt && !va_priv->tx_swr_clk_cnt) {
+			ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv,
+						regmap, VA_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(va_priv->dev);
+				pm_runtime_put_autosuspend(va_priv->dev);
+				goto done;
+			}
+			va_priv->va_clk_status++;
+		} else {
+			ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv,
+						regmap, TX_MCLK, enable);
+			if (ret) {
+				pm_runtime_mark_last_busy(va_priv->dev);
+				pm_runtime_put_autosuspend(va_priv->dev);
+				goto done;
+			}
+			va_priv->tx_clk_status++;
+		}
+		pm_runtime_mark_last_busy(va_priv->dev);
+		pm_runtime_put_autosuspend(va_priv->dev);
+	} else {
+		if (va_priv->va_clk_status && !va_priv->tx_clk_status) {
+			ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv,
+							regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->va_clk_status;
+		} else if (!va_priv->va_clk_status && va_priv->tx_clk_status) {
+			ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv,
+							regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->tx_clk_status;
+		} else if (va_priv->va_clk_status && va_priv->tx_clk_status) {
+			if (!va_priv->va_swr_clk_cnt &&
+				va_priv->tx_swr_clk_cnt) {
+				ret = lpass_cdc_va_macro_tx_va_mclk_enable(
+							va_priv, regmap,
+							VA_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->va_clk_status;
+			} else {
+				ret = lpass_cdc_va_macro_tx_va_mclk_enable(
+							va_priv, regmap,
+							TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->tx_clk_status;
+			}
+
+		} else {
+			dev_dbg(va_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
+		}
+	}
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock usr %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, va_priv->swr_clk_users, va_priv->tx_clk_status,
+		va_priv->va_clk_status);
+done:
+	mutex_unlock(&va_priv->swr_clk_lock);
+	return ret;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+	u16 adc_mux_reg = 0;
+	bool ret = false;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return ret;
+
+	adc_mux_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1 +
+			LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+		if (!va_priv->swr_dmic_enable)
+			return true;
+	}
+
+	return ret;
+}
+
+static void lpass_cdc_va_macro_tx_hpf_corner_freq_callback(
+						struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct lpass_cdc_va_macro_priv *va_priv;
+	struct snd_soc_component *component;
+	u16 dec_cfg_reg, hpf_gate_reg;
+	u8 hpf_cut_off_freq;
+	u16 adc_reg = 0, adc_n = 0;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	va_priv = hpf_work->va_priv;
+	component = va_priv->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0 +
+			LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+	hpf_gate_reg = LPASS_CDC_VA_TX0_TX_PATH_SEC2 +
+			LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator;
+
+	dev_dbg(va_priv->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
+		__func__, hpf_work->decimator, hpf_cut_off_freq);
+
+	if (is_amic_enabled(component, hpf_work->decimator)) {
+		adc_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
+			LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET *
+			hpf_work->decimator;
+		adc_n = snd_soc_component_read(component, adc_reg) &
+				LPASS_CDC_VA_MACRO_SWR_MIC_MUX_SEL_MASK;
+		/* analog mic clear TX hold */
+		lpass_cdc_clear_amic_tx_hold(component->dev, adc_n);
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x03, 0x02);
+		/* Add delay between toggle hpf gate based on sample rate */
+		switch (va_priv->pcm_rate[hpf_work->decimator]) {
+		case 0:
+			usleep_range(125, 130);
+			break;
+		case 1:
+			usleep_range(62, 65);
+			break;
+		case 3:
+			usleep_range(31, 32);
+			break;
+		case 4:
+			usleep_range(20, 21);
+			break;
+		case 5:
+			usleep_range(10, 11);
+			break;
+		case 6:
+			usleep_range(5, 6);
+			break;
+		default:
+			usleep_range(125, 130);
+		}
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x03, 0x01);
+	} else {
+		snd_soc_component_update_bits(component,
+				dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
+				hpf_cut_off_freq << 5);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x02, 0x02);
+		/* Minimum 1 clk cycle delay is required as per HW spec */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      0x02, 0x00);
+	}
+	lpass_cdc_va_macro_wake_enable(va_priv, 0);
+}
+
+static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work)
+{
+	struct va_mute_work *va_mute_dwork;
+	struct snd_soc_component *component = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv;
+	struct delayed_work *delayed_work;
+	u16 tx_vol_ctl_reg, decimator;
+
+	delayed_work = to_delayed_work(work);
+	va_mute_dwork = container_of(delayed_work, struct va_mute_work, dwork);
+	va_priv = va_mute_dwork->va_priv;
+	component = va_priv->component;
+	decimator = va_mute_dwork->decimator;
+
+	tx_vol_ctl_reg =
+		LPASS_CDC_VA_TX0_TX_PATH_CTL +
+			LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
+	dev_dbg(va_priv->dev, "%s: decimator %u unmute\n",
+		__func__, decimator);
+	lpass_cdc_va_macro_wake_enable(va_priv, 0);
+}
+
+static int lpass_cdc_va_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;
+	u16 mic_sel_reg, dmic_clk_reg;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val > e->items - 1)
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__,
+		widget->name, val);
+
+	switch (e->reg) {
+	case LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = LPASS_CDC_VA_TX1_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = LPASS_CDC_VA_TX2_TX_PATH_CFG0;
+		break;
+	case LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = LPASS_CDC_VA_TX3_TX_PATH_CFG0;
+		break;
+	default:
+		dev_err_ratelimited(component->dev, "%s: e->reg: 0x%x not expected\n",
+			__func__, e->reg);
+		return -EINVAL;
+	}
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
+		if (val != 0) {
+			if (!va_priv->swr_dmic_enable) {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x0 << 7);
+			} else {
+				snd_soc_component_update_bits(component,
+							mic_sel_reg,
+							1 << 7, 0x1 << 7);
+				snd_soc_component_update_bits(component,
+					LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+				dmic_clk_reg =
+					LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0 +
+						((val - 5)/2) * 4;
+				snd_soc_component_update_bits(component,
+					dmic_clk_reg,
+					0x0E, va_priv->dmic_clk_div << 0x1);
+			}
+		}
+	} else {
+		/* DMIC selected */
+		if (val != 0)
+			snd_soc_component_update_bits(component, mic_sel_reg,
+					1 << 7, 1 << 7);
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int lpass_cdc_va_macro_lpi_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = va_priv->lpi_enable;
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_lpi_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	va_priv->lpi_enable = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_swr_dmic_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = va_priv->swr_dmic_enable;
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_swr_dmic_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	va_priv->swr_dmic_enable = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+
+static int lpass_cdc_va_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(dec_id, &va_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int lpass_cdc_va_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 dec_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (test_bit(dec_id, &va_priv->active_ch_mask[dai_id])) {
+			dev_err_ratelimited(component->dev, "%s: channel is already enabled, dec_id = %d, dai_id = %d\n",
+					__func__, dec_id, dai_id);
+		} else {
+			set_bit(dec_id, &va_priv->active_ch_mask[dai_id]);
+			va_priv->active_ch_cnt[dai_id]++;
+		}
+	} else {
+		if (!test_bit(dec_id, &va_priv->active_ch_mask[dai_id])) {
+			dev_err_ratelimited(component->dev, "%s: channel is already disabled, dec_id = %d, dai_id = %d\n",
+					__func__, dec_id, dai_id);
+		} else {
+			va_priv->active_ch_cnt[dai_id]--;
+			clear_bit(dec_id, &va_priv->active_ch_mask[dai_id]);
+		}
+	}
+
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_enable_dmic(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event, u16 adc_mux0_cfg)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+	unsigned int dmic = 0;
+
+	dmic = (snd_soc_component_read(component, adc_mux0_cfg) >> 4) - 1;
+	
+	dev_dbg(component->dev, "%s: event %d DMIC%d\n",
+		__func__, event,  dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		lpass_cdc_dmic_clk_enable(component, (u32)dmic, (u32)DMIC_VA, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		lpass_cdc_dmic_clk_enable(component, (u32)dmic, (u32)DMIC_VA, false);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_va_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;
+	u16 tx_gain_ctl_reg;
+	u8 hpf_cut_off_freq;
+	u16 adc_mux_reg = 0;
+	u16 adc_mux0_reg = 0;
+	u16 tx_fs_reg = 0;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	int hpf_delay = LPASS_CDC_VA_TX_DMIC_HPF_DELAY_MS;
+	int unmute_delay = LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	decimator = w->shift;
+
+	dev_dbg(va_dev, "%s(): widget = %s decimator = %u\n", __func__,
+		w->name, decimator);
+
+	tx_vol_ctl_reg = LPASS_CDC_VA_TX0_TX_PATH_CTL +
+				LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	hpf_gate_reg = LPASS_CDC_VA_TX0_TX_PATH_SEC2 +
+				LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	dec_cfg_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0 +
+				LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	tx_gain_ctl_reg = LPASS_CDC_VA_TX0_TX_VOL_CTL +
+				LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	adc_mux_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1 +
+			LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	adc_mux0_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
+			LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	tx_fs_reg = LPASS_CDC_VA_TX0_TX_PATH_CTL +
+				LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+	va_priv->pcm_rate[decimator] = (snd_soc_component_read(component,
+				tx_fs_reg) & 0x0F);
+
+	if(!is_amic_enabled(component, decimator))
+		lpass_cdc_va_macro_enable_dmic(w, kcontrol, event, adc_mux0_reg);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+			dec_cfg_reg, 0x06, va_priv->dec_mode[decimator] <<
+			LPASS_CDC_VA_MACRO_ADC_MODE_CFG0_SHIFT);
+		/* Enable TX PGA Mute */
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* Enable TX CLK */
+		snd_soc_component_update_bits(component,
+				tx_vol_ctl_reg, 0x20, 0x20);
+		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(
+					component, dec_cfg_reg) &
+				   TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+		va_priv->va_hpf_work[decimator].hpf_cut_off_freq =
+							hpf_cut_off_freq;
+
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					    TX_HPF_CUT_OFF_FREQ_MASK,
+					    CF_MIN_3DB_150HZ << 5);
+		}
+		if (is_amic_enabled(component, decimator)) {
+			hpf_delay = LPASS_CDC_VA_TX_AMIC_HPF_DELAY_MS;
+			unmute_delay = LPASS_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS;
+			if (va_tx_unmute_delay < unmute_delay)
+				va_tx_unmute_delay = unmute_delay;
+		}
+		snd_soc_component_update_bits(component,
+				hpf_gate_reg, 0x03, 0x02);
+		if (!is_amic_enabled(component, decimator))
+			snd_soc_component_update_bits(component,
+				hpf_gate_reg, 0x03, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+			hpf_gate_reg, 0x03, 0x01);
+		/*
+		 * 6ms delay is required as per HW spec
+		 */
+		usleep_range(6000, 6010);
+		/* schedule work queue to Remove Mute */
+		lpass_cdc_va_macro_wake_enable(va_priv, 1);
+		queue_delayed_work(system_freezable_wq,
+				   &va_priv->va_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(va_tx_unmute_delay));
+		if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq !=
+							CF_MIN_3DB_150HZ) {
+		lpass_cdc_va_macro_wake_enable(va_priv, 1);
+			queue_delayed_work(system_freezable_wq,
+					&va_priv->va_hpf_work[decimator].dwork,
+					msecs_to_jiffies(hpf_delay));
+		}
+		/* apply gain after decimator is enabled */
+		snd_soc_component_write(component, tx_gain_ctl_reg,
+			snd_soc_component_read(component, tx_gain_ctl_reg));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			va_priv->va_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x10, 0x10);
+		if (cancel_delayed_work_sync(
+		    &va_priv->va_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_update_bits(component,
+						dec_cfg_reg,
+						TX_HPF_CUT_OFF_FREQ_MASK,
+						hpf_cut_off_freq << 5);
+				if (is_amic_enabled(component, decimator))
+					snd_soc_component_update_bits(component,
+						hpf_gate_reg,
+						0x03, 0x02);
+				else
+					snd_soc_component_update_bits(component,
+						hpf_gate_reg,
+						0x03, 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,
+						0x03, 0x01);
+			}
+		}
+		lpass_cdc_va_macro_wake_enable(va_priv, 0);
+		cancel_delayed_work_sync(
+				&va_priv->va_mute_dwork[decimator].dwork);
+		lpass_cdc_va_macro_wake_enable(va_priv, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable TX CLK */
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x20, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x40, 0x40);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x40, 0x00);
+		snd_soc_component_update_bits(component, tx_vol_ctl_reg,
+					0x10, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_va_macro_enable_tx(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 device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (va_priv->dapm_tx_clk_status > 0) {
+			ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   false);
+			va_priv->dapm_tx_clk_status--;
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   true);
+		if (!ret)
+			va_priv->dapm_tx_clk_status++;
+		break;
+	default:
+		dev_err_ratelimited(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int lpass_cdc_va_macro_enable_micbias(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 device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	if (!va_priv->micb_supply) {
+		dev_err_ratelimited(va_dev,
+			"%s:regulator not provided in dtsi\n", __func__);
+		return -EINVAL;
+	}
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (va_priv->micb_users++ > 0)
+			return 0;
+		ret = regulator_set_voltage(va_priv->micb_supply,
+				      va_priv->micb_voltage,
+				      va_priv->micb_voltage);
+		if (ret) {
+			dev_err_ratelimited(va_dev, "%s: Setting voltage failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = regulator_set_load(va_priv->micb_supply,
+					 va_priv->micb_current);
+		if (ret) {
+			dev_err_ratelimited(va_dev, "%s: Setting current failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = regulator_enable(va_priv->micb_supply);
+		if (ret) {
+			dev_err_ratelimited(va_dev, "%s: regulator enable failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (--va_priv->micb_users > 0)
+			return 0;
+		if (va_priv->micb_users < 0) {
+			va_priv->micb_users = 0;
+			dev_dbg(va_dev, "%s: regulator already disabled\n",
+				__func__);
+			return 0;
+		}
+		ret = regulator_disable(va_priv->micb_supply);
+		if (ret) {
+			dev_err_ratelimited(va_dev, "%s: regulator disable failed, err = %d\n",
+				__func__, ret);
+			return ret;
+		}
+		regulator_set_voltage(va_priv->micb_supply, 0,
+				va_priv->micb_voltage);
+		regulator_set_load(va_priv->micb_supply, 0);
+		break;
+	}
+	return 0;
+}
+
+static inline int lpass_cdc_va_macro_path_get(const char *wname,
+				    unsigned int *path_num)
+{
+	int ret = 0;
+	char *widget_name = NULL;
+	char *w_name = NULL;
+	char *path_num_char = NULL;
+	char *path_name = NULL;
+
+	widget_name = kstrndup(wname, 10, GFP_KERNEL);
+	if (!widget_name)
+		return -EINVAL;
+
+	w_name = widget_name;
+
+	path_name = strsep(&widget_name, " ");
+	if (!path_name) {
+		pr_err_ratelimited("%s: Invalid widget name = %s\n",
+			__func__, widget_name);
+		ret = -EINVAL;
+		goto err;
+	}
+	path_num_char = strpbrk(path_name, "01234567");
+	if (!path_num_char) {
+		pr_err_ratelimited("%s: va path index not found\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = kstrtouint(path_num_char, 10, path_num);
+	if (ret < 0)
+		pr_err_ratelimited("%s: Invalid tx path = %s\n",
+			__func__, w_name);
+
+err:
+	kfree(w_name);
+	return ret;
+}
+
+static int lpass_cdc_va_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 lpass_cdc_va_macro_priv *priv = NULL;
+	struct device *va_dev = NULL;
+	int ret = 0;
+	int path = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev, &priv, __func__))
+		return -EINVAL;
+
+	ret = lpass_cdc_va_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	ucontrol->value.integer.value[0] = priv->dec_mode[path];
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_va_macro_priv *priv = NULL;
+	struct device *va_dev = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int ret = 0;
+	int path = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev, &priv, __func__))
+		return -EINVAL;
+
+	ret = lpass_cdc_va_macro_path_get(kcontrol->id.name, &path);
+	if (ret)
+		return ret;
+
+	priv->dec_mode[path] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	int tx_fs_rate = -EINVAL;
+	struct snd_soc_component *component = dai->component;
+	u32 decimator, sample_rate;
+	u16 tx_fs_reg = 0;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		dai->name, dai->id, params_rate(params),
+		params_channels(params));
+
+	sample_rate = params_rate(params);
+	if (sample_rate > 16000)
+		va_priv->clk_div_switch = true;
+	else
+		va_priv->clk_div_switch = false;
+	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_ratelimited(va_dev, "%s: Invalid TX sample rate: %d\n",
+			__func__, params_rate(params));
+		return -EINVAL;
+	}
+	for_each_set_bit(decimator, &va_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_VA_MACRO_DEC_MAX) {
+		if (decimator >= 0) {
+			tx_fs_reg = LPASS_CDC_VA_TX0_TX_PATH_CTL +
+				  LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator;
+			dev_dbg(va_dev, "%s: set DEC%u rate to %u\n",
+				__func__, decimator, sample_rate);
+			snd_soc_component_update_bits(component, tx_fs_reg,
+						0x0F, tx_fs_rate);
+		} else {
+			dev_err_ratelimited(va_dev,
+				"%s: ERROR: Invalid decimator: %d\n",
+				__func__, decimator);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int lpass_cdc_va_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 device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	switch (dai->id) {
+	case LPASS_CDC_VA_MACRO_AIF1_CAP:
+	case LPASS_CDC_VA_MACRO_AIF2_CAP:
+	case LPASS_CDC_VA_MACRO_AIF3_CAP:
+		*tx_slot = va_priv->active_ch_mask[dai->id];
+		*tx_num = va_priv->active_ch_cnt[dai->id];
+		break;
+	default:
+		dev_err_ratelimited(va_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static struct snd_soc_dai_ops lpass_cdc_va_macro_dai_ops = {
+	.hw_params = lpass_cdc_va_macro_hw_params,
+	.get_channel_map = lpass_cdc_va_macro_get_channel_map,
+};
+
+static struct snd_soc_dai_driver lpass_cdc_va_macro_dai[] = {
+	{
+		.name = "va_macro_tx1",
+		.id = LPASS_CDC_VA_MACRO_AIF1_CAP,
+		.capture = {
+			.stream_name = "VA_AIF1 Capture",
+			.rates = LPASS_CDC_VA_MACRO_RATES,
+			.formats = LPASS_CDC_VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_va_macro_dai_ops,
+	},
+	{
+		.name = "va_macro_tx2",
+		.id = LPASS_CDC_VA_MACRO_AIF2_CAP,
+		.capture = {
+			.stream_name = "VA_AIF2 Capture",
+			.rates = LPASS_CDC_VA_MACRO_RATES,
+			.formats = LPASS_CDC_VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_va_macro_dai_ops,
+	},
+	{
+		.name = "va_macro_tx3",
+		.id = LPASS_CDC_VA_MACRO_AIF3_CAP,
+		.capture = {
+			.stream_name = "VA_AIF3 Capture",
+			.rates = LPASS_CDC_VA_MACRO_RATES,
+			.formats = LPASS_CDC_VA_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &lpass_cdc_va_macro_dai_ops,
+	},
+};
+
+#define STRING(name) #name
+#define LPASS_CDC_VA_MACRO_DAPM_ENUM(name, reg, offset, text) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM(STRING(name), name##_enum)
+
+#define LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
+static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
+static const struct snd_kcontrol_new name##_mux = \
+		SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
+
+#define LPASS_CDC_VA_MACRO_DAPM_MUX(name, shift, kctl) \
+		SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
+
+static const char * const adc_mux_text[] = {
+	"MSM_DMIC", "SWR_MIC"
+};
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1,
+		   0, adc_mux_text);
+LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1,
+		   0, adc_mux_text);
+
+static const char * const dmic_mux_text[] = {
+	"ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
+	"DMIC4", "DMIC5", "DMIC6", "DMIC7"
+};
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			4, dmic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+static const char * const smic_mux_text[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text, snd_soc_dapm_get_enum_double,
+			lpass_cdc_va_macro_put_dec_enum);
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0,
+			lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_va_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF1_CAP, 0,
+		lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF2_CAP, 0,
+		lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF3_CAP, 0,
+		lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		LPASS_CDC_VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer, ARRAY_SIZE(va_aif1_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		LPASS_CDC_VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer, ARRAY_SIZE(va_aif2_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		LPASS_CDC_VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer, ARRAY_SIZE(va_aif3_cap_mixer)),
+
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3),
+
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2),
+	LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3),
+
+	SND_SOC_DAPM_INPUT("VA SWR_INPUT"),
+
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS", SND_SOC_NOPM, 0, 0,
+		lpass_cdc_va_macro_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_ADC("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 0,
+			   &va_dec0_mux, lpass_cdc_va_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("VA DEC1 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 0,
+			   &va_dec1_mux, lpass_cdc_va_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("VA DEC2 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 0,
+			   &va_dec2_mux, lpass_cdc_va_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("VA DEC3 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 0,
+			   &va_dec3_mux, lpass_cdc_va_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("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      lpass_cdc_va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", 0, SND_SOC_NOPM, 0, 0,
+			      lpass_cdc_va_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			      lpass_cdc_va_macro_tx_swr_clk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", -1, SND_SOC_NOPM, 0, 0,
+			      lpass_cdc_va_macro_swr_clk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route va_audio_map[] = {
+	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF3 CAP", NULL, "VA_MCLK"},
+
+	{"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"},
+	{"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"},
+	{"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"},
+
+	{"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"},
+	{"VA DMIC MUX0", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX0", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX0", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX0", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX0", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX0", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX0", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX0", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"},
+	{"VA SMIC MUX0", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX0", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"},
+	{"VA DMIC MUX1", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX1", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX1", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX1", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX1", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX1", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX1", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX1", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"},
+	{"VA SMIC MUX1", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX1", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"},
+	{"VA DMIC MUX2", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX2", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX2", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX2", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX2", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX2", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX2", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX2", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"},
+	{"VA SMIC MUX2", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX2", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"},
+	{"VA DMIC MUX3", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX3", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX3", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX3", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX3", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX3", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX3", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX3", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"},
+	{"VA SMIC MUX3", "SWR_MIC0", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC1", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC2", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC3", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC4", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC5", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC6", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC7", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC8", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"},
+	{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"},
+
+	{"VA SWR_INPUT", NULL, "VA_SWR_PWR"},
+
+	{"VA SWR_INPUT", NULL, "VA_SWR_CLK"},
+};
+
+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_EXT(ARRAY_SIZE(dec_mode_mux_text),
+			    dec_mode_mux_text);
+
+static const struct snd_kcontrol_new lpass_cdc_va_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("VA_DEC0 Volume",
+			  LPASS_CDC_VA_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC1 Volume",
+			  LPASS_CDC_VA_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC2 Volume",
+			  LPASS_CDC_VA_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("VA_DEC3 Volume",
+			  LPASS_CDC_VA_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
+		lpass_cdc_va_macro_lpi_get, lpass_cdc_va_macro_lpi_put),
+
+	SOC_SINGLE_EXT("VA_SWR_DMIC Enable", 0, 0, 1, 0,
+		lpass_cdc_va_macro_swr_dmic_get, lpass_cdc_va_macro_swr_dmic_put),
+
+	SOC_ENUM_EXT("VA_DEC0 MODE", dec_mode_mux_enum,
+			lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC1 MODE", dec_mode_mux_enum,
+			lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC2 MODE", dec_mode_mux_enum,
+			lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("VA_DEC3 MODE", dec_mode_mux_enum,
+			lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put),
+};
+
+static int lpass_cdc_va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
+				      struct lpass_cdc_va_macro_priv *va_priv)
+{
+	u32 div_factor;
+	u32 mclk_rate = LPASS_CDC_VA_MACRO_MCLK_FREQ;
+
+	if (dmic_sample_rate == LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
+	    mclk_rate % dmic_sample_rate != 0)
+		goto undefined_rate;
+
+	div_factor = mclk_rate / dmic_sample_rate;
+
+	switch (div_factor) {
+	case 2:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_2;
+		break;
+	case 3:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_3;
+		break;
+	case 4:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_4;
+		break;
+	case 6:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_6;
+		break;
+	case 8:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_8;
+		break;
+	case 16:
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_16;
+		break;
+	default:
+		/* Any other DIV factor is invalid */
+		goto undefined_rate;
+	}
+
+	/* Valid dmic DIV factors */
+	dev_dbg(va_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+		__func__, div_factor, mclk_rate);
+
+	return dmic_sample_rate;
+
+undefined_rate:
+	dev_dbg(va_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
+		 __func__, dmic_sample_rate, mclk_rate);
+	dmic_sample_rate = LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
+
+	return dmic_sample_rate;
+}
+
+static int lpass_cdc_va_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret, i;
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	va_dev = lpass_cdc_get_device_ptr(component->dev, VA_MACRO);
+	if (!va_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	va_priv = dev_get_drvdata(va_dev);
+	if (!va_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	va_priv->lpi_enable = false;
+	va_priv->swr_dmic_enable = false;
+	//va_priv->register_event_listener = false;
+
+	va_priv->version = lpass_cdc_get_version(va_dev);
+
+	ret = snd_soc_dapm_new_controls(dapm,
+			lpass_cdc_va_macro_dapm_widgets,
+			ARRAY_SIZE(lpass_cdc_va_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(va_dev, "%s: Failed to add controls\n",
+			__func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
+				ARRAY_SIZE(va_audio_map));
+	if (ret < 0) {
+		dev_err(va_dev, "%s: Failed to add routes\n",
+			__func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(va_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component,
+			lpass_cdc_va_macro_snd_controls,
+			ARRAY_SIZE(lpass_cdc_va_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+			__func__);
+		return ret;
+	}
+
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF1 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF2 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF3 Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_INPUT");
+	snd_soc_dapm_sync(dapm);
+
+	va_priv->dev_up = true;
+
+	for (i = 0; i < LPASS_CDC_VA_MACRO_NUM_DECIMATORS; i++) {
+		va_priv->va_hpf_work[i].va_priv = va_priv;
+		va_priv->va_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&va_priv->va_hpf_work[i].dwork,
+			lpass_cdc_va_macro_tx_hpf_corner_freq_callback);
+	}
+
+	for (i = 0; i < LPASS_CDC_VA_MACRO_NUM_DECIMATORS; i++) {
+		va_priv->va_mute_dwork[i].va_priv = va_priv;
+		va_priv->va_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&va_priv->va_mute_dwork[i].dwork,
+			  lpass_cdc_va_macro_mute_update_callback);
+	}
+	va_priv->component = component;
+
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE, 0xCC);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE, 0xCC);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE, 0xCC);
+
+	return 0;
+}
+
+static int lpass_cdc_va_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					 &va_priv, __func__))
+		return -EINVAL;
+
+	va_priv->component = NULL;
+	return 0;
+}
+
+static void lpass_cdc_va_macro_add_child_devices(struct work_struct *work)
+{
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct lpass_cdc_va_macro_swr_ctrl_data *swr_ctrl_data = NULL;
+	struct lpass_cdc_va_macro_swr_ctrl_data *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct lpass_cdc_va_macro_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[LPASS_CDC_VA_MACRO_SWR_STRING_LEN] = "";
+	bool va_swr_master_node = false;
+
+	va_priv = container_of(work, struct lpass_cdc_va_macro_priv,
+			     lpass_cdc_va_macro_add_child_devices_work);
+	if (!va_priv) {
+		pr_err("%s: Memory for va_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!va_priv->dev) {
+		pr_err("%s: VA dev does not exist\n", __func__);
+		return;
+	}
+
+	if (!va_priv->dev->of_node) {
+		dev_err(va_priv->dev,
+			"%s: DT node for va_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &va_priv->swr_plat_data;
+	va_priv->child_count = 0;
+
+	for_each_available_child_of_node(va_priv->dev->of_node, node) {
+		va_swr_master_node = false;
+		if (strnstr(node->name, "va_swr_master",
+                                strlen("va_swr_master")) != NULL)
+			va_swr_master_node = true;
+
+		if (va_swr_master_node)
+			strlcpy(plat_dev_name, "va_swr_ctrl",
+				(LPASS_CDC_VA_MACRO_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(LPASS_CDC_VA_MACRO_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(va_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = va_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (va_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct lpass_cdc_va_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].va_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			va_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (va_priv->child_count < LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX)
+			va_priv->pdev_child_devices[
+					va_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < va_priv->child_count; count++)
+		platform_device_put(va_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int lpass_cdc_va_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int lpass_cdc_va_macro_reg_wake_irq(struct snd_soc_component *component,
+				 u32 data)
+{
+	struct device *va_dev = NULL;
+	struct lpass_cdc_va_macro_priv *va_priv = NULL;
+	u32 ipc_wakeup = data;
+	int ret = 0;
+
+	if (!lpass_cdc_va_macro_get_data(component, &va_dev,
+					&va_priv, __func__))
+		return -EINVAL;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+
+	return ret;
+}
+
+static void lpass_cdc_va_macro_init_ops(struct macro_ops *ops,
+			      char __iomem *va_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->dai_ptr = lpass_cdc_va_macro_dai;
+	ops->num_dais = ARRAY_SIZE(lpass_cdc_va_macro_dai);
+	ops->init = lpass_cdc_va_macro_init;
+	ops->exit = lpass_cdc_va_macro_deinit;
+	ops->io_base = va_io_base;
+	ops->event_handler = lpass_cdc_va_macro_event_handler;
+	ops->set_port_map = lpass_cdc_va_macro_set_port_map;
+	ops->reg_wake_irq = lpass_cdc_va_macro_reg_wake_irq;
+	ops->clk_div_get = lpass_cdc_va_macro_clk_div_get;
+}
+
+static int lpass_cdc_va_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops;
+	struct lpass_cdc_va_macro_priv *va_priv;
+	u32 va_base_addr, sample_rate = 0;
+	char __iomem *va_io_base;
+	const char *micb_supply_str = "va-vdd-micb-supply";
+	const char *micb_supply_str1 = "va-vdd-micb";
+	const char *micb_voltage_str = "qcom,va-vdd-micb-voltage";
+	const char *micb_current_str = "qcom,va-vdd-micb-current";
+	int ret = 0;
+	const char *dmic_sample_rate = "qcom,va-dmic-sample-rate";
+	u32 default_clk_id = 0, use_clk_id = 0;
+	struct clk *lpass_audio_hw_vote = NULL;
+	u32 is_used_va_swr_gpio = 0;
+	const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	va_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_va_macro_priv),
+			    GFP_KERNEL);
+	if (!va_priv)
+		return -ENOMEM;
+
+	va_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &va_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
+				   &sample_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %d entry in dt\n",
+			__func__, sample_rate);
+		va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_2;
+	} else {
+		if (lpass_cdc_va_macro_validate_dmic_sample_rate(
+		sample_rate, va_priv) ==
+			LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
+			return -EINVAL;
+	}
+
+	if (of_find_property(pdev->dev.of_node, is_used_va_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_va_swr_gpio_dt,
+					   &is_used_va_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_va_swr_gpio_dt);
+			is_used_va_swr_gpio = 0;
+		}
+	}
+
+	va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,va-swr-gpios", 0);
+	if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if ((msm_cdc_pinctrl_get_state(va_priv->va_swr_gpio_p) < 0) &&
+		is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
+	va_io_base = devm_ioremap(&pdev->dev, va_base_addr,
+				  LPASS_CDC_VA_MACRO_MAX_OFFSET);
+	if (!va_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -EINVAL;
+	}
+	va_priv->va_io_base = va_io_base;
+
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	va_priv->lpass_audio_hw_vote = lpass_audio_hw_vote;
+
+	if (of_parse_phandle(pdev->dev.of_node, micb_supply_str, 0)) {
+		va_priv->micb_supply = devm_regulator_get(&pdev->dev,
+						micb_supply_str1);
+		if (IS_ERR(va_priv->micb_supply)) {
+			ret = PTR_ERR(va_priv->micb_supply);
+			dev_err(&pdev->dev,
+				"%s:Failed to get micbias supply for VA Mic %d\n",
+				__func__, ret);
+			return ret;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					micb_voltage_str,
+					&va_priv->micb_voltage);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s:Looking up %s property in node %s failed\n",
+				__func__, micb_voltage_str,
+				pdev->dev.of_node->full_name);
+			return ret;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					micb_current_str,
+					&va_priv->micb_current);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s:Looking up %s property in node %s failed\n",
+				__func__, micb_current_str,
+				pdev->dev.of_node->full_name);
+			return ret;
+		}
+	}
+	use_clk_id = VA_CORE_CLK; /* default to using VA CORE CLK */
+	if (of_find_property(pdev->dev.of_node, "qcom,use-clk-id", NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node, "qcom,use-clk-id",
+				&use_clk_id);
+		if (ret) {
+			dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+					__func__, "qcom,use-clk-id");
+			use_clk_id = VA_CORE_CLK;
+		}
+	}
+	va_priv->clk_id = use_clk_id;
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,default-clk-id");
+		default_clk_id = use_clk_id;
+	}
+	va_priv->default_clk_id = default_clk_id;
+	va_priv->current_clk_id = TX_CORE_CLK;
+	va_priv->wlock_holders = 0;
+
+	va_priv->use_lpi_mixer_control = false;
+	if (of_find_property(pdev->dev.of_node, "use-lpi-control", NULL)) {
+		dev_dbg(&pdev->dev, "%s(): Usage of LPI Enable mixer control is enabled\n",
+				__func__);
+		va_priv->use_lpi_mixer_control = true;
+	}
+
+	if (is_used_va_swr_gpio) {
+		va_priv->reset_swr = true;
+		INIT_WORK(&va_priv->lpass_cdc_va_macro_add_child_devices_work,
+			  lpass_cdc_va_macro_add_child_devices);
+		va_priv->swr_plat_data.handle = (void *) va_priv;
+		va_priv->swr_plat_data.read = NULL;
+		va_priv->swr_plat_data.write = NULL;
+		va_priv->swr_plat_data.bulk_write = NULL;
+		va_priv->swr_plat_data.clk = lpass_cdc_va_macro_swrm_clock;
+		va_priv->swr_plat_data.core_vote = lpass_cdc_va_macro_core_vote;
+		va_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&va_priv->swr_clk_lock);
+	}
+	va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
+	va_priv->pre_dev_up = true;
+
+	mutex_init(&va_priv->mclk_lock);
+	mutex_init(&va_priv->wlock);
+	dev_set_drvdata(&pdev->dev, va_priv);
+	lpass_cdc_va_macro_init_ops(&ops, va_io_base);
+	ops.clk_id_req = va_priv->default_clk_id;
+	ops.default_clk_id = va_priv->default_clk_id;
+	ret = lpass_cdc_register_macro(&pdev->dev, VA_MACRO, &ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
+		goto reg_macro_fail;
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	if (is_used_va_swr_gpio)
+		schedule_work(&va_priv->lpass_cdc_va_macro_add_child_devices_work);
+	return ret;
+
+reg_macro_fail:
+	mutex_destroy(&va_priv->mclk_lock);
+	mutex_destroy(&va_priv->wlock);
+	if (is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
+	return ret;
+}
+
+static int lpass_cdc_va_macro_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_va_macro_priv *va_priv;
+	int count = 0;
+
+	va_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!va_priv)
+		return -EINVAL;
+	if (va_priv->is_used_va_swr_gpio) {
+		if (va_priv->swr_ctrl_data)
+			kfree(va_priv->swr_ctrl_data);
+		for (count = 0; count < va_priv->child_count &&
+			count < LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				va_priv->pdev_child_devices[count]);
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	lpass_cdc_unregister_macro(&pdev->dev, VA_MACRO);
+	mutex_destroy(&va_priv->mclk_lock);
+	mutex_destroy(&va_priv->wlock);
+	if (va_priv->is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
+	return 0;
+}
+
+
+static const struct of_device_id lpass_cdc_va_macro_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-va-macro"},
+	{}
+};
+
+static const struct dev_pm_ops lpass_cdc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_cdc_runtime_suspend,
+		lpass_cdc_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_cdc_va_macro_driver = {
+	.driver = {
+		.name = "lpass_cdc_va_macro",
+		.owner = THIS_MODULE,
+		.pm = &lpass_cdc_dev_pm_ops,
+		.of_match_table = lpass_cdc_va_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_va_macro_probe,
+	.remove = lpass_cdc_va_macro_remove,
+};
+
+module_platform_driver(lpass_cdc_va_macro_driver);
+
+MODULE_DESCRIPTION("LPASS codec VA macro driver");
+MODULE_LICENSE("GPL v2");

+ 4206 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -0,0 +1,4206 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. 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 <linux/thermal.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+
+#include <asoc/msm-cdc-pinctrl.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-comp.h"
+#include "lpass-cdc-registers.h"
+#include "lpass-cdc-wsa-macro.h"
+#include "lpass-cdc-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define LPASS_CDC_WSA_MACRO_MAX_OFFSET 0x1000
+
+#define LPASS_CDC_WSA_MACRO_RX_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 LPASS_CDC_WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define LPASS_CDC_WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define LPASS_CDC_WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_48000)
+#define LPASS_CDC_WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define LPASS_CDC_WSA_MACRO_CPS_RATES (48000)
+#define LPASS_CDC_WSA_MACRO_CPS_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+#define NUM_INTERPOLATORS 2
+
+#define LPASS_CDC_WSA_MACRO_MUX_INP_SHFT 0x3
+#define LPASS_CDC_WSA_MACRO_MUX_INP_MASK1 0x07
+#define LPASS_CDC_WSA_MACRO_MUX_INP_MASK2 0x38
+#define LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET 0x8
+#define LPASS_CDC_WSA_MACRO_MUX_CFG1_OFFSET 0x4
+#define LPASS_CDC_WSA_MACRO_RX_COMP_OFFSET \
+		(LPASS_CDC_WSA_COMPANDER1_CTL0 - LPASS_CDC_WSA_COMPANDER0_CTL0)
+#define LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET \
+		(LPASS_CDC_WSA_SOFTCLIP1_CRC - LPASS_CDC_WSA_SOFTCLIP0_CRC)
+#define LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET \
+		(LPASS_CDC_WSA_RX1_RX_PATH_CTL - LPASS_CDC_WSA_RX0_RX_PATH_CTL)
+#define LPASS_CDC_WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
+#define LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
+#define LPASS_CDC_WSA_MACRO_FS_RATE_MASK 0x0F
+#define LPASS_CDC_WSA_MACRO_EC_MIX_TX0_MASK 0x03
+#define LPASS_CDC_WSA_MACRO_EC_MIX_TX1_MASK 0x18
+
+#define LPASS_CDC_WSA_MACRO_MAX_DMA_CH_PER_PORT 0x2
+#define LPASS_CDC_WSA_MACRO_THERMAL_MAX_STATE 11
+
+enum {
+	LPASS_CDC_WSA_MACRO_RX0 = 0,
+	LPASS_CDC_WSA_MACRO_RX1,
+	LPASS_CDC_WSA_MACRO_RX_MIX,
+	LPASS_CDC_WSA_MACRO_RX_MIX0 = LPASS_CDC_WSA_MACRO_RX_MIX,
+	LPASS_CDC_WSA_MACRO_RX_MIX1,
+	LPASS_CDC_WSA_MACRO_RX4,
+	LPASS_CDC_WSA_MACRO_RX5,
+	LPASS_CDC_WSA_MACRO_RX6,
+	LPASS_CDC_WSA_MACRO_RX7,
+	LPASS_CDC_WSA_MACRO_RX8,
+	LPASS_CDC_WSA_MACRO_RX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA_MACRO_TX0 = 0,
+	LPASS_CDC_WSA_MACRO_TX1,
+	LPASS_CDC_WSA_MACRO_TX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA_MACRO_EC0_MUX = 0,
+	LPASS_CDC_WSA_MACRO_EC1_MUX,
+	LPASS_CDC_WSA_MACRO_EC_MUX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA_MACRO_COMP1, /* SPK_L */
+	LPASS_CDC_WSA_MACRO_COMP2, /* SPK_R */
+	LPASS_CDC_WSA_MACRO_COMP_MAX
+};
+
+enum {
+	LPASS_CDC_WSA_MACRO_SOFTCLIP0, /* RX0 */
+	LPASS_CDC_WSA_MACRO_SOFTCLIP1, /* RX1 */
+	LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX
+};
+
+enum {
+	INTn_1_INP_SEL_ZERO = 0,
+	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,
+	INTn_1_INP_SEL_RX6,
+	INTn_1_INP_SEL_RX7,
+	INTn_1_INP_SEL_RX8,
+	INTn_1_INP_SEL_DEC0,
+	INTn_1_INP_SEL_DEC1,
+};
+
+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,
+	INTn_2_INP_SEL_RX6,
+	INTn_2_INP_SEL_RX7,
+	INTn_2_INP_SEL_RX8,
+};
+
+enum {
+	IDLE_DETECT,
+	NG1,
+	NG2,
+	NG3,
+};
+
+static struct lpass_cdc_comp_setting comp_setting_table[G_MAX_DB] = {
+	{42, 0, 42},
+	{39, 0, 42},
+	{36, 0, 42},
+	{33, 0, 42},
+	{30, 0, 42},
+	{27, 0, 42},
+	{24, 0, 42},
+	{21, 0, 42},
+	{18, 0, 42},
+};
+
+struct interp_sample_rate {
+	int sample_rate;
+	int rate_val;
+};
+
+/*
+ * Structure used to update codec
+ * register defaults after reset
+ */
+struct lpass_cdc_wsa_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static struct interp_sample_rate int_prim_sample_rate_val[] = {
+	{8000, 0x0},	/* 8K */
+	{16000, 0x1},	/* 16K */
+	{24000, -EINVAL},/* 24K */
+	{32000, 0x3},	/* 32K */
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+	{384000, 0x7},	/* 384K */
+	{44100, 0x8}, /* 44.1K */
+};
+
+static struct interp_sample_rate int_mix_sample_rate_val[] = {
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+};
+
+#define LPASS_CDC_WSA_MACRO_SWR_STRING_LEN 80
+
+static int lpass_cdc_wsa_macro_core_vote(void *handle, bool enable);
+static int lpass_cdc_wsa_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+static int lpass_cdc_wsa_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);
+static int lpass_cdc_wsa_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
+
+#define LPASS_CDC_WSA_MACRO_VTH_TO_REG(vth) ((vth) == 0 ? 255 : (vth))
+/* Hold instance to soundwire platform device */
+struct lpass_cdc_wsa_macro_swr_ctrl_data {
+	struct platform_device *wsa_swr_pdev;
+};
+static int lpass_cdc_wsa_macro_enable_vi_decimator(struct snd_soc_component *component);
+
+#define LPASS_CDC_WSA_MACRO_SET_VOLUME_TLV(xname, xreg, xmin, xmax, tlv_array) \
+{	.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+		SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+	.tlv.p  = (tlv_array), \
+	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
+	.put = lpass_cdc_wsa_macro_set_digital_volume, \
+	.private_value = (unsigned long)&(struct soc_mixer_control) \
+	{.reg = xreg, .rreg = xreg,  \
+	.min = xmin, .max = xmax, \
+	.sign_bit = 7,} }
+
+struct lpass_cdc_wsa_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+enum {
+	LPASS_CDC_WSA_MACRO_AIF_INVALID = 0,
+	LPASS_CDC_WSA_MACRO_AIF1_PB,
+	LPASS_CDC_WSA_MACRO_AIF_MIX1_PB,
+	LPASS_CDC_WSA_MACRO_AIF_VI,
+	LPASS_CDC_WSA_MACRO_AIF_ECHO,
+	LPASS_CDC_WSA_MACRO_AIF_CPS,
+	LPASS_CDC_WSA_MACRO_MAX_DAIS,
+};
+
+
+#define LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX 3
+
+/*
+ * @dev: wsa macro device pointer
+ * @comp_enabled: compander enable mixer value set
+ * @ec_hq: echo HQ enable mixer value set
+ * @prim_int_users: Users of interpolator
+ * @wsa_mclk_users: WSA MCLK users count
+ * @swr_clk_users: SWR clk users count
+ * @vi_feed_value: VI sense mask
+ * @mclk_lock: to lock mclk operations
+ * @swr_clk_lock: to lock swr master clock operations
+ * @swr_ctrl_data: SoundWire data structure
+ * @swr_plat_data: Soundwire platform data
+ * @lpass_cdc_wsa_macro_add_child_devices_work: work for adding child devices
+ * @wsa_swr_gpio_p: used by pinctrl API
+ * @component: codec handle
+ * @rx_0_count: RX0 interpolation users
+ * @rx_1_count: RX1 interpolation users
+ * @active_ch_mask: channel mask for all AIF DAIs
+ * @active_ch_cnt: channel count of all AIF DAIs
+ * @rx_port_value: mixer ctl value of WSA RX MUXes
+ * @wsa_io_base: Base address of WSA macro addr space
+ * @wsa_sys_gain System gain value, see wsa driver
+ * @wsa_bat_cfg Battery Configuration value, see wsa driver
+ * @wsa_rload Resistor load value for WSA Speaker, see wsa driver
+ */
+struct lpass_cdc_wsa_macro_priv {
+	struct device *dev;
+	int comp_enabled[LPASS_CDC_WSA_MACRO_COMP_MAX];
+	int comp_mode[LPASS_CDC_WSA_MACRO_COMP_MAX];
+	int ec_hq[LPASS_CDC_WSA_MACRO_RX1 + 1];
+	u16 prim_int_users[LPASS_CDC_WSA_MACRO_RX1 + 1];
+	u16 wsa_mclk_users;
+	u16 swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	unsigned int vi_feed_value;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct lpass_cdc_wsa_macro_swr_ctrl_data *swr_ctrl_data;
+	struct lpass_cdc_wsa_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct lpass_cdc_wsa_macro_add_child_devices_work;
+	struct device_node *wsa_swr_gpio_p;
+	struct snd_soc_component *component;
+	int rx_0_count;
+	int rx_1_count;
+	unsigned long active_ch_mask[LPASS_CDC_WSA_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[LPASS_CDC_WSA_MACRO_MAX_DAIS];
+	u16 bit_width[LPASS_CDC_WSA_MACRO_MAX_DAIS];
+	int rx_port_value[LPASS_CDC_WSA_MACRO_RX_MAX];
+	char __iomem *wsa_io_base;
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int wsa_spkrrecv;
+	int spkr_gain_offset;
+	int spkr_mode;
+	int is_softclip_on[LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX];
+	int softclip_clk_users[LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX];
+	char __iomem *mclk_mode_muxsel;
+	u16 default_clk_id;
+	u32 pcm_rate_vi;
+	int wsa_digital_mute_status[LPASS_CDC_WSA_MACRO_RX_MAX];
+	u8 rx0_origin_gain;
+	u8 rx1_origin_gain;
+	struct thermal_cooling_device *tcdev;
+	uint32_t thermal_cur_state;
+	uint32_t thermal_max_state;
+	struct work_struct lpass_cdc_wsa_macro_cooling_work;
+	bool pbr_enable;
+	u32 wsa_sys_gain[2 * (LPASS_CDC_WSA_MACRO_RX1 + 1)];
+	u32 wsa_bat_cfg[LPASS_CDC_WSA_MACRO_RX1 + 1];
+	u32 wsa_rload[LPASS_CDC_WSA_MACRO_RX1 + 1];
+	u32 wsa_fs_ctl_reg;
+	u8 idle_detect_en;
+	int noise_gate_mode;
+	bool pre_dev_up;
+	int pbr_clk_users;
+	char __iomem *wsa_fs_reg_base;
+};
+
+static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[];
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+/* for Version 2P6 */
+static const char *const rx_text_v2p6[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4",
+	"RX5", "RX6", "RX7", "RX8", "DEC0", "DEC1"
+};
+
+static const char *const rx_mix_text_v2p6[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8"
+};
+
+/* for Version 2P5 */
+static const char *const rx_text_v2p5[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4",
+	"RX5", "DEC0", "DEC1"
+};
+
+static const char *const rx_mix_text_v2p5[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5"
+};
+
+static const char *const rx_mix_ec_text[] = {
+	"ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
+};
+
+static const char *const rx_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF_MIX1_PB"
+};
+
+static const char *const rx_sidetone_mix_text[] = {
+	"ZERO", "SRC0"
+};
+
+static const char * const lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text[] = {
+	"OFF", "ON"
+};
+
+static const char * const lpass_cdc_wsa_macro_comp_mode_text[] = {
+	"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
+	"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
+};
+
+static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum,
+			lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text);
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_comp_mode_enum,
+			lpass_cdc_wsa_macro_comp_mode_text);
+
+/* RX INT0 */
+static const struct soc_enum rx0_sidetone_mix_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
+
+/* for Version 2P5 */
+static const struct soc_enum rx0_prim_inp0_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		0, 9, rx_text_v2p5);
+
+static const struct soc_enum rx0_prim_inp1_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		3, 9, rx_text_v2p5);
+
+static const struct soc_enum rx0_prim_inp2_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		3, 9, rx_text_v2p5);
+
+static const struct soc_enum rx0_mix_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		0, 7, rx_mix_text_v2p5);
+
+static const struct snd_kcontrol_new rx0_prim_inp0_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx0_prim_inp1_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx0_prim_inp2_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx0_mix_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum_v2p5);
+
+static const struct soc_enum rx1_prim_inp0_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		0, 9, rx_text_v2p5);
+
+static const struct soc_enum rx1_prim_inp1_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		3, 9, rx_text_v2p5);
+
+static const struct soc_enum rx1_prim_inp2_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		3, 9, rx_text_v2p5);
+
+static const struct soc_enum rx1_mix_chain_enum_v2p5 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		0, 7, rx_mix_text_v2p5);
+
+static const struct snd_kcontrol_new rx1_prim_inp0_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx1_prim_inp1_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx1_prim_inp2_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum_v2p5);
+
+static const struct snd_kcontrol_new rx1_mix_mux_v2p5 =
+	SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum_v2p5);
+/* End of Version 2P5 */
+
+/* for Version 2P6 */
+static const struct soc_enum rx0_prim_inp0_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		0, 12, rx_text_v2p6);
+
+static const struct soc_enum rx0_prim_inp1_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0,
+		3, 12, rx_text_v2p6);
+
+static const struct soc_enum rx0_prim_inp2_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		3, 12, rx_text_v2p6);
+
+static const struct soc_enum rx0_mix_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
+		0, 10, rx_mix_text_v2p6);
+
+static const struct snd_kcontrol_new rx0_prim_inp0_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx0_prim_inp1_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx0_prim_inp2_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx0_mix_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum_v2p6);
+
+static const struct soc_enum rx1_prim_inp0_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		0, 12, rx_text_v2p6);
+
+static const struct soc_enum rx1_prim_inp1_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
+		3, 12, rx_text_v2p6);
+
+static const struct soc_enum rx1_prim_inp2_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		3, 12, rx_text_v2p6);
+
+static const struct soc_enum rx1_mix_chain_enum_v2p6 =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1,
+		0, 10, rx_mix_text_v2p6);
+
+static const struct snd_kcontrol_new rx1_prim_inp0_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx1_prim_inp1_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx1_prim_inp2_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum_v2p6);
+
+static const struct snd_kcontrol_new rx1_mix_mux_v2p6 =
+	SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum_v2p6);
+/* End of Version 2P6 */
+
+static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
+	SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
+
+static const struct soc_enum rx_mix_ec0_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		0, 3, rx_mix_ec_text);
+
+static const struct soc_enum rx_mix_ec1_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		3, 3, rx_mix_ec_text);
+
+static const struct snd_kcontrol_new rx_mix_ec0_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
+
+static const struct snd_kcontrol_new rx_mix_ec1_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
+
+static struct snd_soc_dai_ops lpass_cdc_wsa_macro_dai_ops = {
+	.hw_params = lpass_cdc_wsa_macro_hw_params,
+	.get_channel_map = lpass_cdc_wsa_macro_get_channel_map,
+	.mute_stream = lpass_cdc_wsa_macro_mute_stream,
+};
+
+static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[] = {
+	{
+		.name = "wsa_macro_rx1",
+		.id = LPASS_CDC_WSA_MACRO_AIF1_PB,
+		.playback = {
+			.stream_name = "WSA_AIF1 Playback",
+			.rates = LPASS_CDC_WSA_MACRO_RX_RATES,
+			.formats = LPASS_CDC_WSA_MACRO_RX_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_rx_mix",
+		.id = LPASS_CDC_WSA_MACRO_AIF_MIX1_PB,
+		.playback = {
+			.stream_name = "WSA_AIF_MIX1 Playback",
+			.rates = LPASS_CDC_WSA_MACRO_RX_MIX_RATES,
+			.formats = LPASS_CDC_WSA_MACRO_RX_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_vifeedback",
+		.id = LPASS_CDC_WSA_MACRO_AIF_VI,
+		.capture = {
+			.stream_name = "WSA_AIF_VI Capture",
+			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
+			.formats = LPASS_CDC_WSA_MACRO_RX_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_echo",
+		.id = LPASS_CDC_WSA_MACRO_AIF_ECHO,
+		.capture = {
+			.stream_name = "WSA_AIF_ECHO Capture",
+			.rates = LPASS_CDC_WSA_MACRO_ECHO_RATES,
+			.formats = LPASS_CDC_WSA_MACRO_ECHO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
+	{
+		.name = "wsa_macro_cpsfeedback",
+		.id = LPASS_CDC_WSA_MACRO_AIF_CPS,
+		.capture = {
+			.stream_name = "WSA_AIF_CPS Capture",
+			.rates = LPASS_CDC_WSA_MACRO_CPS_RATES,
+			.formats = LPASS_CDC_WSA_MACRO_CPS_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
+};
+
+static bool lpass_cdc_wsa_macro_get_data(struct snd_soc_component *component,
+			       struct device **wsa_dev,
+			       struct lpass_cdc_wsa_macro_priv **wsa_priv,
+			       const char *func_name)
+{
+	*wsa_dev = lpass_cdc_get_device_ptr(component->dev,
+							WSA_MACRO);
+	if (!(*wsa_dev)) {
+		dev_err_ratelimited(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+	*wsa_priv = dev_get_drvdata((*wsa_dev));
+	if (!(*wsa_priv) || !(*wsa_priv)->component) {
+		dev_err_ratelimited(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+	return true;
+}
+
+static int lpass_cdc_wsa_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (wsa_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int lpass_cdc_wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					    u8 int_prim_fs_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 int_mux_cfg0_val, int_mux_cfg1_val;
+	u8 inp0_sel, inp1_sel, inp2_sel;
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_WSA_MACRO_RX_MAX) {
+		int_1_mix1_inp = port;
+		if ((int_1_mix1_inp < LPASS_CDC_WSA_MACRO_RX0) ||
+			(int_1_mix1_inp > LPASS_CDC_WSA_MACRO_RX_MAX)) {
+			dev_err_ratelimited(wsa_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg0 = LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0;
+
+		/*
+		 * Loop through all interpolator MUX inputs and find out
+		 * to which interpolator input, the cdc_dma rx port
+		 * is connected
+		 */
+		for (j = 0; j < NUM_INTERPOLATORS; j++) {
+			int_mux_cfg1 = int_mux_cfg0 + LPASS_CDC_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 & LPASS_CDC_WSA_MACRO_MUX_INP_MASK1;
+			inp1_sel = (int_mux_cfg0_val >>
+					LPASS_CDC_WSA_MACRO_MUX_INP_SHFT) &
+					LPASS_CDC_WSA_MACRO_MUX_INP_MASK1;
+			inp2_sel = (int_mux_cfg1_val >>
+					LPASS_CDC_WSA_MACRO_MUX_INP_SHFT) &
+					LPASS_CDC_WSA_MACRO_MUX_INP_MASK1;
+			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 = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
+					     LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * j;
+				dev_dbg(wsa_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_1\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa_dev,
+					"%s: set INT%u_1 sample rate to %u\n",
+					__func__, j, sample_rate);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						LPASS_CDC_WSA_MACRO_FS_RATE_MASK,
+						int_prim_fs_rate_reg_val);
+			}
+			int_mux_cfg0 += LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					u8 int_mix_fs_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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+
+	for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_WSA_MACRO_RX_MAX) {
+		int_2_inp = port;
+		if ((int_2_inp < LPASS_CDC_WSA_MACRO_RX0) ||
+			(int_2_inp > LPASS_CDC_WSA_MACRO_RX_MIX1)) {
+			dev_err_ratelimited(wsa_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg1 = LPASS_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) &
+							LPASS_CDC_WSA_MACRO_MUX_INP_MASK1;
+			if (int_mux_cfg1_val == int_2_inp +
+							INTn_2_INP_SEL_RX0) {
+				int_fs_reg =
+					LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+					LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * j;
+
+				dev_dbg(wsa_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_2\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa_dev,
+					"%s: set INT%u_2 sample rate to %u\n",
+					__func__, j, sample_rate);
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						LPASS_CDC_WSA_MACRO_FS_RATE_MASK,
+						int_mix_fs_rate_reg_val);
+			}
+			int_mux_cfg1 += LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+				       u32 sample_rate)
+{
+	int rate_val = 0;
+	int i, ret;
+
+	/* set mixing path rate */
+	for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_mix_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_mix_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
+			(rate_val < 0))
+		goto prim_rate;
+	ret = lpass_cdc_wsa_macro_set_mix_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+prim_rate:
+	/* set primary path sample rate */
+	for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_prim_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_prim_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
+			(rate_val < 0))
+		return -EINVAL;
+	ret = lpass_cdc_wsa_macro_set_prim_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+	return ret;
+}
+
+static int lpass_cdc_wsa_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;
+	int ret;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv)
+		return -EINVAL;
+
+	dev_dbg(component->dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = lpass_cdc_wsa_macro_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			dev_err_ratelimited(component->dev,
+				"%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		switch (params_width(params)) {
+		case 16:
+			wsa_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa_priv->bit_width[dai->id] = 24;
+			break;
+		case 32:
+			wsa_priv->bit_width[dai->id] = 32;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+		}
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		if (dai->id == LPASS_CDC_WSA_MACRO_AIF_VI)
+			wsa_priv->pcm_rate_vi = params_rate(params);
+		switch (params_width(params)) {
+		case 16:
+			wsa_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa_priv->bit_width[dai->id] = 24;
+			break;
+		case 32:
+			wsa_priv->bit_width[dai->id] = 32;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+			}
+			break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 val = 0, mask = 0, cnt = 0, temp = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv)
+		return -EINVAL;
+
+	switch (dai->id) {
+	case LPASS_CDC_WSA_MACRO_AIF_VI:
+		for_each_set_bit(temp, &wsa_priv->active_ch_mask[dai->id],
+					LPASS_CDC_WSA_MACRO_TX_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == LPASS_CDC_WSA_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		if (mask & 0x0C)
+			mask = mask >> 0x2;
+
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	case LPASS_CDC_WSA_MACRO_AIF_CPS:
+		*tx_slot = wsa_priv->active_ch_mask[dai->id];
+		*tx_num = wsa_priv->active_ch_cnt[dai->id];
+		break;
+	case LPASS_CDC_WSA_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA_MACRO_AIF_MIX1_PB:
+		for_each_set_bit(temp, &wsa_priv->active_ch_mask[dai->id],
+					LPASS_CDC_WSA_MACRO_RX_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == LPASS_CDC_WSA_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		if (mask & 0x0C)
+			mask = mask >> 0x2;
+		*rx_slot = mask;
+		*rx_num = cnt;
+		break;
+	case LPASS_CDC_WSA_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,
+			LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
+		if (val & LPASS_CDC_WSA_MACRO_EC_MIX_TX1_MASK) {
+			mask |= 0x2;
+			cnt++;
+		}
+		if (val & LPASS_CDC_WSA_MACRO_EC_MIX_TX0_MASK) {
+			mask |= 0x1;
+			cnt++;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	default:
+		dev_err_ratelimited(wsa_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static void lpass_cdc_wsa_unmute_interpolator(struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	uint16_t j = 0, reg = 0, mix_reg = 0;
+
+	switch (dai->id) {
+	case LPASS_CDC_WSA_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA_MACRO_AIF_MIX1_PB:
+		for (j = 0; j < NUM_INTERPOLATORS; ++j) {
+			reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
+				(j * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET);
+			mix_reg = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+				(j * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET);
+
+			snd_soc_component_update_bits(component, reg, 0x10, 0x00);
+			snd_soc_component_update_bits(component, mix_reg, 0x10, 0x00);
+		}
+	}
+}
+
+static int lpass_cdc_wsa_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	bool adie_lb = false;
+	uint32_t temp;
+
+	if (mute)
+		return 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+	switch (dai->id) {
+	case LPASS_CDC_WSA_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA_MACRO_AIF_MIX1_PB:
+		lpass_cdc_wsa_pa_on(wsa_dev, adie_lb);
+		lpass_cdc_wsa_unmute_interpolator(dai);
+		lpass_cdc_wsa_macro_enable_vi_decimator(component);
+		break;
+	default:
+		break;
+	}
+	if ((test_bit(LPASS_CDC_WSA_MACRO_RX4,
+			&wsa_priv->active_ch_mask[dai->id]) ||
+			test_bit(LPASS_CDC_WSA_MACRO_RX5,
+			&wsa_priv->active_ch_mask[dai->id])) &&
+			wsa_priv->wsa_fs_reg_base) {
+		temp = ioread32(wsa_priv->wsa_fs_reg_base);
+		if (temp != 0) {
+			temp = 0;
+			iowrite32(temp, wsa_priv->wsa_fs_reg_base);
+		}
+		dev_dbg(wsa_dev, "%s: LPASS_WSA_FS_CTL : %d", __func__, temp);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_mclk_enable(
+				struct lpass_cdc_wsa_macro_priv *wsa_priv,
+				 bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
+
+	mutex_lock(&wsa_priv->mclk_lock);
+	if (mclk_enable) {
+		if (wsa_priv->wsa_mclk_users == 0) {
+			ret = lpass_cdc_clk_rsc_request_clock(wsa_priv->dev,
+							wsa_priv->default_clk_id,
+							wsa_priv->default_clk_id,
+							true);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa request clock enable failed\n",
+					__func__);
+				goto exit;
+			}
+			lpass_cdc_clk_rsc_fs_gen_request(wsa_priv->dev,
+						  true);
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					WSA_START_OFFSET,
+					WSA_MAX_OFFSET);
+			/* 9.6MHz MCLK, set value 0x00 if other frequency */
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			/* Toggle fs_cntr_clr bit*/
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x0);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		wsa_priv->wsa_mclk_users++;
+	} else {
+		if (wsa_priv->wsa_mclk_users <= 0) {
+			dev_err_ratelimited(wsa_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa_priv->wsa_mclk_users = 0;
+			goto exit;
+		}
+		wsa_priv->wsa_mclk_users--;
+		if (wsa_priv->wsa_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_clk_rsc_fs_gen_request(wsa_priv->dev,
+						  false);
+
+			lpass_cdc_clk_rsc_request_clock(wsa_priv->dev,
+						  wsa_priv->default_clk_id,
+						  wsa_priv->default_clk_id,
+						  false);
+		}
+	}
+exit:
+	mutex_unlock(&wsa_priv->mclk_lock);
+	return ret;
+}
+
+static int lpass_cdc_wsa_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);
+	int ret = 0;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 1, true);
+		if (ret)
+			wsa_priv->dapm_mclk_enable = false;
+		else
+			wsa_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (wsa_priv->dapm_mclk_enable) {
+			lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 0, true);
+			wsa_priv->dapm_mclk_enable = false;
+		}
+		break;
+	default:
+		dev_err_ratelimited(wsa_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_wsa_macro_event_handler(struct snd_soc_component *component,
+				   u16 event, u32 data)
+{
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case LPASS_CDC_MACRO_EVT_SSR_DOWN:
+		wsa_priv->pre_dev_up = false;
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(wsa_dev) ||
+		     !pm_runtime_suspended(wsa_dev))) {
+			ret = lpass_cdc_runtime_suspend(wsa_dev);
+			if (!ret) {
+				pm_runtime_disable(wsa_dev);
+				pm_runtime_set_suspended(wsa_dev);
+				pm_runtime_enable(wsa_dev);
+			}
+		}
+		break;
+	case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_UP:
+		wsa_priv->pre_dev_up = true;
+		/* reset swr after ssr/pdr */
+		wsa_priv->reset_swr = true;
+		if (wsa_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case LPASS_CDC_MACRO_EVT_CLK_RESET:
+		lpass_cdc_rsc_clk_reset(wsa_dev, WSA_CORE_CLK);
+		lpass_cdc_rsc_clk_reset(wsa_dev, WSA_TX_CORE_CLK);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_enable_vi_decimator(struct snd_soc_component *component)
+{
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u8 val = 0x0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	usleep_range(5000, 5500);
+	dev_dbg(wsa_dev, "%s: wsa_priv->pcm_rate_vi %d\n", __func__, wsa_priv->pcm_rate_vi);
+	switch (wsa_priv->pcm_rate_vi) {
+	case 48000:
+		val = 0x04;
+		break;
+	case 24000:
+		val = 0x02;
+		break;
+	case 8000:
+	default:
+		val = 0x00;
+		break;
+	}
+
+	if (test_bit(LPASS_CDC_WSA_MACRO_TX0,
+		&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+		dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__);
+		/* Enable V&I sensing */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+		0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+		0x20, 0x20);
+		usleep_range(1000, 1500);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+		0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		usleep_range(1000, 1500);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+	}
+	if (test_bit(LPASS_CDC_WSA_MACRO_TX1,
+		&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+		dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__);
+		/* Enable V&I sensing */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		usleep_range(1000, 1500);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		usleep_range(1000, 1500);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_disable_vi_feedback(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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMD:
+		if (test_bit(LPASS_CDC_WSA_MACRO_TX0,
+			&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		if (test_bit(LPASS_CDC_WSA_MACRO_TX1,
+			&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_wsa_macro_hd2_control(struct snd_soc_component *component,
+				  u16 reg, int event)
+{
+	u16 hd2_scale_reg;
+	u16 hd2_enable_reg = 0;
+
+	if (reg == LPASS_CDC_WSA_RX0_RX_PATH_CTL) {
+		hd2_scale_reg = LPASS_CDC_WSA_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_CDC_WSA_RX0_RX_PATH_CFG0;
+	}
+	if (reg == LPASS_CDC_WSA_RX1_RX_PATH_CTL) {
+		hd2_scale_reg = LPASS_CDC_WSA_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_CDC_WSA_RX1_RX_PATH_CFG0;
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x10);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x01);
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x04);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x00);
+	}
+}
+
+static int lpass_cdc_wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+	int ch_cnt;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
+		    !wsa_priv->rx_0_count)
+			wsa_priv->rx_0_count++;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
+		    !wsa_priv->rx_1_count)
+			wsa_priv->rx_1_count++;
+		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
+
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_UP, NULL);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
+		    wsa_priv->rx_0_count)
+			wsa_priv->rx_0_count--;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) &&
+		    wsa_priv->rx_1_count)
+			wsa_priv->rx_1_count--;
+		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
+
+		break;
+	}
+	dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
+		__func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_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;
+	int offset_val = 0;
+	int val = 0;
+	uint16_t mix_reg = 0;
+	uint16_t reg = 0;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) {
+		gain_reg = LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL;
+		reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
+			(LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET *  w->shift);
+		mix_reg = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
+	} else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) {
+		gain_reg = LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL;
+		reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL +
+			(LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET *  w->shift);
+		mix_reg = LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL +
+			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: No gain register avail for %s\n",
+			__func__, w->name);
+		return 0;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);
+		usleep_range(500, 510);
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+					reg, 0x20, 0x20);
+		snd_soc_component_update_bits(component,
+					mix_reg, 0x20, 0x20);
+		lpass_cdc_wsa_macro_enable_swr(w, kcontrol, event);
+		val = snd_soc_component_read(component, gain_reg);
+		val += offset_val;
+		snd_soc_component_write(component, gain_reg, val);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+					w->reg, 0x20, 0x00);
+		lpass_cdc_wsa_macro_enable_swr(w, kcontrol, event);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_config_compander(struct snd_soc_component *component,
+				int comp, int event)
+{
+	u16 comp_ctl0_reg, comp_ctl8_reg, rx_path_cfg0_reg;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	struct lpass_cdc_comp_setting *comp_settings = NULL;
+	u16 mode = 0;
+	u16 index = 0;
+	int sys_gain, bat_cfg, sys_gain_int, upper_gain, lower_gain;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (comp >= LPASS_CDC_WSA_MACRO_COMP_MAX || comp < 0) {
+		dev_err(component->dev, "%s: Invalid compander value: %d\n",
+					__func__, comp);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp + 1, wsa_priv->comp_enabled[comp]);
+
+	if (!wsa_priv->comp_enabled[comp])
+		return 0;
+
+	mode = wsa_priv->comp_mode[comp];
+	if (mode >= G_MAX_DB || mode < 0)
+		mode = 0;
+	comp_ctl0_reg = LPASS_CDC_WSA_COMPANDER0_CTL0 +
+					(comp * LPASS_CDC_WSA_MACRO_RX_COMP_OFFSET);
+	comp_ctl8_reg = LPASS_CDC_WSA_COMPANDER0_CTL8 +
+					(comp * LPASS_CDC_WSA_MACRO_RX_COMP_OFFSET);
+	rx_path_cfg0_reg = LPASS_CDC_WSA_RX0_RX_PATH_CFG0 +
+					(comp * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET);
+	comp_settings = &comp_setting_table[mode];
+
+	/* If System has battery configuration */
+	if (wsa_priv->wsa_bat_cfg[comp]) {
+		index = (comp * 2) + wsa_priv->wsa_spkrrecv;
+		if (index >= (2 * (LPASS_CDC_WSA_MACRO_RX1 + 1))) {
+			dev_err(component->dev, "%s: Invalid index: %d\n",
+					__func__, index);
+			return -EINVAL;
+		}
+		sys_gain = wsa_priv->wsa_sys_gain[index];
+		bat_cfg = wsa_priv->wsa_bat_cfg[comp];
+		/* Convert enum to value and
+		 * multiply all values by 10 to avoid float
+		 */
+		sys_gain_int = -15 * sys_gain + 210;
+		switch (bat_cfg) {
+		case CONFIG_1S:
+		case EXT_1S:
+			if (sys_gain > G_13P5_DB) {
+				upper_gain = sys_gain_int + 60;
+				lower_gain = 0;
+			} else {
+				upper_gain = 210;
+				lower_gain = 0;
+			}
+			break;
+		case CONFIG_3S:
+		case EXT_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 75;
+			break;
+		case EXT_ABOVE_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 120;
+			break;
+		default:
+			upper_gain = sys_gain_int;
+			lower_gain = 0;
+			break;
+		}
+		/* Truncate after calculation */
+		comp_settings->lower_gain_int = (lower_gain * 2) / 10;
+		comp_settings->upper_gain_int = (upper_gain * 2) / 10;
+	}
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		lpass_cdc_update_compander_setting(component,
+					comp_ctl8_reg,
+					comp_settings);
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x04);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_wsa_macro_enable_softclip_clk(struct snd_soc_component *component,
+					 struct lpass_cdc_wsa_macro_priv *wsa_priv,
+					 int path,
+					 bool enable)
+{
+	u16 softclip_clk_reg = LPASS_CDC_WSA_SOFTCLIP0_CRC +
+			(path * LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET);
+	u8 softclip_mux_mask = (1 << path);
+	u8 softclip_mux_value = (1 << path);
+
+	dev_dbg(component->dev, "%s: path %d, enable %d\n",
+		__func__, path, enable);
+	if (enable) {
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, softclip_mux_value);
+		}
+		wsa_priv->softclip_clk_users[path]++;
+	} else {
+		wsa_priv->softclip_clk_users[path]--;
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, 0x00);
+		}
+	}
+}
+
+static int lpass_cdc_wsa_macro_config_softclip(struct snd_soc_component *component,
+				int path, int event)
+{
+	u16 softclip_ctrl_reg = 0;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (path == LPASS_CDC_WSA_MACRO_COMP1)
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP0;
+	else if (path == LPASS_CDC_WSA_MACRO_COMP2)
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP1;
+
+	dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n",
+		__func__, event, softclip_path,
+		wsa_priv->is_softclip_on[softclip_path]);
+
+	if (!wsa_priv->is_softclip_on[softclip_path])
+		return 0;
+
+	softclip_ctrl_reg = LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
+				(softclip_path * LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock and mux */
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+				softclip_path, true);
+		/* Enable Softclip control */
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x00);
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+				softclip_path, false);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_was_macro_config_pbr(struct snd_soc_component *component,
+					  int path, int event)
+{
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 reg1 = 0, reg2 = 0, reg3 = 0;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (path == LPASS_CDC_WSA_MACRO_COMP1) {
+		reg1 = LPASS_CDC_WSA_COMPANDER0_CTL0;
+		reg2 = LPASS_CDC_WSA_RX0_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA_RX0_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP0;
+	} else if (path == LPASS_CDC_WSA_MACRO_COMP2) {
+		reg1 = LPASS_CDC_WSA_COMPANDER1_CTL0;
+		reg2 = LPASS_CDC_WSA_RX1_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA_RX1_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP1;
+	}
+	if (!wsa_priv->pbr_enable || wsa_priv->wsa_bat_cfg[path] >= EXT_1S ||
+	    wsa_priv->wsa_sys_gain[path * 2] > G_12_DB ||
+	    wsa_priv->wsa_spkrrecv || !reg1 || !reg2 || !reg3)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x40);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x80);
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+					softclip_path, true);
+		if (wsa_priv->pbr_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_PBR_PATH_CTL,
+				0x01, 0x01);
+		++wsa_priv->pbr_clk_users;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		if (wsa_priv->pbr_clk_users == 1)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_PBR_PATH_CTL,
+				0x01, 0x00);
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+					softclip_path, false);
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x00);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x00);
+		--wsa_priv->pbr_clk_users;
+		if (wsa_priv->pbr_clk_users < 0)
+			wsa_priv->pbr_clk_users = 0;
+	}
+	return 0;
+}
+
+static bool lpass_cdc_wsa_macro_adie_lb(struct snd_soc_component *component,
+			      int interp_idx)
+{
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
+	int int_1_rx = INTn_1_INP_SEL_DEC0;
+	int int_2_rx = INTn_1_INP_SEL_DEC1;
+	u32 version;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	int_mux_cfg0 = LPASS_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;
+
+	version = lpass_cdc_get_version(wsa_dev);
+
+	/* For Lpass version <= 2.5 the config mux didnot have rx6,rx7,rx8.
+	 * So decrease by 3 will select the correct index.
+	 */
+	if (version <= LPASS_CDC_VERSION_2_5) {
+		int_1_rx = int_1_rx - 3;
+		int_2_rx = int_2_rx - 3;
+	}
+
+	if (int_n_inp0 == int_1_rx ||
+		int_n_inp0 == int_2_rx)
+		return true;
+
+	int_n_inp1 = int_mux_cfg0_val >> 4;
+	if (int_n_inp1 == int_1_rx ||
+		int_n_inp1 == int_2_rx)
+		return true;
+
+	int_n_inp2 = int_mux_cfg1_val >> 4;
+	if (int_n_inp2 == int_1_rx ||
+		int_n_inp2 == int_2_rx)
+		return true;
+
+	return false;
+}
+
+static int lpass_cdc_wsa_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 reg = 0;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	bool adie_lb = false;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+
+	reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
+			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, reg, 0x40, 0x40);
+		usleep_range(500, 510);
+		snd_soc_component_update_bits(component, reg, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+					reg, 0x20, 0x20);
+		if (lpass_cdc_wsa_macro_adie_lb(component, w->shift)) {
+			adie_lb = true;
+			lpass_cdc_wsa_pa_on(wsa_dev, adie_lb);
+			snd_soc_component_update_bits(component,
+						reg, 0x10, 0x00);
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
+{
+	u16 prim_int_reg = 0;
+
+	switch (reg) {
+	case LPASS_CDC_WSA_RX0_RX_PATH_CTL:
+	case LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL:
+		prim_int_reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL;
+		*ind = 0;
+		break;
+	case LPASS_CDC_WSA_RX1_RX_PATH_CTL:
+	case LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL:
+		prim_int_reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL;
+		*ind = 1;
+		break;
+	}
+
+	return prim_int_reg;
+}
+
+static int lpass_cdc_wsa_macro_enable_prim_interpolator(
+				struct snd_soc_component *component,
+				u16 reg, int event)
+{
+	u16 prim_int_reg;
+	u16 ind = 0;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	prim_int_reg = lpass_cdc_wsa_macro_interp_get_primary_reg(reg, &ind);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wsa_priv->prim_int_users[ind]++;
+		if (wsa_priv->prim_int_users[ind] == 1) {
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_CFG3_OFFSET,
+				0x03, 0x03);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					    0x10, 0x10);
+			lpass_cdc_wsa_macro_hd2_control(component, prim_int_reg, event);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x1);
+		}
+		if ((reg != prim_int_reg) &&
+		    ((snd_soc_component_read(
+				component, prim_int_reg)) & 0x10))
+			snd_soc_component_update_bits(component, reg,
+					0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wsa_priv->prim_int_users[ind]--;
+		if (wsa_priv->prim_int_users[ind] == 0) {
+			snd_soc_component_update_bits(component, prim_int_reg,
+					1 << 0x5, 0 << 0x5);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x0);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x40);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x00);
+			lpass_cdc_wsa_macro_hd2_control(component, prim_int_reg, event);
+		}
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n",
+		__func__, ind, wsa_priv->prim_int_users[ind]);
+	return 0;
+}
+
+static void lpass_cdc_macro_idle_detect_control(struct snd_soc_component *component,
+					 struct lpass_cdc_wsa_macro_priv *wsa_priv,
+					 int interp, int event)
+{
+	int reg = 0, mask = 0, val = 0, source_reg = 0;
+	u16 mode = 0;
+
+	dev_dbg(component->dev, "%s: Idle_detect_en value: %d\n", __func__,
+		wsa_priv->idle_detect_en);
+
+	if (!wsa_priv->idle_detect_en)
+		return;
+
+	if (interp == LPASS_CDC_WSA_MACRO_COMP1) {
+		source_reg = LPASS_CDC_WSA_RX0_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA_IDLE_DETECT_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == LPASS_CDC_WSA_MACRO_COMP2) {
+		source_reg = LPASS_CDC_WSA_RX1_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA_IDLE_DETECT_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	mode = wsa_priv->comp_mode[interp];
+
+	if ((wsa_priv->noise_gate_mode == NG2 && mode >= G_13P5_DB) ||
+			wsa_priv->noise_gate_mode == IDLE_DETECT || !wsa_priv->pbr_enable ||
+			wsa_priv->wsa_spkrrecv) {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x00);
+		dev_dbg(component->dev, "%s: Idle detect source: Legacy\n", __func__);
+	} else {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x80);
+		dev_dbg(component->dev, "%s: Idle detect source: PRE-LA\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, reg, mask, val);
+		dev_dbg(component->dev, "%s: Idle detect clks ON\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		snd_soc_component_write(component,
+				LPASS_CDC_WSA_IDLE_DETECT_CFG3, 0x0);
+		dev_dbg(component->dev, "%s: Idle detect clks OFF\n", __func__);
+	}
+}
+
+static int lpass_cdc_wsa_macro_enable_interpolator(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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u8 gain = 0;
+	u16 reg = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) {
+		reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL;
+	} else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) {
+		reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: Interpolator reg not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Reset if needed */
+		lpass_cdc_wsa_macro_enable_prim_interpolator(component, reg, event);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (!strcmp(w->name, "WSA_RX INT0 INTERP")) {
+			gain = (u8)(wsa_priv->rx0_origin_gain -
+					wsa_priv->thermal_cur_state);
+			if (snd_soc_component_read(wsa_priv->component,
+					 LPASS_CDC_WSA_RX0_RX_VOL_CTL) != gain) {
+				snd_soc_component_update_bits(wsa_priv->component,
+					LPASS_CDC_WSA_RX0_RX_VOL_CTL, 0xFF, gain);
+				dev_dbg(wsa_priv->dev,
+					"%s: RX0 current thermal state: %d, "
+					"adjusted gain: %#x\n",
+					__func__, wsa_priv->thermal_cur_state, gain);
+			}
+		}
+
+		if (!strcmp(w->name, "WSA_RX INT1 INTERP")) {
+			gain = (u8)(wsa_priv->rx1_origin_gain -
+					wsa_priv->thermal_cur_state);
+			if (snd_soc_component_read(wsa_priv->component,
+					 LPASS_CDC_WSA_RX1_RX_VOL_CTL) != gain) {
+				snd_soc_component_update_bits(wsa_priv->component,
+					LPASS_CDC_WSA_RX1_RX_VOL_CTL, 0xFF, gain);
+				dev_dbg(wsa_priv->dev,
+					"%s: RX1 current thermal state: %d, "
+					"adjusted gain: %#x\n",
+					__func__, wsa_priv->thermal_cur_state, gain);
+			}
+		}
+
+		lpass_cdc_wsa_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa_priv,
+				w->shift, event);
+		lpass_cdc_wsa_macro_config_softclip(component, w->shift, event);
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
+		if (wsa_priv->wsa_spkrrecv)
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_WSA_RX0_RX_PATH_CFG1,
+					0x08, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08);
+		lpass_cdc_wsa_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa_priv,
+				w->shift, event);
+		lpass_cdc_wsa_macro_config_softclip(component, w->shift, event);
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
+		lpass_cdc_wsa_macro_enable_prim_interpolator(component, reg, event);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_spk_boost_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);
+	u16 boost_path_ctl, boost_path_cfg1;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) {
+		boost_path_ctl = LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL;
+		boost_path_cfg1 = LPASS_CDC_WSA_RX0_RX_PATH_CFG1;
+	} else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) {
+		boost_path_ctl = LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL;
+		boost_path_cfg1 = LPASS_CDC_WSA_RX1_RX_PATH_CFG1;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: unknown widget: %s\n",
+			__func__, w->name);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x00);
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int lpass_cdc_wsa_macro_enable_vbat(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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 vbat_path_cfg = 0;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
+		vbat_path_cfg = LPASS_CDC_WSA_RX0_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP0;
+	} else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
+		vbat_path_cfg = LPASS_CDC_WSA_RX1_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP1;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x80);
+		/* Use attenuation mode */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x02, 0x00);
+		/*
+		 * BCL block needs softclip clock and mux config to be enabled
+		 */
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+					softclip_path, true);
+		/* Enable VBAT at channel level */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+				0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		/* Enable CB decode block clock */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
+		/* Enable BCL path */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
+		/* Request for BCL data */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x02, 0x02);
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x02, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv,
+			softclip_path, false);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err_ratelimited(wsa_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa_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);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 val, ec_tx = 0, ec_hq_reg;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_component_read(component,
+				LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
+	if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
+		ec_tx = (val & 0x07) - 1;
+	else
+		ec_tx = ((val & 0x38) >> 0x3) - 1;
+
+	if (ec_tx < 0 || ec_tx >= (LPASS_CDC_WSA_MACRO_RX1 + 1)) {
+		dev_err_ratelimited(wsa_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (wsa_priv->ec_hq[ec_tx]) {
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+				0x1 << ec_tx, 0x1 << ec_tx);
+		ec_hq_reg = LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
+							0x40 * ec_tx;
+		snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
+		ec_hq_reg = LPASS_CDC_WSA_EC_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 int lpass_cdc_wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
+		__func__, wsa_priv->ec_hq[ec_tx], value);
+	wsa_priv->ec_hq[ec_tx] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_get_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int wsa_rx_shift = ((struct soc_multi_mixer_control *)
+		       kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+		wsa_priv->wsa_digital_mute_status[wsa_rx_shift];
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int wsa_rx_shift = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	pm_runtime_get_sync(wsa_priv->dev);
+	switch (wsa_rx_shift) {
+	case 0:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX0_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 1:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX1_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 2:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	case 3:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	default:
+		pr_err_ratelimited("%s: invalid argument rx_shift = %d\n", __func__,
+			wsa_rx_shift);
+		ret = -EINVAL;
+	}
+	pm_runtime_mark_last_busy(wsa_priv->dev);
+	pm_runtime_put_autosuspend(wsa_priv->dev);
+
+	dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n",
+		__func__, wsa_rx_shift, value);
+	wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value;
+
+	return ret;
+}
+
+static int lpass_cdc_wsa_macro_set_digital_volume(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	struct soc_mixer_control *mc =
+			(struct soc_mixer_control *)kcontrol->private_value;
+	u8 gain = 0;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (!wsa_priv) {
+		pr_err_ratelimited("%s: priv is null for macro!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+	if (mc->reg == LPASS_CDC_WSA_RX0_RX_VOL_CTL) {
+		wsa_priv->rx0_origin_gain =
+			(u8)snd_soc_component_read(wsa_priv->component,
+							mc->reg);
+		gain = (u8)(wsa_priv->rx0_origin_gain -
+				wsa_priv->thermal_cur_state);
+	} else if (mc->reg == LPASS_CDC_WSA_RX1_RX_VOL_CTL) {
+		wsa_priv->rx1_origin_gain =
+			(u8)snd_soc_component_read(wsa_priv->component,
+							mc->reg);
+		gain = (u8)(wsa_priv->rx1_origin_gain -
+				wsa_priv->thermal_cur_state);
+	} else {
+		dev_err_ratelimited(wsa_priv->dev,
+			"%s: Incorrect RX Path selected\n", __func__);
+		return -EINVAL;
+	}
+
+	/* only adjust gain if thermal state is positive */
+	if (wsa_priv->dapm_mclk_enable &&
+	    wsa_priv->thermal_cur_state > 0) {
+		snd_soc_component_update_bits(wsa_priv->component,
+			mc->reg, 0xFF, gain);
+		dev_dbg(wsa_priv->dev,
+			"%s: Current thermal state: %d, adjusted gain: %x\n",
+			__func__, wsa_priv->thermal_cur_state, gain);
+	}
+
+	return ret;
+}
+
+static int lpass_cdc_wsa_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp];
+	return 0;
+}
+
+static int lpass_cdc_wsa_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		__func__, comp + 1, wsa_priv->comp_enabled[comp], value);
+	wsa_priv->comp_enabled[comp] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->wsa_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+		__func__, wsa_priv->wsa_spkrrecv);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_idle_detect_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	struct device *wsa_dev = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->idle_detect_en;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_idle_detect_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	struct device *wsa_dev = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->idle_detect_en = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 idx = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (strnstr(kcontrol->id.name, "RX0", sizeof("WSA_RX0")))
+		idx = LPASS_CDC_WSA_MACRO_COMP1;
+	if (strnstr(kcontrol->id.name, "RX1", sizeof("WSA_RX1")))
+		idx = LPASS_CDC_WSA_MACRO_COMP2;
+	ucontrol->value.integer.value[0] = wsa_priv->comp_mode[idx];
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_comp_mode_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	u16 idx = 0;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (strnstr(kcontrol->id.name, "RX0", sizeof("WSA_RX0")))
+		idx = LPASS_CDC_WSA_MACRO_COMP1;
+	if (strnstr(kcontrol->id.name, "RX1", sizeof("WSA_RX1")))
+		idx = LPASS_CDC_WSA_MACRO_COMP2;
+
+	if (ucontrol->value.integer.value[0] < G_MAX_DB && ucontrol->value.integer.value[0] >= 0)
+		wsa_priv->comp_mode[idx] = ucontrol->value.integer.value[0];
+	else
+		return 0;
+
+	dev_dbg(component->dev, "%s: comp_mode = %d\n", __func__,
+		wsa_priv->comp_mode[idx]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_rx_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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			wsa_priv->rx_port_value[widget->shift];
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_rx_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 bit_input = 0;
+	u32 aif_rst;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	aif_rst = wsa_priv->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err_ratelimited(wsa_dev, "%s: AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst >= LPASS_CDC_WSA_MACRO_MAX_DAIS) {
+			dev_err_ratelimited(wsa_dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	wsa_priv->rx_port_value[widget->shift] = rx_port_value;
+
+	bit_input = widget->shift;
+
+	dev_dbg(wsa_dev,
+		"%s: mux input: %d, mux output: %d, bit: %d\n",
+		__func__, rx_port_value, widget->shift, bit_input);
+
+	switch (rx_port_value) {
+	case 0:
+		if (wsa_priv->active_ch_cnt[aif_rst]) {
+			clear_bit(bit_input,
+				  &wsa_priv->active_ch_mask[aif_rst]);
+			wsa_priv->active_ch_cnt[aif_rst]--;
+		}
+		break;
+	case 1:
+	case 2:
+		set_bit(bit_input,
+			&wsa_priv->active_ch_mask[rx_port_value]);
+		wsa_priv->active_ch_cnt[rx_port_value]++;
+		break;
+	default:
+		dev_err_ratelimited(wsa_dev,
+			"%s: Invalid AIF_ID for WSA RX MUX %d\n",
+			__func__, rx_port_value);
+		return -EINVAL;
+	}
+
+	snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+					rx_port_value, e, update);
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+	    ((snd_soc_component_read(
+		component, LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
+	    1 : 0);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x04, 0x04);
+	else
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG,
+			0x04, 0x00);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_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 device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->is_softclip_on[path] =  ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__,
+		path, wsa_priv->is_softclip_on[path]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_pbr_enable_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->pbr_enable;
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_pbr_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->pbr_enable = ucontrol->value.integer.value[0];
+	return 0;
+
+}
+
+
+static const struct snd_kcontrol_new lpass_cdc_wsa_macro_snd_controls[] = {
+	SOC_ENUM_EXT("GSM mode Enable", lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum,
+		     lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_get,
+		     lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_ENUM_EXT("WSA_RX0 comp_mode", lpass_cdc_wsa_macro_comp_mode_enum,
+		     lpass_cdc_wsa_macro_comp_mode_get,
+		     lpass_cdc_wsa_macro_comp_mode_put),
+	SOC_ENUM_EXT("WSA_RX1 comp_mode", lpass_cdc_wsa_macro_comp_mode_enum,
+		     lpass_cdc_wsa_macro_comp_mode_get,
+		     lpass_cdc_wsa_macro_comp_mode_put),
+	SOC_SINGLE_EXT("WSA SPKRRECV", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_wsa_macro_ear_spkrrecv_get,
+			lpass_cdc_wsa_macro_ear_spkrrecv_put),
+	SOC_SINGLE_EXT("Idle Detect", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa_macro_idle_detect_get,
+			lpass_cdc_wsa_macro_idle_detect_put),
+	SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_SOFTCLIP0, 1, 0,
+			lpass_cdc_wsa_macro_soft_clip_enable_get,
+			lpass_cdc_wsa_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_SOFTCLIP1, 1, 0,
+			lpass_cdc_wsa_macro_soft_clip_enable_get,
+			lpass_cdc_wsa_macro_soft_clip_enable_put),
+	LPASS_CDC_WSA_MACRO_SET_VOLUME_TLV("WSA_RX0 Digital Volume",
+					   LPASS_CDC_WSA_RX0_RX_VOL_CTL,
+					   -84, 40, digital_gain),
+	LPASS_CDC_WSA_MACRO_SET_VOLUME_TLV("WSA_RX1 Digital Volume",
+					   LPASS_CDC_WSA_RX1_RX_VOL_CTL,
+					   -84, 40, digital_gain),
+	SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0, 1,
+			0, lpass_cdc_wsa_macro_get_rx_mute_status,
+			lpass_cdc_wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX1 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1, 1,
+			0, lpass_cdc_wsa_macro_get_rx_mute_status,
+			lpass_cdc_wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX0_MIX Digital Mute", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_RX_MIX0, 1, 0, lpass_cdc_wsa_macro_get_rx_mute_status,
+			lpass_cdc_wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_RX1_MIX Digital Mute", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_RX_MIX1, 1, 0, lpass_cdc_wsa_macro_get_rx_mute_status,
+			lpass_cdc_wsa_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_COMP1, 1, 0,
+		lpass_cdc_wsa_macro_get_compander, lpass_cdc_wsa_macro_set_compander),
+	SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_COMP2, 1, 0,
+		lpass_cdc_wsa_macro_get_compander, lpass_cdc_wsa_macro_set_compander),
+	SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0,
+			1, 0, lpass_cdc_wsa_macro_get_ec_hq, lpass_cdc_wsa_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1,
+			1, 0, lpass_cdc_wsa_macro_get_ec_hq, lpass_cdc_wsa_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA PBR Enable", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa_macro_pbr_enable_get,
+			lpass_cdc_wsa_macro_pbr_enable_put),
+};
+
+static const struct soc_enum rx_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
+
+static const struct snd_kcontrol_new rx_mux[LPASS_CDC_WSA_MACRO_RX_MAX] = {
+	SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum,
+			  lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum,
+			  lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum,
+			  lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum,
+			  lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX4 Mux", rx_mux_enum,
+			lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA RX5 Mux", rx_mux_enum,
+			lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put),
+};
+
+static int lpass_cdc_wsa_macro_vi_feed_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_vi_feed_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 soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->vi_feed_value = ucontrol->value.integer.value[0];
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]);
+			wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]);
+			wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]);
+			wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]);
+			wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_vi_mixer[] = {
+	SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa_macro_vi_feed_mixer_get,
+			lpass_cdc_wsa_macro_vi_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa_macro_vi_feed_mixer_get,
+			lpass_cdc_wsa_macro_vi_feed_mixer_put),
+};
+
+static int lpass_cdc_wsa_macro_cps_feed_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_cps_feed_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 soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_cps_mixer[] = {
+	SOC_SINGLE_EXT("WSA_SPKR_CPS_1", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa_macro_cps_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA_SPKR_CPS_2", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa_macro_cps_feed_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets_v2p6[] = {
+
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp0_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp1_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp2_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx0_mix_mux_v2p6, lpass_cdc_wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp0_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp1_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp2_mux_v2p6, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx1_mix_mux_v2p6, lpass_cdc_wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets_v2p5[] = {
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp0_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp1_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp2_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx0_mix_mux_v2p5, lpass_cdc_wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp0_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp1_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp2_mux_v2p5, lpass_cdc_wsa_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx1_mix_mux_v2p5, lpass_cdc_wsa_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_VI, 0,
+		lpass_cdc_wsa_macro_disable_vi_feedback,
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT("WSA AIF_CPS", "WSA_AIF_CPS Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_VI,
+		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MIXER("WSA_AIF_CPS Mixer", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_CPS,
+		0, aif_cps_mixer, ARRAY_SIZE(aif_cps_mixer)),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_EC0_MUX, 0,
+			&rx_mix_ec0_mux, lpass_cdc_wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
+			LPASS_CDC_WSA_MACRO_EC1_MUX, 0,
+			&rx_mix_ec1_mux, lpass_cdc_wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX0]),
+	SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX1]),
+	SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX_MIX0, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX_MIX0]),
+	SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX_MIX1, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX_MIX1]),
+	SND_SOC_DAPM_MUX("WSA RX4 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX4, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX4]),
+	SND_SOC_DAPM_MUX("WSA RX5 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX5, 0,
+				&rx_mux[LPASS_CDC_WSA_MACRO_RX5]),
+
+	SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
+			0, 0, NULL, 0, lpass_cdc_wsa_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_PGA_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
+			1, 0, NULL, 0, lpass_cdc_wsa_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
+			   LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
+			   &rx0_sidetone_mix_mux, lpass_cdc_wsa_macro_enable_swr,
+			  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
+
+	SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
+	SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
+		LPASS_CDC_WSA_MACRO_COMP1, 0, NULL, 0, lpass_cdc_wsa_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM,
+		LPASS_CDC_WSA_MACRO_COMP2, 0, NULL, 0, lpass_cdc_wsa_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, lpass_cdc_wsa_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, lpass_cdc_wsa_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int0_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int0_vbat_mix_switch),
+		lpass_cdc_wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int1_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int1_vbat_mix_switch),
+		lpass_cdc_wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
+
+	SND_SOC_DAPM_INPUT("CPSINPUT_WSA"),
+
+	SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
+	SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
+
+	SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	lpass_cdc_wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route wsa_audio_map[] = {
+	/* VI Feedback */
+	{"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"},
+	{"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"},
+	{"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
+	{"WSA AIF_VI", NULL, "WSA_MCLK"},
+
+	/* CPS Feedback */
+	{"WSA_AIF_CPS Mixer", "WSA_SPKR_CPS_1", "CPSINPUT_WSA"},
+	{"WSA_AIF_CPS Mixer", "WSA_SPKR_CPS_2", "CPSINPUT_WSA"},
+	{"WSA AIF_CPS", NULL, "WSA_AIF_CPS Mixer"},
+	{"WSA AIF_CPS", NULL, "WSA_MCLK"},
+
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA_MCLK"},
+
+	{"WSA AIF1 PB", NULL, "WSA_MCLK"},
+	{"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},
+
+	{"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX4 MUX", "AIF1_PB", "WSA AIF1 PB"},
+	{"WSA RX5 MUX", "AIF1_PB", "WSA AIF1 PB"},
+
+	{"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX4 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+	{"WSA RX5 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"},
+
+	{"WSA RX0", NULL, "WSA RX0 MUX"},
+	{"WSA RX1", NULL, "WSA RX1 MUX"},
+	{"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"},
+	{"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"},
+	{"WSA RX4", NULL, "WSA RX4 MUX"},
+	{"WSA RX5", NULL, "WSA RX5 MUX"},
+
+	{"WSA_RX0 INP0", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP0", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP0", "RX4", "WSA RX4"},
+	{"WSA_RX0 INP0", "RX5", "WSA RX5"},
+	{"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
+
+	{"WSA_RX0 INP1", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP1", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP1", "RX4", "WSA RX4"},
+	{"WSA_RX0 INP1", "RX5", "WSA RX5"},
+	{"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
+
+	{"WSA_RX0 INP2", "RX0", "WSA RX0"},
+	{"WSA_RX0 INP2", "RX1", "WSA RX1"},
+	{"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP2", "RX4", "WSA RX4"},
+	{"WSA_RX0 INP2", "RX5", "WSA RX5"},
+	{"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
+
+	{"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
+	{"WSA_RX0 MIX INP", "RX1", "WSA RX1"},
+	{"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 MIX INP", "RX4", "WSA RX4"},
+	{"WSA_RX0 MIX INP", "RX5", "WSA RX5"},
+	{"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"},
+
+	{"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
+	{"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
+	{"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
+	{"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
+	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
+
+	{"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
+	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
+
+	{"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
+	{"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
+
+	{"WSA_RX1 INP0", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP0", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP0", "RX4", "WSA RX4"},
+	{"WSA_RX1 INP0", "RX5", "WSA RX5"},
+	{"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
+
+	{"WSA_RX1 INP1", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP1", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP1", "RX4", "WSA RX4"},
+	{"WSA_RX1 INP1", "RX5", "WSA RX5"},
+	{"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
+
+	{"WSA_RX1 INP2", "RX0", "WSA RX0"},
+	{"WSA_RX1 INP2", "RX1", "WSA RX1"},
+	{"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP2", "RX4", "WSA RX4"},
+	{"WSA_RX1 INP2", "RX5", "WSA RX5"},
+	{"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
+	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
+
+	{"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
+	{"WSA_RX1 MIX INP", "RX1", "WSA RX1"},
+	{"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"},
+	{"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 MIX INP", "RX4", "WSA RX4"},
+	{"WSA_RX1 MIX INP", "RX5", "WSA RX5"},
+	{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"},
+
+	{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
+	{"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
+
+	{"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
+	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
+
+	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
+	{"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
+	{"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
+};
+
+static void lpass_cdc_wsa_macro_init_pbr(struct snd_soc_component *component)
+{
+	int sys_gain, bat_cfg, rload;
+	int vth1, vth2, vth3, vth4, vth5, vth6, vth7, vth8, vth9;
+	int vth10, vth11, vth12, vth13, vth14, vth15;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return;
+
+	/* RX0 */
+	sys_gain = wsa_priv->wsa_sys_gain[0];
+	bat_cfg = wsa_priv->wsa_bat_cfg[0];
+	rload = wsa_priv->wsa_rload[0];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA_ILIM_CFG1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA_ILIM_CFG9, 0xC0, (bat_cfg - 1) << 0x6);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG2, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG3, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG4, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG5, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG6, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG7, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG8, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG9, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG10, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG11, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG12, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG13, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG14, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG15, vth15);
+
+	/* RX1 */
+	sys_gain = wsa_priv->wsa_sys_gain[2];
+	bat_cfg = wsa_priv->wsa_bat_cfg[1];
+	rload = wsa_priv->wsa_rload[1];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0_1, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0_1, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0_1, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA_ILIM_CFG0_1, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA_ILIM_CFG1_1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA_ILIM_CFG9, 0x30, (bat_cfg - 1) << 0x4);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG1_1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG2_1, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG3_1, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG4_1, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG5_1, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG6_1, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG7_1, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG8_1, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG9_1, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG10_1, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG11_1, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG12_1, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG13_1, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG14_1, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA_PBR_CFG15_1, vth15);
+}
+
+static const struct lpass_cdc_wsa_macro_reg_mask_val
+				lpass_cdc_wsa_macro_reg_init[] = {
+	{LPASS_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
+	{LPASS_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
+	{LPASS_CDC_WSA_COMPANDER0_CTL7, 0x3E, 0x2e},
+	{LPASS_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
+	{LPASS_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
+	{LPASS_CDC_WSA_COMPANDER1_CTL7, 0x3E, 0x2e},
+	{LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
+	{LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
+	{LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
+	{LPASS_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08},
+	{LPASS_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02},
+	{LPASS_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01},
+	{LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{LPASS_CDC_WSA_LA_CFG, 0x3F, 0xF},
+	{LPASS_CDC_WSA_PBR_CFG16, 0xFF, 0x42},
+	{LPASS_CDC_WSA_PBR_CFG19, 0xFF, 0xFC},
+	{LPASS_CDC_WSA_PBR_CFG20, 0xF0, 0x60},
+	{LPASS_CDC_WSA_ILIM_CFG1, 0x70, 0x40},
+	{LPASS_CDC_WSA_ILIM_CFG0, 0x03, 0x01},
+	{LPASS_CDC_WSA_ILIM_CFG3, 0x1F, 0x15},
+	{LPASS_CDC_WSA_LA_CFG_1, 0x3F, 0x0F},
+	{LPASS_CDC_WSA_PBR_CFG16_1, 0xFF, 0x42},
+	{LPASS_CDC_WSA_PBR_CFG21, 0xFF, 0xFC},
+	{LPASS_CDC_WSA_PBR_CFG22, 0xF0, 0x60},
+	{LPASS_CDC_WSA_ILIM_CFG1_1, 0x70, 0x40},
+	{LPASS_CDC_WSA_ILIM_CFG0_1, 0x03, 0x01},
+	{LPASS_CDC_WSA_ILIM_CFG4, 0x1F, 0x15},
+	{LPASS_CDC_WSA_ILIM_CFG2_1, 0xFF, 0x2A},
+	{LPASS_CDC_WSA_ILIM_CFG2, 0x3F, 0x1B},
+	{LPASS_CDC_WSA_ILIM_CFG9, 0x0F, 0x05},
+	{LPASS_CDC_WSA_IDLE_DETECT_CFG1, 0xFF, 0x1D},
+};
+
+static void lpass_cdc_wsa_macro_init_reg(struct snd_soc_component *component)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpass_cdc_wsa_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				lpass_cdc_wsa_macro_reg_init[i].reg,
+				lpass_cdc_wsa_macro_reg_init[i].mask,
+				lpass_cdc_wsa_macro_reg_init[i].val);
+	lpass_cdc_wsa_macro_init_pbr(component);
+}
+
+static int lpass_cdc_wsa_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = (struct lpass_cdc_wsa_macro_priv *) handle;
+
+	if (wsa_priv == NULL) {
+		pr_err_ratelimited("%s: wsa priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!wsa_priv->pre_dev_up && enable) {
+		pr_debug("%s: adsp is not up\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(wsa_priv->dev);
+		if (lpass_cdc_check_core_votes(wsa_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(wsa_priv->dev);
+		pm_runtime_mark_last_busy(wsa_priv->dev);
+	}
+
+	return rc;
+}
+
+static int wsa_swrm_clock(void *handle, bool enable)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = (struct lpass_cdc_wsa_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wsa_priv->swr_clk_lock);
+
+	dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(wsa_priv->dev);
+		if (wsa_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						wsa_priv->wsa_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa_priv->dev);
+				pm_runtime_put_autosuspend(wsa_priv->dev);
+				goto exit;
+			}
+			ret = lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 1, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						wsa_priv->wsa_swr_gpio_p);
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa_priv->dev);
+				pm_runtime_put_autosuspend(wsa_priv->dev);
+				goto exit;
+			}
+			if (wsa_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (wsa_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+				0x1C, 0x0C);
+			wsa_priv->reset_swr = false;
+		}
+		wsa_priv->swr_clk_users++;
+		pm_runtime_mark_last_busy(wsa_priv->dev);
+		pm_runtime_put_autosuspend(wsa_priv->dev);
+	} else {
+		if (wsa_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(wsa_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa_priv->swr_clk_users = 0;
+			goto exit;
+		}
+		wsa_priv->swr_clk_users--;
+		if (wsa_priv->swr_clk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 0, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						wsa_priv->wsa_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa_priv->dev,
+					"%s: wsa swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n",
+		__func__, wsa_priv->swr_clk_users);
+exit:
+	mutex_unlock(&wsa_priv->swr_clk_lock);
+	return ret;
+}
+
+/* Thermal Functions */
+static int lpass_cdc_wsa_macro_get_max_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long *state)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = cdev->devdata;
+	if (!wsa_priv) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	*state = wsa_priv->thermal_max_state;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_get_cur_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long *state)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = cdev->devdata;
+
+	if (!wsa_priv) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	*state = wsa_priv->thermal_cur_state;
+
+	pr_debug("%s: thermal current state:%lu\n", __func__, *state);
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_set_cur_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long state)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = cdev->devdata;
+
+	if (!wsa_priv || !wsa_priv->dev) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (state <= wsa_priv->thermal_max_state) {
+		wsa_priv->thermal_cur_state = state;
+	} else {
+		dev_err_ratelimited(wsa_priv->dev,
+			"%s: incorrect requested state:%d\n",
+			__func__, state);
+		return -EINVAL;
+	}
+
+	dev_dbg(wsa_priv->dev,
+		"%s: set the thermal current state to %d\n",
+		__func__, wsa_priv->thermal_cur_state);
+
+	schedule_work(&wsa_priv->lpass_cdc_wsa_macro_cooling_work);
+
+	return 0;
+}
+
+static struct thermal_cooling_device_ops wsa_cooling_ops = {
+	.get_max_state = lpass_cdc_wsa_macro_get_max_state,
+	.get_cur_state = lpass_cdc_wsa_macro_get_cur_state,
+	.set_cur_state = lpass_cdc_wsa_macro_set_cur_state,
+};
+
+static int lpass_cdc_wsa_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret;
+	u32 version;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	wsa_dev = lpass_cdc_get_device_ptr(component->dev, WSA_MACRO);
+	if (!wsa_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa_macro_dapm_widgets,
+					ARRAY_SIZE(lpass_cdc_wsa_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add controls\n", __func__);
+		return ret;
+	}
+
+	version = lpass_cdc_get_version(wsa_dev);
+
+	if (version <= LPASS_CDC_VERSION_2_5) {
+		ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa_macro_dapm_widgets_v2p5,
+						ARRAY_SIZE(lpass_cdc_wsa_macro_dapm_widgets_v2p5));
+		if (ret < 0) {
+			dev_err(wsa_dev, "%s: Failed to add lpass v2p5 controls\n", __func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa_macro_dapm_widgets_v2p6,
+					ARRAY_SIZE(lpass_cdc_wsa_macro_dapm_widgets_v2p6));
+		if (ret < 0) {
+			dev_err(wsa_dev, "%s: Failed to add lpass v2p6 controls\n", __func__);
+			return ret;
+		}
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map,
+					ARRAY_SIZE(wsa_audio_map));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add routes\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component, lpass_cdc_wsa_macro_snd_controls,
+				   ARRAY_SIZE(lpass_cdc_wsa_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__);
+		return ret;
+	}
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_CPS Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
+	snd_soc_dapm_ignore_suspend(dapm, "CPSINPUT_WSA");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");
+	snd_soc_dapm_sync(dapm);
+
+	wsa_priv->component = component;
+	wsa_priv->spkr_gain_offset = LPASS_CDC_WSA_MACRO_GAIN_OFFSET_0_DB;
+	lpass_cdc_wsa_macro_init_reg(component);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->component = NULL;
+
+	return 0;
+}
+
+static void lpass_cdc_wsa_macro_add_child_devices(struct work_struct *work)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv;
+	struct platform_device *pdev;
+	struct device_node *node;
+	struct lpass_cdc_wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
+	int ret;
+	u16 count = 0, ctrl_num = 0;
+	struct lpass_cdc_wsa_macro_swr_ctrl_platform_data *platdata;
+	char plat_dev_name[LPASS_CDC_WSA_MACRO_SWR_STRING_LEN];
+
+	wsa_priv = container_of(work, struct lpass_cdc_wsa_macro_priv,
+			     lpass_cdc_wsa_macro_add_child_devices_work);
+	if (!wsa_priv) {
+		pr_err("%s: Memory for wsa_priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
+		dev_err(wsa_priv->dev,
+			"%s: DT node for wsa_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &wsa_priv->swr_plat_data;
+	wsa_priv->child_count = 0;
+
+	for_each_available_child_of_node(wsa_priv->dev->of_node, node) {
+		if (strnstr(node->name, "wsa_swr_master",
+				strlen("wsa_swr_master")) != NULL)
+			strlcpy(plat_dev_name, "wsa_swr_ctrl",
+				(LPASS_CDC_WSA_MACRO_SWR_STRING_LEN - 1));
+		else if (strnstr(node->name, "msm_cdc_pinctrl",
+				 strlen("msm_cdc_pinctrl")) != NULL)
+			strlcpy(plat_dev_name, node->name,
+				(LPASS_CDC_WSA_MACRO_SWR_STRING_LEN - 1));
+		else
+			continue;
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = wsa_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (strnstr(node->name, "wsa_swr_master",
+				strlen("wsa_swr_master")) != NULL) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct lpass_cdc_wsa_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				dev_err(&pdev->dev, "out of memory\n");
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			wsa_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (wsa_priv->child_count < LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX)
+			wsa_priv->pdev_child_devices[
+					wsa_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+
+	return;
+fail_pdev_add:
+	for (count = 0; count < wsa_priv->child_count; count++)
+		platform_device_put(wsa_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static void lpass_cdc_wsa_macro_cooling_adjust_gain(struct work_struct *work)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv;
+	u8 gain = 0;
+
+	wsa_priv = container_of(work, struct lpass_cdc_wsa_macro_priv,
+			     lpass_cdc_wsa_macro_cooling_work);
+	if (!wsa_priv) {
+		pr_err("%s: priv is null for macro!\n",
+			__func__);
+		return;
+	}
+	if (!wsa_priv->dev || !wsa_priv->dev->of_node) {
+		dev_err(wsa_priv->dev,
+			"%s: DT node for wsa_priv does not exist\n", __func__);
+		return;
+	}
+
+	/* Only adjust the volume when WSA clock is enabled */
+	if (wsa_priv->dapm_mclk_enable) {
+		gain = (u8)(wsa_priv->rx0_origin_gain -
+				wsa_priv->thermal_cur_state);
+		snd_soc_component_update_bits(wsa_priv->component,
+			LPASS_CDC_WSA_RX0_RX_VOL_CTL, 0xFF, gain);
+		dev_dbg(wsa_priv->dev,
+			"%s: RX0 current thermal state: %d, "
+			"adjusted gain: %#x\n",
+			__func__, wsa_priv->thermal_cur_state, gain);
+
+		gain = (u8)(wsa_priv->rx1_origin_gain -
+				wsa_priv->thermal_cur_state);
+		snd_soc_component_update_bits(wsa_priv->component,
+			LPASS_CDC_WSA_RX1_RX_VOL_CTL, 0xFF, gain);
+		dev_dbg(wsa_priv->dev,
+			"%s: RX1 current thermal state: %d, "
+			"adjusted gain: %#x\n",
+			__func__, wsa_priv->thermal_cur_state, gain);
+	}
+
+	return;
+}
+
+static int lpass_cdc_wsa_macro_read_array(struct platform_device *pdev,
+					  const char *name, int num_values,
+					  u32 *output)
+{
+	u32 len, ret, size;
+
+	if (!of_find_property(pdev->dev.of_node, name, &size)) {
+		dev_info(&pdev->dev, "%s: missing %s\n", __func__, name);
+		return 0;
+	}
+
+	len = size / sizeof(u32);
+	if (len != num_values) {
+		dev_info(&pdev->dev, "%s: invalid number of %s\n", __func__, name);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node, name, output, len);
+	if (ret)
+		dev_info(&pdev->dev, "%s: Failed to read %s\n", __func__, name);
+
+	return 0;
+
+}
+
+static void lpass_cdc_wsa_macro_init_ops(struct macro_ops *ops,
+			       char __iomem *wsa_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = lpass_cdc_wsa_macro_init;
+	ops->exit = lpass_cdc_wsa_macro_deinit;
+	ops->io_base = wsa_io_base;
+	ops->dai_ptr = lpass_cdc_wsa_macro_dai;
+	ops->num_dais = ARRAY_SIZE(lpass_cdc_wsa_macro_dai);
+	ops->event_handler = lpass_cdc_wsa_macro_event_handler;
+	ops->set_port_map = lpass_cdc_wsa_macro_set_port_map;
+}
+
+static int lpass_cdc_wsa_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv;
+	u32 wsa_base_addr, default_clk_id, thermal_max_state;
+	char __iomem *wsa_io_base;
+	int ret = 0;
+	u32 is_used_wsa_swr_gpio = 1;
+	u32 noise_gate_mode;
+	const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_wsa_macro_priv),
+				GFP_KERNEL);
+	if (!wsa_priv)
+		return -ENOMEM;
+
+	wsa_priv->pre_dev_up = true;
+	wsa_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &wsa_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "wsa_data_fs_ctl_reg",
+					&wsa_priv->wsa_fs_ctl_reg);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: error finding %s entry in dt\n",
+			__func__, "wsa_data_fs_ctl_reg");
+	}
+
+	if (!wsa_priv->wsa_fs_reg_base && wsa_priv->wsa_fs_ctl_reg)
+		wsa_priv->wsa_fs_reg_base = devm_ioremap(&pdev->dev,
+			wsa_priv->wsa_fs_ctl_reg, LPASS_CDC_WSA_MACRO_MAX_OFFSET);
+
+	if (of_find_property(pdev->dev.of_node, is_used_wsa_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_wsa_swr_gpio_dt,
+					   &is_used_wsa_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_wsa_swr_gpio_dt);
+			is_used_wsa_swr_gpio = 1;
+		}
+	}
+	wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,wsa-swr-gpios", 0);
+	if (!wsa_priv->wsa_swr_gpio_p && is_used_wsa_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(wsa_priv->wsa_swr_gpio_p) < 0 &&
+			is_used_wsa_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				wsa_priv->wsa_swr_gpio_p, false);
+
+	wsa_io_base = devm_ioremap(&pdev->dev,
+				   wsa_base_addr, LPASS_CDC_WSA_MACRO_MAX_OFFSET);
+	if (!wsa_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -EINVAL;
+	}
+
+	lpass_cdc_wsa_macro_read_array(pdev, "qcom,wsa-rloads",
+		LPASS_CDC_WSA_MACRO_RX1 + 1, wsa_priv->wsa_rload);
+	lpass_cdc_wsa_macro_read_array(pdev, "qcom,wsa-system-gains",
+		2 * (LPASS_CDC_WSA_MACRO_RX1 + 1), wsa_priv->wsa_sys_gain);
+	lpass_cdc_wsa_macro_read_array(pdev, "qcom,wsa-bat-cfgs",
+		LPASS_CDC_WSA_MACRO_RX1 + 1, wsa_priv->wsa_bat_cfg);
+
+
+	wsa_priv->wsa_io_base = wsa_io_base;
+	wsa_priv->reset_swr = true;
+	INIT_WORK(&wsa_priv->lpass_cdc_wsa_macro_add_child_devices_work,
+		  lpass_cdc_wsa_macro_add_child_devices);
+	INIT_WORK(&wsa_priv->lpass_cdc_wsa_macro_cooling_work,
+		  lpass_cdc_wsa_macro_cooling_adjust_gain);
+	wsa_priv->swr_plat_data.handle = (void *) wsa_priv;
+	wsa_priv->swr_plat_data.read = NULL;
+	wsa_priv->swr_plat_data.write = NULL;
+	wsa_priv->swr_plat_data.bulk_write = NULL;
+	wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
+	wsa_priv->swr_plat_data.core_vote = lpass_cdc_wsa_macro_core_vote;
+	wsa_priv->swr_plat_data.handle_irq = NULL;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,mux0-clk-id");
+		default_clk_id = WSA_CORE_CLK;
+	}
+
+	wsa_priv->default_clk_id  = default_clk_id;
+
+	dev_set_drvdata(&pdev->dev, wsa_priv);
+	mutex_init(&wsa_priv->mclk_lock);
+	mutex_init(&wsa_priv->swr_clk_lock);
+	lpass_cdc_wsa_macro_init_ops(&ops, wsa_io_base);
+	ops.clk_id_req = wsa_priv->default_clk_id;
+	ops.default_clk_id = wsa_priv->default_clk_id;
+
+	ret = lpass_cdc_register_macro(&pdev->dev, WSA_MACRO, &ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
+		goto reg_macro_fail;
+	}
+
+	if (of_find_property(wsa_priv->dev->of_node, "#cooling-cells", NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,thermal-max-state",
+					   &thermal_max_state);
+		if (ret) {
+			dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
+				__func__, "qcom,thermal-max-state");
+			wsa_priv->thermal_max_state =
+					LPASS_CDC_WSA_MACRO_THERMAL_MAX_STATE;
+		} else {
+			wsa_priv->thermal_max_state = thermal_max_state;
+		}
+		wsa_priv->tcdev = devm_thermal_of_cooling_device_register(
+						&pdev->dev,
+						wsa_priv->dev->of_node,
+						"wsa", wsa_priv,
+						&wsa_cooling_ops);
+		if (IS_ERR(wsa_priv->tcdev)) {
+			dev_err(&pdev->dev,
+				"%s: failed to register wsa macro as cooling device\n",
+				__func__);
+			wsa_priv->tcdev = NULL;
+		}
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,noise-gate-mode", &noise_gate_mode);
+	if (ret) {
+		dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,noise-gate-mode");
+		wsa_priv->noise_gate_mode = IDLE_DETECT;
+	} else {
+		if (noise_gate_mode >= IDLE_DETECT && noise_gate_mode <= NG3)
+			wsa_priv->noise_gate_mode = noise_gate_mode;
+		else
+			wsa_priv->noise_gate_mode = IDLE_DETECT;
+	}
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	schedule_work(&wsa_priv->lpass_cdc_wsa_macro_add_child_devices_work);
+	return ret;
+reg_macro_fail:
+	mutex_destroy(&wsa_priv->mclk_lock);
+	mutex_destroy(&wsa_priv->swr_clk_lock);
+	return ret;
+}
+
+static int lpass_cdc_wsa_macro_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_wsa_macro_priv *wsa_priv;
+	u16 count = 0;
+
+	wsa_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!wsa_priv)
+		return -EINVAL;
+
+	if (wsa_priv->tcdev)
+		thermal_cooling_device_unregister(wsa_priv->tcdev);
+
+	for (count = 0; count < wsa_priv->child_count &&
+		count < LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(wsa_priv->pdev_child_devices[count]);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	lpass_cdc_unregister_macro(&pdev->dev, WSA_MACRO);
+	mutex_destroy(&wsa_priv->mclk_lock);
+	mutex_destroy(&wsa_priv->swr_clk_lock);
+	return 0;
+}
+
+static const struct of_device_id lpass_cdc_wsa_macro_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-wsa-macro"},
+	{}
+};
+
+static const struct dev_pm_ops lpass_cdc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_cdc_runtime_suspend,
+		lpass_cdc_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_cdc_wsa_macro_driver = {
+	.driver = {
+		.name = "lpass_cdc_wsa_macro",
+		.owner = THIS_MODULE,
+		.pm = &lpass_cdc_dev_pm_ops,
+		.of_match_table = lpass_cdc_wsa_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_wsa_macro_probe,
+	.remove = lpass_cdc_wsa_macro_remove,
+};
+
+module_platform_driver(lpass_cdc_wsa_macro_driver);
+
+MODULE_DESCRIPTION("WSA macro driver");
+MODULE_LICENSE("GPL v2");

+ 22 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.h

@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+#ifndef LPASS_CDC_WSA_MACRO_H
+#define LPASS_CDC_WSA_MACRO_H
+
+/*
+ * Selects compander and smart boost settings
+ * for a given speaker mode
+ */
+enum {
+	LPASS_CDC_WSA_MACRO_SPKR_MODE_DEFAULT,
+	LPASS_CDC_WSA_MACRO_SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */
+};
+
+/* Rx path gain offsets */
+enum {
+	LPASS_CDC_WSA_MACRO_GAIN_OFFSET_M1P5_DB,
+	LPASS_CDC_WSA_MACRO_GAIN_OFFSET_0_DB,
+};
+
+#endif

+ 4100 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c

@@ -0,0 +1,4100 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. 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 <linux/thermal.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
+
+#include <asoc/msm-cdc-pinctrl.h>
+#include "lpass-cdc.h"
+#include "lpass-cdc-comp.h"
+#include "lpass-cdc-registers.h"
+#include "lpass-cdc-wsa2-macro.h"
+#include "lpass-cdc-clk-rsc.h"
+
+#define AUTO_SUSPEND_DELAY  50 /* delay in msec */
+#define LPASS_CDC_WSA2_MACRO_MAX_OFFSET 0x1000
+
+#define LPASS_CDC_WSA2_MACRO_RX_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 LPASS_CDC_WSA2_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define LPASS_CDC_WSA2_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define LPASS_CDC_WSA2_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_48000)
+#define LPASS_CDC_WSA2_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define LPASS_CDC_WSA2_MACRO_CPS_RATES (SNDRV_PCM_RATE_48000)
+#define LPASS_CDC_WSA2_MACRO_CPS_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+#define NUM_INTERPOLATORS 2
+
+#define LPASS_CDC_WSA2_MACRO_MUX_INP_SHFT 0x3
+#define LPASS_CDC_WSA2_MACRO_MUX_INP_MASK1 0x07
+#define LPASS_CDC_WSA2_MACRO_MUX_INP_MASK2 0x38
+#define LPASS_CDC_WSA2_MACRO_MUX_CFG_OFFSET 0x8
+#define LPASS_CDC_WSA2_MACRO_MUX_CFG1_OFFSET 0x4
+#define LPASS_CDC_WSA2_MACRO_RX_COMP_OFFSET \
+		(LPASS_CDC_WSA2_COMPANDER1_CTL0 - LPASS_CDC_WSA2_COMPANDER0_CTL0)
+#define LPASS_CDC_WSA2_MACRO_RX_SOFTCLIP_OFFSET \
+		(LPASS_CDC_WSA2_SOFTCLIP1_CRC - LPASS_CDC_WSA2_SOFTCLIP0_CRC)
+#define LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET \
+		(LPASS_CDC_WSA2_RX1_RX_PATH_CTL - LPASS_CDC_WSA2_RX0_RX_PATH_CTL)
+#define LPASS_CDC_WSA2_MACRO_RX_PATH_CFG3_OFFSET 0x10
+#define LPASS_CDC_WSA2_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
+#define LPASS_CDC_WSA2_MACRO_FS_RATE_MASK 0x0F
+#define LPASS_CDC_WSA2_MACRO_EC_MIX_TX0_MASK 0x03
+#define LPASS_CDC_WSA2_MACRO_EC_MIX_TX1_MASK 0x18
+
+#define LPASS_CDC_WSA2_MACRO_MAX_DMA_CH_PER_PORT 0x2
+#define LPASS_CDC_WSA2_MACRO_THERMAL_MAX_STATE 11
+
+enum {
+	LPASS_CDC_WSA2_MACRO_RX0 = 0,
+	LPASS_CDC_WSA2_MACRO_RX1,
+	LPASS_CDC_WSA2_MACRO_RX_MIX,
+	LPASS_CDC_WSA2_MACRO_RX_MIX0 = LPASS_CDC_WSA2_MACRO_RX_MIX,
+	LPASS_CDC_WSA2_MACRO_RX_MIX1,
+	LPASS_CDC_WSA2_MACRO_RX4,
+	LPASS_CDC_WSA2_MACRO_RX5,
+	LPASS_CDC_WSA2_MACRO_RX6,
+	LPASS_CDC_WSA2_MACRO_RX7,
+	LPASS_CDC_WSA2_MACRO_RX8,
+	LPASS_CDC_WSA2_MACRO_RX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA2_MACRO_TX0 = 0,
+	LPASS_CDC_WSA2_MACRO_TX1,
+	LPASS_CDC_WSA2_MACRO_TX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA2_MACRO_EC0_MUX = 0,
+	LPASS_CDC_WSA2_MACRO_EC1_MUX,
+	LPASS_CDC_WSA2_MACRO_EC_MUX_MAX,
+};
+
+enum {
+	LPASS_CDC_WSA2_MACRO_COMP1, /* SPK_L */
+	LPASS_CDC_WSA2_MACRO_COMP2, /* SPK_R */
+	LPASS_CDC_WSA2_MACRO_COMP_MAX
+};
+
+enum {
+	LPASS_CDC_WSA2_MACRO_SOFTCLIP0, /* RX0 */
+	LPASS_CDC_WSA2_MACRO_SOFTCLIP1, /* RX1 */
+	LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX
+};
+
+enum {
+	INTn_1_INP_SEL_ZERO = 0,
+	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,
+	INTn_1_INP_SEL_RX6,
+	INTn_1_INP_SEL_RX7,
+	INTn_1_INP_SEL_RX8,
+	INTn_1_INP_SEL_DEC0,
+	INTn_1_INP_SEL_DEC1,
+};
+
+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,
+	INTn_2_INP_SEL_RX6,
+	INTn_2_INP_SEL_RX7,
+	INTn_2_INP_SEL_RX8,
+};
+
+enum {
+	IDLE_DETECT,
+	NG1,
+	NG2,
+	NG3,
+};
+
+static struct lpass_cdc_comp_setting comp_setting_table[G_MAX_DB] = {
+	{42, 0, 42},
+	{39, 0, 42},
+	{36, 0, 42},
+	{33, 0, 42},
+	{30, 0, 42},
+	{27, 0, 42},
+	{24, 0, 42},
+	{21, 0, 42},
+	{18, 0, 42},
+};
+
+struct interp_sample_rate {
+	int sample_rate;
+	int rate_val;
+};
+
+/*
+ * Structure used to update codec
+ * register defaults after reset
+ */
+struct lpass_cdc_wsa2_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static struct interp_sample_rate int_prim_sample_rate_val[] = {
+	{8000, 0x0},	/* 8K */
+	{16000, 0x1},	/* 16K */
+	{24000, -EINVAL},/* 24K */
+	{32000, 0x3},	/* 32K */
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+	{384000, 0x7},	/* 384K */
+	{44100, 0x8}, /* 44.1K */
+};
+
+static struct interp_sample_rate int_mix_sample_rate_val[] = {
+	{48000, 0x4},	/* 48K */
+	{96000, 0x5},	/* 96K */
+	{192000, 0x6},	/* 192K */
+};
+
+#define LPASS_CDC_WSA2_MACRO_SWR_STRING_LEN 80
+
+static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable);
+static int lpass_cdc_wsa2_macro_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *dai);
+static int lpass_cdc_wsa2_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);
+static int lpass_cdc_wsa2_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
+
+#define LPASS_CDC_WSA2_MACRO_VTH_TO_REG(vth) ((vth) == 0 ? 255 : (vth))
+/* Hold instance to soundwire platform device */
+struct lpass_cdc_wsa2_macro_swr_ctrl_data {
+	struct platform_device *wsa2_swr_pdev;
+};
+static int lpass_cdc_wsa2_macro_enable_vi_decimator(struct snd_soc_component *component);
+
+#define LPASS_CDC_WSA2_MACRO_SET_VOLUME_TLV(xname, xreg, xmin, xmax, tlv_array) \
+{	.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+		SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+	.tlv.p  = (tlv_array), \
+	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
+	.put = lpass_cdc_wsa2_macro_set_digital_volume, \
+	.private_value = (unsigned long)&(struct soc_mixer_control) \
+	{.reg = xreg, .rreg = xreg,  \
+	.min = xmin, .max = xmax, \
+	.sign_bit = 7,} }
+
+struct lpass_cdc_wsa2_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*core_vote)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
+enum {
+	LPASS_CDC_WSA2_MACRO_AIF_INVALID = 0,
+	LPASS_CDC_WSA2_MACRO_AIF1_PB,
+	LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB,
+	LPASS_CDC_WSA2_MACRO_AIF_VI,
+	LPASS_CDC_WSA2_MACRO_AIF_ECHO,
+	LPASS_CDC_WSA2_MACRO_AIF_CPS,
+	LPASS_CDC_WSA2_MACRO_MAX_DAIS,
+};
+
+
+#define LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX 3
+
+/*
+ * @dev: wsa2 macro device pointer
+ * @comp_enabled: compander enable mixer value set
+ * @ec_hq: echo HQ enable mixer value set
+ * @prim_int_users: Users of interpolator
+ * @wsa2_mclk_users: WSA2 MCLK users count
+ * @swr_clk_users: SWR clk users count
+ * @vi_feed_value: VI sense mask
+ * @mclk_lock: to lock mclk operations
+ * @swr_clk_lock: to lock swr master clock operations
+ * @swr_ctrl_data: SoundWire data structure
+ * @swr_plat_data: Soundwire platform data
+ * @lpass_cdc_wsa2_macro_add_child_devices_work: work for adding child devices
+ * @wsa2_swr_gpio_p: used by pinctrl API
+ * @component: codec handle
+ * @rx_0_count: RX0 interpolation users
+ * @rx_1_count: RX1 interpolation users
+ * @active_ch_mask: channel mask for all AIF DAIs
+ * @active_ch_cnt: channel count of all AIF DAIs
+ * @rx_port_value: mixer ctl value of WSA2 RX MUXes
+ * @wsa2_io_base: Base address of WSA2 macro addr space
+ * @wsa2_sys_gain System gain value, see wsa2 driver
+ * @wsa2_bat_cfg Battery Configuration value, see wsa2 driver
+ * @wsa2_rload Resistor load value for WSA2 Speaker, see wsa2 driver
+ */
+struct lpass_cdc_wsa2_macro_priv {
+	struct device *dev;
+	int comp_enabled[LPASS_CDC_WSA2_MACRO_COMP_MAX];
+	int comp_mode[LPASS_CDC_WSA2_MACRO_COMP_MAX];
+	int ec_hq[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u16 prim_int_users[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u16 wsa2_mclk_users;
+	u16 swr_clk_users;
+	bool dapm_mclk_enable;
+	bool reset_swr;
+	unsigned int vi_feed_value;
+	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
+	struct lpass_cdc_wsa2_macro_swr_ctrl_data *swr_ctrl_data;
+	struct lpass_cdc_wsa2_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct lpass_cdc_wsa2_macro_add_child_devices_work;
+	struct device_node *wsa2_swr_gpio_p;
+	struct snd_soc_component *component;
+	int rx_0_count;
+	int rx_1_count;
+	unsigned long active_ch_mask[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
+	u16 bit_width[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
+	int rx_port_value[LPASS_CDC_WSA2_MACRO_RX_MAX];
+	char __iomem *wsa2_io_base;
+	struct platform_device *pdev_child_devices
+			[LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX];
+	int child_count;
+	int wsa2_spkrrecv;
+	int spkr_gain_offset;
+	int spkr_mode;
+	int is_softclip_on[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
+	int softclip_clk_users[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
+	char __iomem *mclk_mode_muxsel;
+	u16 default_clk_id;
+	u32 pcm_rate_vi;
+	int wsa2_digital_mute_status[LPASS_CDC_WSA2_MACRO_RX_MAX];
+	u8 rx0_origin_gain;
+	u8 rx1_origin_gain;
+	struct thermal_cooling_device *tcdev;
+	uint32_t thermal_cur_state;
+	uint32_t thermal_max_state;
+	struct work_struct lpass_cdc_wsa2_macro_cooling_work;
+	bool pbr_enable;
+	u32 wsa2_sys_gain[2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1)];
+	u32 wsa2_bat_cfg[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u32 wsa2_rload[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u32 wsa2_fs_ctl_reg;
+	u8 idle_detect_en;
+	int noise_gate_mode;
+	bool pre_dev_up;
+	int pbr_clk_users;
+	char __iomem *wsa2_fs_reg_base;
+	bool wsa2_2ch_dma_enable;
+};
+
+static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[];
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+
+static const char *const rx_text[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4",
+	"RX5", "RX6", "RX7", "RX8", "DEC0", "DEC1"
+};
+
+static const char *const rx_mix_text[] = {
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8"
+};
+
+static const char *const rx_mix_ec_text[] = {
+	"ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
+};
+
+static const char *const rx_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF_MIX1_PB"
+};
+
+static const char *const rx_sidetone_mix_text[] = {
+	"ZERO", "SRC0"
+};
+
+static const char * const lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text[] = {
+	"OFF", "ON"
+};
+
+static const char * const lpass_cdc_wsa2_macro_comp_mode_text[] = {
+	"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
+	"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
+};
+
+static const struct snd_kcontrol_new wsa2_int0_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA2 RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new wsa2_int1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA2 RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
+			lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text);
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
+			lpass_cdc_wsa2_macro_comp_mode_text);
+
+/* RX INT0 */
+static const struct soc_enum rx0_prim_inp0_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
+		0, 12, rx_text);
+
+static const struct soc_enum rx0_prim_inp1_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
+		3, 12, rx_text);
+
+static const struct soc_enum rx0_prim_inp2_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
+		3, 12, rx_text);
+
+static const struct soc_enum rx0_mix_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
+		0, 10, rx_mix_text);
+
+static const struct soc_enum rx0_sidetone_mix_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
+
+static const struct snd_kcontrol_new rx0_prim_inp0_mux =
+	SOC_DAPM_ENUM("WSA2_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx0_prim_inp1_mux =
+	SOC_DAPM_ENUM("WSA2_RX0 INP1 Mux", rx0_prim_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx0_prim_inp2_mux =
+	SOC_DAPM_ENUM("WSA2_RX0 INP2 Mux", rx0_prim_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx0_mix_mux =
+	SOC_DAPM_ENUM("WSA2_RX0 MIX Mux", rx0_mix_chain_enum);
+
+static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
+	SOC_DAPM_ENUM("WSA2_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
+
+/* RX INT1 */
+static const struct soc_enum rx1_prim_inp0_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
+		0, 12, rx_text);
+
+static const struct soc_enum rx1_prim_inp1_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
+		3, 12, rx_text);
+
+static const struct soc_enum rx1_prim_inp2_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
+		3, 12, rx_text);
+
+static const struct soc_enum rx1_mix_chain_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
+		0, 10, rx_mix_text);
+
+static const struct snd_kcontrol_new rx1_prim_inp0_mux =
+	SOC_DAPM_ENUM("WSA2_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx1_prim_inp1_mux =
+	SOC_DAPM_ENUM("WSA2_RX1 INP1 Mux", rx1_prim_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx1_prim_inp2_mux =
+	SOC_DAPM_ENUM("WSA2_RX1 INP2 Mux", rx1_prim_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix_mux =
+	SOC_DAPM_ENUM("WSA2_RX1 MIX Mux", rx1_mix_chain_enum);
+
+static const struct soc_enum rx_mix_ec0_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0,
+		0, 3, rx_mix_ec_text);
+
+static const struct soc_enum rx_mix_ec1_enum =
+	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0,
+		3, 3, rx_mix_ec_text);
+
+static const struct snd_kcontrol_new rx_mix_ec0_mux =
+	SOC_DAPM_ENUM("WSA2 RX_MIX EC0_Mux", rx_mix_ec0_enum);
+
+static const struct snd_kcontrol_new rx_mix_ec1_mux =
+	SOC_DAPM_ENUM("WSA2 RX_MIX EC1_Mux", rx_mix_ec1_enum);
+
+static struct snd_soc_dai_ops lpass_cdc_wsa2_macro_dai_ops = {
+	.hw_params = lpass_cdc_wsa2_macro_hw_params,
+	.get_channel_map = lpass_cdc_wsa2_macro_get_channel_map,
+	.mute_stream = lpass_cdc_wsa2_macro_mute_stream,
+};
+
+static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[] = {
+	{
+		.name = "wsa2_macro_rx1",
+		.id = LPASS_CDC_WSA2_MACRO_AIF1_PB,
+		.playback = {
+			.stream_name = "WSA2_AIF1 Playback",
+			.rates = LPASS_CDC_WSA2_MACRO_RX_RATES,
+			.formats = LPASS_CDC_WSA2_MACRO_RX_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa2_macro_dai_ops,
+	},
+	{
+		.name = "wsa2_macro_rx_mix",
+		.id = LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB,
+		.playback = {
+			.stream_name = "WSA2_AIF_MIX1 Playback",
+			.rates = LPASS_CDC_WSA2_MACRO_RX_MIX_RATES,
+			.formats = LPASS_CDC_WSA2_MACRO_RX_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa2_macro_dai_ops,
+	},
+	{
+		.name = "wsa2_macro_vifeedback",
+		.id = LPASS_CDC_WSA2_MACRO_AIF_VI,
+		.capture = {
+			.stream_name = "WSA2_AIF_VI Capture",
+			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
+			.formats = LPASS_CDC_WSA2_MACRO_RX_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &lpass_cdc_wsa2_macro_dai_ops,
+	},
+	{
+		.name = "wsa2_macro_echo",
+		.id = LPASS_CDC_WSA2_MACRO_AIF_ECHO,
+		.capture = {
+			.stream_name = "WSA2_AIF_ECHO Capture",
+			.rates = LPASS_CDC_WSA2_MACRO_ECHO_RATES,
+			.formats = LPASS_CDC_WSA2_MACRO_ECHO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa2_macro_dai_ops,
+	},
+        {
+                .name = "wsa2_macro_cpsfeedback",
+                .id = LPASS_CDC_WSA2_MACRO_AIF_CPS,
+                .capture = {
+                        .stream_name = "WSA2_AIF_CPS Capture",
+                        .rates = LPASS_CDC_WSA2_MACRO_CPS_RATES,
+                        .formats = LPASS_CDC_WSA2_MACRO_CPS_FORMATS,
+                        .rate_max = 48000,
+                        .rate_min = 48000,
+                        .channels_min = 1,
+                        .channels_max = 2,
+                },
+                .ops = &lpass_cdc_wsa2_macro_dai_ops,
+        },
+};
+
+static bool lpass_cdc_wsa2_macro_get_data(struct snd_soc_component *component,
+			       struct device **wsa2_dev,
+			       struct lpass_cdc_wsa2_macro_priv **wsa2_priv,
+			       const char *func_name)
+{
+	*wsa2_dev = lpass_cdc_get_device_ptr(component->dev,
+							WSA2_MACRO);
+	if (!(*wsa2_dev)) {
+		dev_err_ratelimited(component->dev,
+			"%s: null device for macro!\n", func_name);
+		return false;
+	}
+	*wsa2_priv = dev_get_drvdata((*wsa2_dev));
+	if (!(*wsa2_priv) || !(*wsa2_priv)->component) {
+		dev_err_ratelimited(component->dev,
+			"%s: priv is null for macro!\n", func_name);
+		return false;
+	}
+	return true;
+}
+
+static int lpass_cdc_wsa2_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (wsa2_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			wsa2_priv->swr_ctrl_data[0].wsa2_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int lpass_cdc_wsa2_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					    u8 int_prim_fs_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 int_mux_cfg0_val, int_mux_cfg1_val;
+	u8 inp0_sel, inp1_sel, inp2_sel;
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	for_each_set_bit(port, &wsa2_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_WSA2_MACRO_RX_MAX) {
+		int_1_mix1_inp = port;
+		if ((int_1_mix1_inp < LPASS_CDC_WSA2_MACRO_RX0) ||
+			(int_1_mix1_inp >= LPASS_CDC_WSA2_MACRO_RX_MAX)) {
+			dev_err_ratelimited(wsa2_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg0 = LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0;
+
+		/*
+		 * Loop through all interpolator MUX inputs and find out
+		 * to which interpolator input, the cdc_dma rx port
+		 * is connected
+		 */
+		for (j = 0; j < NUM_INTERPOLATORS; j++) {
+			int_mux_cfg1 = int_mux_cfg0 + LPASS_CDC_WSA2_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 & LPASS_CDC_WSA2_MACRO_MUX_INP_MASK1;
+			inp1_sel = (int_mux_cfg0_val >>
+					LPASS_CDC_WSA2_MACRO_MUX_INP_SHFT) &
+					LPASS_CDC_WSA2_MACRO_MUX_INP_MASK1;
+			inp2_sel = (int_mux_cfg1_val >>
+					LPASS_CDC_WSA2_MACRO_MUX_INP_SHFT) &
+					LPASS_CDC_WSA2_MACRO_MUX_INP_MASK1;
+			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 = LPASS_CDC_WSA2_RX0_RX_PATH_CTL +
+					     LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET * j;
+				dev_dbg(wsa2_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_1\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa2_dev,
+					"%s: set INT%u_1 sample rate to %u\n",
+					__func__, j, sample_rate);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						LPASS_CDC_WSA2_MACRO_FS_RATE_MASK,
+						int_prim_fs_rate_reg_val);
+			}
+			int_mux_cfg0 += LPASS_CDC_WSA2_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					u8 int_mix_fs_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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+
+	for_each_set_bit(port, &wsa2_priv->active_ch_mask[dai->id],
+			 LPASS_CDC_WSA2_MACRO_RX_MAX) {
+		int_2_inp = port;
+		if ((int_2_inp < LPASS_CDC_WSA2_MACRO_RX0) ||
+			(int_2_inp > LPASS_CDC_WSA2_MACRO_RX_MIX1)) {
+			dev_err_ratelimited(wsa2_dev,
+				"%s: Invalid RX port, Dai ID is %d\n",
+				__func__, dai->id);
+			return -EINVAL;
+		}
+
+		int_mux_cfg1 = LPASS_CDC_WSA2_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) &
+							LPASS_CDC_WSA2_MACRO_MUX_INP_MASK1;
+			if (int_mux_cfg1_val == int_2_inp +
+							INTn_2_INP_SEL_RX0) {
+				int_fs_reg =
+					LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL +
+					LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET * j;
+
+				dev_dbg(wsa2_dev,
+					"%s: AIF_PB DAI(%d) connected to INT%u_2\n",
+					__func__, dai->id, j);
+				dev_dbg(wsa2_dev,
+					"%s: set INT%u_2 sample rate to %u\n",
+					__func__, j, sample_rate);
+				snd_soc_component_update_bits(component,
+						int_fs_reg,
+						LPASS_CDC_WSA2_MACRO_FS_RATE_MASK,
+						int_mix_fs_rate_reg_val);
+			}
+			int_mux_cfg1 += LPASS_CDC_WSA2_MACRO_MUX_CFG_OFFSET;
+		}
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+				       u32 sample_rate)
+{
+	int rate_val = 0;
+	int i, ret;
+
+	/* set mixing path rate */
+	for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_mix_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_mix_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) ||
+			(rate_val < 0))
+		goto prim_rate;
+	ret = lpass_cdc_wsa2_macro_set_mix_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+prim_rate:
+	/* set primary path sample rate */
+	for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) {
+		if (sample_rate ==
+				int_prim_sample_rate_val[i].sample_rate) {
+			rate_val =
+				int_prim_sample_rate_val[i].rate_val;
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) ||
+			(rate_val < 0))
+		return -EINVAL;
+	ret = lpass_cdc_wsa2_macro_set_prim_interpolator_rate(dai,
+			(u8) rate_val, sample_rate);
+	return ret;
+}
+
+static int lpass_cdc_wsa2_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;
+	int ret;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv = dev_get_drvdata(wsa2_dev);
+	if (!wsa2_priv)
+		return -EINVAL;
+
+	dev_dbg(component->dev,
+		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = lpass_cdc_wsa2_macro_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			dev_err_ratelimited(component->dev,
+				"%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		switch (params_width(params)) {
+		case 16:
+			wsa2_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa2_priv->bit_width[dai->id] = 24;
+			break;
+		case 32:
+			wsa2_priv->bit_width[dai->id] = 32;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+		}
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		if (dai->id == LPASS_CDC_WSA2_MACRO_AIF_VI)
+			wsa2_priv->pcm_rate_vi = params_rate(params);
+
+		switch (params_width(params)) {
+		case 16:
+			wsa2_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa2_priv->bit_width[dai->id] = 24;
+			break;
+		case 32:
+			wsa2_priv->bit_width[dai->id] = 32;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 val = 0, mask = 0, cnt = 0, temp = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv = dev_get_drvdata(wsa2_dev);
+	if (!wsa2_priv)
+		return -EINVAL;
+
+	switch (dai->id) {
+	case LPASS_CDC_WSA2_MACRO_AIF_VI:
+		for_each_set_bit(temp, &wsa2_priv->active_ch_mask[dai->id],
+					LPASS_CDC_WSA2_MACRO_TX_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == LPASS_CDC_WSA2_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		/* consider WSA2 Backend is used when 2ch_dma is enabled
+		 * and doesn't require channel mask shift
+		 */
+		if (!wsa2_priv->wsa2_2ch_dma_enable) {
+			if (mask & 0x03)
+				mask = mask << 0x2;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	case LPASS_CDC_WSA2_MACRO_AIF_CPS:
+		*tx_slot = wsa2_priv->active_ch_mask[dai->id];
+		*tx_num = wsa2_priv->active_ch_cnt[dai->id];
+		break;
+	case LPASS_CDC_WSA2_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB:
+		for_each_set_bit(temp, &wsa2_priv->active_ch_mask[dai->id],
+					LPASS_CDC_WSA2_MACRO_RX_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == LPASS_CDC_WSA2_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		if (mask & 0x30)
+			mask = mask >> 0x4;
+		else
+			mask = mask << 0x2;
+		*rx_slot = mask;
+		*rx_num = cnt;
+		break;
+	case LPASS_CDC_WSA2_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,
+			LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0);
+		if (val & LPASS_CDC_WSA2_MACRO_EC_MIX_TX1_MASK) {
+			mask |= 0x2;
+			cnt++;
+		}
+		if (val & LPASS_CDC_WSA2_MACRO_EC_MIX_TX0_MASK) {
+			mask |= 0x1;
+			cnt++;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	default:
+		dev_err(wsa2_dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static void lpass_cdc_wsa2_unmute_interpolator(struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	uint16_t j = 0, reg = 0, mix_reg = 0;
+
+	switch (dai->id) {
+	case LPASS_CDC_WSA2_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB:
+		for (j = 0; j < NUM_INTERPOLATORS; ++j) {
+			reg = LPASS_CDC_WSA2_RX0_RX_PATH_CTL +
+				(j * LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET);
+			mix_reg = LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL +
+				(j * LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET);
+
+			snd_soc_component_update_bits(component, reg, 0x10, 0x00);
+			snd_soc_component_update_bits(component, mix_reg, 0x10, 0x00);
+		}
+	}
+}
+
+static int lpass_cdc_wsa2_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	uint32_t temp;
+
+	bool adie_lb = false;
+
+	if (mute)
+		return 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+	switch (dai->id) {
+	case LPASS_CDC_WSA2_MACRO_AIF1_PB:
+	case LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB:
+		lpass_cdc_wsa_pa_on(wsa2_dev, adie_lb);
+		lpass_cdc_wsa2_unmute_interpolator(dai);
+		lpass_cdc_wsa2_macro_enable_vi_decimator(component);
+		break;
+	default:
+		break;
+	}
+
+	if ((test_bit(LPASS_CDC_WSA2_MACRO_RX4,
+			&wsa2_priv->active_ch_mask[dai->id]) ||
+			test_bit(LPASS_CDC_WSA2_MACRO_RX5,
+			&wsa2_priv->active_ch_mask[dai->id])) &&
+			wsa2_priv->wsa2_fs_reg_base) {
+		temp = ioread32(wsa2_priv->wsa2_fs_reg_base);
+		if (temp != 1) {
+			temp = 1;
+			iowrite32(temp, wsa2_priv->wsa2_fs_reg_base);
+		}
+		dev_dbg(wsa2_dev, "%s: LPASS_WSA_FS_CTL : %d", __func__, temp);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_mclk_enable(
+				struct lpass_cdc_wsa2_macro_priv *wsa2_priv,
+				 bool mclk_enable, bool dapm)
+{
+	struct regmap *regmap = dev_get_regmap(wsa2_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(wsa2_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(wsa2_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
+		__func__, mclk_enable, dapm, wsa2_priv->wsa2_mclk_users);
+
+	mutex_lock(&wsa2_priv->mclk_lock);
+	if (mclk_enable) {
+		if (wsa2_priv->wsa2_mclk_users == 0) {
+			ret = lpass_cdc_clk_rsc_request_clock(wsa2_priv->dev,
+							wsa2_priv->default_clk_id,
+							wsa2_priv->default_clk_id,
+							true);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa2_priv->dev,
+					"%s: wsa2 request clock enable failed\n",
+					__func__);
+				goto exit;
+			}
+			lpass_cdc_clk_rsc_fs_gen_request(wsa2_priv->dev,
+						  true);
+			regcache_mark_dirty(regmap);
+			regcache_sync_region(regmap,
+					WSA2_START_OFFSET,
+					WSA2_MAX_OFFSET);
+			/* 9.6MHz MCLK, set value 0x00 if other frequency */
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_TOP_FREQ_MCLK, 0x01, 0x01);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x01);
+			/* Toggle fs_cntr_clr bit*/
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x02, 0x0);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x01);
+		}
+		wsa2_priv->wsa2_mclk_users++;
+	} else {
+		if (wsa2_priv->wsa2_mclk_users <= 0) {
+			dev_err_ratelimited(wsa2_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa2_priv->wsa2_mclk_users = 0;
+			goto exit;
+		}
+		wsa2_priv->wsa2_mclk_users--;
+		if (wsa2_priv->wsa2_mclk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_FS_CNT_CONTROL,
+				0x01, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_MCLK_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_clk_rsc_fs_gen_request(wsa2_priv->dev,
+						  false);
+
+			lpass_cdc_clk_rsc_request_clock(wsa2_priv->dev,
+						  wsa2_priv->default_clk_id,
+						  wsa2_priv->default_clk_id,
+						  false);
+		}
+	}
+exit:
+	mutex_unlock(&wsa2_priv->mclk_lock);
+	return ret;
+}
+
+static int lpass_cdc_wsa2_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);
+	int ret = 0;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa2_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = lpass_cdc_wsa2_macro_mclk_enable(wsa2_priv, 1, true);
+		if (ret)
+			wsa2_priv->dapm_mclk_enable = false;
+		else
+			wsa2_priv->dapm_mclk_enable = true;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (wsa2_priv->dapm_mclk_enable) {
+			lpass_cdc_wsa2_macro_mclk_enable(wsa2_priv, 0, true);
+			wsa2_priv->dapm_mclk_enable = false;
+		}
+		break;
+	default:
+		dev_err_ratelimited(wsa2_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lpass_cdc_wsa2_macro_event_handler(struct snd_soc_component *component,
+				   u16 event, u32 data)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case LPASS_CDC_MACRO_EVT_SSR_DOWN:
+		wsa2_priv->pre_dev_up = false;
+		if (wsa2_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa2_priv->swr_ctrl_data[0].wsa2_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
+		if ((!pm_runtime_enabled(wsa2_dev) ||
+		     !pm_runtime_suspended(wsa2_dev))) {
+			ret = lpass_cdc_runtime_suspend(wsa2_dev);
+			if (!ret) {
+				pm_runtime_disable(wsa2_dev);
+				pm_runtime_set_suspended(wsa2_dev);
+				pm_runtime_enable(wsa2_dev);
+			}
+		}
+		break;
+	case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
+		break;
+	case LPASS_CDC_MACRO_EVT_SSR_UP:
+		wsa2_priv->pre_dev_up = true;
+		/* reset swr after ssr/pdr */
+		wsa2_priv->reset_swr = true;
+		if (wsa2_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa2_priv->swr_ctrl_data[0].wsa2_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
+	case LPASS_CDC_MACRO_EVT_CLK_RESET:
+		lpass_cdc_rsc_clk_reset(wsa2_dev, WSA2_CORE_CLK);
+		lpass_cdc_rsc_clk_reset(wsa2_dev, WSA2_TX_CORE_CLK);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_enable_vi_decimator(struct snd_soc_component *component)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u8 val = 0x0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	usleep_range(5000, 5500);
+	dev_dbg(wsa2_dev, "%s: wsa2_priv->pcm_rate_vi %d\n", __func__, wsa2_priv->pcm_rate_vi);
+	switch (wsa2_priv->pcm_rate_vi) {
+	case 48000:
+		val = 0x04;
+		break;
+	case 24000:
+		val = 0x02;
+		break;
+	case 8000:
+	default:
+		val = 0x00;
+		break;
+	}
+
+        if (test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+		&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+		dev_dbg(wsa2_dev, "%s: spkr1 enabled\n", __func__);
+		/* Enable V&I sensing */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+	}
+
+	if (test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+		&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+		dev_dbg(wsa2_dev, "%s: spkr2 enabled\n", __func__);
+		/* Enable V&I sensing */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+			0x20, 0x20);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+			0x0F, val);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+			0x10, 0x10);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+			0x20, 0x00);
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_disable_vi_feedback(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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMD:
+		if (test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+			&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			dev_dbg(wsa2_dev, "%s: spkr1 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		if (test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+			&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			/* Disable V&I sensing */
+			dev_dbg(wsa2_dev, "%s: spkr2 disabled\n", __func__);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x20);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+				0x10, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CTL,
+				0x20, 0x00);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_wsa2_macro_hd2_control(struct snd_soc_component *component,
+				  u16 reg, int event)
+{
+	u16 hd2_scale_reg;
+	u16 hd2_enable_reg = 0;
+
+	if (reg == LPASS_CDC_WSA2_RX0_RX_PATH_CTL) {
+		hd2_scale_reg = LPASS_CDC_WSA2_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG0;
+	}
+	if (reg == LPASS_CDC_WSA2_RX1_RX_PATH_CTL) {
+		hd2_scale_reg = LPASS_CDC_WSA2_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = LPASS_CDC_WSA2_RX1_RX_PATH_CFG0;
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x10);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x01);
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x04);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, hd2_enable_reg,
+						0x04, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x03, 0x00);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+						0x3C, 0x00);
+	}
+}
+
+static int lpass_cdc_wsa2_macro_enable_swr(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+	int ch_cnt;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA2_RX0"))) &&
+		    !wsa2_priv->rx_0_count)
+			wsa2_priv->rx_0_count++;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA2_RX1"))) &&
+		    !wsa2_priv->rx_1_count)
+			wsa2_priv->rx_1_count++;
+		ch_cnt = wsa2_priv->rx_0_count + wsa2_priv->rx_1_count;
+
+		if (wsa2_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa2_priv->swr_ctrl_data[0].wsa2_swr_pdev,
+				SWR_DEVICE_UP, NULL);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (!(strnstr(w->name, "RX0", sizeof("WSA2_RX0"))) &&
+		    wsa2_priv->rx_0_count)
+			wsa2_priv->rx_0_count--;
+		if (!(strnstr(w->name, "RX1", sizeof("WSA2_RX1"))) &&
+		    wsa2_priv->rx_1_count)
+			wsa2_priv->rx_1_count--;
+		ch_cnt = wsa2_priv->rx_0_count + wsa2_priv->rx_1_count;
+
+		break;
+	}
+	dev_dbg(wsa2_priv->dev, "%s: current swr ch cnt: %d\n",
+		__func__, wsa2_priv->rx_0_count + wsa2_priv->rx_1_count);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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;
+	int offset_val = 0;
+	int val = 0;
+	uint16_t mix_reg = 0;
+	uint16_t reg = 0;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA2_RX0 MIX INP"))) {
+		gain_reg = LPASS_CDC_WSA2_RX0_RX_VOL_MIX_CTL;
+	} else if (!(strcmp(w->name, "WSA2_RX1 MIX INP"))) {
+		gain_reg = LPASS_CDC_WSA2_RX1_RX_VOL_MIX_CTL;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: No gain register avail for %s\n",
+			__func__, w->name);
+		return 0;
+	}
+
+	reg = LPASS_CDC_WSA2_RX0_RX_PATH_CTL +
+				LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET * w->shift;
+	mix_reg = LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL +
+				LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET * w->shift;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);
+		usleep_range(500, 510);
+		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00);
+		snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+		snd_soc_component_update_bits(component,
+					mix_reg, 0x20, 0x20);
+		lpass_cdc_wsa2_macro_enable_swr(w, kcontrol, event);
+		val = snd_soc_component_read(component, gain_reg);
+		val += offset_val;
+		snd_soc_component_write(component, gain_reg, val);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+					w->reg, 0x20, 0x00);
+		lpass_cdc_wsa2_macro_enable_swr(w, kcontrol, event);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_config_compander(struct snd_soc_component *component,
+				int comp, int event)
+{
+	u16 comp_ctl0_reg, comp_ctl8_reg, rx_path_cfg0_reg;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct lpass_cdc_comp_setting *comp_settings = NULL;
+	u16 mode = 0;
+	u16 index = 0;
+	int sys_gain, bat_cfg, sys_gain_int, upper_gain, lower_gain;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
+		__func__, event, comp + 1, wsa2_priv->comp_enabled[comp]);
+
+	if (comp >= LPASS_CDC_WSA2_MACRO_COMP_MAX || comp < 0) {
+		dev_err(component->dev, "%s: Invalid compander value: %d\n",
+							__func__, comp);
+		return -EINVAL;
+	}
+
+	if (!wsa2_priv->comp_enabled[comp])
+		return 0;
+
+	mode = wsa2_priv->comp_mode[comp];
+	if (mode >= G_MAX_DB || mode < 0)
+		mode = 0;
+	comp_ctl0_reg = LPASS_CDC_WSA2_COMPANDER0_CTL0 +
+					(comp * LPASS_CDC_WSA2_MACRO_RX_COMP_OFFSET);
+	comp_ctl8_reg = LPASS_CDC_WSA2_COMPANDER0_CTL8 +
+					(comp * LPASS_CDC_WSA2_MACRO_RX_COMP_OFFSET);
+	rx_path_cfg0_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG0 +
+					(comp * LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET);
+	comp_settings = &comp_setting_table[mode];
+
+	/* If System has battery configuration */
+	if (wsa2_priv->wsa2_bat_cfg[comp]) {
+		index = (comp * 2) + wsa2_priv->wsa2_spkrrecv;
+		if (index >= (2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1))) {
+			dev_err(component->dev, "%s: Invalid index: %d\n",
+					__func__, index);
+			return -EINVAL;
+		}
+		sys_gain = wsa2_priv->wsa2_sys_gain[index];
+		bat_cfg = wsa2_priv->wsa2_bat_cfg[comp];
+		/* Convert enum to value and
+		 * multiply all values by 10 to avoid float
+		 */
+		sys_gain_int = -15 * sys_gain + 210;
+		switch (bat_cfg) {
+		case CONFIG_1S:
+		case EXT_1S:
+			if (sys_gain > G_13P5_DB) {
+				upper_gain = sys_gain_int + 60;
+				lower_gain = 0;
+			} else {
+				upper_gain = 210;
+				lower_gain = 0;
+			}
+			break;
+		case CONFIG_3S:
+		case EXT_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 75;
+			break;
+		case EXT_ABOVE_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 120;
+			break;
+		default:
+			upper_gain = sys_gain_int;
+			lower_gain = 0;
+			break;
+		}
+		/* Truncate after calculation */
+		comp_settings->lower_gain_int = (lower_gain * 2) / 10;
+		comp_settings->upper_gain_int = (upper_gain * 2) / 10;
+	}
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		lpass_cdc_update_compander_setting(component,
+					comp_ctl8_reg,
+					comp_settings);
+		/* Enable Compander Clock */
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x02);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x04);
+		snd_soc_component_update_bits(component, rx_path_cfg0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x02, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x01, 0x00);
+		snd_soc_component_update_bits(component, comp_ctl0_reg,
+						0x04, 0x00);
+	}
+
+	return 0;
+}
+
+static void lpass_cdc_wsa2_macro_enable_softclip_clk(struct snd_soc_component *component,
+					 struct lpass_cdc_wsa2_macro_priv *wsa2_priv,
+					 int path,
+					 bool enable)
+{
+	u16 softclip_clk_reg = LPASS_CDC_WSA2_SOFTCLIP0_CRC +
+			(path * LPASS_CDC_WSA2_MACRO_RX_SOFTCLIP_OFFSET);
+	u8 softclip_mux_mask = (1 << path);
+	u8 softclip_mux_value = (1 << path);
+
+	dev_dbg(component->dev, "%s: path %d, enable %d\n",
+		__func__, path, enable);
+	if (enable) {
+		if (wsa2_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, softclip_mux_value);
+		}
+		wsa2_priv->softclip_clk_users[path]++;
+	} else {
+		wsa2_priv->softclip_clk_users[path]--;
+		if (wsa2_priv->softclip_clk_users[path] == 0) {
+			snd_soc_component_update_bits(component,
+				softclip_clk_reg, 0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, 0x00);
+		}
+	}
+}
+
+static int lpass_cdc_wsa2_macro_config_softclip(struct snd_soc_component *component,
+				int path, int event)
+{
+	u16 softclip_ctrl_reg = 0;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (path == LPASS_CDC_WSA2_MACRO_COMP1)
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP0;
+	else if (path == LPASS_CDC_WSA2_MACRO_COMP2)
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP1;
+
+	dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n",
+		__func__, event, softclip_path,
+		wsa2_priv->is_softclip_on[softclip_path]);
+
+	if (!wsa2_priv->is_softclip_on[softclip_path])
+		return 0;
+
+	softclip_ctrl_reg = LPASS_CDC_WSA2_SOFTCLIP0_SOFTCLIP_CTRL +
+				(softclip_path * LPASS_CDC_WSA2_MACRO_RX_SOFTCLIP_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock and mux */
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+				softclip_path, true);
+		/* Enable Softclip control */
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, softclip_ctrl_reg,
+				0x01, 0x00);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+				softclip_path, false);
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_was_macro_config_pbr(struct snd_soc_component *component,
+					  int path, int event)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 reg1 = 0, reg2 = 0, reg3 = 0;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (path == LPASS_CDC_WSA2_MACRO_COMP1) {
+		reg1 = LPASS_CDC_WSA2_COMPANDER0_CTL0;
+		reg2 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP0;
+	} else if (path == LPASS_CDC_WSA2_MACRO_COMP2) {
+		reg1 = LPASS_CDC_WSA2_COMPANDER1_CTL0;
+		reg2 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP1;
+	}
+	if (!wsa2_priv->pbr_enable || wsa2_priv->wsa2_bat_cfg[path] >= EXT_1S ||
+	    wsa2_priv->wsa2_sys_gain[path * 2] > G_12_DB ||
+	    wsa2_priv->wsa2_spkrrecv || !reg1 || !reg2 || !reg3)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x40);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x80);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+					softclip_path, true);
+		if (wsa2_priv->pbr_clk_users == 0)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_PBR_PATH_CTL,
+				0x01, 0x01);
+		++wsa2_priv->pbr_clk_users;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		if (wsa2_priv->pbr_clk_users)
+			snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_PBR_PATH_CTL,
+				0x01, 0x00);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+					softclip_path, false);
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x00);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x00);
+		--wsa2_priv->pbr_clk_users;
+		if (wsa2_priv->pbr_clk_users < 0)
+			wsa2_priv->pbr_clk_users = 0;
+	}
+	return 0;
+}
+
+static bool lpass_cdc_wsa2_macro_adie_lb(struct snd_soc_component *component,
+			      int interp_idx)
+{
+	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
+	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
+
+	int_mux_cfg0 = LPASS_CDC_WSA2_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;
+	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;
+	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;
+	if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
+		int_n_inp2 == INTn_1_INP_SEL_DEC1)
+		return true;
+
+	return false;
+}
+
+static int lpass_cdc_wsa2_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 reg = 0;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	bool adie_lb = false;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	reg = LPASS_CDC_WSA2_RX0_RX_PATH_CTL +
+			LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET * w->shift;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, reg, 0x40, 0x40);
+		usleep_range(500, 510);
+		snd_soc_component_update_bits(component, reg, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+					reg, 0x20, 0x20);
+		if (lpass_cdc_wsa2_macro_adie_lb(component, w->shift)) {
+			adie_lb = true;
+			lpass_cdc_wsa_pa_on(wsa2_dev, adie_lb);
+			snd_soc_component_update_bits(component,
+						reg, 0x10, 0x00);
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_interp_get_primary_reg(u16 reg, u16 *ind)
+{
+	u16 prim_int_reg = 0;
+
+	switch (reg) {
+	case LPASS_CDC_WSA2_RX0_RX_PATH_CTL:
+	case LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL:
+		prim_int_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CTL;
+		*ind = 0;
+		break;
+	case LPASS_CDC_WSA2_RX1_RX_PATH_CTL:
+	case LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CTL:
+		prim_int_reg = LPASS_CDC_WSA2_RX1_RX_PATH_CTL;
+		*ind = 1;
+		break;
+	}
+
+	return prim_int_reg;
+}
+
+static int lpass_cdc_wsa2_macro_enable_prim_interpolator(
+				struct snd_soc_component *component,
+				u16 reg, int event)
+{
+	u16 prim_int_reg;
+	u16 ind = 0;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	prim_int_reg = lpass_cdc_wsa2_macro_interp_get_primary_reg(reg, &ind);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wsa2_priv->prim_int_users[ind]++;
+		if (wsa2_priv->prim_int_users[ind] == 1) {
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA2_MACRO_RX_PATH_CFG3_OFFSET,
+				0x03, 0x03);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					    0x10, 0x10);
+			lpass_cdc_wsa2_macro_hd2_control(component, prim_int_reg, event);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA2_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x1);
+		}
+		if ((reg != prim_int_reg) &&
+		    ((snd_soc_component_read(
+				component, prim_int_reg)) & 0x10))
+			snd_soc_component_update_bits(component, reg,
+					0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wsa2_priv->prim_int_users[ind]--;
+		if (wsa2_priv->prim_int_users[ind] == 0) {
+			snd_soc_component_update_bits(component, prim_int_reg,
+					1 << 0x5, 0 << 0x5);
+			snd_soc_component_update_bits(component,
+				prim_int_reg + LPASS_CDC_WSA2_MACRO_RX_PATH_DSMDEM_OFFSET,
+				0x1, 0x0);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x40);
+			snd_soc_component_update_bits(component, prim_int_reg,
+					0x40, 0x00);
+			lpass_cdc_wsa2_macro_hd2_control(component, prim_int_reg, event);
+		}
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n",
+		__func__, ind, wsa2_priv->prim_int_users[ind]);
+	return 0;
+}
+
+static void lpass_cdc_macro_idle_detect_control(struct snd_soc_component *component,
+					 struct lpass_cdc_wsa2_macro_priv *wsa2_priv,
+					 int interp, int event)
+{
+	int reg = 0, mask = 0, val = 0, source_reg = 0;
+	u16 mode = 0;
+
+	dev_dbg(component->dev, "%s: Idle_detect_en value: %d\n", __func__,
+		wsa2_priv->idle_detect_en);
+
+	if (!wsa2_priv->idle_detect_en)
+		return;
+
+	if (interp == LPASS_CDC_WSA2_MACRO_COMP1) {
+		source_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == LPASS_CDC_WSA2_MACRO_COMP2) {
+		source_reg = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	mode = wsa2_priv->comp_mode[interp];
+
+	if ((wsa2_priv->noise_gate_mode == NG2 && mode >= G_13P5_DB) ||
+			wsa2_priv->noise_gate_mode == IDLE_DETECT || !wsa2_priv->pbr_enable ||
+			wsa2_priv->wsa2_spkrrecv) {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x00);
+		dev_dbg(component->dev, "%s: Idle detect source: Legacy\n", __func__);
+	} else {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x80);
+		dev_dbg(component->dev, "%s: Idle detect source: PRE-LA\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, reg, mask, val);
+		dev_dbg(component->dev, "%s: Idle detect clks ON\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		snd_soc_component_write(component,
+				LPASS_CDC_WSA2_IDLE_DETECT_CFG3, 0x0);
+		dev_dbg(component->dev, "%s: Idle detect clks OFF\n", __func__);
+	}
+}
+
+static int lpass_cdc_wsa2_macro_enable_interpolator(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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u8 gain = 0;
+	u16 reg = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
+
+	if (!(strcmp(w->name, "WSA2_RX INT0 INTERP"))) {
+		reg = LPASS_CDC_WSA2_RX0_RX_PATH_CTL;
+	} else if (!(strcmp(w->name, "WSA2_RX INT1 INTERP"))) {
+		reg = LPASS_CDC_WSA2_RX1_RX_PATH_CTL;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: Interpolator reg not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Reset if needed */
+		lpass_cdc_wsa2_macro_enable_prim_interpolator(component, reg, event);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (!strcmp(w->name, "WSA2_RX INT0 INTERP")) {
+			gain = (u8)(wsa2_priv->rx0_origin_gain -
+					wsa2_priv->thermal_cur_state);
+			if (snd_soc_component_read(wsa2_priv->component,
+					 LPASS_CDC_WSA2_RX0_RX_VOL_CTL) != gain) {
+				snd_soc_component_update_bits(wsa2_priv->component,
+					LPASS_CDC_WSA2_RX0_RX_VOL_CTL, 0xFF, gain);
+				dev_dbg(wsa2_priv->dev,
+					"%s: RX0 current thermal state: %d, "
+					"adjusted gain: %#x\n",
+					__func__, wsa2_priv->thermal_cur_state, gain);
+			}
+		}
+
+		if (!strcmp(w->name, "WSA2_RX INT1 INTERP")) {
+			gain = (u8)(wsa2_priv->rx1_origin_gain -
+					wsa2_priv->thermal_cur_state);
+			if (snd_soc_component_read(wsa2_priv->component,
+					 LPASS_CDC_WSA2_RX1_RX_VOL_CTL) != gain) {
+				snd_soc_component_update_bits(wsa2_priv->component,
+					LPASS_CDC_WSA2_RX1_RX_VOL_CTL, 0xFF, gain);
+				dev_dbg(wsa2_priv->dev,
+					"%s: RX1 current thermal state: %d, "
+					"adjusted gain: %#x\n",
+					__func__, wsa2_priv->thermal_cur_state, gain);
+			}
+		}
+
+		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
+				w->shift, event);
+		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
+		if (wsa2_priv->wsa2_spkrrecv)
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_WSA2_RX0_RX_PATH_CFG1,
+					0x08, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08);
+		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
+				w->shift, event);
+		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
+		lpass_cdc_wsa2_macro_enable_prim_interpolator(component, reg, event);
+		break;
+	}
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_spk_boost_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);
+	u16 boost_path_ctl, boost_path_cfg1;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+
+	if (!strcmp(w->name, "WSA2_RX INT0 CHAIN")) {
+		boost_path_ctl = LPASS_CDC_WSA2_BOOST0_BOOST_PATH_CTL;
+		boost_path_cfg1 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG1;
+	} else if (!strcmp(w->name, "WSA2_RX INT1 CHAIN")) {
+		boost_path_ctl = LPASS_CDC_WSA2_BOOST1_BOOST_PATH_CTL;
+		boost_path_cfg1 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG1;
+	} else {
+		dev_err_ratelimited(component->dev, "%s: unknown widget: %s\n",
+			__func__, w->name);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x01);
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, boost_path_ctl,
+						0x10, 0x00);
+		snd_soc_component_update_bits(component, boost_path_cfg1,
+						0x01, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int lpass_cdc_wsa2_macro_enable_vbat(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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 vbat_path_cfg = 0;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!strcmp(w->name, "WSA2_RX INT0 VBAT")) {
+		vbat_path_cfg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP0;
+	} else if (!strcmp(w->name, "WSA2_RX INT1 VBAT")) {
+		vbat_path_cfg = LPASS_CDC_WSA2_RX1_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP1;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x80);
+		/* Use attenuation mode */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG, 0x02, 0x00);
+		/*
+		 * BCL block needs softclip clock and mux config to be enabled
+		 */
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+					softclip_path, true);
+		/* Enable VBAT at channel level */
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+				0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		/* Enable CB decode block clock */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
+		/* Enable BCL path */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
+		/* Request for BCL data */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x80, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG,
+			0x02, 0x02);
+		snd_soc_component_update_bits(component, vbat_path_cfg,
+			0x02, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+			softclip_path, false);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err_ratelimited(wsa2_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 val, ec_tx = 0, ec_hq_reg;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa2_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_component_read(component,
+				LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0);
+	if (!(strcmp(w->name, "WSA2 RX_MIX EC0_MUX")))
+		ec_tx = (val & 0x07) - 1;
+	else
+		ec_tx = ((val & 0x38) >> 0x3) - 1;
+
+	if (ec_tx < 0 || ec_tx >= (LPASS_CDC_WSA2_MACRO_RX1 + 1)) {
+		dev_err_ratelimited(wsa2_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (wsa2_priv->ec_hq[ec_tx]) {
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX_INP_MUX_RX_MIX_CFG0,
+				0x1 << ec_tx, 0x1 << ec_tx);
+		ec_hq_reg = LPASS_CDC_WSA2_EC_HQ0_EC_REF_HQ_PATH_CTL +
+							0x40 * ec_tx;
+		snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
+		ec_hq_reg = LPASS_CDC_WSA2_EC_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 int lpass_cdc_wsa2_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->ec_hq[ec_tx];
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa2_dev, "%s: enable current %d, new %d\n",
+		__func__, wsa2_priv->ec_hq[ec_tx], value);
+	wsa2_priv->ec_hq[ec_tx] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_get_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int wsa2_rx_shift = ((struct soc_multi_mixer_control *)
+		       kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+		wsa2_priv->wsa2_digital_mute_status[wsa2_rx_shift];
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int value = ucontrol->value.integer.value[0];
+	int wsa2_rx_shift = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	pm_runtime_get_sync(wsa2_priv->dev);
+	switch (wsa2_rx_shift) {
+	case 0:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX0_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 1:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX1_RX_PATH_CTL,
+				0x10, value << 4);
+		break;
+	case 2:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	case 3:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CTL,
+				0x10, value << 4);
+		break;
+	default:
+		pr_err_ratelimited("%s: invalid argument rx_shift = %d\n", __func__,
+			wsa2_rx_shift);
+		ret = -EINVAL;
+	}
+	pm_runtime_mark_last_busy(wsa2_priv->dev);
+	pm_runtime_put_autosuspend(wsa2_priv->dev);
+
+	dev_dbg(component->dev, "%s: WSA2 Digital Mute RX %d Enable %d\n",
+		__func__, wsa2_rx_shift, value);
+	wsa2_priv->wsa2_digital_mute_status[wsa2_rx_shift] = value;
+
+	return ret;
+}
+
+static int lpass_cdc_wsa2_macro_set_digital_volume(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct soc_mixer_control *mc =
+			(struct soc_mixer_control *)kcontrol->private_value;
+	u8 gain = 0;
+	int ret = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (!wsa2_priv) {
+		pr_err_ratelimited("%s: priv is null for macro!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+	if (mc->reg == LPASS_CDC_WSA2_RX0_RX_VOL_CTL) {
+		wsa2_priv->rx0_origin_gain =
+			(u8)snd_soc_component_read(wsa2_priv->component,
+							mc->reg);
+		gain = (u8)(wsa2_priv->rx0_origin_gain -
+				wsa2_priv->thermal_cur_state);
+	} else if (mc->reg == LPASS_CDC_WSA2_RX1_RX_VOL_CTL) {
+		wsa2_priv->rx1_origin_gain =
+			(u8)snd_soc_component_read(wsa2_priv->component,
+							mc->reg);
+		gain = (u8)(wsa2_priv->rx1_origin_gain -
+				wsa2_priv->thermal_cur_state);
+	} else {
+		dev_err_ratelimited(wsa2_priv->dev,
+			"%s: Incorrect RX Path selected\n", __func__);
+		return -EINVAL;
+	}
+
+	/* only adjust gain if thermal state is positive */
+	if (wsa2_priv->dapm_mclk_enable &&
+	    wsa2_priv->thermal_cur_state > 0) {
+		snd_soc_component_update_bits(wsa2_priv->component,
+			mc->reg, 0xFF, gain);
+		dev_dbg(wsa2_priv->dev,
+			"%s: Current thermal state: %d, adjusted gain: %x\n",
+			__func__, wsa2_priv->thermal_cur_state, gain);
+	}
+
+	return ret;
+}
+
+static int lpass_cdc_wsa2_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->comp_enabled[comp];
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n",
+		__func__, comp + 1, wsa2_priv->comp_enabled[comp], value);
+	wsa2_priv->comp_enabled[comp] = value;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->wsa2_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->wsa2_spkrrecv = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+		__func__, wsa2_priv->wsa2_spkrrecv);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_idle_detect_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct device *wsa2_dev = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->idle_detect_en;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_idle_detect_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct device *wsa2_dev = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->idle_detect_en = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 idx = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (strnstr(kcontrol->id.name, "RX0", sizeof("WSA2_RX0")))
+		idx = LPASS_CDC_WSA2_MACRO_COMP1;
+	if (strnstr(kcontrol->id.name, "RX1", sizeof("WSA2_RX1")))
+		idx = LPASS_CDC_WSA2_MACRO_COMP2;
+	ucontrol->value.integer.value[0] = wsa2_priv->comp_mode[idx];
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_comp_mode_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 idx = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (strnstr(kcontrol->id.name, "RX0", sizeof("WSA2_RX0")))
+		idx = LPASS_CDC_WSA2_MACRO_COMP1;
+	if (strnstr(kcontrol->id.name, "RX1", sizeof("WSA2_RX1")))
+		idx = LPASS_CDC_WSA2_MACRO_COMP2;
+
+	if (ucontrol->value.integer.value[0] < G_MAX_DB &&
+						ucontrol->value.integer.value[0] >= 0)
+		wsa2_priv->comp_mode[idx] =  ucontrol->value.integer.value[0];
+	else
+		return 0;
+
+	dev_dbg(component->dev, "%s: comp_mode = %d\n", __func__,
+		wsa2_priv->comp_mode[idx]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_rx_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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			wsa2_priv->rx_port_value[widget->shift];
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_rx_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 bit_input = 0;
+	u32 aif_rst;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	aif_rst = wsa2_priv->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err_ratelimited(wsa2_dev, "%s: AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst >= LPASS_CDC_WSA2_MACRO_MAX_DAIS) {
+			dev_err_ratelimited(wsa2_dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	wsa2_priv->rx_port_value[widget->shift] = rx_port_value;
+
+	bit_input = widget->shift;
+
+	dev_dbg(wsa2_dev,
+		"%s: mux input: %d, mux output: %d, bit: %d\n",
+		__func__, rx_port_value, widget->shift, bit_input);
+
+	switch (rx_port_value) {
+	case 0:
+		if (wsa2_priv->active_ch_cnt[aif_rst]) {
+			clear_bit(bit_input,
+				  &wsa2_priv->active_ch_mask[aif_rst]);
+			wsa2_priv->active_ch_cnt[aif_rst]--;
+		}
+		break;
+	case 1:
+	case 2:
+		set_bit(bit_input,
+			&wsa2_priv->active_ch_mask[rx_port_value]);
+		wsa2_priv->active_ch_cnt[rx_port_value]++;
+		break;
+	default:
+		dev_err_ratelimited(wsa2_dev,
+			"%s: Invalid AIF_ID for WSA2 RX MUX %d\n",
+			__func__, rx_port_value);
+		return -EINVAL;
+	}
+
+	snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+					rx_port_value, e, update);
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+	    ((snd_soc_component_read(
+		component, LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG) & 0x04) ?
+	    1 : 0);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+
+	dev_dbg(component->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG,
+			0x04, 0x04);
+	else
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_VBAT_BCL_VBAT_CFG,
+			0x04, 0x00);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->is_softclip_on[path];
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_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 device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->is_softclip_on[path] =  ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__,
+		path, wsa2_priv->is_softclip_on[path]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_pbr_enable_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->pbr_enable;
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_pbr_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->pbr_enable = ucontrol->value.integer.value[0];
+	return 0;
+
+}
+
+static int lpass_cdc_wsa2_macro_2ch_dma_enable_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->wsa2_2ch_dma_enable;
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_2ch_dma_enable_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->wsa2_2ch_dma_enable = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
+	SOC_ENUM_EXT("WSA2_GSM mode Enable", lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
+		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_get,
+		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_ENUM_EXT("WSA2_RX0 comp_mode", lpass_cdc_wsa2_macro_comp_mode_enum,
+		     lpass_cdc_wsa2_macro_comp_mode_get,
+		     lpass_cdc_wsa2_macro_comp_mode_put),
+	SOC_ENUM_EXT("WSA2_RX1 comp_mode", lpass_cdc_wsa2_macro_comp_mode_enum,
+		     lpass_cdc_wsa2_macro_comp_mode_get,
+		     lpass_cdc_wsa2_macro_comp_mode_put),
+	SOC_SINGLE_EXT("WSA2 SPKRRECV", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_get,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_put),
+	SOC_SINGLE_EXT("WSA2 Idle Detect", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa2_macro_idle_detect_get,
+			lpass_cdc_wsa2_macro_idle_detect_put),
+	SOC_SINGLE_EXT("WSA2_Softclip0 Enable", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_SOFTCLIP0, 1, 0,
+			lpass_cdc_wsa2_macro_soft_clip_enable_get,
+			lpass_cdc_wsa2_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("WSA2_Softclip1 Enable", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_SOFTCLIP1, 1, 0,
+			lpass_cdc_wsa2_macro_soft_clip_enable_get,
+			lpass_cdc_wsa2_macro_soft_clip_enable_put),
+	LPASS_CDC_WSA2_MACRO_SET_VOLUME_TLV("WSA2_RX0 Digital Volume",
+					   LPASS_CDC_WSA2_RX0_RX_VOL_CTL,
+					   -84, 40, digital_gain),
+	LPASS_CDC_WSA2_MACRO_SET_VOLUME_TLV("WSA2_RX1 Digital Volume",
+					   LPASS_CDC_WSA2_RX1_RX_VOL_CTL,
+					   -84, 40, digital_gain),
+	SOC_SINGLE_EXT("WSA2_RX0 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX0, 1,
+			0, lpass_cdc_wsa2_macro_get_rx_mute_status,
+			lpass_cdc_wsa2_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA2_RX1 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX1, 1,
+			0, lpass_cdc_wsa2_macro_get_rx_mute_status,
+			lpass_cdc_wsa2_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA2_RX0_MIX Digital Mute", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_RX_MIX0, 1, 0, lpass_cdc_wsa2_macro_get_rx_mute_status,
+			lpass_cdc_wsa2_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA2_RX1_MIX Digital Mute", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_RX_MIX1, 1, 0, lpass_cdc_wsa2_macro_get_rx_mute_status,
+			lpass_cdc_wsa2_macro_set_rx_mute_status),
+	SOC_SINGLE_EXT("WSA2_COMP1 Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_COMP1, 1, 0,
+		lpass_cdc_wsa2_macro_get_compander, lpass_cdc_wsa2_macro_set_compander),
+	SOC_SINGLE_EXT("WSA2_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_COMP2, 1, 0,
+		lpass_cdc_wsa2_macro_get_compander, lpass_cdc_wsa2_macro_set_compander),
+	SOC_SINGLE_EXT("WSA2_RX0 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX0,
+			1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA2_RX1 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX1,
+			1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA2 PBR Enable", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa2_macro_pbr_enable_get,
+			lpass_cdc_wsa2_macro_pbr_enable_put),
+	SOC_SINGLE_EXT("WSA2 2CH_DMA ENABLE", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa2_macro_2ch_dma_enable_get,
+			lpass_cdc_wsa2_macro_2ch_dma_enable_put),
+};
+
+static const struct soc_enum rx_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text);
+
+static const struct snd_kcontrol_new rx_mux[LPASS_CDC_WSA2_MACRO_RX_MAX] = {
+	SOC_DAPM_ENUM_EXT("WSA2 RX0 Mux", rx_mux_enum,
+			  lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA2 RX1 Mux", rx_mux_enum,
+			  lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA2 RX_MIX0 Mux", rx_mux_enum,
+			  lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA2 RX_MIX1 Mux", rx_mux_enum,
+			  lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA2 RX4 Mux", rx_mux_enum,
+			lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("WSA2 RX5 Mux", rx_mux_enum,
+			lpass_cdc_wsa2_macro_rx_mux_get, lpass_cdc_wsa2_macro_rx_mux_put),
+};
+
+static int lpass_cdc_wsa2_macro_vi_feed_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa2_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_vi_feed_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 soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->vi_feed_value = ucontrol->value.integer.value[0];
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_VI]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_VI]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_VI]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_VI]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_VI]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_vi_mixer[] = {
+	SOC_SINGLE_EXT("WSA2_SPKR_VI_1", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa2_macro_vi_feed_mixer_get,
+			lpass_cdc_wsa2_macro_vi_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA2_SPKR_VI_2", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa2_macro_vi_feed_mixer_get,
+			lpass_cdc_wsa2_macro_vi_feed_mixer_put),
+};
+
+static int lpass_cdc_wsa2_macro_cps_feed_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_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa2_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_cps_feed_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 soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_cps_mixer[] = {
+	SOC_SINGLE_EXT("WSA2_SPKR_CPS_1", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA2_SPKR_CPS_2", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget lpass_cdc_wsa2_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("WSA2 AIF1 PB", "WSA2_AIF1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("WSA2 AIF_MIX1 PB", "WSA2_AIF_MIX1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT_E("WSA2 AIF_VI", "WSA2_AIF_VI Capture", 0,
+		SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_AIF_VI, 0,
+		lpass_cdc_wsa2_macro_disable_vi_feedback,
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT("WSA2 AIF_ECHO", "WSA2_AIF_ECHO Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT("WSA2 AIF_CPS", "WSA2_AIF_CPS Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MIXER("WSA2_AIF_VI Mixer", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_AIF_VI,
+		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MIXER("WSA2_AIF_CPS Mixer", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_AIF_CPS,
+		0, aif_cps_mixer, ARRAY_SIZE(aif_cps_mixer)),
+	SND_SOC_DAPM_MUX_E("WSA2 RX_MIX EC0_MUX", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_EC0_MUX, 0,
+			&rx_mix_ec0_mux, lpass_cdc_wsa2_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2 RX_MIX EC1_MUX", SND_SOC_NOPM,
+			LPASS_CDC_WSA2_MACRO_EC1_MUX, 0,
+			&rx_mix_ec1_mux, lpass_cdc_wsa2_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("WSA2 RX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX0, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX0]),
+	SND_SOC_DAPM_MUX("WSA2 RX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX1, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX1]),
+	SND_SOC_DAPM_MUX("WSA2 RX_MIX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX_MIX0, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX_MIX0]),
+	SND_SOC_DAPM_MUX("WSA2 RX_MIX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX_MIX1, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX_MIX1]),
+	SND_SOC_DAPM_MUX("WSA2 RX4 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX4, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX4]),
+	SND_SOC_DAPM_MUX("WSA2 RX5 MUX", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX5, 0,
+				&rx_mux[LPASS_CDC_WSA2_MACRO_RX5]),
+
+	SND_SOC_DAPM_MIXER("WSA2 RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2 RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2 RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2 RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2 RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2 RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("WSA2_RX0 INP0", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp0_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX0 INP1", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp1_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX0 INP2", SND_SOC_NOPM, 0, 0,
+		&rx0_prim_inp2_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX0 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx0_mix_mux, lpass_cdc_wsa2_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX1 INP0", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp0_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp1_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_prim_inp2_mux, lpass_cdc_wsa2_macro_enable_swr,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA2_RX1 MIX INP", SND_SOC_NOPM,
+		0, 0, &rx1_mix_mux, lpass_cdc_wsa2_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("WSA2_RX INT0 MIX", SND_SOC_NOPM,
+			0, 0, NULL, 0, lpass_cdc_wsa2_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_PGA_E("WSA2_RX INT1 MIX", SND_SOC_NOPM,
+			1, 0, NULL, 0, lpass_cdc_wsa2_macro_enable_main_path,
+			SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER("WSA2_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("WSA2_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("WSA2_RX0 INT0 SIDETONE MIX",
+			   LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 4, 0,
+			   &rx0_sidetone_mix_mux, lpass_cdc_wsa2_macro_enable_swr,
+			  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_INPUT("WSA2 SRC0_INP"),
+
+	SND_SOC_DAPM_INPUT("WSA2_TX DEC0_INP"),
+	SND_SOC_DAPM_INPUT("WSA2_TX DEC1_INP"),
+
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT0 INTERP", SND_SOC_NOPM,
+		LPASS_CDC_WSA2_MACRO_COMP1, 0, NULL, 0, lpass_cdc_wsa2_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT1 INTERP", SND_SOC_NOPM,
+		LPASS_CDC_WSA2_MACRO_COMP2, 0, NULL, 0, lpass_cdc_wsa2_macro_enable_interpolator,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, lpass_cdc_wsa2_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0,
+		NULL, 0, lpass_cdc_wsa2_macro_spk_boost_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT0 VBAT", SND_SOC_NOPM,
+		0, 0, wsa2_int0_vbat_mix_switch,
+		ARRAY_SIZE(wsa2_int0_vbat_mix_switch),
+		lpass_cdc_wsa2_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA2_RX INT1 VBAT", SND_SOC_NOPM,
+		0, 0, wsa2_int1_vbat_mix_switch,
+		ARRAY_SIZE(wsa2_int1_vbat_mix_switch),
+		lpass_cdc_wsa2_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("VIINPUT_WSA2"),
+
+	SND_SOC_DAPM_INPUT("CPSINPUT_WSA2"),
+
+	SND_SOC_DAPM_OUTPUT("WSA2_SPK1 OUT"),
+	SND_SOC_DAPM_OUTPUT("WSA2_SPK2 OUT"),
+
+	SND_SOC_DAPM_SUPPLY_S("WSA2_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	lpass_cdc_wsa2_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route wsa2_audio_map[] = {
+	/* VI Feedback */
+	{"WSA2_AIF_VI Mixer", "WSA2_SPKR_VI_1", "VIINPUT_WSA2"},
+	{"WSA2_AIF_VI Mixer", "WSA2_SPKR_VI_2", "VIINPUT_WSA2"},
+	{"WSA2 AIF_VI", NULL, "WSA2_AIF_VI Mixer"},
+	{"WSA2 AIF_VI", NULL, "WSA2_MCLK"},
+
+	/* VI Feedback */
+	{"WSA2_AIF_CPS Mixer", "WSA2_SPKR_CPS_1", "CPSINPUT_WSA2"},
+	{"WSA2_AIF_CPS Mixer", "WSA2_SPKR_CPS_2", "CPSINPUT_WSA2"},
+	{"WSA2 AIF_CPS", NULL, "WSA2_AIF_CPS Mixer"},
+	{"WSA2 AIF_CPS", NULL, "WSA2_MCLK"},
+
+	{"WSA2 RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA2_RX INT0 SEC MIX"},
+	{"WSA2 RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA2_RX INT0 SEC MIX"},
+	{"WSA2 RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA2_RX INT1 SEC MIX"},
+	{"WSA2 RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA2_RX INT1 SEC MIX"},
+	{"WSA2 AIF_ECHO", NULL, "WSA2 RX_MIX EC0_MUX"},
+	{"WSA2 AIF_ECHO", NULL, "WSA2 RX_MIX EC1_MUX"},
+	{"WSA2 AIF_ECHO", NULL, "WSA2_MCLK"},
+
+	{"WSA2 AIF1 PB", NULL, "WSA2_MCLK"},
+	{"WSA2 AIF_MIX1 PB", NULL, "WSA2_MCLK"},
+
+	{"WSA2 RX0 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+	{"WSA2 RX1 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+	{"WSA2 RX_MIX0 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+	{"WSA2 RX_MIX1 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+	{"WSA2 RX4 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+	{"WSA2 RX5 MUX", "AIF1_PB", "WSA2 AIF1 PB"},
+
+	{"WSA2 RX0 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+	{"WSA2 RX1 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+	{"WSA2 RX_MIX0 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+	{"WSA2 RX_MIX1 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+	{"WSA2 RX4 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+	{"WSA2 RX5 MUX", "AIF_MIX1_PB", "WSA2 AIF_MIX1 PB"},
+
+	{"WSA2 RX0", NULL, "WSA2 RX0 MUX"},
+	{"WSA2 RX1", NULL, "WSA2 RX1 MUX"},
+	{"WSA2 RX_MIX0", NULL, "WSA2 RX_MIX0 MUX"},
+	{"WSA2 RX_MIX1", NULL, "WSA2 RX_MIX1 MUX"},
+	{"WSA2 RX4", NULL, "WSA2 RX4 MUX"},
+	{"WSA2 RX5", NULL, "WSA2 RX5 MUX"},
+
+	{"WSA2_RX0 INP0", "RX0", "WSA2 RX0"},
+	{"WSA2_RX0 INP0", "RX1", "WSA2 RX1"},
+	{"WSA2_RX0 INP0", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX0 INP0", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX0 INP0", "RX4", "WSA2 RX4"},
+	{"WSA2_RX0 INP0", "RX5", "WSA2 RX5"},
+	{"WSA2_RX0 INP0", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX0 INP0", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT0 MIX", NULL, "WSA2_RX0 INP0"},
+
+	{"WSA2_RX0 INP1", "RX0", "WSA2 RX0"},
+	{"WSA2_RX0 INP1", "RX1", "WSA2 RX1"},
+	{"WSA2_RX0 INP1", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX0 INP1", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX0 INP1", "RX4", "WSA2 RX4"},
+	{"WSA2_RX0 INP1", "RX5", "WSA2 RX5"},
+	{"WSA2_RX0 INP1", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX0 INP1", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT0 MIX", NULL, "WSA2_RX0 INP1"},
+
+	{"WSA2_RX0 INP2", "RX0", "WSA2 RX0"},
+	{"WSA2_RX0 INP2", "RX1", "WSA2 RX1"},
+	{"WSA2_RX0 INP2", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX0 INP2", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX0 INP2", "RX4", "WSA2 RX4"},
+	{"WSA2_RX0 INP2", "RX5", "WSA2 RX5"},
+	{"WSA2_RX0 INP2", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX0 INP2", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT0 MIX", NULL, "WSA2_RX0 INP2"},
+
+	{"WSA2_RX0 MIX INP", "RX0", "WSA2 RX0"},
+	{"WSA2_RX0 MIX INP", "RX1", "WSA2 RX1"},
+	{"WSA2_RX0 MIX INP", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX0 MIX INP", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX0 MIX INP", "RX4", "WSA2 RX4"},
+	{"WSA2_RX0 MIX INP", "RX5", "WSA2 RX5"},
+	{"WSA2_RX INT0 SEC MIX", NULL, "WSA2_RX0 MIX INP"},
+
+	{"WSA2_RX INT0 SEC MIX", NULL, "WSA2_RX INT0 MIX"},
+	{"WSA2_RX INT0 INTERP", NULL, "WSA2_RX INT0 SEC MIX"},
+	{"WSA2_RX0 INT0 SIDETONE MIX", "SRC0", "WSA2 SRC0_INP"},
+	{"WSA2_RX INT0 INTERP", NULL, "WSA2_RX0 INT0 SIDETONE MIX"},
+	{"WSA2_RX INT0 CHAIN", NULL, "WSA2_RX INT0 INTERP"},
+
+	{"WSA2_RX INT0 VBAT", "WSA2 RX0 VBAT Enable", "WSA2_RX INT0 INTERP"},
+	{"WSA2_RX INT0 CHAIN", NULL, "WSA2_RX INT0 VBAT"},
+
+	{"WSA2_SPK1 OUT", NULL, "WSA2_RX INT0 CHAIN"},
+	{"WSA2_SPK1 OUT", NULL, "WSA2_MCLK"},
+
+	{"WSA2_RX1 INP0", "RX0", "WSA2 RX0"},
+	{"WSA2_RX1 INP0", "RX1", "WSA2 RX1"},
+	{"WSA2_RX1 INP0", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX1 INP0", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX1 INP0", "RX4", "WSA2 RX4"},
+	{"WSA2_RX1 INP0", "RX5", "WSA2 RX5"},
+	{"WSA2_RX1 INP0", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX1 INP0", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT1 MIX", NULL, "WSA2_RX1 INP0"},
+
+	{"WSA2_RX1 INP1", "RX0", "WSA2 RX0"},
+	{"WSA2_RX1 INP1", "RX1", "WSA2 RX1"},
+	{"WSA2_RX1 INP1", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX1 INP1", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX1 INP1", "RX4", "WSA2 RX4"},
+	{"WSA2_RX1 INP1", "RX5", "WSA2 RX5"},
+	{"WSA2_RX1 INP1", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX1 INP1", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT1 MIX", NULL, "WSA2_RX1 INP1"},
+
+	{"WSA2_RX1 INP2", "RX0", "WSA2 RX0"},
+	{"WSA2_RX1 INP2", "RX1", "WSA2 RX1"},
+	{"WSA2_RX1 INP2", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX1 INP2", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX1 INP2", "RX4", "WSA2 RX4"},
+	{"WSA2_RX1 INP2", "RX5", "WSA2 RX5"},
+	{"WSA2_RX1 INP2", "DEC0", "WSA2_TX DEC0_INP"},
+	{"WSA2_RX1 INP2", "DEC1", "WSA2_TX DEC1_INP"},
+	{"WSA2_RX INT1 MIX", NULL, "WSA2_RX1 INP2"},
+
+	{"WSA2_RX1 MIX INP", "RX0", "WSA2 RX0"},
+	{"WSA2_RX1 MIX INP", "RX1", "WSA2 RX1"},
+	{"WSA2_RX1 MIX INP", "RX_MIX0", "WSA2 RX_MIX0"},
+	{"WSA2_RX1 MIX INP", "RX_MIX1", "WSA2 RX_MIX1"},
+	{"WSA2_RX1 MIX INP", "RX4", "WSA2 RX4"},
+	{"WSA2_RX1 MIX INP", "RX5", "WSA2 RX5"},
+	{"WSA2_RX INT1 SEC MIX", NULL, "WSA2_RX1 MIX INP"},
+
+	{"WSA2_RX INT1 SEC MIX", NULL, "WSA2_RX INT1 MIX"},
+	{"WSA2_RX INT1 INTERP", NULL, "WSA2_RX INT1 SEC MIX"},
+
+	{"WSA2_RX INT1 VBAT", "WSA2 RX1 VBAT Enable", "WSA2_RX INT1 INTERP"},
+	{"WSA2_RX INT1 CHAIN", NULL, "WSA2_RX INT1 VBAT"},
+
+	{"WSA2_RX INT1 CHAIN", NULL, "WSA2_RX INT1 INTERP"},
+	{"WSA2_SPK2 OUT", NULL, "WSA2_RX INT1 CHAIN"},
+	{"WSA2_SPK2 OUT", NULL, "WSA2_MCLK"},
+};
+
+static void lpass_cdc_wsa2_macro_init_pbr(struct snd_soc_component *component)
+{
+	int sys_gain, bat_cfg, rload;
+	int vth1, vth2, vth3, vth4, vth5, vth6, vth7, vth8, vth9;
+	int vth10, vth11, vth12, vth13, vth14, vth15;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return;
+
+	/* RX0 */
+	sys_gain = wsa2_priv->wsa2_sys_gain[0];
+	bat_cfg = wsa2_priv->wsa2_bat_cfg[0];
+	rload = wsa2_priv->wsa2_rload[0];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG9, 0xC0, (bat_cfg - 1) << 0x6);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15, vth15);
+
+	/* RX1 */
+	sys_gain = wsa2_priv->wsa2_sys_gain[2];
+	bat_cfg = wsa2_priv->wsa2_bat_cfg[1];
+	rload = wsa2_priv->wsa2_rload[1];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG1_1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG9, 0x30, (bat_cfg - 1) << 0x4);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1_1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2_1, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3_1, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4_1, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5_1, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6_1, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7_1, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8_1, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9_1, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10_1, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11_1, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12_1, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13_1, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14_1, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15_1, vth15);
+}
+
+static const struct lpass_cdc_wsa2_macro_reg_mask_val
+				lpass_cdc_wsa2_macro_reg_init[] = {
+	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG1, 0x3F, 0x12},
+	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG2, 0x1C, 0x08},
+	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x3E, 0x2e},
+	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG1, 0x3F, 0x12},
+	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG2, 0x1C, 0x08},
+	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x3E, 0x2e},
+	{LPASS_CDC_WSA2_BOOST0_BOOST_CTL, 0x70, 0x58},
+	{LPASS_CDC_WSA2_BOOST1_BOOST_CTL, 0x70, 0x58},
+	{LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08},
+	{LPASS_CDC_WSA2_RX1_RX_PATH_CFG1, 0x08, 0x08},
+	{LPASS_CDC_WSA2_TOP_TOP_CFG1, 0x02, 0x02},
+	{LPASS_CDC_WSA2_TOP_TOP_CFG1, 0x01, 0x01},
+	{LPASS_CDC_WSA2_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_RX0_RX_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_RX1_RX_PATH_CFG0, 0x01, 0x01},
+	{LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{LPASS_CDC_WSA2_LA_CFG, 0x3F, 0xF},
+	{LPASS_CDC_WSA2_PBR_CFG16, 0xFF, 0x42},
+	{LPASS_CDC_WSA2_PBR_CFG19, 0xFF, 0xFC},
+	{LPASS_CDC_WSA2_PBR_CFG20, 0xF0, 0x60},
+	{LPASS_CDC_WSA2_ILIM_CFG1, 0x70, 0x40},
+	{LPASS_CDC_WSA2_ILIM_CFG0, 0x03, 0x01},
+	{LPASS_CDC_WSA2_ILIM_CFG3, 0x1F, 0x15},
+	{LPASS_CDC_WSA2_LA_CFG_1, 0x3F, 0x0F},
+	{LPASS_CDC_WSA2_PBR_CFG16_1, 0xFF, 0x42},
+	{LPASS_CDC_WSA2_PBR_CFG21, 0xFF, 0xFC},
+	{LPASS_CDC_WSA2_PBR_CFG22, 0xF0, 0x60},
+	{LPASS_CDC_WSA2_ILIM_CFG1_1, 0x70, 0x40},
+	{LPASS_CDC_WSA2_ILIM_CFG0_1, 0x03, 0x01},
+	{LPASS_CDC_WSA2_ILIM_CFG4, 0x1F, 0x15},
+	{LPASS_CDC_WSA2_ILIM_CFG2_1, 0xFF, 0x2A},
+	{LPASS_CDC_WSA2_ILIM_CFG2, 0x3F, 0x1B},
+	{LPASS_CDC_WSA2_ILIM_CFG9, 0x0F, 0x05},
+	{LPASS_CDC_WSA2_IDLE_DETECT_CFG1, 0xFF, 0x1D},
+};
+
+static void lpass_cdc_wsa2_macro_init_reg(struct snd_soc_component *component)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpass_cdc_wsa2_macro_reg_init); i++)
+		snd_soc_component_update_bits(component,
+				lpass_cdc_wsa2_macro_reg_init[i].reg,
+				lpass_cdc_wsa2_macro_reg_init[i].mask,
+				lpass_cdc_wsa2_macro_reg_init[i].val);
+	lpass_cdc_wsa2_macro_init_pbr(component);
+}
+
+static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
+{
+	int rc = 0;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = (struct lpass_cdc_wsa2_macro_priv *) handle;
+
+	if (wsa2_priv == NULL) {
+		pr_err_ratelimited("%s: wsa2 priv data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!wsa2_priv->pre_dev_up && enable) {
+		pr_debug("%s: adsp is not up\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		pm_runtime_get_sync(wsa2_priv->dev);
+		if (lpass_cdc_check_core_votes(wsa2_priv->dev))
+			rc = 0;
+		else
+			rc = -ENOTSYNC;
+	} else {
+		pm_runtime_put_autosuspend(wsa2_priv->dev);
+		pm_runtime_mark_last_busy(wsa2_priv->dev);
+	}
+
+	return rc;
+}
+
+static int wsa2_swrm_clock(void *handle, bool enable)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = (struct lpass_cdc_wsa2_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(wsa2_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err_ratelimited(wsa2_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wsa2_priv->swr_clk_lock);
+
+	dev_dbg(wsa2_priv->dev, "%s: swrm clock %s\n",
+		__func__, (enable ? "enable" : "disable"));
+	if (enable) {
+		pm_runtime_get_sync(wsa2_priv->dev);
+		if (wsa2_priv->swr_clk_users == 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						wsa2_priv->wsa2_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa2_priv->dev,
+					"%s: wsa2 swr pinctrl enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa2_priv->dev);
+				pm_runtime_put_autosuspend(wsa2_priv->dev);
+				goto exit;
+			}
+			ret = lpass_cdc_wsa2_macro_mclk_enable(wsa2_priv, 1, true);
+			if (ret < 0) {
+				msm_cdc_pinctrl_select_sleep_state(
+						wsa2_priv->wsa2_swr_gpio_p);
+				dev_err_ratelimited(wsa2_priv->dev,
+					"%s: wsa2 request clock enable failed\n",
+					__func__);
+				pm_runtime_mark_last_busy(wsa2_priv->dev);
+				pm_runtime_put_autosuspend(wsa2_priv->dev);
+				goto exit;
+			}
+			if (wsa2_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (wsa2_priv->reset_swr)
+				regmap_update_bits(regmap,
+					LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL,
+				0x1C, 0x0C);
+			wsa2_priv->reset_swr = false;
+		}
+		wsa2_priv->swr_clk_users++;
+		pm_runtime_mark_last_busy(wsa2_priv->dev);
+		pm_runtime_put_autosuspend(wsa2_priv->dev);
+	} else {
+		if (wsa2_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(wsa2_priv->dev, "%s: clock already disabled\n",
+			__func__);
+			wsa2_priv->swr_clk_users = 0;
+			goto exit;
+		}
+		wsa2_priv->swr_clk_users--;
+		if (wsa2_priv->swr_clk_users == 0) {
+			regmap_update_bits(regmap,
+				LPASS_CDC_WSA2_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+			lpass_cdc_wsa2_macro_mclk_enable(wsa2_priv, 0, true);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						wsa2_priv->wsa2_swr_gpio_p);
+			if (ret < 0) {
+				dev_err_ratelimited(wsa2_priv->dev,
+					"%s: wsa2 swr pinctrl disable failed\n",
+					__func__);
+				goto exit;
+			}
+		}
+	}
+	dev_dbg(wsa2_priv->dev, "%s: swrm clock users %d\n",
+		__func__, wsa2_priv->swr_clk_users);
+exit:
+	mutex_unlock(&wsa2_priv->swr_clk_lock);
+	return ret;
+}
+
+/* Thermal Functions */
+static int lpass_cdc_wsa2_macro_get_max_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long *state)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = cdev->devdata;
+	if (!wsa2_priv) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	*state = wsa2_priv->thermal_max_state;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_get_cur_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long *state)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = cdev->devdata;
+
+	if (!wsa2_priv) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	*state = wsa2_priv->thermal_cur_state;
+
+	pr_debug("%s: thermal current state:%lu\n", __func__, *state);
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_set_cur_state(
+					struct thermal_cooling_device *cdev,
+					unsigned long state)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = cdev->devdata;
+
+	if (!wsa2_priv || !wsa2_priv->dev) {
+		pr_err_ratelimited("%s: cdev->devdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (state <= wsa2_priv->thermal_max_state) {
+		wsa2_priv->thermal_cur_state = state;
+	} else {
+		dev_err_ratelimited(wsa2_priv->dev,
+			"%s: incorrect requested state:%d\n",
+			__func__, state);
+		return -EINVAL;
+	}
+
+	dev_dbg(wsa2_priv->dev,
+		"%s: set the thermal current state to %d\n",
+		__func__, wsa2_priv->thermal_cur_state);
+
+	schedule_work(&wsa2_priv->lpass_cdc_wsa2_macro_cooling_work);
+
+	return 0;
+}
+
+static struct thermal_cooling_device_ops wsa2_cooling_ops = {
+	.get_max_state = lpass_cdc_wsa2_macro_get_max_state,
+	.get_cur_state = lpass_cdc_wsa2_macro_get_cur_state,
+	.set_cur_state = lpass_cdc_wsa2_macro_set_cur_state,
+};
+
+static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	wsa2_dev = lpass_cdc_get_device_ptr(component->dev, WSA2_MACRO);
+	if (!wsa2_dev) {
+		dev_err(component->dev,
+			"%s: null device for macro!\n", __func__);
+		return -EINVAL;
+	}
+	wsa2_priv = dev_get_drvdata(wsa2_dev);
+	if (!wsa2_priv) {
+		dev_err(component->dev,
+			"%s: priv is null for macro!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa2_macro_dapm_widgets,
+					ARRAY_SIZE(lpass_cdc_wsa2_macro_dapm_widgets));
+	if (ret < 0) {
+		dev_err(wsa2_dev, "%s: Failed to add controls\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, wsa2_audio_map,
+					ARRAY_SIZE(wsa2_audio_map));
+	if (ret < 0) {
+		dev_err(wsa2_dev, "%s: Failed to add routes\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_new_widgets(dapm->card);
+	if (ret < 0) {
+		dev_err(wsa2_dev, "%s: Failed to add widgets\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component, lpass_cdc_wsa2_macro_snd_controls,
+				   ARRAY_SIZE(lpass_cdc_wsa2_macro_snd_controls));
+	if (ret < 0) {
+		dev_err(wsa2_dev, "%s: Failed to add snd_ctls\n", __func__);
+		return ret;
+	}
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_AIF1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_AIF_MIX1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_AIF_VI Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_AIF_ECHO Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_SPK1 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_SPK2 OUT");
+	snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA2");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2 SRC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_TX DEC0_INP");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA2_TX DEC1_INP");
+	snd_soc_dapm_sync(dapm);
+
+	wsa2_priv->component = component;
+	wsa2_priv->spkr_gain_offset = LPASS_CDC_WSA2_MACRO_GAIN_OFFSET_0_DB;
+	lpass_cdc_wsa2_macro_init_reg(component);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_deinit(struct snd_soc_component *component)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->component = NULL;
+
+	return 0;
+}
+
+static void lpass_cdc_wsa2_macro_add_child_devices(struct work_struct *work)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv;
+	struct platform_device *pdev;
+	struct device_node *node;
+	struct lpass_cdc_wsa2_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
+	int ret;
+	u16 count = 0, ctrl_num = 0;
+	struct lpass_cdc_wsa2_macro_swr_ctrl_platform_data *platdata;
+	char plat_dev_name[LPASS_CDC_WSA2_MACRO_SWR_STRING_LEN];
+
+	wsa2_priv = container_of(work, struct lpass_cdc_wsa2_macro_priv,
+			     lpass_cdc_wsa2_macro_add_child_devices_work);
+	if (!wsa2_priv) {
+		pr_err("%s: Memory for wsa2_priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!wsa2_priv->dev || !wsa2_priv->dev->of_node) {
+		dev_err(wsa2_priv->dev,
+			"%s: DT node for wsa2_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &wsa2_priv->swr_plat_data;
+	wsa2_priv->child_count = 0;
+
+	for_each_available_child_of_node(wsa2_priv->dev->of_node, node) {
+		if (strnstr(node->name, "wsa2_swr_master",
+				strlen("wsa2_swr_master")) != NULL)
+			strlcpy(plat_dev_name, "wsa2_swr_ctrl",
+				(LPASS_CDC_WSA2_MACRO_SWR_STRING_LEN - 1));
+		else if (strnstr(node->name, "msm_cdc_pinctrl",
+				 strlen("msm_cdc_pinctrl")) != NULL)
+			strlcpy(plat_dev_name, node->name,
+				(LPASS_CDC_WSA2_MACRO_SWR_STRING_LEN - 1));
+		else
+			continue;
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(wsa2_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = wsa2_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (strnstr(node->name, "wsa2_swr_master",
+				strlen("wsa2_swr_master")) != NULL) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct lpass_cdc_wsa2_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				dev_err(&pdev->dev, "out of memory\n");
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].wsa2_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Adding soundwire ctrl device(s)\n",
+				__func__);
+			wsa2_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (wsa2_priv->child_count < LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX)
+			wsa2_priv->pdev_child_devices[
+					wsa2_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+
+	return;
+fail_pdev_add:
+	for (count = 0; count < wsa2_priv->child_count; count++)
+		platform_device_put(wsa2_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static void lpass_cdc_wsa2_macro_cooling_adjust_gain(struct work_struct *work)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv;
+	u8 gain = 0;
+
+	wsa2_priv = container_of(work, struct lpass_cdc_wsa2_macro_priv,
+			     lpass_cdc_wsa2_macro_cooling_work);
+	if (!wsa2_priv) {
+		pr_err("%s: priv is null for macro!\n",
+			__func__);
+		return;
+	}
+	if (!wsa2_priv->dev || !wsa2_priv->dev->of_node) {
+		dev_err(wsa2_priv->dev,
+			"%s: DT node for wsa2_priv does not exist\n", __func__);
+		return;
+	}
+
+	/* Only adjust the volume when WSA2 clock is enabled */
+	if (wsa2_priv->dapm_mclk_enable) {
+		gain = (u8)(wsa2_priv->rx0_origin_gain -
+				wsa2_priv->thermal_cur_state);
+		snd_soc_component_update_bits(wsa2_priv->component,
+			LPASS_CDC_WSA2_RX0_RX_VOL_CTL, 0xFF, gain);
+		dev_dbg(wsa2_priv->dev,
+			"%s: RX0 current thermal state: %d, "
+			"adjusted gain: %#x\n",
+			__func__, wsa2_priv->thermal_cur_state, gain);
+
+		gain = (u8)(wsa2_priv->rx1_origin_gain -
+				wsa2_priv->thermal_cur_state);
+		snd_soc_component_update_bits(wsa2_priv->component,
+			LPASS_CDC_WSA2_RX1_RX_VOL_CTL, 0xFF, gain);
+		dev_dbg(wsa2_priv->dev,
+			"%s: RX1 current thermal state: %d, "
+			"adjusted gain: %#x\n",
+			__func__, wsa2_priv->thermal_cur_state, gain);
+	}
+
+	return;
+}
+
+static int lpass_cdc_wsa2_macro_read_array(struct platform_device *pdev,
+					  const char *name, int num_values,
+					  u32 *output)
+{
+	u32 len, ret, size;
+
+	if (!of_find_property(pdev->dev.of_node, name, &size)) {
+		dev_info(&pdev->dev, "%s: missing %s\n", __func__, name);
+		return 0;
+	}
+
+	len = size / sizeof(u32);
+	if (len != num_values) {
+		dev_info(&pdev->dev, "%s: invalid number of %s\n", __func__, name);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node, name, output, len);
+	if (ret)
+		dev_info(&pdev->dev, "%s: Failed to read %s\n", __func__, name);
+
+	return 0;
+
+}
+
+static void lpass_cdc_wsa2_macro_init_ops(struct macro_ops *ops,
+			       char __iomem *wsa2_io_base)
+{
+	memset(ops, 0, sizeof(struct macro_ops));
+	ops->init = lpass_cdc_wsa2_macro_init;
+	ops->exit = lpass_cdc_wsa2_macro_deinit;
+	ops->io_base = wsa2_io_base;
+	ops->dai_ptr = lpass_cdc_wsa2_macro_dai;
+	ops->num_dais = ARRAY_SIZE(lpass_cdc_wsa2_macro_dai);
+	ops->event_handler = lpass_cdc_wsa2_macro_event_handler;
+	ops->set_port_map = lpass_cdc_wsa2_macro_set_port_map;
+}
+
+static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
+{
+	struct macro_ops ops;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv;
+	u32 wsa2_base_addr, default_clk_id, thermal_max_state;
+	char __iomem *wsa2_io_base;
+	int ret = 0;
+	u32 is_used_wsa2_swr_gpio = 1;
+	u32 noise_gate_mode;
+	const char *is_used_wsa2_swr_gpio_dt = "qcom,is-used-swr-gpio";
+
+	if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	wsa2_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_wsa2_macro_priv),
+				GFP_KERNEL);
+	if (!wsa2_priv)
+		return -ENOMEM;
+
+	wsa2_priv->pre_dev_up = true;
+	wsa2_priv->dev = &pdev->dev;
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &wsa2_base_addr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "reg");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "wsa_data_fs_ctl_reg",
+						&wsa2_priv->wsa2_fs_ctl_reg);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: error finding %s entry in dt\n",
+			__func__, "wsa_data_fs_ctl_reg");
+	}
+
+	if (!wsa2_priv->wsa2_fs_reg_base && wsa2_priv->wsa2_fs_ctl_reg)
+		wsa2_priv->wsa2_fs_reg_base = devm_ioremap(&pdev->dev,
+			wsa2_priv->wsa2_fs_ctl_reg, LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
+
+	if (of_find_property(pdev->dev.of_node, is_used_wsa2_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_wsa2_swr_gpio_dt,
+					   &is_used_wsa2_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_wsa2_swr_gpio_dt);
+			is_used_wsa2_swr_gpio = 1;
+		}
+	}
+	wsa2_priv->wsa2_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,wsa2-swr-gpios", 0);
+	if (!wsa2_priv->wsa2_swr_gpio_p && is_used_wsa2_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (msm_cdc_pinctrl_get_state(wsa2_priv->wsa2_swr_gpio_p) < 0 &&
+			is_used_wsa2_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				wsa2_priv->wsa2_swr_gpio_p, false);
+
+	wsa2_io_base = devm_ioremap(&pdev->dev,
+				   wsa2_base_addr, LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
+	if (!wsa2_io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+		return -EINVAL;
+	}
+
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa-rloads",
+		LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_rload);
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa-system-gains",
+		2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1), wsa2_priv->wsa2_sys_gain);
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa-bat-cfgs",
+		LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_bat_cfg);
+
+
+	wsa2_priv->wsa2_io_base = wsa2_io_base;
+	wsa2_priv->reset_swr = true;
+	INIT_WORK(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work,
+		  lpass_cdc_wsa2_macro_add_child_devices);
+	INIT_WORK(&wsa2_priv->lpass_cdc_wsa2_macro_cooling_work,
+		  lpass_cdc_wsa2_macro_cooling_adjust_gain);
+	wsa2_priv->swr_plat_data.handle = (void *) wsa2_priv;
+	wsa2_priv->swr_plat_data.read = NULL;
+	wsa2_priv->swr_plat_data.write = NULL;
+	wsa2_priv->swr_plat_data.bulk_write = NULL;
+	wsa2_priv->swr_plat_data.clk = wsa2_swrm_clock;
+	wsa2_priv->swr_plat_data.core_vote = lpass_cdc_wsa2_macro_core_vote;
+	wsa2_priv->swr_plat_data.handle_irq = NULL;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
+				   &default_clk_id);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,mux0-clk-id");
+		default_clk_id = WSA2_CORE_CLK;
+	}
+
+	wsa2_priv->default_clk_id  = default_clk_id;
+
+	dev_set_drvdata(&pdev->dev, wsa2_priv);
+	mutex_init(&wsa2_priv->mclk_lock);
+	mutex_init(&wsa2_priv->swr_clk_lock);
+	lpass_cdc_wsa2_macro_init_ops(&ops, wsa2_io_base);
+	ops.clk_id_req = wsa2_priv->default_clk_id;
+	ops.default_clk_id = wsa2_priv->default_clk_id;
+
+	ret = lpass_cdc_register_macro(&pdev->dev, WSA2_MACRO, &ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
+		goto reg_macro_fail;
+	}
+
+	if (of_find_property(wsa2_priv->dev->of_node, "#cooling-cells", NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,thermal-max-state",
+					   &thermal_max_state);
+		if (ret) {
+			dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
+				__func__, "qcom,thermal-max-state");
+			wsa2_priv->thermal_max_state =
+					LPASS_CDC_WSA2_MACRO_THERMAL_MAX_STATE;
+		} else {
+			wsa2_priv->thermal_max_state = thermal_max_state;
+		}
+		wsa2_priv->tcdev = devm_thermal_of_cooling_device_register(
+						&pdev->dev,
+						wsa2_priv->dev->of_node,
+						"wsa2", wsa2_priv,
+						&wsa2_cooling_ops);
+		if (IS_ERR(wsa2_priv->tcdev)) {
+			dev_err(&pdev->dev,
+				"%s: failed to register wsa2 macro as cooling device\n",
+				__func__);
+			wsa2_priv->tcdev = NULL;
+		}
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,noise-gate-mode", &noise_gate_mode);
+	if (ret) {
+		dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,noise-gate-mode");
+		wsa2_priv->noise_gate_mode = IDLE_DETECT;
+	} else {
+		if (noise_gate_mode >= IDLE_DETECT && noise_gate_mode <= NG3)
+			wsa2_priv->noise_gate_mode = noise_gate_mode;
+		else
+			wsa2_priv->noise_gate_mode = IDLE_DETECT;
+	}
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
+	pm_runtime_enable(&pdev->dev);
+	schedule_work(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work);
+	return ret;
+reg_macro_fail:
+	mutex_destroy(&wsa2_priv->mclk_lock);
+	mutex_destroy(&wsa2_priv->swr_clk_lock);
+	return ret;
+}
+
+static int lpass_cdc_wsa2_macro_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv;
+	u16 count = 0;
+
+	wsa2_priv = dev_get_drvdata(&pdev->dev);
+
+	if (!wsa2_priv)
+		return -EINVAL;
+
+	if (wsa2_priv->tcdev)
+		thermal_cooling_device_unregister(wsa2_priv->tcdev);
+
+	for (count = 0; count < wsa2_priv->child_count &&
+		count < LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(wsa2_priv->pdev_child_devices[count]);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	lpass_cdc_unregister_macro(&pdev->dev, WSA2_MACRO);
+	mutex_destroy(&wsa2_priv->mclk_lock);
+	mutex_destroy(&wsa2_priv->swr_clk_lock);
+	return 0;
+}
+
+static const struct of_device_id lpass_cdc_wsa2_macro_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc-wsa2-macro"},
+	{}
+};
+
+static const struct dev_pm_ops lpass_cdc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		lpass_cdc_runtime_suspend,
+		lpass_cdc_runtime_resume,
+		NULL
+	)
+};
+
+static struct platform_driver lpass_cdc_wsa2_macro_driver = {
+	.driver = {
+		.name = "lpass_cdc_wsa2_macro",
+		.owner = THIS_MODULE,
+		.pm = &lpass_cdc_dev_pm_ops,
+		.of_match_table = lpass_cdc_wsa2_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_wsa2_macro_probe,
+	.remove = lpass_cdc_wsa2_macro_remove,
+};
+
+module_platform_driver(lpass_cdc_wsa2_macro_driver);
+
+MODULE_DESCRIPTION("WSA2 macro driver");
+MODULE_LICENSE("GPL v2");

+ 22 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.h

@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+#ifndef LPASS_CDC_WSA2_MACRO_H
+#define LPASS_CDC_WSA2_MACRO_H
+
+/*
+ * Selects compander and smart boost settings
+ * for a given speaker mode
+ */
+enum {
+	LPASS_CDC_WSA2_MACRO_SPKR_MODE_DEFAULT,
+	LPASS_CDC_WSA2_MACRO_SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */
+};
+
+/* Rx path gain offsets */
+enum {
+	LPASS_CDC_WSA2_MACRO_GAIN_OFFSET_M1P5_DB,
+	LPASS_CDC_WSA2_MACRO_GAIN_OFFSET_0_DB,
+};
+
+#endif

+ 1571 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc.c

@@ -0,0 +1,1571 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <soc/snd_event.h>
+#include <linux/pm_runtime.h>
+#include <soc/swr-common.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+#include "lpass-cdc.h"
+#include "internal.h"
+#include "lpass-cdc-clk-rsc.h"
+#include <linux/qti-regmap-debugfs.h>
+
+#define DRV_NAME "lpass-cdc"
+
+#define LPASS_CDC_VERSION_ENTRY_SIZE 32
+#define LPASS_CDC_STRING_LEN 80
+
+static const struct snd_soc_component_driver lpass_cdc;
+
+/* pm runtime auto suspend timer in msecs */
+#define LPASS_CDC_AUTO_SUSPEND_DELAY          100 /* delay in msec */
+
+/* MCLK_MUX table for all macros */
+static u16 lpass_cdc_mclk_mux_tbl[MAX_MACRO][MCLK_MUX_MAX] = {
+	{TX_MACRO, VA_MACRO},
+	{TX_MACRO, RX_MACRO},
+	{TX_MACRO, WSA_MACRO},
+	{TX_MACRO, VA_MACRO},
+};
+
+static bool lpass_cdc_is_valid_codec_dev(struct device *dev);
+
+int lpass_cdc_set_port_map(struct snd_soc_component *component,
+			u32 size, void *data)
+{
+	struct lpass_cdc_priv *priv = NULL;
+	struct swr_mstr_port_map *map = NULL;
+	u16 idx;
+
+	if (!component || (size == 0) || !data)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!lpass_cdc_is_valid_codec_dev(priv->dev)) {
+		dev_err_ratelimited(priv->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+	map = (struct swr_mstr_port_map *)data;
+
+	for (idx = 0; idx < size; idx++) {
+		if (priv->macro_params[map->id].set_port_map)
+			priv->macro_params[map->id].set_port_map(component,
+						map->uc,
+						SWR_MSTR_PORT_LEN,
+						map->swr_port_params);
+		map += 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_set_port_map);
+
+static void lpass_cdc_ahb_write_device(char __iomem *io_base,
+				    u16 reg, u8 value)
+{
+	u32 temp = (u32)(value) & 0x000000FF;
+
+	iowrite32(temp, io_base + reg);
+}
+
+static void lpass_cdc_ahb_read_device(char __iomem *io_base,
+				   u16 reg, u8 *value)
+{
+	u32 temp;
+
+	temp = ioread32(io_base + reg);
+	*value = (u8)temp;
+}
+
+static int __lpass_cdc_reg_read(struct lpass_cdc_priv *priv,
+			     u16 macro_id, u16 reg, u8 *val)
+{
+	int ret = 0;
+
+	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		ret = -EINVAL;
+		goto ssr_err;
+	}
+
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+		mutex_lock(&priv->vote_lock);
+		if (((priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+			(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))) {
+			goto vote_err;
+		}
+	}
+	lpass_cdc_ahb_read_device(
+		priv->macro_params[macro_id].io_base, reg, val);
+
+vote_err:
+	if (priv->macro_params[VA_MACRO].dev) {
+		mutex_unlock(&priv->vote_lock);
+		pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
+		pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
+	}
+ssr_err:
+	mutex_unlock(&priv->clk_lock);
+	return ret;
+}
+
+static int __lpass_cdc_reg_write(struct lpass_cdc_priv *priv,
+			      u16 macro_id, u16 reg, u8 val)
+{
+	int ret = 0;
+
+	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		ret = -EINVAL;
+		goto ssr_err;
+	}
+	if (priv->macro_params[VA_MACRO].dev) {
+		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+		mutex_lock(&priv->vote_lock);
+		if (((priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+			(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))) {
+			goto vote_err;
+		}
+	}
+	lpass_cdc_ahb_write_device(
+		priv->macro_params[macro_id].io_base, reg, val);
+
+vote_err:
+	if (priv->macro_params[VA_MACRO].dev) {
+		mutex_unlock(&priv->vote_lock);
+		pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
+		pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
+	}
+ssr_err:
+	mutex_unlock(&priv->clk_lock);
+	return ret;
+}
+
+static int lpass_cdc_update_wcd_event(void *handle, u16 event, u32 data)
+{
+	struct lpass_cdc_priv *priv = (struct lpass_cdc_priv *)handle;
+
+	if (!priv) {
+		pr_err_ratelimited("%s:Invalid lpass_cdc priv handle\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case WCD_LPASS_CDC_EVT_RX_MUTE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_RX_MUTE, data);
+		break;
+	case WCD_LPASS_CDC_EVT_IMPED_TRUE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_IMPED_TRUE, data);
+		break;
+	case WCD_LPASS_CDC_EVT_IMPED_FALSE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_IMPED_FALSE, data);
+		break;
+	case WCD_LPASS_CDC_EVT_RX_COMPANDER_SOFT_RST:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST, data);
+		break;
+	case WCD_LPASS_CDC_EVT_BCS_CLK_OFF:
+		if (priv->macro_params[TX_MACRO].event_handler)
+			priv->macro_params[TX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_BCS_CLK_OFF, data);
+		break;
+	case WCD_LPASS_CDC_EVT_RX_PA_GAIN_UPDATE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE,
+				data);
+		break;
+	case WCD_LPASS_CDC_EVT_HPHL_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE, data);
+		break;
+	case WCD_LPASS_CDC_EVT_HPHR_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE, data);
+		break;
+	default:
+		dev_err_ratelimited(priv->dev, "%s: Invalid event %d trigger from wcd\n",
+			__func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int lpass_cdc_register_notifier(void *handle,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct lpass_cdc_priv *priv = (struct lpass_cdc_priv *)handle;
+
+	if (!priv || !nblock) {
+		pr_err_ratelimited("%s: lpass_cdc priv or nblock is null\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		return blocking_notifier_chain_register(&priv->notifier,
+							nblock);
+
+	return blocking_notifier_chain_unregister(&priv->notifier,
+						  nblock);
+}
+
+static void lpass_cdc_notifier_call(struct lpass_cdc_priv *priv,
+				     u32 data)
+{
+	dev_dbg(priv->dev, "%s: notifier call, data:%d\n", __func__, data);
+	blocking_notifier_call_chain(&priv->notifier,
+				     data, (void *)priv->wcd_dev);
+}
+
+static bool lpass_cdc_is_valid_child_dev(struct device *dev)
+{
+	if (of_device_is_compatible(dev->parent->of_node, "qcom,lpass-cdc"))
+		return true;
+
+	return false;
+}
+
+static bool lpass_cdc_is_valid_codec_dev(struct device *dev)
+{
+	if (of_device_is_compatible(dev->of_node, "qcom,lpass-cdc"))
+		return true;
+
+	return false;
+}
+
+/**
+ * lpass_cdc_clear_amic_tx_hold - clears AMIC register on analog codec
+ *
+ * @dev: lpass_cdc device ptr.
+ *
+ */
+void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+	struct lpass_cdc_priv *priv;
+	u16 event;
+	u16 amic = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+
+	if (!lpass_cdc_is_valid_codec_dev(dev)) {
+		pr_err("%s: invalid codec\n", __func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	event = LPASS_CDC_WCD_EVT_TX_CH_HOLD_CLEAR;
+	if (adc_n == LPASS_CDC_ADC0)
+		amic = 0x1;
+	else if (adc_n == LPASS_CDC_ADC1)
+		amic = 0x2;
+	else if (adc_n == LPASS_CDC_ADC2)
+		amic = 0x2;
+	else if (adc_n == LPASS_CDC_ADC3)
+		amic = 0x3;
+	else
+		return;
+
+	lpass_cdc_notifier_call(priv, (amic << 0x10 | event));
+}
+EXPORT_SYMBOL(lpass_cdc_clear_amic_tx_hold);
+
+/**
+ * lpass_cdc_get_device_ptr - Get child or macro device ptr
+ *
+ * @dev: lpass_cdc device ptr.
+ * @macro_id: ID of macro calling this API.
+ *
+ * Returns dev ptr on success or NULL on error.
+ */
+struct device *lpass_cdc_get_device_ptr(struct device *dev, u16 macro_id)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return NULL;
+	}
+
+	if (!lpass_cdc_is_valid_codec_dev(dev)) {
+		pr_err_ratelimited("%s: invalid codec\n", __func__);
+		return NULL;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err_ratelimited(dev, "%s: priv is null or invalid macro\n", __func__);
+		return NULL;
+	}
+
+	return priv->macro_params[macro_id].dev;
+}
+EXPORT_SYMBOL(lpass_cdc_get_device_ptr);
+
+/**
+ * lpass_cdc_get_rsc_clk_device_ptr - Get rsc clk device ptr
+ *
+ * @dev: lpass_cdc device ptr.
+ *
+ * Returns dev ptr on success or NULL on error.
+ */
+struct device *lpass_cdc_get_rsc_clk_device_ptr(struct device *dev)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return NULL;
+	}
+
+	if (!lpass_cdc_is_valid_codec_dev(dev)) {
+		pr_err_ratelimited("%s: invalid codec\n", __func__);
+		return NULL;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return NULL;
+	}
+
+	return priv->clk_dev;
+}
+EXPORT_SYMBOL(lpass_cdc_get_rsc_clk_device_ptr);
+
+static int lpass_cdc_copy_dais_from_macro(struct lpass_cdc_priv *priv)
+{
+	struct snd_soc_dai_driver *dai_ptr;
+	u16 macro_idx;
+
+	/* memcpy into lpass_cdc_dais all macro dais */
+	if (!priv->lpass_cdc_dais)
+		priv->lpass_cdc_dais = devm_kzalloc(priv->dev,
+						priv->num_dais *
+						sizeof(
+						struct snd_soc_dai_driver),
+						GFP_KERNEL);
+	if (!priv->lpass_cdc_dais)
+		return -ENOMEM;
+
+	dai_ptr = priv->lpass_cdc_dais;
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].dai_ptr) {
+			memcpy(dai_ptr,
+			       priv->macro_params[macro_idx].dai_ptr,
+			       priv->macro_params[macro_idx].num_dais *
+			       sizeof(struct snd_soc_dai_driver));
+			dai_ptr += priv->macro_params[macro_idx].num_dais;
+		}
+	}
+	return 0;
+}
+
+/**
+ * lpass_cdc_register_res_clk - Registers rsc clk driver to lpass_cdc
+ *
+ * @dev: rsc clk device ptr.
+ * @rsc_clk_cb: event handler callback for notifications like SSR
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t rsc_clk_cb)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev || !rsc_clk_cb) {
+		pr_err_ratelimited("%s: dev or rsc_clk_cb is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: child device :%pK not added yet\n",
+			__func__, dev);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->clk_dev = dev;
+	priv->rsc_clk_cb = rsc_clk_cb;
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_register_res_clk);
+
+/**
+ * lpass_cdc_unregister_res_clk - Unregisters rsc clk driver from lpass_cdc
+ *
+ * @dev: resource clk device ptr.
+ */
+void lpass_cdc_unregister_res_clk(struct device *dev)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is NULL\n", __func__);
+		return;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: child device :%pK not added\n",
+			__func__, dev);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+
+	priv->clk_dev = NULL;
+	priv->rsc_clk_cb = NULL;
+}
+EXPORT_SYMBOL(lpass_cdc_unregister_res_clk);
+
+static u8 lpass_cdc_dmic_clk_div_get(struct snd_soc_component *component,
+				   u32 mode)
+{
+	struct lpass_cdc_priv* priv = snd_soc_component_get_drvdata(component);
+	int macro = (mode ? VA_MACRO : TX_MACRO);
+	int ret = 0;
+
+	if (priv->macro_params[macro].clk_div_get) {
+		ret = priv->macro_params[macro].clk_div_get(component);
+		if (ret >= 0)
+			return ret;
+	}
+
+	return 1;
+}
+
+int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable)
+{
+	struct lpass_cdc_priv* priv = snd_soc_component_get_drvdata(component);
+	u8  dmic_clk_en = 0x01;
+	u16 dmic_clk_reg = 0;
+	s32 *dmic_clk_cnt = NULL;
+	u8 *dmic_clk_div = NULL;
+	u8 freq_change_mask = 0;
+	u8 clk_div = 0;
+
+	dev_dbg(component->dev, "%s: enable: %d, tx_mode:%d, dmic: %d\n",
+		__func__, enable, tx_mode, dmic);
+
+	switch (dmic) {
+	case 0:
+	case 1:
+		dmic_clk_cnt = &(priv->dmic_0_1_clk_cnt);
+		dmic_clk_div = &(priv->dmic_0_1_clk_div);
+		dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC0_CTL;
+		freq_change_mask = 0x01;
+		break;
+	case 2:
+	case 3:
+		dmic_clk_cnt = &(priv->dmic_2_3_clk_cnt);
+		dmic_clk_div = &(priv->dmic_2_3_clk_div);
+		dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC1_CTL;
+		freq_change_mask = 0x02;
+		break;
+	case 4:
+	case 5:
+		dmic_clk_cnt = &(priv->dmic_4_5_clk_cnt);
+		dmic_clk_div = &(priv->dmic_4_5_clk_div);
+		dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC2_CTL;
+		freq_change_mask = 0x04;
+		break;
+	case 6:
+	case 7:
+		dmic_clk_cnt = &(priv->dmic_6_7_clk_cnt);
+		dmic_clk_div = &(priv->dmic_6_7_clk_div);
+		dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC3_CTL;
+		freq_change_mask = 0x08;
+		break;
+	default:
+		dev_err_ratelimited(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	}
+	dev_dbg(component->dev, "%s: DMIC%d dmic_clk_cnt %d\n",
+			__func__, dmic, *dmic_clk_cnt);
+	if (enable) {
+		clk_div = lpass_cdc_dmic_clk_div_get(component, tx_mode);
+		(*dmic_clk_cnt)++;
+		if (*dmic_clk_cnt == 1) {
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+					0x80, 0x00);
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+						0x0E, clk_div << 0x1);
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+					dmic_clk_en, dmic_clk_en);
+		} else {
+			if (*dmic_clk_div > clk_div) {
+				snd_soc_component_update_bits(component,
+						LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+						freq_change_mask, freq_change_mask);
+				snd_soc_component_update_bits(component, dmic_clk_reg,
+						0x0E, clk_div << 0x1);
+				snd_soc_component_update_bits(component,
+						LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+						freq_change_mask, 0x00);
+			} else {
+				clk_div = *dmic_clk_div;
+			}
+		}
+		*dmic_clk_div = clk_div;
+	} else {
+		(*dmic_clk_cnt)--;
+		if (*dmic_clk_cnt  == 0) {
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+					dmic_clk_en, 0);
+			clk_div = 0;
+			snd_soc_component_update_bits(component, dmic_clk_reg,
+							0x0E, clk_div << 0x1);
+		} else {
+			clk_div = lpass_cdc_dmic_clk_div_get(component, tx_mode);
+			if (*dmic_clk_div > clk_div) {
+				clk_div = lpass_cdc_dmic_clk_div_get(component, !tx_mode);
+				snd_soc_component_update_bits(component,
+							LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+							freq_change_mask, freq_change_mask);
+				snd_soc_component_update_bits(component, dmic_clk_reg,
+								0x0E, clk_div << 0x1);
+				snd_soc_component_update_bits(component,
+							LPASS_CDC_VA_TOP_CSR_DMIC_CFG,
+							freq_change_mask, 0x00);
+			} else {
+				clk_div = *dmic_clk_div;
+			}
+		}
+		*dmic_clk_div = clk_div;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_dmic_clk_enable);
+
+bool lpass_cdc_is_va_macro_registered(struct device *dev)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return false;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: child device calling is not added yet\n",
+			__func__);
+		return false;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return false;
+	}
+	return priv->macros_supported[VA_MACRO];
+}
+EXPORT_SYMBOL(lpass_cdc_is_va_macro_registered);
+
+/**
+ * lpass_cdc_register_macro - Registers macro to lpass_cdc
+ *
+ * @dev: macro device ptr.
+ * @macro_id: ID of macro calling this API.
+ * @ops: macro params to register.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
+			  struct macro_ops *ops)
+{
+	struct lpass_cdc_priv *priv;
+	int ret = -EINVAL;
+
+	if (!dev || !ops) {
+		pr_err("%s: dev or ops is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro:%d not added yet\n",
+			__func__, macro_id);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err(dev, "%s: priv is null or invalid macro\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->macro_params[macro_id].clk_id_req = ops->clk_id_req;
+	priv->macro_params[macro_id].default_clk_id = ops->default_clk_id;
+	priv->macro_params[macro_id].init = ops->init;
+	priv->macro_params[macro_id].exit = ops->exit;
+	priv->macro_params[macro_id].io_base = ops->io_base;
+	priv->macro_params[macro_id].num_dais = ops->num_dais;
+	priv->macro_params[macro_id].dai_ptr = ops->dai_ptr;
+	priv->macro_params[macro_id].event_handler = ops->event_handler;
+	priv->macro_params[macro_id].set_port_map = ops->set_port_map;
+	priv->macro_params[macro_id].dev = dev;
+	priv->current_mclk_mux_macro[macro_id] =
+				lpass_cdc_mclk_mux_tbl[macro_id][MCLK_MUX0];
+	if (macro_id == TX_MACRO) {
+		priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq;
+		priv->macro_params[macro_id].reg_evt_listener =
+							ops->reg_evt_listener;
+		priv->macro_params[macro_id].clk_enable = ops->clk_enable;
+	}
+	if (macro_id == TX_MACRO || macro_id == VA_MACRO)
+		priv->macro_params[macro_id].clk_div_get = ops->clk_div_get;
+
+	if (macro_id == VA_MACRO)
+		priv->macro_params[macro_id].reg_wake_irq =
+						ops->reg_wake_irq;
+	mutex_lock(&priv->macro_lock);
+	priv->num_dais += ops->num_dais;
+	priv->num_macros_registered++;
+	priv->macros_supported[macro_id] = true;
+
+	dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id);
+
+	if (priv->num_macros_registered == priv->num_macros) {
+		ret = lpass_cdc_copy_dais_from_macro(priv);
+		if (ret < 0) {
+			dev_err(dev, "%s: copy_dais failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
+			return ret;
+		}
+		if (priv->macros_supported[TX_MACRO] == false) {
+			lpass_cdc_mclk_mux_tbl[WSA_MACRO][MCLK_MUX0] = WSA_MACRO;
+			priv->current_mclk_mux_macro[WSA_MACRO] = WSA_MACRO;
+			lpass_cdc_mclk_mux_tbl[VA_MACRO][MCLK_MUX0] = VA_MACRO;
+			priv->current_mclk_mux_macro[VA_MACRO] = VA_MACRO;
+		}
+		ret = snd_soc_register_component(dev->parent, &lpass_cdc,
+				priv->lpass_cdc_dais, priv->num_dais);
+		if (ret < 0) {
+			dev_err(dev, "%s: register codec failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
+			return ret;
+		}
+	}
+	mutex_unlock(&priv->macro_lock);
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_register_macro);
+
+/**
+ * lpass_cdc_unregister_macro - De-Register macro from lpass_cdc
+ *
+ * @dev: macro device ptr.
+ * @macro_id: ID of macro calling this API.
+ *
+ */
+void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: macro:%d not in valid registered macro-list\n",
+			__func__, macro_id);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv || (macro_id >= MAX_MACRO)) {
+		dev_err_ratelimited(dev, "%s: priv is null or invalid macro\n", __func__);
+		return;
+	}
+
+	priv->macro_params[macro_id].init = NULL;
+	priv->macro_params[macro_id].num_dais = 0;
+	priv->macro_params[macro_id].dai_ptr = NULL;
+	priv->macro_params[macro_id].event_handler = NULL;
+	priv->macro_params[macro_id].dev = NULL;
+	if (macro_id == TX_MACRO) {
+		priv->macro_params[macro_id].reg_wake_irq = NULL;
+		priv->macro_params[macro_id].reg_evt_listener = NULL;
+		priv->macro_params[macro_id].clk_enable = NULL;
+	}
+	if (macro_id == TX_MACRO || macro_id == VA_MACRO)
+		priv->macro_params[macro_id].clk_div_get = NULL;
+
+	priv->num_dais -= priv->macro_params[macro_id].num_dais;
+	priv->num_macros_registered--;
+
+	/* UNREGISTER CODEC HERE */
+	if (priv->num_macros - 1 == priv->num_macros_registered)
+		snd_soc_unregister_component(dev->parent);
+}
+EXPORT_SYMBOL(lpass_cdc_unregister_macro);
+
+void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on)
+{
+	struct lpass_cdc_priv *priv;
+	u32 val;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: not a valid child dev\n",
+			__func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	if (is_native_on)
+		val = 0x2;  /* 11.2896M */
+	else
+		val = 0x0; /* 9.6M */
+
+	lpass_cdc_notifier_call(priv,
+		((val << 16) | LPASS_CDC_WCD_EVT_CLK_NOTIFY));
+
+}
+EXPORT_SYMBOL(lpass_cdc_notify_wcd_rx_clk);
+
+void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: not a valid child dev\n",
+			__func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	if (adie_lb)
+		lpass_cdc_notifier_call(priv,
+			LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB);
+	else
+		lpass_cdc_notifier_call(priv,
+			LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK);
+}
+EXPORT_SYMBOL(lpass_cdc_wsa_pa_on);
+
+int lpass_cdc_get_version(struct device *dev)
+{
+	struct lpass_cdc_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro not added yet\n",
+			__func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+	return priv->version;
+}
+EXPORT_SYMBOL(lpass_cdc_get_version);
+
+static ssize_t lpass_cdc_version_read(struct snd_info_entry *entry,
+				void *file_private_data,
+				struct file *file,
+				char __user *buf, size_t count,
+				loff_t pos)
+{
+	struct lpass_cdc_priv *priv;
+	char buffer[LPASS_CDC_VERSION_ENTRY_SIZE];
+	int len = 0;
+
+	priv = (struct lpass_cdc_priv *) entry->private_data;
+	if (!priv) {
+		pr_err_ratelimited("%s: lpass_cdc priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (priv->version) {
+	case LPASS_CDC_VERSION_1_0:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_1_0\n");
+		break;
+	case LPASS_CDC_VERSION_1_1:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_1_1\n");
+		break;
+	case LPASS_CDC_VERSION_1_2:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_1_2\n");
+		break;
+	case LPASS_CDC_VERSION_2_1:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_2_1\n");
+		break;
+	case LPASS_CDC_VERSION_2_5:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_2_5\n");
+		break;
+	case LPASS_CDC_VERSION_2_6:
+		len = snprintf(buffer, sizeof(buffer), "LPASS-CDC_2_6\n");
+		break;
+	default:
+		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
+	}
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static int lpass_cdc_ssr_enable(struct device *dev, void *data)
+{
+	struct lpass_cdc_priv *priv = data;
+	int macro_idx;
+
+	if (priv->initial_boot) {
+		priv->initial_boot = false;
+		return 0;
+	}
+
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_UP);
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].event_handler)
+			priv->macro_params[macro_idx].event_handler(
+				priv->component,
+				LPASS_CDC_MACRO_EVT_CLK_RESET, 0x0);
+	}
+
+	mutex_lock(&priv->clk_lock);
+	priv->pre_dev_up = true;
+	mutex_unlock(&priv->clk_lock);
+
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP);
+
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			LPASS_CDC_MACRO_EVT_PRE_SSR_UP, 0x0);
+	}
+
+	regcache_cache_only(priv->regmap, false);
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = true;
+	mutex_unlock(&priv->clk_lock);
+	regcache_mark_dirty(priv->regmap);
+	lpass_cdc_clk_rsc_enable_all_clocks(priv->clk_dev, true);
+	regcache_sync(priv->regmap);
+	/* Add a 100usec sleep to ensure last register write is done */
+	usleep_range(100,110);
+	lpass_cdc_clk_rsc_enable_all_clocks(priv->clk_dev, false);
+	/* call ssr event for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			LPASS_CDC_MACRO_EVT_SSR_UP, 0x0);
+	}
+	lpass_cdc_notifier_call(priv, LPASS_CDC_WCD_EVT_SSR_UP);
+	return 0;
+}
+
+static void lpass_cdc_ssr_disable(struct device *dev, void *data)
+{
+	struct lpass_cdc_priv *priv = data;
+	int macro_idx;
+
+	if (!priv->dev_up) {
+		dev_err_ratelimited(priv->dev,
+				    "%s: already disabled\n", __func__);
+		return;
+	}
+
+	regcache_cache_only(priv->regmap, true);
+
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = false;
+	priv->pre_dev_up = false;
+	mutex_unlock(&priv->clk_lock);
+	if (priv->rsc_clk_cb)
+		priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_DOWN);
+	/* call ssr event for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (!priv->macro_params[macro_idx].event_handler)
+			continue;
+		priv->macro_params[macro_idx].event_handler(
+			priv->component,
+			LPASS_CDC_MACRO_EVT_SSR_DOWN, 0x0);
+	}
+	lpass_cdc_notifier_call(priv, LPASS_CDC_WCD_EVT_SSR_DOWN);
+}
+
+static struct snd_info_entry_ops lpass_cdc_info_ops = {
+	.read = lpass_cdc_version_read,
+};
+
+static const struct snd_event_ops lpass_cdc_ssr_ops = {
+	.enable = lpass_cdc_ssr_enable,
+	.disable = lpass_cdc_ssr_disable,
+};
+
+/*
+ * lpass_cdc_info_create_codec_entry - creates lpass_cdc module
+ * @codec_root: The parent directory
+ * @component: Codec component instance
+ *
+ * Creates lpass_cdc module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int lpass_cdc_info_create_codec_entry(struct snd_info_entry *codec_root,
+				   struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct lpass_cdc_priv *priv;
+	struct snd_soc_card *card;
+
+	if (!codec_root || !component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (priv->entry) {
+		dev_dbg(priv->dev,
+			"%s:lpass_cdc module already created\n", __func__);
+		return 0;
+	}
+	card = component->card;
+	priv->entry = snd_info_create_module_entry(codec_root->module,
+					     "lpass-cdc", codec_root);
+	if (!priv->entry) {
+		dev_dbg(component->dev, "%s: failed to create lpass_cdc entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+	priv->entry->mode = S_IFDIR | 0555;
+	if (snd_info_register(priv->entry) < 0) {
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+
+	version_entry = snd_info_create_card_entry(card->snd_card,
+						   "version",
+						   priv->entry);
+	if (!version_entry) {
+		dev_err_ratelimited(component->dev, "%s: failed to create lpass_cdc version entry\n",
+			__func__);
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = priv;
+	version_entry->size = LPASS_CDC_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &lpass_cdc_info_ops;
+
+	if (snd_info_register(version_entry) < 0) {
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
+	priv->version_entry = version_entry;
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_info_create_codec_entry);
+
+/**
+ * lpass_cdc_register_wake_irq - Register wake irq of Tx macro
+ *
+ * @component: codec component ptr.
+ * @ipc_wakeup: bool to identify ipc_wakeup to be used or HW interrupt line.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int lpass_cdc_register_wake_irq(struct snd_soc_component *component,
+			     u32 ipc_wakeup)
+{
+	struct lpass_cdc_priv *priv = NULL;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!lpass_cdc_is_valid_codec_dev(priv->dev)) {
+		dev_err_ratelimited(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[VA_MACRO].reg_wake_irq)
+		priv->macro_params[VA_MACRO].reg_wake_irq(
+				component, ipc_wakeup);
+
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_register_wake_irq);
+
+/**
+ * lpass_cdc_tx_mclk_enable - Enable/Disable TX Macro mclk
+ *
+ * @component: pointer to codec component instance.
+ * @enable: set true to enable, otherwise false.
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int lpass_cdc_tx_mclk_enable(struct snd_soc_component *component,
+			  bool enable)
+{
+	struct lpass_cdc_priv *priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!lpass_cdc_is_valid_codec_dev(priv->dev)) {
+		dev_err_ratelimited(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[TX_MACRO].clk_enable)
+		ret = priv->macro_params[TX_MACRO].clk_enable(component,
+								enable);
+
+	return ret;
+}
+EXPORT_SYMBOL(lpass_cdc_tx_mclk_enable);
+
+/**
+ * lpass_cdc_register_event_listener - Register/Deregister to event listener
+ *
+ * @component: pointer to codec component instance.
+ * @enable: when set to 1 registers to event listener otherwise, derigisters
+ *          from the event listener
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int lpass_cdc_register_event_listener(struct snd_soc_component *component,
+				   bool enable)
+{
+	struct lpass_cdc_priv *priv = NULL;
+	int ret = 0;
+
+	if (!component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (!priv)
+		return -EINVAL;
+
+	if (!lpass_cdc_is_valid_codec_dev(priv->dev)) {
+		dev_err_ratelimited(component->dev, "%s: invalid codec\n", __func__);
+		return -EINVAL;
+	}
+
+	if (priv->macro_params[TX_MACRO].reg_evt_listener)
+		ret = priv->macro_params[TX_MACRO].reg_evt_listener(component,
+								    enable);
+
+	return ret;
+}
+EXPORT_SYMBOL(lpass_cdc_register_event_listener);
+
+static int lpass_cdc_soc_codec_probe(struct snd_soc_component *component)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(component->dev);
+	int macro_idx, ret = 0;
+	u8 core_id_0 = 0, core_id_1 = 0, core_id_2 = 0;
+
+	snd_soc_component_init_regmap(component, priv->regmap);
+
+	if (!priv->version) {
+		/*
+		 * In order for the ADIE RTC to differentiate between targets
+		 * version info is used.
+		 * Assign 1.0 for target with only one macro
+		 * Assign 1.1 for target with two macros
+		 * Assign 1.2 for target with more than two macros
+		 */
+		if (priv->num_macros_registered == 1)
+			priv->version = LPASS_CDC_VERSION_1_0;
+		else if (priv->num_macros_registered == 2)
+			priv->version = LPASS_CDC_VERSION_1_1;
+		else if (priv->num_macros_registered > 2)
+			priv->version = LPASS_CDC_VERSION_1_2;
+	}
+
+	/* Assign lpass_cdc version */
+	core_id_0 = snd_soc_component_read(component,
+					LPASS_CDC_VA_TOP_CSR_CORE_ID_0);
+	core_id_1 = snd_soc_component_read(component,
+					LPASS_CDC_VA_TOP_CSR_CORE_ID_1);
+	core_id_2 = snd_soc_component_read(component,
+					LPASS_CDC_VA_TOP_CSR_CORE_ID_2);
+	if ((core_id_0 == 0x01) && (core_id_1 == 0x0F))
+		priv->version = LPASS_CDC_VERSION_2_0;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0E))
+		priv->version = LPASS_CDC_VERSION_2_1;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51))
+		priv->version = LPASS_CDC_VERSION_2_5;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x60 || core_id_2 == 0x61))
+		priv->version = LPASS_CDC_VERSION_2_6;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x70 || core_id_2 == 0x71))
+		priv->version = LPASS_CDC_VERSION_2_7;
+	if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81))
+		priv->version = LPASS_CDC_VERSION_2_8;
+
+	/* call init for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].init) {
+			ret = priv->macro_params[macro_idx].init(component);
+			if (ret < 0) {
+				dev_err(component->dev,
+					"%s: init for macro %d failed\n",
+					__func__, macro_idx);
+				goto err;
+			}
+		}
+	}
+	priv->component = component;
+
+	ret = snd_event_client_register(priv->dev, &lpass_cdc_ssr_ops, priv);
+	if (!ret) {
+		snd_event_notify(priv->dev, SND_EVENT_UP);
+	} else {
+		dev_err(component->dev,
+			"%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	dev_dbg(component->dev, "%s: lpass_cdc soc codec probe success\n",
+		__func__);
+err:
+	return ret;
+}
+
+static void lpass_cdc_soc_codec_remove(struct snd_soc_component *component)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(component->dev);
+	int macro_idx;
+
+	snd_event_client_deregister(priv->dev);
+	/* call exit for supported macros */
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++)
+		if (priv->macro_params[macro_idx].exit)
+			priv->macro_params[macro_idx].exit(component);
+
+	return;
+}
+
+static const struct snd_soc_component_driver lpass_cdc = {
+	.name = DRV_NAME,
+	.probe = lpass_cdc_soc_codec_probe,
+	.remove = lpass_cdc_soc_codec_remove,
+};
+
+static void lpass_cdc_add_child_devices(struct work_struct *work)
+{
+	struct lpass_cdc_priv *priv;
+	bool split_codec = false;
+	struct platform_device *pdev;
+	struct device_node *node;
+	int ret = 0, count = 0;
+	struct wcd_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[LPASS_CDC_STRING_LEN] = "";
+
+	priv = container_of(work, struct lpass_cdc_priv,
+			    lpass_cdc_add_child_devices_work);
+	if (!priv) {
+		pr_err("%s: Memory for lpass_cdc priv does not exist\n",
+			__func__);
+		return;
+	}
+	if (!priv->dev || !priv->dev->of_node) {
+		dev_err(priv->dev, "%s: DT node for lpass_cdc does not exist\n",
+			__func__);
+		return;
+	}
+
+	platdata = &priv->plat_data;
+	priv->child_count = 0;
+
+	for_each_available_child_of_node(priv->dev->of_node, node) {
+		split_codec = false;
+		if (of_find_property(node, "qcom,split-codec", NULL)) {
+			split_codec = true;
+			dev_dbg(priv->dev, "%s: split codec slave exists\n",
+				__func__);
+		}
+
+		strlcpy(plat_dev_name, node->name,
+				(LPASS_CDC_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = priv->dev;
+		pdev->dev.of_node = node;
+
+		priv->dev->platform_data = platdata;
+		if (split_codec)
+			priv->wcd_dev = &pdev->dev;
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			platform_device_put(pdev);
+			goto fail_pdev_add;
+		}
+
+		if (priv->child_count < LPASS_CDC_CHILD_DEVICES_MAX)
+			priv->pdev_child_devices[priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < priv->child_count; count++)
+		platform_device_put(priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int lpass_cdc_probe(struct platform_device *pdev)
+{
+	struct lpass_cdc_priv *priv;
+	u32 num_macros = 0;
+	int ret;
+	struct clk *lpass_core_hw_vote = NULL;
+	struct clk *lpass_audio_hw_vote = NULL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_priv),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-macros",
+				   &num_macros);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s:num-macros property not found\n",
+			__func__);
+		return ret;
+	}
+	priv->num_macros = num_macros;
+	if (priv->num_macros > MAX_MACRO) {
+		dev_err(&pdev->dev,
+			"%s:num_macros(%d) > MAX_MACRO(%d) than supported\n",
+			__func__, priv->num_macros, MAX_MACRO);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,lpass-cdc-version", &priv->version);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s:lpass_cdc version not specified\n",
+			__func__);
+		ret = 0;
+	}
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier);
+	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->pre_dev_up = true;
+	priv->initial_boot = true;
+	priv->regmap = lpass_cdc_regmap_init(priv->dev,
+					  &lpass_cdc_regmap_config);
+	if (IS_ERR_OR_NULL((void *)(priv->regmap))) {
+		dev_err(&pdev->dev, "%s:regmap init failed\n", __func__);
+		return -EINVAL;
+	}
+
+	devm_regmap_qti_debugfs_register(priv->dev, priv->regmap);
+
+	priv->read_dev = __lpass_cdc_reg_read;
+	priv->write_dev = __lpass_cdc_reg_write;
+
+	priv->plat_data.handle = (void *) priv;
+	priv->plat_data.update_wcd_event = lpass_cdc_update_wcd_event;
+	priv->plat_data.register_notifier = lpass_cdc_register_notifier;
+
+	priv->core_hw_vote_count = 0;
+	priv->core_audio_vote_count = 0;
+
+	dev_set_drvdata(&pdev->dev, priv);
+	mutex_init(&priv->macro_lock);
+	mutex_init(&priv->io_lock);
+	mutex_init(&priv->clk_lock);
+	mutex_init(&priv->vote_lock);
+	INIT_WORK(&priv->lpass_cdc_add_child_devices_work,
+		  lpass_cdc_add_child_devices);
+
+	/* Register LPASS core hw vote */
+	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
+	if (IS_ERR(lpass_core_hw_vote)) {
+		ret = PTR_ERR(lpass_core_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_core_hw_vote", ret);
+		lpass_core_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_core_hw_vote = lpass_core_hw_vote;
+
+	/* Register LPASS audio hw vote */
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	priv->lpass_audio_hw_vote = lpass_audio_hw_vote;
+	schedule_work(&priv->lpass_cdc_add_child_devices_work);
+
+	return 0;
+}
+
+static int lpass_cdc_remove(struct platform_device *pdev)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	of_platform_depopulate(&pdev->dev);
+	mutex_destroy(&priv->macro_lock);
+	mutex_destroy(&priv->io_lock);
+	mutex_destroy(&priv->clk_lock);
+	mutex_destroy(&priv->vote_lock);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int lpass_cdc_runtime_resume(struct device *dev)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent);
+	int ret = 0;
+
+	dev_dbg(dev,"%s, enter\n", __func__);
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
+		goto audio_vote;
+	}
+
+	if (priv->core_hw_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote, dev);
+		if (ret < 0) {
+			dev_err_ratelimited(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+			goto audio_vote;
+		}
+	}
+	priv->core_hw_vote_count++;
+
+audio_vote:
+	if (priv->lpass_audio_hw_vote == NULL) {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__);
+		goto done;
+	}
+
+	if (priv->core_audio_vote_count == 0) {
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote, dev);
+		if (ret < 0) {
+			dev_err_ratelimited(dev, "%s:lpass audio hw enable failed\n",
+				__func__);
+			goto core_clk_vote;
+		}
+	}
+	priv->core_audio_vote_count++;
+
+core_clk_vote:
+	if (priv->core_clk_vote_count == 0) {
+		ret = lpass_cdc_clk_rsc_request_clock(dev, TX_CORE_CLK,
+							  TX_CORE_CLK, true);
+		if (ret < 0) {
+			dev_err_ratelimited(dev, "%s:lpass Tx core clk enable failed\n",
+				__func__);
+			goto done;
+		}
+	}
+	priv->core_clk_vote_count++;
+
+done:
+	mutex_unlock(&priv->vote_lock);
+	dev_dbg(dev, "%s, leave, hw_vote %d, audio_vote %d, core_clk_vote %d\n",
+		 __func__, priv->core_hw_vote_count,
+		 priv->core_audio_vote_count, priv->core_clk_vote_count);
+	pm_runtime_set_autosuspend_delay(priv->dev, LPASS_CDC_AUTO_SUSPEND_DELAY);
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_runtime_resume);
+
+int lpass_cdc_runtime_suspend(struct device *dev)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent);
+
+	dev_dbg(dev,"%s, enter\n", __func__);
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote != NULL) {
+		if (--priv->core_hw_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_core_hw_vote, dev);
+		if (priv->core_hw_vote_count < 0)
+			priv->core_hw_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass core hw node\n",
+			__func__);
+	}
+
+	if (priv->lpass_audio_hw_vote != NULL) {
+		if (--priv->core_audio_vote_count == 0)
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_audio_hw_vote, dev);
+		if (priv->core_audio_vote_count < 0)
+			priv->core_audio_vote_count = 0;
+	} else {
+		dev_dbg(dev, "%s: Invalid lpass audio hw node\n",
+			__func__);
+	}
+
+	if (--priv->core_clk_vote_count == 0) {
+		lpass_cdc_clk_rsc_request_clock(dev, TX_CORE_CLK,
+						  TX_CORE_CLK, false);
+	}
+	if (priv->core_clk_vote_count < 0)
+		priv->core_clk_vote_count = 0;
+
+	mutex_unlock(&priv->vote_lock);
+	dev_dbg(dev, "%s, leave, hw_vote %d, audio_vote %d, core_clk_vote %d\n",
+		 __func__, priv->core_hw_vote_count,
+		 priv->core_audio_vote_count, priv->core_clk_vote_count);
+	return 0;
+}
+EXPORT_SYMBOL(lpass_cdc_runtime_suspend);
+#endif /* CONFIG_PM */
+
+bool lpass_cdc_check_core_votes(struct device *dev)
+{
+	struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent);
+	bool ret = true;
+	mutex_lock(&priv->vote_lock);
+	if (!priv->pre_dev_up ||
+		(priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+		(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))
+		ret = false;
+	mutex_unlock(&priv->vote_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(lpass_cdc_check_core_votes);
+
+static const struct of_device_id lpass_cdc_dt_match[] = {
+	{.compatible = "qcom,lpass-cdc"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, lpass_cdc_dt_match);
+
+static struct platform_driver lpass_cdc_drv = {
+	.driver = {
+		.name = "lpass-cdc",
+		.owner = THIS_MODULE,
+		.of_match_table = lpass_cdc_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = lpass_cdc_probe,
+	.remove = lpass_cdc_remove,
+};
+
+static int lpass_cdc_drv_init(void)
+{
+	return platform_driver_register(&lpass_cdc_drv);
+}
+
+static void lpass_cdc_drv_exit(void)
+{
+	platform_driver_unregister(&lpass_cdc_drv);
+}
+
+static int __init lpass_cdc_init(void)
+{
+	lpass_cdc_drv_init();
+	lpass_cdc_clk_rsc_mgr_init();
+	return 0;
+}
+module_init(lpass_cdc_init);
+
+static void __exit lpass_cdc_exit(void)
+{
+	lpass_cdc_clk_rsc_mgr_exit();
+	lpass_cdc_drv_exit();
+}
+module_exit(lpass_cdc_exit);
+
+MODULE_DESCRIPTION("LPASS Codec driver");
+MODULE_LICENSE("GPL v2");

+ 394 - 0
qcom/opensource/audio-kernel/asoc/codecs/lpass-cdc/lpass-cdc.h

@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef LPASS_CDC_H
+#define LPASS_CDC_H
+
+#include <sound/soc.h>
+#include <linux/regmap.h>
+
+#define LPASS_CDC_VERSION_1_0 0x0001
+#define LPASS_CDC_VERSION_1_1 0x0002
+#define LPASS_CDC_VERSION_1_2 0x0003
+#define LPASS_CDC_VERSION_2_0 0x0004
+#define LPASS_CDC_VERSION_2_1 0x0005
+#define LPASS_CDC_VERSION_2_5 0x0006
+#define LPASS_CDC_VERSION_2_6 0x0007
+#define LPASS_CDC_VERSION_2_7 0x0008
+#define LPASS_CDC_VERSION_2_8 0x0009
+
+enum {
+	START_MACRO,
+	TX_MACRO = START_MACRO,
+	RX_MACRO,
+	WSA_MACRO,
+	VA_MACRO,
+	WSA2_MACRO,
+	MAX_MACRO
+};
+
+enum mclk_mux {
+	MCLK_MUX0,
+	MCLK_MUX1,
+	MCLK_MUX_MAX
+};
+
+enum {
+	LPASS_CDC_ADC0 = 1,
+	LPASS_CDC_ADC1,
+	LPASS_CDC_ADC2,
+	LPASS_CDC_ADC3,
+	LPASS_CDC_ADC_MAX
+};
+
+enum {
+	LPASS_CDC_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
+	LPASS_CDC_MACRO_EVT_IMPED_TRUE, /* for imped true */
+	LPASS_CDC_MACRO_EVT_IMPED_FALSE, /* for imped false */
+	LPASS_CDC_MACRO_EVT_SSR_DOWN,
+	LPASS_CDC_MACRO_EVT_SSR_UP,
+	LPASS_CDC_MACRO_EVT_WAIT_VA_CLK_RESET,
+	LPASS_CDC_MACRO_EVT_CLK_RESET,
+	LPASS_CDC_MACRO_EVT_REG_WAKE_IRQ,
+	LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST,
+	LPASS_CDC_MACRO_EVT_BCS_CLK_OFF,
+	LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP,
+	LPASS_CDC_MACRO_EVT_PRE_SSR_UP,
+	LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE,
+	LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE, /* Enable HD2 cfg for HPHL */
+	LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE, /* Enable HD2 cfg for HPHR */
+};
+
+enum {
+	DMIC_TX = 0,
+	DMIC_VA = 1,
+
+};
+
+struct macro_ops {
+	int (*init)(struct snd_soc_component *component);
+	int (*exit)(struct snd_soc_component *component);
+	u16 num_dais;
+	struct device *dev;
+	struct snd_soc_dai_driver *dai_ptr;
+	int (*mclk_fn)(struct device *dev, bool enable);
+	int (*event_handler)(struct snd_soc_component *component, u16 event,
+			     u32 data);
+	int (*reg_wake_irq)(struct snd_soc_component *component, u32 data);
+	int (*set_port_map)(struct snd_soc_component *component, u32 uc,
+			    u32 size, void *data);
+	int (*clk_div_get)(struct snd_soc_component *component);
+	int (*reg_evt_listener)(struct snd_soc_component *component, bool en);
+	int (*clk_enable)(struct snd_soc_component *c, bool en);
+	char __iomem *io_base;
+	u16 clk_id_req;
+	u16 default_clk_id;
+};
+
+enum {
+	G_21_DB = 0,
+	G_19P5_DB,
+	G_18_DB,
+	G_16P5_DB,
+	G_15_DB,
+	G_13P5_DB,
+	G_12_DB,
+	G_10P5_DB,
+	G_9_DB,
+	G_7P5_DB,
+	G_6_DB,
+	G_4P5_DB,
+	G_3_DB,
+	G_1P5_DB,
+	G_0_DB,
+	G_M1P5_DB,
+	G_M3_DB,
+	G_M4P5_DB,
+	G_M6_DB,
+	G_MAX_DB,
+};
+
+enum {
+	EXT_ABOVE_3S,
+	CONFIG_1S,
+	CONFIG_2S,
+	CONFIG_3S,
+	EXT_1S,
+	EXT_2S,
+	EXT_3S,
+	CONFIG_MAX,
+};
+
+enum {
+	WSA_4_OHMS = 0,
+	WSA_6_OHMS,
+	WSA_8_OHMS,
+	WSA_32_OHMS,
+	WSA_MAX_OHMS,
+};
+
+/*
+ * PBR Thresholds from system_gain, bat_cfg, and rload
+ * EXT_ABOVE_3S: WSA_4_OHMS, WSA_6_OHMS, WSA_8_OHMS, WSA_32_OHMS, CONFIG_1S: ...
+ */
+static const int pbr_vth1_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	/* G_21_DB */
+	{
+		{0, 0, 0, 0}, {81, 92, 106, 0},
+		{121, 148, 144, 0}, {158, 193, 192, 0}
+	},
+	/* G_19P5_DB */
+	{
+		{0, 0, 0, 0}, {96, 109, 126, 0},
+		{143, 148, 203, 0}, {188, 198, 255, 0}
+	},
+	/* G_18_DB */
+	{
+		{0, 0, 0, 0}, {106, 130, 150, 0},
+		{144, 209, 241, 0}, {192, 255, 255, 0}
+	},
+	/* G_16P5_DB */
+	{
+		{0, 0, 0, 0}, {135, 154, 178, 0},
+		{202, 248, 255, 0}, {255, 255, 255, 0}
+	},
+	/* G_15_DB */
+	{
+		{0, 0, 0, 0}, {160, 183, 211, 0},
+		{240, 255, 255, 0}, {255, 255, 255, 0}
+	},
+	 /* G_13P5_DB */
+	{
+		{0, 0, 0, 0}, {190, 217, 251, 0},
+		{255, 255, 255, 0}, {255, 255, 255, 0}
+	},
+	/* G_12_DB */
+	{
+		{0, 0, 0, 0}, {226, 255, 255, 0},
+		{225, 255, 255, 0}, {255, 255, 255, 0}
+	},
+};
+static const int pbr_vth2_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 112, 0}, {0, 0, 151, 0}, {0, 0, 196, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 115, 0, 0}, {0, 155, 0, 0},  {0, 201, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {112, 0, 0, 0}, {150, 0, 0, 0},  {195, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth3_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 118, 0}, {0, 0, 157, 0}, {0, 0, 199, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 122, 0, 0},  {0, 162, 0, 0}, {0, 205, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {118, 0, 0, 0},  {157, 0, 0, 0},  {199, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth4_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 125, 0}, {0, 0, 163, 0}, {0, 0, 202, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 129, 0, 0},  {0, 168, 0, 0}, {0, 208, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {125, 0, 0, 0},   {163, 0, 0, 0},  {202, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth5_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 131, 0}, {0, 0, 170, 0}, {0, 0, 205, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 135, 0, 0},  {0, 175, 0, 0}, {0, 211, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {131, 0, 0, 0},   {170, 0, 0, 0},  {205, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth6_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 138, 0}, {0, 0, 176, 0}, {0, 0, 208, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 142, 0, 0}, {0, 182, 0, 0}, {0, 215, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {138, 0, 0, 0},  {176, 0, 0, 0},  {208, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth7_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 144, 0}, {0, 0, 183, 0}, {0, 0, 212, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 148, 0, 0}, {0, 188, 0, 0}, {0, 218, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {0, 0, 144, 0}, {0, 0, 183, 0}, {0, 0, 212, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth8_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 151, 0}, {0, 0, 189, 0}, {0, 0, 215, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 155, 0, 0}, {0, 195, 0, 0}, {0, 221, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {150, 0, 0, 0},  {189, 0, 0, 0}, {215, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth9_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 157, 0}, {0, 0, 196, 0}, {0, 0, 218, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 162, 0, 0}, {0, 201, 0, 0}, {0, 225, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {157, 0, 0, 0}, {195, 0, 0, 0}, {218, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth10_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 163, 0}, {0, 0, 202, 0}, {0, 0, 221, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 168, 0, 0}, {0, 208, 0, 0}, {0, 228, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {163, 0, 0, 0}, {202, 0, 0, 0}, {221, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth11_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 170, 0}, {0, 0, 208, 0}, {0, 0, 225, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 175, 0, 0}, {0, 215, 0, 0}, {0, 231, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {170, 0, 0, 0}, {208, 0, 0, 0}, {224, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth12_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 176, 0}, {0, 0, 215, 0}, {0, 0, 228, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 182, 0, 0}, {0, 221, 0, 0}, {0, 234, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {176, 0, 0, 0}, {215, 0, 0, 0}, {228, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth13_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 183, 0}, {0, 0, 221, 0}, {0, 0, 231, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 188, 0, 0}, {0, 228, 0, 0}, {0, 238, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {183, 0, 0, 0}, {221, 0, 0, 0}, {231, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth14_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 189, 0}, {0, 0, 228, 0}, {0, 0, 234, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 195, 0, 0}, {0, 234, 0, 0}, {0, 241, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {189, 0, 0, 0}, {228, 0, 0, 0}, {234, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth15_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 196, 0}, {0, 0, 234, 0}, {0, 0, 237, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 201, 0, 0}, {0, 241, 0, 0}, {0, 244, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {195, 0, 0, 0}, {234, 0, 0, 0}, {237, 0, 0, 0} }, /* G_18_DB   */
+};
+
+typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event);
+
+#if IS_ENABLED(CONFIG_SND_SOC_LPASS_CDC)
+int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t cb);
+void lpass_cdc_unregister_res_clk(struct device *dev);
+bool lpass_cdc_is_va_macro_registered(struct device *dev);
+int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
+			  struct macro_ops *ops);
+void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id);
+struct device *lpass_cdc_get_device_ptr(struct device *dev, u16 macro_id);
+struct device *lpass_cdc_get_rsc_clk_device_ptr(struct device *dev);
+int lpass_cdc_info_create_codec_entry(
+		struct snd_info_entry *codec_root,
+		struct snd_soc_component *component);
+int lpass_cdc_register_wake_irq(struct snd_soc_component *component, u32 data);
+void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n);
+int lpass_cdc_runtime_resume(struct device *dev);
+int lpass_cdc_runtime_suspend(struct device *dev);
+int lpass_cdc_set_port_map(struct snd_soc_component *component, u32 size, void *data);
+int lpass_cdc_register_event_listener(struct snd_soc_component *component,
+				   bool enable);
+void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb);
+void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on);
+bool lpass_cdc_check_core_votes(struct device *dev);
+int lpass_cdc_tx_mclk_enable(struct snd_soc_component *c, bool enable);
+int lpass_cdc_get_version(struct device *dev);
+int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable);
+
+/* RX MACRO utilities */
+int lpass_cdc_rx_set_fir_capability(struct snd_soc_component *component,
+					bool capable);
+#else
+static inline int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t cb)
+{
+	return 0;
+}
+static inline void lpass_cdc_unregister_res_clk(struct device *dev)
+{
+}
+
+static bool lpass_cdc_is_va_macro_registered(struct device *dev)
+{
+	return false;
+}
+
+static inline int lpass_cdc_register_macro(struct device *dev,
+					u16 macro_id,
+					struct macro_ops *ops)
+{
+	return 0;
+}
+
+static inline void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id)
+{
+}
+
+static inline struct device *lpass_cdc_get_device_ptr(struct device *dev,
+						   u16 macro_id)
+{
+	return NULL;
+}
+
+static int lpass_cdc_info_create_codec_entry(
+		struct snd_info_entry *codec_root,
+		struct snd_soc_component *component)
+{
+	return 0;
+}
+
+static inline void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+}
+
+static inline int lpass_cdc_register_wake_irq(struct snd_soc_component *component,
+					   u32 data)
+{
+	return 0;
+}
+
+static inline int lpass_cdc_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+static int lpass_cdc_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static inline int lpass_cdc_set_port_map(struct snd_soc_component *component,
+				u32 size, void *data)
+{
+	return 0;
+}
+
+static inline int lpass_cdc_register_event_listener(
+					struct snd_soc_component *component,
+					bool enable)
+{
+	return 0;
+}
+
+static void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb)
+{
+}
+
+static void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on)
+{
+}
+
+static inline bool lpass_cdc_check_core_votes(struct device *dev)
+{
+	return false;
+}
+
+static int lpass_cdc_get_version(struct device *dev)
+{
+	return 0;
+}
+
+static int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component,
+			   u32 dmic, u32 tx_mode, bool enable)
+{
+	return 0;
+}
+static int lpass_cdc_tx_mclk_enable(struct snd_soc_component *c, bool enable)
+{
+	return 0;
+}
+/* RX MACRO utilities */
+static int lpass_cdc_rx_set_fir_capability(struct snd_soc_component *component,
+						bool capable)
+{
+	return 0;
+}
+#endif /* CONFIG_SND_SOC_LPASS_CDC */
+#endif /* LPASS_CDC_H */

+ 393 - 0
qcom/opensource/audio-kernel/asoc/codecs/msm-cdc-pinctrl.c

@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/qcom-pinctrl.h>
+#include <asoc/msm-cdc-pinctrl.h>
+
+#define MAX_GPIOS 16
+
+struct msm_cdc_pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_active;
+	struct pinctrl_state *pinctrl_sleep;
+	struct pinctrl_state *pinctrl_alt_active;
+	int gpio;
+	bool state;
+	u32 tlmm_gpio[MAX_GPIOS];
+	char __iomem *chip_wakeup_register[MAX_GPIOS];
+	u32 chip_wakeup_maskbit[MAX_GPIOS];
+	u32 count;
+	u32 wakeup_reg_count;
+	bool wakeup_capable;
+	bool chip_wakeup_reg;
+};
+
+static struct msm_cdc_pinctrl_info *msm_cdc_pinctrl_get_gpiodata(
+						struct device_node *np)
+{
+	struct platform_device *pdev;
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	if (!np) {
+		pr_err_ratelimited("%s: device node is null\n", __func__);
+		return NULL;
+	}
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev) {
+		pr_err_ratelimited("%s: platform device not found!\n", __func__);
+		return NULL;
+	}
+
+	gpio_data = dev_get_drvdata(&pdev->dev);
+	if (!gpio_data)
+		dev_err_ratelimited(&pdev->dev, "%s: cannot find cdc gpio info\n",
+			__func__);
+
+	return gpio_data;
+}
+
+/*
+ * msm_cdc_get_gpio_state: select pinctrl sleep state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure and GPIO value on success
+ */
+int msm_cdc_get_gpio_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+	int value = -EINVAL;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return value;
+
+	if (gpio_is_valid(gpio_data->gpio))
+		value = gpio_get_value_cansleep(gpio_data->gpio);
+
+	return value;
+}
+EXPORT_SYMBOL(msm_cdc_get_gpio_state);
+
+/*
+ * msm_cdc_pinctrl_select_sleep_state: select pinctrl sleep state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure
+ */
+int msm_cdc_pinctrl_select_sleep_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (!gpio_data->pinctrl_sleep) {
+		pr_err_ratelimited("%s: pinctrl sleep state is null\n", __func__);
+		return -EINVAL;
+	}
+	gpio_data->state = false;
+
+	return pinctrl_select_state(gpio_data->pinctrl,
+				    gpio_data->pinctrl_sleep);
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_select_sleep_state);
+
+/*
+ * msm_cdc_pinctrl_select_alt_active_state: select pinctrl alt_active state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure
+ */
+int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (!gpio_data->pinctrl_alt_active) {
+		pr_err_ratelimited("%s: pinctrl alt_active state is null\n", __func__);
+		return -EINVAL;
+	}
+	gpio_data->state = true;
+
+	return pinctrl_select_state(gpio_data->pinctrl,
+				    gpio_data->pinctrl_alt_active);
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_select_alt_active_state);
+
+/*
+ * msm_cdc_pinctrl_select_active_state: select pinctrl active state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure
+ */
+int msm_cdc_pinctrl_select_active_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (!gpio_data->pinctrl_active) {
+		pr_err_ratelimited("%s: pinctrl active state is null\n", __func__);
+		return -EINVAL;
+	}
+	gpio_data->state = true;
+
+	return pinctrl_select_state(gpio_data->pinctrl,
+				    gpio_data->pinctrl_active);
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_select_active_state);
+
+/*
+ * msm_cdc_pinctrl_get_state: get curren pinctrl state
+ * @np: pointer to struct device_node
+ *
+ * Returns 0 for sleep state, 1 for active state,
+ * error code for failure
+ */
+int msm_cdc_pinctrl_get_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	return gpio_data->state;
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_get_state);
+
+/*
+ * msm_cdc_pinctrl_set_wakeup_capable: Set a pinctrl to wakeup capable
+ * @np: pointer to struct device_node
+ * @enable: wakeup capable when set to true
+ *
+ * Returns 0 for success and error code for failure
+ */
+int msm_cdc_pinctrl_set_wakeup_capable(struct device_node *np, bool enable)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+	int ret = 0;
+	u32 i = 0, temp = 0;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (gpio_data->wakeup_capable) {
+		for (i = 0; i < gpio_data->count; i++) {
+			ret = msm_gpio_mpm_wake_set(gpio_data->tlmm_gpio[i],
+						    enable);
+			if (ret < 0)
+				goto exit;
+		}
+	}
+	if (gpio_data->chip_wakeup_reg) {
+		for (i = 0; i < gpio_data->wakeup_reg_count; i++) {
+			temp = ioread32(gpio_data->chip_wakeup_register[i]);
+			if (enable)
+				temp |= (1 <<
+					 gpio_data->chip_wakeup_maskbit[i]);
+			else
+				temp &= ~(1 <<
+					  gpio_data->chip_wakeup_maskbit[i]);
+			iowrite32(temp, gpio_data->chip_wakeup_register[i]);
+		}
+	}
+exit:
+	return ret;
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_set_wakeup_capable);
+
+static int msm_cdc_pinctrl_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_cdc_pinctrl_info *gpio_data;
+	u32 tlmm_gpio[MAX_GPIOS] = {0};
+	u32 chip_wakeup_reg[MAX_GPIOS] = {0};
+	u32 chip_wakeup_default_val[MAX_GPIOS] = {0};
+	u32 i = 0, temp = 0;
+	int count = 0;
+
+	gpio_data = devm_kzalloc(&pdev->dev,
+				 sizeof(struct msm_cdc_pinctrl_info),
+				 GFP_KERNEL);
+	if (!gpio_data)
+		return -ENOMEM;
+
+	gpio_data->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl)) {
+		dev_err(&pdev->dev, "%s: Cannot get cdc gpio pinctrl:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl));
+		ret = PTR_ERR(gpio_data->pinctrl);
+		goto err_pctrl_get;
+	}
+
+	gpio_data->pinctrl_active = pinctrl_lookup_state(
+					gpio_data->pinctrl, "aud_active");
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl_active)) {
+		dev_err(&pdev->dev, "%s: Cannot get aud_active pinctrl state:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl_active));
+		ret = PTR_ERR(gpio_data->pinctrl_active);
+		goto err_lookup_state;
+	}
+
+	gpio_data->pinctrl_sleep = pinctrl_lookup_state(
+					gpio_data->pinctrl, "aud_sleep");
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl_sleep)) {
+		dev_err(&pdev->dev, "%s: Cannot get aud_sleep pinctrl state:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl_sleep));
+		ret = PTR_ERR(gpio_data->pinctrl_sleep);
+		goto err_lookup_state;
+	}
+
+	gpio_data->pinctrl_alt_active = pinctrl_lookup_state(
+					gpio_data->pinctrl, "aud_alt_active");
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl_alt_active)) {
+		dev_dbg(&pdev->dev, "%s: Cannot get aud_alt_active pinctrl state:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl_alt_active));
+	}
+
+	/* skip setting to sleep state for LPI_TLMM GPIOs */
+	if (!of_property_read_bool(pdev->dev.of_node, "qcom,lpi-gpios")) {
+		/* Set pinctrl state to aud_sleep by default */
+		ret = pinctrl_select_state(gpio_data->pinctrl,
+					   gpio_data->pinctrl_sleep);
+		if (ret)
+			dev_err(&pdev->dev, "%s: set cdc gpio sleep state fail: %d\n",
+				__func__, ret);
+	}
+
+
+	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,chip-wakeup-reg");
+	if (count <= 0)
+		goto cdc_tlmm_gpio;
+	if (!of_property_read_u32_array(pdev->dev.of_node, "qcom,chip-wakeup-reg",
+				chip_wakeup_reg, count)) {
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					   "qcom,chip-wakeup-maskbit",
+					   gpio_data->chip_wakeup_maskbit, count)) {
+			dev_err(&pdev->dev,
+				"chip-wakeup-maskbit needed if chip-wakeup-reg is defined!\n");
+			goto cdc_tlmm_gpio;
+		}
+		gpio_data->chip_wakeup_reg = true;
+		for (i = 0; i < count; i++) {
+			gpio_data->chip_wakeup_register[i] =
+				devm_ioremap(&pdev->dev, chip_wakeup_reg[i], 0x4);
+		}
+		if (!of_property_read_u32_array(pdev->dev.of_node,
+					"qcom,chip-wakeup-default-val",
+					chip_wakeup_default_val, count)) {
+			for (i = 0; i < count; i++) {
+				temp = ioread32(gpio_data->chip_wakeup_register[i]);
+				if (chip_wakeup_default_val[i])
+					temp |= (1 <<
+						 gpio_data->chip_wakeup_maskbit[i]);
+				else
+					temp &= ~(1 <<
+						  gpio_data->chip_wakeup_maskbit[i]);
+				iowrite32(temp, gpio_data->chip_wakeup_register[i]);
+			}
+		}
+		gpio_data->wakeup_reg_count = count;
+	}
+
+cdc_tlmm_gpio:
+	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,tlmm-pins");
+	if (count <= 0)
+		goto cdc_rst;
+	if (!of_property_read_u32_array(pdev->dev.of_node, "qcom,tlmm-pins",
+				tlmm_gpio, count)) {
+		gpio_data->wakeup_capable = true;
+		for (i = 0; i < count; i++)
+			gpio_data->tlmm_gpio[i] = tlmm_gpio[i];
+		gpio_data->count = count;
+	}
+
+cdc_rst:
+	gpio_data->gpio = of_get_named_gpio(pdev->dev.of_node,
+					    "qcom,cdc-rst-n-gpio", 0);
+	if (gpio_is_valid(gpio_data->gpio)) {
+		ret = gpio_request(gpio_data->gpio, "MSM_CDC_RESET");
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to request gpio %d\n",
+				__func__, gpio_data->gpio);
+			goto err_lookup_state;
+		}
+	}
+
+	dev_set_drvdata(&pdev->dev, gpio_data);
+	return 0;
+
+err_lookup_state:
+	devm_pinctrl_put(gpio_data->pinctrl);
+err_pctrl_get:
+	devm_kfree(&pdev->dev, gpio_data);
+	return ret;
+}
+
+static int msm_cdc_pinctrl_remove(struct platform_device *pdev)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = dev_get_drvdata(&pdev->dev);
+
+	/* to free the requested gpio before exiting */
+	if (gpio_data) {
+		if (gpio_is_valid(gpio_data->gpio))
+			gpio_free(gpio_data->gpio);
+
+		if (gpio_data->pinctrl)
+			devm_pinctrl_put(gpio_data->pinctrl);
+	}
+
+	devm_kfree(&pdev->dev, gpio_data);
+
+	return 0;
+}
+
+static const struct of_device_id msm_cdc_pinctrl_match[] = {
+	{.compatible = "qcom,msm-cdc-pinctrl"},
+	{}
+};
+
+static struct platform_driver msm_cdc_pinctrl_driver = {
+	.driver = {
+		.name = "msm-cdc-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_cdc_pinctrl_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_cdc_pinctrl_probe,
+	.remove = msm_cdc_pinctrl_remove,
+};
+
+int msm_cdc_pinctrl_drv_init(void)
+{
+	return platform_driver_register(&msm_cdc_pinctrl_driver);
+}
+
+void msm_cdc_pinctrl_drv_exit(void)
+{
+	platform_driver_unregister(&msm_cdc_pinctrl_driver);
+}
+MODULE_DESCRIPTION("MSM CODEC pin control platform driver");
+MODULE_LICENSE("GPL v2");

+ 932 - 0
qcom/opensource/audio-kernel/asoc/codecs/msm-cdc-supply.c

@@ -0,0 +1,932 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <asoc/msm-cdc-supply.h>
+#include <sound/soc.h>
+
+#define CODEC_DT_MAX_PROP_SIZE 40
+
+static int msm_cdc_dt_parse_vreg_info(struct device *dev,
+				      struct cdc_regulator *cdc_vreg,
+				      const char *name, bool is_ond)
+{
+	char prop_name[CODEC_DT_MAX_PROP_SIZE];
+	struct device_node *regulator_node = NULL;
+	const __be32 *prop;
+	int len, rc;
+	u32 prop_val;
+
+	/* Parse supply name */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply", name);
+
+	regulator_node = of_parse_phandle(dev->of_node, prop_name, 0);
+	if (!regulator_node) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		rc = -EINVAL;
+		goto done;
+	}
+	cdc_vreg->name = name;
+	cdc_vreg->ondemand = is_ond;
+
+	/* Parse supply - voltage */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-voltage", name);
+	prop = of_get_property(dev->of_node, prop_name, &len);
+	if (!prop || (len != (2 * sizeof(__be32)))) {
+		dev_err(dev, "%s: %s %s property\n", __func__,
+			prop ? "invalid format" : "no", prop_name);
+		rc = -EINVAL;
+		goto done;
+	} else {
+		cdc_vreg->min_uV = be32_to_cpup(&prop[0]);
+		cdc_vreg->max_uV = be32_to_cpup(&prop[1]);
+	}
+
+	/* Parse supply - current */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-current", name);
+	rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (rc) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		goto done;
+	}
+	cdc_vreg->optimum_uA = prop_val;
+
+	/* Parse supply - LPM or NOM mode(default NOM) */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-lpm-supported", name);
+	rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (rc) {
+		dev_dbg(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		cdc_vreg->lpm_supported = 0;
+		rc = 0;
+	} else {
+		cdc_vreg->lpm_supported = prop_val;
+	}
+
+	/* Parse supply - retention mode */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-rem-supported", name);
+	rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (rc) {
+		dev_dbg(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		cdc_vreg->rem_supported = 0;
+		rc = 0;
+	} else {
+		cdc_vreg->rem_supported = prop_val;
+	}
+
+	dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d rem %d\n",
+		 __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
+		 cdc_vreg->optimum_uA, cdc_vreg->ondemand,
+		 cdc_vreg->lpm_supported, cdc_vreg->rem_supported);
+
+done:
+	return rc;
+}
+
+static int msm_cdc_parse_supplies(struct device *dev,
+				  struct cdc_regulator *cdc_reg,
+				  const char *sup_list, int sup_cnt,
+				  bool is_ond)
+{
+	int idx, rc = 0;
+	const char *name = NULL;
+
+	for (idx = 0; idx < sup_cnt; idx++) {
+		rc = of_property_read_string_index(dev->of_node, sup_list, idx,
+						   &name);
+		if (rc) {
+			dev_err(dev, "%s: read string %s[%d] error (%d)\n",
+				__func__, sup_list, idx, rc);
+			goto done;
+		}
+
+		dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
+			__func__, name, sup_list);
+
+		rc = msm_cdc_dt_parse_vreg_info(dev, &cdc_reg[idx], name,
+						is_ond);
+		if (rc) {
+			dev_err(dev, "%s: parse %s vreg info failed (%d)\n",
+				__func__, name, rc);
+			goto done;
+		}
+	}
+
+done:
+	return rc;
+}
+
+static int msm_cdc_check_supply_param(struct device *dev,
+				      struct cdc_regulator *cdc_vreg,
+				      int num_supplies)
+{
+	if (!dev) {
+		pr_err_ratelimited("%s: device is NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!cdc_vreg || (num_supplies <= 0)) {
+		dev_err_ratelimited(dev, "%s: supply check failed: vreg: %pK, num_supplies: %d\n",
+			__func__, cdc_vreg, num_supplies);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * msm_cdc_is_ondemand_supply:
+ *	return if ondemand supply true or not
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ *
+ * Return true/false
+ */
+bool msm_cdc_is_ondemand_supply(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies,
+				char *supply_name)
+{
+	bool rc = false;
+	int ret, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return rc;
+	}
+	/* input parameter validation */
+	ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (ret)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand &&
+			!strcmp(cdc_vreg[i].name, supply_name))
+			return true;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
+
+/*
+ * msm_cdc_supply_supports_retention_mode:
+ *	On certain hardware configurations, This means that the
+ *	PM will disable the supply and remove its power vote
+ *	if the PM enters into a suspended state.
+ *
+ *	return if supply supports retention mode or not
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ *
+ * Return true/false
+ */
+bool msm_cdc_supply_supports_retention_mode(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies, char *supply_name)
+{
+	bool rc = false;
+	int ret, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return rc;
+	}
+	/* input parameter validation */
+	ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (ret)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].rem_supported &&
+			!strcmp(cdc_vreg[i].name, supply_name))
+			return true;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_supply_supports_retention_mode);
+
+/*
+ * msm_cdc_check_supply_vote:
+ *
+ *	return true if supply has voted for regulator enable
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ *
+ * Return true/false
+ */
+bool msm_cdc_check_supply_vote(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies,
+				char *supply_name)
+{
+	bool rc = false;
+	int ret, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return rc;
+	}
+
+	/* input parameter validation */
+	ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (ret)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (strcmp(cdc_vreg[i].name, supply_name) != 0)
+			continue;
+
+		return cdc_vreg[i].vote;
+	}
+
+	dev_err_ratelimited(dev,
+		"%s: Unable to find vote for supply %s\n",
+		__func__, supply_name);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(msm_cdc_check_supply_vote);
+
+/*
+ * msm_cdc_set_supply_min_voltage:
+ *	Set min supply voltage for particular supply
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: Supply name to change voltage for
+ * @vval_min: Min voltage to be set in uV
+ * @override_min_vol: True if override min voltage from default
+ * Return error code if unable to set voltage
+ */
+int msm_cdc_set_supply_min_voltage(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies, char *supply_name,
+				    int vval_min, bool override_min_vol)
+{
+	int rc = 0, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+	for (i = 0; i < num_supplies; i++) {
+		if (!strcmp(cdc_vreg[i].name, supply_name)) {
+			if (override_min_vol)
+				regulator_set_voltage(supplies[i].consumer,
+					vval_min, cdc_vreg[i].max_uV);
+			else
+				regulator_set_voltage(supplies[i].consumer,
+				    cdc_vreg[i].min_uV, cdc_vreg[i].max_uV);
+			break;
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_set_supply_min_voltage);
+
+/*
+ * msm_cdc_disable_ondemand_supply:
+ *	Disable codec ondemand supply
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: Ondemand supply name to be enabled
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_disable_ondemand_supply(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies,
+				    char *supply_name)
+{
+	int rc, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	dev_dbg(dev, "%s: Disabling on-demand supply %s\n",
+		__func__, supply_name);
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand &&
+			!strcmp(cdc_vreg[i].name, supply_name)) {
+			if (!cdc_vreg[i].vote) {
+				dev_err_ratelimited(dev,
+					"%s: Attempted to disable already disabled supply %s\n",
+					__func__, supplies[i].supply);
+				break;
+			}
+
+			rc = regulator_disable(supplies[i].consumer);
+			if (rc)
+				dev_err_ratelimited(dev,
+					"%s: failed to disable supply %s, err:%d\n",
+					__func__, supplies[i].supply, rc);
+			else
+				cdc_vreg[i].vote = false;
+			break;
+		}
+	}
+	if (i == num_supplies) {
+		dev_err_ratelimited(dev, "%s: not able to find supply %s\n",
+			__func__, supply_name);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_disable_ondemand_supply);
+
+/*
+ * msm_cdc_enable_ondemand_supply:
+ *	Enable codec ondemand supply
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: Ondemand supply name to be enabled
+ *
+ * Return error code if supply enable is failed
+ */
+int msm_cdc_enable_ondemand_supply(struct device *dev,
+				   struct regulator_bulk_data *supplies,
+				   struct cdc_regulator *cdc_vreg,
+				   int num_supplies,
+				   char *supply_name)
+{
+	int rc, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err_ratelimited("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	dev_dbg(dev, "%s: Enabling on-demand supply %s\n",
+		__func__, supply_name);
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand &&
+			!strcmp(cdc_vreg[i].name, supply_name)) {
+			if (cdc_vreg[i].vote) {
+				dev_err_ratelimited(dev,
+					"%s: Attempted to enable already enabled supply %s\n",
+					__func__, supplies[i].supply);
+				break;
+			}
+
+			rc = regulator_enable(supplies[i].consumer);
+			if (rc)
+				dev_err_ratelimited(dev, "%s: failed to enable supply %s, rc: %d\n",
+					__func__, supplies[i].supply, rc);
+			else
+				cdc_vreg[i].vote = true;
+			break;
+		}
+	}
+	if (i == num_supplies) {
+		dev_err_ratelimited(dev, "%s: not able to find supply %s\n",
+			__func__, supply_name);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply);
+
+/*
+ * msm_cdc_set_supplies_lpm_mode:
+ *	Update load for given supply string
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ * @min_max: Apply optimum or 0 current
+ *
+ * Return error code if set current fail
+ */
+int msm_cdc_set_supplies_lpm_mode(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies,
+				bool flag)
+{
+	int rc = 0, i;
+
+	if (!supplies) {
+		pr_err_ratelimited("%s: supplies is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].lpm_supported) {
+			rc = regulator_set_load(
+				supplies[i].consumer,
+				flag ? 0 : cdc_vreg[i].optimum_uA);
+			if (rc)
+				dev_err_ratelimited(dev,
+					"%s: failed to set supply %s to %s, err:%d\n",
+					__func__, supplies[i].supply,
+					flag ? "LPM" : "NOM",
+					rc);
+			else
+				dev_dbg(dev, "%s: regulator %s load set to %s\n",
+					__func__, supplies[i].supply,
+					flag ? "LPM" : "NOM");
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_set_supplies_lpm_mode);
+
+/*
+ * msm_cdc_disable_static_supplies:
+ *	Disable codec static supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_disable_static_supplies(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies)
+{
+	int rc, i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand)
+			continue;
+
+		rc = regulator_disable(supplies[i].consumer);
+		if (rc)
+			dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
+				__func__, supplies[i].supply, rc);
+		else {
+			cdc_vreg[i].vote = false;
+			dev_dbg(dev, "%s: disabled regulator %s\n",
+				__func__, supplies[i].supply);
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
+
+/*
+ * msm_cdc_release_supplies:
+ *	Release codec power supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_release_supplies(struct device *dev,
+			     struct regulator_bulk_data *supplies,
+			     struct cdc_regulator *cdc_vreg,
+			     int num_supplies)
+{
+	int rc = 0;
+	int i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
+					num_supplies);
+	for (i = 0; i < num_supplies; i++) {
+		if (regulator_count_voltages(supplies[i].consumer) < 0)
+			continue;
+
+		regulator_set_voltage(supplies[i].consumer, 0,
+				      cdc_vreg[i].max_uV);
+		regulator_set_load(supplies[i].consumer, 0);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_release_supplies);
+
+/*
+ * msm_cdc_enable_static_supplies:
+ *	Enable codec static supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply enable is failed
+ */
+int msm_cdc_enable_static_supplies(struct device *dev,
+				   struct regulator_bulk_data *supplies,
+				   struct cdc_regulator *cdc_vreg,
+				   int num_supplies)
+{
+	int rc, i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand)
+			continue;
+
+		rc = regulator_enable(supplies[i].consumer);
+		if (rc) {
+			dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
+				__func__, supplies[i].supply, rc);
+			break;
+		} else
+			cdc_vreg[i].vote = true;
+	}
+
+	if (rc) {
+		while (i--) {
+			if (cdc_vreg[i].ondemand)
+				continue;
+
+			if (regulator_disable(supplies[i].consumer) == 0)
+				cdc_vreg[i].vote = false;
+			else
+				dev_err(dev, "%s: failed to disable supply %s during unwind\n",
+					__func__, supplies[i].supply);
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
+
+/*
+ * msm_cdc_init_supplies:
+ *	Initialize codec static supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply init is failed
+ */
+int msm_cdc_init_supplies(struct device *dev,
+			  struct regulator_bulk_data **supplies,
+			  struct cdc_regulator *cdc_vreg,
+			  int num_supplies)
+{
+	return msm_cdc_init_supplies_v2(dev, supplies, cdc_vreg,
+					num_supplies, false);
+}
+EXPORT_SYMBOL(msm_cdc_init_supplies);
+
+/*
+ * msm_cdc_init_supplies_v2:
+ *	Initialize codec static supplies.
+ *	Initialize codec dynamic supplies based on vote_regulator_on_demand
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @vote_regulator_on_demand: initialize codec dynamic supplies at runtime
+ *
+ * Return error code if supply init is failed
+ */
+int msm_cdc_init_supplies_v2(struct device *dev,
+			  struct regulator_bulk_data **supplies,
+			  struct cdc_regulator *cdc_vreg,
+			  int num_supplies, u32 vote_regulator_on_demand)
+{
+	struct regulator_bulk_data *vsup;
+	int rc;
+	int i;
+
+	if (!dev || !cdc_vreg) {
+		pr_err("%s: device pointer or dce_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	vsup = devm_kcalloc(dev, num_supplies,
+			    sizeof(struct regulator_bulk_data),
+			    GFP_KERNEL);
+	if (!vsup)
+		return -ENOMEM;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (!cdc_vreg[i].name) {
+			dev_err(dev, "%s: supply name not defined\n",
+				__func__);
+			rc = -EINVAL;
+			goto err_supply;
+		}
+		vsup[i].supply = cdc_vreg[i].name;
+	}
+
+	rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
+	if (rc) {
+		dev_err(dev, "%s: failed to get supplies (%d)\n",
+			__func__, rc);
+		goto err_supply;
+	}
+
+	/* Set voltage and current on regulators */
+	for (i = 0; i < num_supplies; i++) {
+		if (regulator_count_voltages(vsup[i].consumer) < 0)
+			continue;
+
+		if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
+			continue;
+
+		cdc_vreg[i].regulator = vsup[i].consumer;
+
+		rc = regulator_set_voltage(vsup[i].consumer,
+					   cdc_vreg[i].min_uV,
+					   cdc_vreg[i].max_uV);
+		if (rc) {
+			dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
+				__func__, vsup[i].supply, rc);
+			goto err_supply;
+		}
+		rc = regulator_set_load(vsup[i].consumer,
+					cdc_vreg[i].optimum_uA);
+		if (rc < 0) {
+			dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
+				__func__, vsup[i].supply, rc);
+			goto err_supply;
+		}
+	}
+
+	*supplies = vsup;
+
+	return 0;
+
+err_supply:
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_init_supplies_v2);
+
+/*
+ * msm_cdc_get_power_supplies:
+ *	Get codec power supplies from device tree.
+ *	Allocate memory to hold regulator data for
+ *	all power supplies.
+ *
+ * @dev: pointer to codec device
+ * @cdc_vreg: pointer to codec regulator
+ * @total_num_supplies: total number of supplies read from DT
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_get_power_supplies(struct device *dev,
+			       struct cdc_regulator **cdc_vreg,
+			       int *total_num_supplies)
+{
+	const char *static_prop_name = "qcom,cdc-static-supplies";
+	const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+	const char *cp_prop_name = "qcom,cdc-cp-supplies";
+	int static_sup_cnt = 0;
+	int ond_sup_cnt = 0;
+	int cp_sup_cnt = 0;
+	int num_supplies = 0;
+	struct cdc_regulator *cdc_reg;
+	int rc;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: device pointer is NULL\n", __func__);
+		return -EINVAL;
+	}
+	static_sup_cnt = of_property_count_strings(dev->of_node,
+						   static_prop_name);
+	if (static_sup_cnt < 0) {
+		dev_err_ratelimited(dev, "%s: Failed to get static supplies(%d)\n",
+			__func__, static_sup_cnt);
+		rc = static_sup_cnt;
+		goto err_supply_cnt;
+	}
+	ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+	if (ond_sup_cnt < 0)
+		ond_sup_cnt = 0;
+
+	cp_sup_cnt = of_property_count_strings(dev->of_node,
+					       cp_prop_name);
+	if (cp_sup_cnt < 0)
+		cp_sup_cnt = 0;
+
+	num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
+	if (num_supplies <= 0) {
+		dev_err_ratelimited(dev, "%s: supply count is 0 or negative\n", __func__);
+		rc = -EINVAL;
+		goto err_supply_cnt;
+	}
+
+	cdc_reg = devm_kcalloc(dev, num_supplies,
+			       sizeof(struct cdc_regulator),
+			       GFP_KERNEL);
+	if (!cdc_reg) {
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+
+	rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
+				    static_sup_cnt, false);
+	if (rc) {
+		dev_err_ratelimited(dev, "%s: failed to parse static supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
+				    ond_prop_name, ond_sup_cnt,
+				    true);
+	if (rc) {
+		dev_err_ratelimited(dev, "%s: failed to parse demand supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	rc = msm_cdc_parse_supplies(dev,
+				    &cdc_reg[static_sup_cnt + ond_sup_cnt],
+				    cp_prop_name, cp_sup_cnt, true);
+	if (rc) {
+		dev_err_ratelimited(dev, "%s: failed to parse cp supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	*cdc_vreg = cdc_reg;
+	*total_num_supplies = num_supplies;
+
+	return 0;
+
+err_sup:
+err_supply_cnt:
+err_mem_alloc:
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_get_power_supplies);
+
+/*
+ * msm_cdc_init_wcd_supply:
+ *	Initialize wcd supply parameters.
+ *
+ * @np: device node pointer to codec device
+ * @name: power supply name
+ * @cdc_supply: codec supply struct to hold wcd params
+ *
+ * Return error code if init failed
+ */
+int msm_cdc_init_wcd_supply(struct device_node *np, const char *name,
+			    struct cdc_wcd_supply *cdc_supply)
+{
+	struct platform_device *pdev = NULL;
+
+	if (!np || !cdc_supply)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev)
+		return -EINVAL;
+
+	cdc_supply->dev = &pdev->dev;
+	cdc_supply->name = name;
+	cdc_supply->component = snd_soc_lookup_component(&pdev->dev, NULL);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_cdc_init_wcd_supply);
+
+/*
+ * msm_cdc_enable_wcd_supply:
+ *	Enable/Disable wcd supply.
+ *
+ * @cdc_supply: codec supply struct to hold wcd params
+ * @enable: bool to inform whether to enable or disable
+ *
+ * Return error code if enable/disable failed
+ */
+int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable)
+{
+	struct snd_soc_component *component = cdc_supply->component;
+	int rc;
+
+	if (!component) {
+		pr_err_ratelimited("%s: Component memory is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable)
+		rc = snd_soc_dapm_force_enable_pin(
+					snd_soc_component_get_dapm(component),
+					cdc_supply->name);
+	else
+		rc = snd_soc_dapm_disable_pin(
+					snd_soc_component_get_dapm(component),
+					cdc_supply->name);
+
+	if (!rc)
+		snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
+	else
+		dev_err_ratelimited(component->dev, "%s: micbias %s force %s pin failed\n",
+			__func__, cdc_supply->name, (enable ? "enable" : "disable"));
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_enable_wcd_supply);

+ 946 - 0
qcom/opensource/audio-kernel/asoc/codecs/msm_hdmi_codec_rx.c

@@ -0,0 +1,946 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/err.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <linux/soc/qcom/msm_ext_display.h>
+
+#define DRV_NAME "HDMI_codec"
+
+#define MSM_EXT_DISP_PCM_RATES	SNDRV_PCM_RATE_48000
+#define AUD_EXT_DISP_ACK_DISCONNECT (AUDIO_ACK_CONNECT ^ AUDIO_ACK_CONNECT)
+#define AUD_EXT_DISP_ACK_CONNECT    (AUDIO_ACK_CONNECT)
+#define AUD_EXT_DISP_ACK_ENABLE     (AUDIO_ACK_SET_ENABLE | AUDIO_ACK_ENABLE)
+
+#define SOC_EXT_DISP_AUDIO_TYPE(index) \
+	static SOC_ENUM_SINGLE_DECL(ext_disp_audio_type##index, SND_SOC_NOPM, \
+				    index, ext_disp_audio_type_text)
+#define SOC_EXT_DISP_AUDIO_ACK_STATE(index) \
+	static SOC_ENUM_SINGLE_DECL(ext_disp_audio_ack_state##index, \
+			    SND_SOC_NOPM, index, ext_disp_audio_ack_text)
+
+#define SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type) \
+	codec_info.type = type; \
+	codec_info.ctrl_id = codec_data->ctl[dai_id]; \
+	codec_info.stream_id = codec_data->stream[dai_id]; \
+
+enum {
+        DP_CONTROLLER0 = 0,
+        DP_CONTROLLER_MAX,
+};
+
+enum {
+	DP_STREAM0 = 0,
+	DP_STREAM1,
+	HDMI,
+	DP_STREAM_MAX,
+};
+
+/*
+ * Dai id cannot be zero, if component has more than one dai and dai id
+ * is used to differentiate between them
+ */
+enum {
+	DP_DAI1 = 1,
+	DP_DAI2,
+	HDMI_DAI,
+	HDMI_MS_DAI,
+	DP_DAI_MAX,
+};
+
+static const char *const ext_disp_audio_type_text[] = {"None", "HDMI", "DP"};
+static const char *const ext_disp_audio_ack_text[] = {"Disconnect",  "Connect",
+						      "Ack_Enable"};
+
+static const struct snd_pcm_hardware dummy_dma_hardware = {
+	/* Random values to keep userspace happy when checking constraints */
+	.info               = SNDRV_PCM_INFO_INTERLEAVED |
+					SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.buffer_bytes_max   = 128*1024,
+	.period_bytes_min   = PAGE_SIZE,
+	.period_bytes_max   = PAGE_SIZE*2,
+	.periods_min        = 2,
+	.periods_max        = 128,
+};
+
+SOC_EXT_DISP_AUDIO_TYPE(1);
+SOC_EXT_DISP_AUDIO_ACK_STATE(1);
+SOC_EXT_DISP_AUDIO_TYPE(2);
+SOC_EXT_DISP_AUDIO_ACK_STATE(2);
+SOC_EXT_DISP_AUDIO_TYPE(3);
+SOC_EXT_DISP_AUDIO_ACK_STATE(3);
+
+struct msm_ext_disp_audio_codec_rx_data {
+	struct platform_device *ext_disp_core_pdev;
+	struct msm_ext_disp_audio_codec_ops ext_disp_ops;
+	struct mutex dp_ops_lock;
+	int cable_status[DP_DAI_MAX];
+	int stream[DP_DAI_MAX];
+	int ctl[DP_DAI_MAX];
+};
+
+static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	struct msm_ext_disp_audio_edid_blk edid_blk;
+	int rc = 0;
+	struct msm_ext_disp_codec_id codec_info;
+	int dai_id = kcontrol->private_value;
+	int type;
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev, "%s: codec_data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
+		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai_id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
+		dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
+			__func__);
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+		uinfo->count = 0;
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return 0;
+	}
+
+	rc = codec_data->ext_disp_ops.get_audio_edid_blk(
+				codec_data->ext_disp_core_pdev, &edid_blk);
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (rc >= 0) {
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+		uinfo->count = edid_blk.audio_data_blk_size +
+			edid_blk.spk_alloc_data_blk_size;
+	}
+
+	dev_dbg(component->dev, "%s: count: %d\n", __func__, uinfo->count);
+
+	return rc;
+}
+
+static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol) {
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	struct msm_ext_disp_audio_edid_blk edid_blk;
+	struct msm_ext_disp_codec_id codec_info;
+	int rc = 0;
+	int dai_id = kcontrol->private_value;
+	int type;
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev, "%s: codec_data is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
+		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai_id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
+		dev_err_ratelimited(component->dev,
+			"%s: codec_data or get_audio_edid_blk() is NULL\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+	rc = codec_data->ext_disp_ops.get_audio_edid_blk(
+			codec_data->ext_disp_core_pdev, &edid_blk);
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (rc >= 0) {
+		if (sizeof(ucontrol->value.bytes.data) <
+			  (edid_blk.audio_data_blk_size +
+			   edid_blk.spk_alloc_data_blk_size)) {
+			dev_err_ratelimited(component->dev,
+				"%s: Not enough memory to copy EDID data\n",
+				__func__);
+			return -ENOMEM;
+		}
+
+		memcpy(ucontrol->value.bytes.data,
+		       edid_blk.audio_data_blk,
+		       edid_blk.audio_data_blk_size);
+		memcpy((ucontrol->value.bytes.data +
+		       edid_blk.audio_data_blk_size),
+		       edid_blk.spk_alloc_data_blk,
+		       edid_blk.spk_alloc_data_blk_size);
+
+		dev_dbg(component->dev, "%s: data_blk_size:%d, spk_alloc_data_blk_size:%d\n",
+			__func__, edid_blk.audio_data_blk_size,
+			edid_blk.spk_alloc_data_blk_size);
+	}
+
+	return rc;
+}
+
+static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	enum msm_ext_disp_cable_state cable_state;
+	enum msm_ext_disp_type disp_type;
+	struct msm_ext_disp_codec_id codec_info;
+	int rc = 0;
+	int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
+	int type;
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev, "%s: codec_data is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
+		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai_id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
+	    !codec_data->ext_disp_ops.get_intf_id || rc) {
+		dev_err_ratelimited(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto cable_err;
+	}
+
+	cable_state = codec_data->ext_disp_ops.cable_status(
+				codec_data->ext_disp_core_pdev, 1);
+	if (cable_state < 0) {
+		dev_err_ratelimited(component->dev, "%s: Error retrieving cable state from ext_disp, err:%d\n",
+			__func__, cable_state);
+		rc = cable_state;
+		goto cable_err;
+	}
+
+	codec_data->cable_status[dai_id] = cable_state;
+	if (cable_state == EXT_DISPLAY_CABLE_DISCONNECT) {
+		dev_err_ratelimited(component->dev, "%s: Display cable disconnected\n",
+			__func__);
+		ucontrol->value.integer.value[0] = 0;
+		rc = 0;
+		goto cable_err;
+	}
+
+	disp_type = codec_data->ext_disp_ops.get_intf_id(
+						codec_data->ext_disp_core_pdev);
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (disp_type >= 0) {
+		switch (disp_type) {
+		case EXT_DISPLAY_TYPE_DP:
+			ucontrol->value.integer.value[0] = 2;
+			rc = 0;
+			break;
+		case EXT_DISPLAY_TYPE_HDMI:
+			ucontrol->value.integer.value[0] = 1;
+			rc = 0;
+			break;
+		default:
+			rc = -EINVAL;
+			dev_err_ratelimited(component->dev, "%s: Invalid disp_type:%d\n",
+			       __func__, disp_type);
+			goto done;
+		}
+		dev_dbg(component->dev, "%s: Display type: %d\n",
+			__func__, disp_type);
+	} else {
+		dev_err_ratelimited(component->dev, "%s: Error retrieving disp_type from ext_disp, err:%d\n",
+			__func__, disp_type);
+		rc = disp_type;
+	}
+	return rc;
+
+cable_err:
+	mutex_unlock(&codec_data->dp_ops_lock);
+done:
+	return rc;
+}
+
+static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	u32 ack_state = 0;
+	struct msm_ext_disp_codec_id codec_info;
+	int rc = 0;
+	int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
+	int type;
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev,
+			"%s: codec_data is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
+		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai_id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+
+	if (!codec_data->ext_disp_ops.acknowledge || rc) {
+		dev_err_ratelimited(component->dev,
+			"%s: codec_data ops acknowledge() is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	switch (ucontrol->value.enumerated.item[0]) {
+	case 0:
+		ack_state = AUD_EXT_DISP_ACK_DISCONNECT;
+		break;
+	case 1:
+		ack_state = AUD_EXT_DISP_ACK_CONNECT;
+		break;
+	case 2:
+		ack_state = AUD_EXT_DISP_ACK_ENABLE;
+		break;
+	default:
+		rc = -EINVAL;
+		dev_err_ratelimited(component->dev,
+			"%s: invalid value %d for mixer ctl\n",
+			__func__, ucontrol->value.enumerated.item[0]);
+		goto err;
+	}
+	dev_dbg(component->dev, "%s: control %d, ack set value 0x%x\n",
+		__func__, ucontrol->value.enumerated.item[0], ack_state);
+
+	rc = codec_data->ext_disp_ops.acknowledge(
+			 codec_data->ext_disp_core_pdev, ack_state);
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (rc < 0) {
+		dev_err_ratelimited(component->dev, "%s: error from acknowledge(), err:%d\n",
+			__func__, rc);
+	}
+	return rc;
+
+err:
+	mutex_unlock(&codec_data->dp_ops_lock);
+	return rc;
+}
+
+static int msm_ext_disp_audio_device_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	int rc = 0;
+	int dai_id = ((struct soc_multi_mixer_control *)
+				kcontrol->private_value)->shift;
+
+	if (dai_id < 0 || dai_id > DP_DAI2) {
+		dev_err_ratelimited(component->dev,
+			"%s: invalid dai id: %d\n", __func__, dai_id);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev,
+			"%s: codec_data or ops acknowledge() is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto done;
+	}
+	ucontrol->value.integer.value[0] = codec_data->ctl[dai_id];
+	ucontrol->value.integer.value[1] = codec_data->stream[dai_id];
+
+done:
+	return rc;
+}
+
+static int msm_ext_disp_audio_device_set(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	int rc = 0;
+	int dai_id = ((struct soc_multi_mixer_control *)
+				kcontrol->private_value)->shift;
+
+	if (dai_id < 0 || dai_id > DP_DAI2) {
+		dev_err_ratelimited(component->dev,
+			"%s: invalid dai id: %d\n", __func__, dai_id);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	codec_data = snd_soc_component_get_drvdata(component);
+	if (!codec_data) {
+		dev_err_ratelimited(component->dev,
+			"%s: codec_data or ops acknowledge() is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	if ((ucontrol->value.integer.value[0] > (DP_CONTROLLER_MAX - 1)) ||
+		(ucontrol->value.integer.value[1] > (DP_STREAM_MAX - 1)) ||
+		(ucontrol->value.integer.value[0] < 0) ||
+		(ucontrol->value.integer.value[1] < 0)) {
+		dev_err_ratelimited(component->dev,
+			"%s: DP audio control index invalid\n",
+			__func__);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	codec_data->ctl[dai_id] = ucontrol->value.integer.value[0];
+	codec_data->stream[dai_id] = ucontrol->value.integer.value[1];
+	mutex_unlock(&codec_data->dp_ops_lock);
+
+done:
+	return rc;
+}
+
+static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
+			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name   = "HDMI EDID",
+		.info   = msm_ext_disp_edid_ctl_info,
+		.get    = msm_ext_disp_edid_get,
+		.private_value = HDMI_DAI,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
+			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name   = "HDMI MS EDID",
+		.info   = msm_ext_disp_edid_ctl_info,
+		.get    = msm_ext_disp_edid_get,
+		.private_value = HDMI_MS_DAI,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
+			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name   = "Display Port EDID",
+		.info   = msm_ext_disp_edid_ctl_info,
+		.get    = msm_ext_disp_edid_get,
+		.private_value = DP_DAI1,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
+			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name   = "Display Port1 EDID",
+		.info   = msm_ext_disp_edid_ctl_info,
+		.get    = msm_ext_disp_edid_get,
+		.private_value = DP_DAI2,
+	},
+	SOC_ENUM_EXT("External Display Type",
+		     ext_disp_audio_type1,
+		     msm_ext_disp_audio_type_get, NULL),
+	SOC_ENUM_EXT("External Display1 Type",
+		     ext_disp_audio_type2,
+		     msm_ext_disp_audio_type_get, NULL),
+	SOC_ENUM_EXT("External HDMI Type",
+		     ext_disp_audio_type3,
+		     msm_ext_disp_audio_type_get, NULL),
+	SOC_ENUM_EXT("External Display Audio Ack",
+		     ext_disp_audio_ack_state1,
+		     NULL, msm_ext_disp_audio_ack_set),
+	SOC_ENUM_EXT("External Display1 Audio Ack",
+		     ext_disp_audio_ack_state2,
+		     NULL, msm_ext_disp_audio_ack_set),
+	SOC_ENUM_EXT("External HDMI Audio Ack",
+		     ext_disp_audio_ack_state3,
+		     NULL, msm_ext_disp_audio_ack_set),
+
+	SOC_SINGLE_MULTI_EXT("External Display Audio Device",
+			SND_SOC_NOPM, DP_DAI1, DP_STREAM_MAX - 1, 0, 2,
+			msm_ext_disp_audio_device_get,
+			msm_ext_disp_audio_device_set),
+	SOC_SINGLE_MULTI_EXT("External Display1 Audio Device",
+			SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2,
+			msm_ext_disp_audio_device_get,
+			msm_ext_disp_audio_device_set),
+	SOC_SINGLE_MULTI_EXT("External HDMI Device",
+			SND_SOC_NOPM, HDMI_MS_DAI, DP_STREAM_MAX - 1, 0, 2,
+			msm_ext_disp_audio_device_get,
+			msm_ext_disp_audio_device_set),
+
+};
+
+static int msm_ext_disp_audio_codec_rx_dai_startup(
+		struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	int ret = 0, rc = 0;
+	struct msm_ext_disp_codec_id codec_info;
+	struct msm_ext_disp_audio_codec_rx_data *codec_data =
+			dev_get_drvdata(dai->component->dev);
+	int type;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+
+	if (!codec_data) {
+		dev_err_ratelimited(dai->dev, "%s() codec_data is null\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (!rtd->dai_link->no_pcm)
+		snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+
+	dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
+		__func__,
+		codec_data->ctl[dai->id], codec_data->stream[dai->id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai->id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+
+	if (!codec_data->ext_disp_ops.cable_status || rc) {
+		dev_err_ratelimited(dai->dev, "%s() cable_status is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+
+	codec_data->cable_status[dai->id] =
+		codec_data->ext_disp_ops.cable_status(
+		codec_data->ext_disp_core_pdev, 1);
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (codec_data->cable_status[dai->id] < 0) {
+		dev_err_ratelimited(dai->dev,
+			"%s() ext disp core is not ready (ret val = %d)\n",
+			__func__, codec_data->cable_status[dai->id]);
+		ret = codec_data->cable_status[dai->id];
+	} else if (!codec_data->cable_status[dai->id]) {
+		dev_err_ratelimited(dai->dev,
+			"%s() ext disp cable is not connected (ret val = %d)\n",
+			__func__, codec_data->cable_status[dai->id]);
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
+static int msm_ext_disp_audio_codec_rx_dai_hw_params(
+		struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct snd_soc_dai *dai)
+{
+	u32 channel_allocation = 0;
+	u32 level_shift  = 0; /* 0dB */
+	bool down_mix = 0;
+	u32 num_channels = params_channels(params);
+	struct msm_ext_disp_codec_id codec_info;
+	int rc = 0;
+	struct msm_ext_disp_audio_setup_params audio_setup_params = {0};
+	int type;
+	struct msm_ext_disp_audio_codec_rx_data *codec_data =
+			dev_get_drvdata(dai->component->dev);
+
+	if (!codec_data) {
+		dev_err_ratelimited(dai->dev, "%s() codec_data is null\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
+		__func__,
+		codec_data->ctl[dai->id], codec_data->stream[dai->id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai->id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+
+	if (!codec_data->ext_disp_ops.audio_info_setup || rc) {
+		dev_err_ratelimited(dai->dev, "%s: audio_info_setup is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&codec_data->dp_ops_lock);
+
+	if (codec_data->cable_status[dai->id] < 0) {
+		dev_err_ratelimited(dai->dev,
+			"%s() ext disp core is not ready (ret val = %d)\n",
+			__func__, codec_data->cable_status[dai->id]);
+		return codec_data->cable_status[dai->id];
+	} else if (!codec_data->cable_status[dai->id]) {
+		dev_err_ratelimited(dai->dev,
+			"%s() ext disp cable is not connected (ret val = %d)\n",
+			__func__, codec_data->cable_status[dai->id]);
+		return -ENODEV;
+	}
+
+	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
+	switch (num_channels) {
+	case 2:
+		channel_allocation  = 0;
+		break;
+	case 3:
+		channel_allocation  = 0x02;/*default to FL/FR/FC*/
+		audio_setup_params.sample_present = 0x3;
+		break;
+	case 4:
+		channel_allocation  = 0x06;/*default to FL/FR/FC/RC*/
+		audio_setup_params.sample_present = 0x7;
+		break;
+	case 5:
+		channel_allocation  = 0x0A;/*default to FL/FR/FC/RR/RL*/
+		audio_setup_params.sample_present = 0x7;
+		break;
+	case 6:
+		channel_allocation  = 0x0B;
+		audio_setup_params.sample_present = 0x7;
+		break;
+	case 7:
+		channel_allocation  = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/
+		audio_setup_params.sample_present = 0xf;
+		break;
+	case 8:
+		channel_allocation  = 0x13;
+		audio_setup_params.sample_present = 0xf;
+		break;
+	default:
+		dev_err_ratelimited(dai->dev, "invalid Channels = %u\n", num_channels);
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->dev,
+		"%s() num_ch %u  samplerate %u channel_allocation = %u\n",
+		__func__, num_channels, params_rate(params),
+		channel_allocation);
+
+	audio_setup_params.sample_rate_hz = params_rate(params);
+	audio_setup_params.num_of_channels = num_channels;
+	audio_setup_params.channel_allocation = channel_allocation;
+	audio_setup_params.level_shift = level_shift;
+	audio_setup_params.down_mix = down_mix;
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (rc)
+		goto end;
+	rc = codec_data->ext_disp_ops.audio_info_setup(
+			codec_data->ext_disp_core_pdev, &audio_setup_params);
+end:
+	mutex_unlock(&codec_data->dp_ops_lock);
+	if (rc < 0) {
+		dev_err_ratelimited(dai->dev,
+			"%s() ext disp core is not ready, rc: %d\n",
+			__func__, rc);
+	}
+
+	return rc;
+}
+
+static void msm_ext_disp_audio_codec_rx_dai_shutdown(
+		struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	int rc = 0;
+	struct msm_ext_disp_codec_id codec_info;
+
+	struct msm_ext_disp_audio_codec_rx_data *codec_data =
+			dev_get_drvdata(dai->component->dev);
+	int type;
+
+	if (!codec_data) {
+		dev_err_ratelimited(dai->dev, "%s() codec_data is null\n",
+			__func__);
+		return;
+	}
+
+	dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
+		__func__,
+		codec_data->ctl[dai->id], codec_data->stream[dai->id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	if (dai->id == HDMI_MS_DAI)
+		type = EXT_DISPLAY_TYPE_HDMI;
+	else
+		type = EXT_DISPLAY_TYPE_DP;
+	SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+
+	if (!codec_data->ext_disp_ops.teardown_done ||
+	    !codec_data->ext_disp_ops.cable_status || rc) {
+		dev_err_ratelimited(dai->dev, "%s: teardown_done or cable_status is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return;
+	}
+
+	rc = codec_data->ext_disp_ops.cable_status(
+			codec_data->ext_disp_core_pdev, 0);
+	if (rc < 0) {
+		dev_err_ratelimited(dai->dev,
+			"%s: ext disp core had problems releasing audio flag\n",
+			__func__);
+	}
+
+	codec_data->ext_disp_ops.teardown_done(
+		codec_data->ext_disp_core_pdev);
+	mutex_unlock(&codec_data->dp_ops_lock);
+}
+
+static int msm_ext_disp_audio_codec_rx_probe(
+		struct snd_soc_component *component)
+{
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+	struct device_node *of_node_parent = NULL;
+
+	codec_data = kzalloc(sizeof(struct msm_ext_disp_audio_codec_rx_data),
+		GFP_KERNEL);
+
+	if (!codec_data) {
+		dev_err(component->dev, "%s(): fail to allocate dai data\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	of_node_parent = of_get_parent(component->dev->of_node);
+	if (!of_node_parent) {
+		dev_err(component->dev, "%s(): Parent device tree node not found\n",
+				__func__);
+		kfree(codec_data);
+		return -ENODEV;
+	}
+
+	codec_data->ext_disp_core_pdev = of_find_device_by_node(of_node_parent);
+	if (!codec_data->ext_disp_core_pdev) {
+		dev_err(component->dev, "%s(): can't get parent pdev\n",
+			__func__);
+		kfree(codec_data);
+		return -ENODEV;
+	}
+
+	if (msm_ext_disp_register_audio_codec(codec_data->ext_disp_core_pdev,
+				&codec_data->ext_disp_ops)) {
+		dev_err(component->dev, "%s(): can't register with ext disp core",
+				__func__);
+		kfree(codec_data);
+		return -ENODEV;
+	}
+
+	mutex_init(&codec_data->dp_ops_lock);
+	dev_set_drvdata(component->dev, codec_data);
+
+	dev_dbg(component->dev, "%s(): registered %s with ext disp core\n",
+		__func__, component->name);
+
+	return 0;
+}
+
+static void msm_ext_disp_audio_codec_rx_remove(
+		struct snd_soc_component *component)
+{
+	struct msm_ext_disp_audio_codec_rx_data *codec_data;
+
+	codec_data = dev_get_drvdata(component->dev);
+	mutex_destroy(&codec_data->dp_ops_lock);
+	kfree(codec_data);
+
+	return;
+}
+
+static struct snd_soc_dai_ops msm_ext_disp_audio_codec_rx_dai_ops = {
+	.startup   = msm_ext_disp_audio_codec_rx_dai_startup,
+	.hw_params = msm_ext_disp_audio_codec_rx_dai_hw_params,
+	.shutdown  = msm_ext_disp_audio_codec_rx_dai_shutdown
+};
+
+static struct snd_soc_dai_driver msm_ext_disp_audio_codec_rx_dais[] = {
+	{
+		.name = "msm_hdmi_audio_codec_rx_dai",
+		.id = HDMI_DAI,
+		.playback = {
+			.stream_name = "HDMI Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min = 48000,
+			.rate_max = 48000,
+			.rates = MSM_EXT_DISP_PCM_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
+	},
+	{
+		.name = "msm_hdmi_ms_audio_codec_rx_dai",
+		.id = HDMI_MS_DAI,
+		.playback = {
+			.stream_name = "HDMI MS Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min = 48000,
+			.rate_max = 48000,
+			.rates = MSM_EXT_DISP_PCM_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
+	},
+	{
+		.name = "msm_dp_audio_codec_rx_dai",
+		.id = DP_DAI1,
+		.playback = {
+			.stream_name = "Display Port Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min = 32000,
+			.rate_max = 192000,
+			.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+				SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |
+                                SNDRV_PCM_RATE_176400,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE |
+				SNDRV_PCM_FMTBIT_S24_3LE,
+		},
+		.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
+	},
+	{
+		.name = "msm_dp_audio_codec_rx1_dai",
+		.id = DP_DAI2,
+		.playback = {
+			.stream_name = "Display Port1 Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min = 48000,
+			.rate_max = 192000,
+			.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+				SNDRV_PCM_RATE_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE |
+				SNDRV_PCM_FMTBIT_S24_3LE,
+		},
+		.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
+	},
+};
+
+static const struct snd_soc_component_driver msm_ext_disp_codec_rx_driver = {
+	.name = DRV_NAME,
+	.probe = msm_ext_disp_audio_codec_rx_probe,
+	.remove =  msm_ext_disp_audio_codec_rx_remove,
+	.controls = msm_ext_disp_codec_rx_controls,
+	.num_controls = ARRAY_SIZE(msm_ext_disp_codec_rx_controls),
+};
+
+static int msm_ext_disp_audio_codec_rx_plat_probe(
+		struct platform_device *pdev)
+{
+	dev_dbg(&pdev->dev, "%s(): dev name %s\n", __func__,
+		dev_name(&pdev->dev));
+
+	return snd_soc_register_component(&pdev->dev,
+		&msm_ext_disp_codec_rx_driver,
+		msm_ext_disp_audio_codec_rx_dais,
+		ARRAY_SIZE(msm_ext_disp_audio_codec_rx_dais));
+}
+
+static int msm_ext_disp_audio_codec_rx_plat_remove(
+		struct platform_device *pdev)
+{
+	snd_soc_unregister_component(&pdev->dev);
+	return 0;
+}
+static const struct of_device_id msm_ext_disp_audio_codec_rx_dt_match[] = {
+	{ .compatible = "qcom,msm-ext-disp-audio-codec-rx", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_ext_disp_audio_codec_rx_dt_match);
+
+static struct platform_driver msm_ext_disp_audio_codec_rx_driver = {
+	.driver = {
+		.name = "msm-ext-disp-audio-codec-rx",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_ext_disp_audio_codec_rx_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_ext_disp_audio_codec_rx_plat_probe,
+	.remove = msm_ext_disp_audio_codec_rx_plat_remove,
+};
+
+static int __init msm_ext_disp_audio_codec_rx_init(void)
+{
+	int rc = 0;
+
+	rc = platform_driver_register(&msm_ext_disp_audio_codec_rx_driver);
+	if (rc) {
+		pr_err("%s: failed to register ext disp codec driver err:%d\n",
+		       __func__, rc);
+	}
+
+	return rc;
+}
+module_init(msm_ext_disp_audio_codec_rx_init);
+
+static void __exit msm_ext_disp_audio_codec_rx_exit(void)
+{
+	platform_driver_unregister(&msm_ext_disp_audio_codec_rx_driver);
+}
+module_exit(msm_ext_disp_audio_codec_rx_exit);
+
+MODULE_DESCRIPTION("MSM External Display Audio CODEC Driver");
+MODULE_LICENSE("GPL v2");

+ 92 - 0
qcom/opensource/audio-kernel/asoc/codecs/msm_stub.c

@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2011-2014, 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "msm-stub-codec"
+
+/* A dummy driver useful only to advertise hardware parameters */
+static struct snd_soc_dai_driver msm_stub_dais[] = {
+	{
+		.name = "msm-stub-rx",
+		.playback = { /* Support maximum range */
+			.stream_name = "Playback",
+			.channels_min = 1,
+			.channels_max = 32,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE |
+				    SNDRV_PCM_FMTBIT_S24_3LE |
+				    SNDRV_PCM_FMTBIT_S32_LE),
+		},
+	},
+	{
+		.name = "msm-stub-tx",
+		.capture = { /* Support maximum range */
+			.stream_name = "Record",
+			.channels_min = 1,
+			.channels_max = 32,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE |
+				    SNDRV_PCM_FMTBIT_S24_3LE |
+				    SNDRV_PCM_FMTBIT_S32_LE),
+		},
+	},
+};
+
+static const struct snd_soc_component_driver soc_msm_stub = {
+	.name = DRV_NAME,
+};
+
+static int msm_stub_dev_probe(struct platform_device *pdev)
+{
+	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
+
+	return snd_soc_register_component(&pdev->dev,
+	&soc_msm_stub, msm_stub_dais, ARRAY_SIZE(msm_stub_dais));
+}
+
+static int msm_stub_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_component(&pdev->dev);
+	return 0;
+}
+static const struct of_device_id msm_stub_codec_dt_match[] = {
+	{ .compatible = "qcom,msm-stub-codec", },
+	{}
+};
+
+static struct platform_driver msm_stub_driver = {
+	.driver = {
+		.name = "msm-stub-codec",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_stub_codec_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_stub_dev_probe,
+	.remove = msm_stub_dev_remove,
+};
+
+static int __init msm_stub_init(void)
+{
+	return platform_driver_register(&msm_stub_driver);
+}
+module_init(msm_stub_init);
+
+static void __exit msm_stub_exit(void)
+{
+	platform_driver_unregister(&msm_stub_driver);
+}
+module_exit(msm_stub_exit);
+
+MODULE_DESCRIPTION("Generic MSM CODEC driver");
+MODULE_LICENSE("GPL v2");

+ 120 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/Kbuild

@@ -0,0 +1,120 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(ANDROID_BUILD_TOP)/kernel/msm-4.19
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_BENGAL), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ ROULEUR ############
+
+# for ROULEUR Codec
+ifdef CONFIG_SND_SOC_ROULEUR
+	ROULEUR_OBJS += rouleur.o
+	ROULEUR_OBJS += rouleur-regmap.o
+	ROULEUR_OBJS += rouleur-tables.o
+	ROULEUR_OBJS += rouleur-mbhc.o
+endif
+
+ifdef CONFIG_PM2250_SPMI
+	PM2250_SPMI_OBJS += pm2250_spmi.o
+endif
+
+ifdef CONFIG_SND_SOC_ROULEUR_SLAVE
+	ROULEUR_SLAVE_OBJS += rouleur_slave.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_ROULEUR) += rouleur_dlkm.o
+rouleur_dlkm-y := $(ROULEUR_OBJS)
+
+obj-$(CONFIG_SND_SOC_ROULEUR_SLAVE) += rouleur_slave_dlkm.o
+rouleur_slave_dlkm-y := $(ROULEUR_SLAVE_OBJS)
+
+obj-$(CONFIG_PM2250_SPMI) += pm2250_spmi_dlkm.o
+pm2250_spmi_dlkm-y := $(PM2250_SPMI_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 168 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/internal.h

@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _ROULEUR_INTERNAL_H
+#define _ROULEUR_INTERNAL_H
+
+#include <asoc/wcd-clsh.h>
+#include <asoc/wcd-mbhc-v2.h>
+#include <asoc/wcd-irq.h>
+#include "rouleur-mbhc.h"
+
+#define ROULEUR_MAX_MICBIAS 3
+
+/* Convert from vout ctl to micbias voltage in mV */
+#define  WCD_VOUT_CTL_TO_MICB(v)  (1600 + v * 50)
+#define MAX_PORT 8
+#define MAX_CH_PER_PORT 8
+
+extern struct regmap_config rouleur_regmap_config;
+
+struct codec_port_info {
+	u32 slave_port_type;
+	u32 master_port_type;
+	u32 ch_mask;
+	u32 num_ch;
+	u32 ch_rate;
+};
+
+struct rouleur_priv {
+	struct device *dev;
+
+	int variant;
+	struct snd_soc_component *component;
+	struct device_node *spmi_np;
+	struct regmap *regmap;
+
+	struct swr_device *rx_swr_dev;
+	struct swr_device *tx_swr_dev;
+
+	s32 micb_ref[ROULEUR_MAX_MICBIAS];
+	s32 pullup_ref[ROULEUR_MAX_MICBIAS];
+
+	struct fw_info *fw_data;
+
+	struct mutex micb_lock;
+	s32 dmic_0_1_clk_cnt;
+	/* mbhc module */
+	struct rouleur_mbhc *mbhc;
+
+	bool comp1_enable;
+	bool comp2_enable;
+	bool dapm_bias_off;
+
+	struct irq_domain *virq;
+	struct wcd_irq_info irq_info;
+	u32 rx_clk_cnt;
+	int num_irq_regs;
+	/* to track the status */
+	unsigned long status_mask;
+
+	u8 num_tx_ports;
+	u8 num_rx_ports;
+	struct codec_port_info
+			tx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
+	struct codec_port_info
+			rx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
+	struct regulator_bulk_data *supplies;
+	struct notifier_block nblock;
+	/* wcd callback to bolero */
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				struct notifier_block *nblock,
+				bool enable);
+	int (*wakeup)(void *handle, bool enable);
+	u32 version;
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+	struct device *spmi_dev;
+	int reset_reg;
+	int mbias_cnt;
+	struct mutex rx_clk_lock;
+	struct mutex main_bias_lock;
+	bool dev_up;
+	bool usbc_hs_status;
+	struct notifier_block psy_nb;
+	struct work_struct soc_eval_work;
+	bool low_soc;
+	int foundry_id_reg;
+	int foundry_id;
+};
+
+struct rouleur_micbias_setting {
+	u32 micb1_mv;
+	u32 micb2_mv;
+	u32 micb3_mv;
+};
+
+struct rouleur_pdata {
+	struct device_node *spmi_np;
+	struct device_node *rx_slave;
+	struct device_node *tx_slave;
+	struct rouleur_micbias_setting micbias;
+
+	struct cdc_regulator *regulator;
+	int num_supplies;
+	int reset_reg;
+	int foundry_id_reg;
+};
+
+struct wcd_ctrl_platform_data {
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				 struct notifier_block *nblock,
+				 bool enable);
+};
+
+enum {
+	WCD_RX1,
+	WCD_RX2,
+	WCD_RX3
+};
+
+enum {
+	/* INTR_CTRL_INT_MASK_0 */
+	ROULEUR_IRQ_MBHC_BUTTON_PRESS_DET = 0,
+	ROULEUR_IRQ_MBHC_BUTTON_RELEASE_DET,
+	ROULEUR_IRQ_MBHC_ELECT_INS_REM_DET,
+	ROULEUR_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	ROULEUR_IRQ_MBHC_SW_DET,
+	ROULEUR_IRQ_HPHR_OCP_INT,
+	ROULEUR_IRQ_HPHR_CNP_INT,
+	ROULEUR_IRQ_HPHL_OCP_INT,
+
+	/* INTR_CTRL_INT_MASK_1 */
+	ROULEUR_IRQ_HPHL_CNP_INT,
+	ROULEUR_IRQ_EAR_CNP_INT,
+	ROULEUR_IRQ_EAR_OCP_INT,
+	ROULEUR_IRQ_LO_CNP_INT,
+	ROULEUR_IRQ_LO_OCP_INT,
+	ROULEUR_IRQ_HPHL_PDM_WD_INT,
+	ROULEUR_IRQ_HPHR_PDM_WD_INT,
+	ROULEUR_IRQ_RESERVED_0,
+
+	/* INTR_CTRL_INT_MASK_2 */
+	ROULEUR_IRQ_RESERVED_1,
+	ROULEUR_IRQ_RESERVED_2,
+	ROULEUR_IRQ_HPHL_SURGE_DET_INT,
+	ROULEUR_IRQ_HPHR_SURGE_DET_INT,
+	ROULEUR_NUM_IRQS,
+};
+
+extern void rouleur_disable_bcs_before_slow_insert(
+				struct snd_soc_component *component,
+				bool bcs_disable);
+extern struct rouleur_mbhc *rouleur_soc_get_mbhc(
+				struct snd_soc_component *component);
+extern int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+					int volt, int micb_num);
+extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv);
+extern int rouleur_micbias_control(struct snd_soc_component *component,
+			int micb_num, int req, bool is_dapm);
+extern int rouleur_global_mbias_enable(struct snd_soc_component *component);
+extern int rouleur_global_mbias_disable(struct snd_soc_component *component);
+#endif

+ 22 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/pm2250-spmi.h

@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _PM2250_SPMI_H
+#define _PM2250_SPMI_H
+
+#ifdef CONFIG_PM2250_SPMI
+int pm2250_spmi_write(struct device *dev, int reg, int value);
+int pm2250_spmi_read(struct device *dev, int reg, int *value);
+#else
+int pm2250_spmi_write(struct device *dev, int reg, int value)
+{
+	return 0;
+}
+int pm2250_spmi_read(struct device *dev, int reg, int *value);
+{
+	return 0;
+}
+#endif	/* CONFIG_PM2250_SPMI */
+
+#endif

+ 128 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/pm2250_spmi.c

@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/**
+ * @regmap: regmap used to access PMIC registers
+ */
+struct pm2250_spmi {
+	struct regmap *regmap;
+};
+
+static const struct of_device_id pm2250_id_table[] = {
+	{ .compatible = "qcom,pm2250-spmi" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, pm2250_id_table);
+
+/**
+ * pm2250_spmi_write: Function to write to PMIC register
+ * @device: node for rouleur device
+ * @reg: PMIC register to write value
+ * @value: Value to be written to PMIC register
+ */
+int pm2250_spmi_write(struct device *dev, int reg, int value)
+{
+	int rc;
+	struct pm2250_spmi *spmi_dd;
+
+	if (!of_device_is_compatible(dev->of_node, "qcom,pm2250-spmi")) {
+		pr_err("%s: Device node is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	spmi_dd = dev_get_drvdata(dev);
+	if (!spmi_dd)
+		return -EINVAL;
+
+	rc = regmap_write(spmi_dd->regmap, reg, value);
+	if (rc)
+		dev_err(dev, "%s: Write to PMIC register failed\n", __func__);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm2250_spmi_write);
+
+/**
+ * pm2250_spmi_read: Function to read PMIC register
+ * @device: node for rouleur device
+ * @reg: PMIC register to read value
+ * @value: Pointer to value of reg to be read
+ */
+int pm2250_spmi_read(struct device *dev, int reg, int *value)
+{
+	int rc;
+	struct pm2250_spmi *spmi_dd;
+
+	if (!of_device_is_compatible(dev->of_node, "qcom,pm2250-spmi")) {
+		pr_err("%s: Device node is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	spmi_dd = dev_get_drvdata(dev);
+	if (!spmi_dd)
+		return -EINVAL;
+
+	rc = regmap_read(spmi_dd->regmap, reg, value);
+	if (rc)
+		dev_err(dev, "%s: Read from PMIC register failed\n", __func__);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm2250_spmi_read);
+
+static int pm2250_spmi_probe(struct platform_device *pdev)
+{
+	struct pm2250_spmi *spmi_dd;
+	const struct of_device_id *match;
+
+	match = of_match_node(pm2250_id_table, pdev->dev.of_node);
+	if (!match)
+		return -ENXIO;
+
+	spmi_dd = devm_kzalloc(&pdev->dev, sizeof(*spmi_dd), GFP_KERNEL);
+	if (spmi_dd == NULL)
+		return -ENOMEM;
+
+	spmi_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!spmi_dd->regmap) {
+		dev_err(&pdev->dev, "Parent regmap unavailable.\n");
+		return -ENXIO;
+	}
+
+	platform_set_drvdata(pdev, spmi_dd);
+
+	dev_dbg(&pdev->dev, "Probe success !!\n");
+
+	return 0;
+}
+
+static int pm2250_spmi_remove(struct platform_device *pdev)
+{
+	of_platform_depopulate(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver pm2250_spmi_driver = {
+	.probe		= pm2250_spmi_probe,
+	.remove		= pm2250_spmi_remove,
+	.driver	= {
+		.name		= "pm2250-spmi",
+		.of_match_table	= pm2250_id_table,
+	},
+};
+module_platform_driver(pm2250_spmi_driver);
+
+MODULE_ALIAS("platform:pm2250-spmi");
+MODULE_DESCRIPTION("PMIC SPMI driver");
+MODULE_LICENSE("GPL v2");

+ 1163 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-mbhc.c

@@ -0,0 +1,1163 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include "rouleur-registers.h"
+#include <asoc/wcdcal-hwdep.h>
+#include <asoc/wcd-mbhc-v2-api.h>
+#include "internal.h"
+
+#define ROULEUR_ZDET_SUPPORTED          true
+/* Z value defined in milliohm */
+#define ROULEUR_ZDET_VAL_100K           100000000
+/* Z floating defined in ohms */
+#define ROULEUR_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE
+
+#define ROULEUR_ZDET_NUM_MEASUREMENTS   100
+#define ROULEUR_ZDET_RMAX               1280000
+#define ROULEUR_ZDET_C1                 7500000
+#define ROULEUR_ZDET_C2                 187
+#define ROULEUR_ZDET_C3                 4500
+
+/* Cross connection thresholds in mV */
+#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 350
+#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 350
+
+#define IMPED_NUM_RETRY 5
+
+static struct wcd_mbhc_register
+	wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
+	WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
+			  ROULEUR_ANA_MBHC_MECH, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_DET_EN",
+			  ROULEUR_ANA_MBHC_MECH, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MECH_DETECTION_TYPE",
+			  ROULEUR_ANA_MBHC_MECH, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_CLAMP_CTL",
+			  ROULEUR_ANA_MBHC_PLUG_DETECT_CTL, 0x30, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_DETECTION_TYPE",
+			  ROULEUR_ANA_MBHC_ELECT, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_CTRL",
+			  ROULEUR_ANA_MBHC_PLUG_DETECT_CTL, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL",
+			  ROULEUR_ANA_MBHC_MECH, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PLUG_TYPE",
+			  ROULEUR_ANA_MBHC_MECH, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_PLUG_TYPE",
+			  ROULEUR_ANA_MBHC_MECH, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SW_HPH_LP_100K_TO_GND",
+			  ROULEUR_ANA_MBHC_MECH, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_SCHMT_ISRC",
+			  ROULEUR_ANA_MBHC_ELECT, 0x06, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_EN",
+			  ROULEUR_ANA_MBHC_ELECT, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_INSREM_DBNC",
+			  ROULEUR_ANA_MBHC_PLUG_DETECT_CTL, 0x0F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_DBNC",
+			  ROULEUR_ANA_MBHC_CTL_1, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_VREF",
+			  ROULEUR_ANA_MBHC_CTL_2, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_COMP_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_IN2P_CLAMP_STATE",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_SCHMT_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_SCHMT_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_SCHMT_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_OCP_FSM_EN",
+			  SND_SOC_NOPM, 0x00, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x07, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_ISRC_CTL",
+			  ROULEUR_ANA_MBHC_ELECT, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
+			  ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x06, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
+			  SND_SOC_NOPM, 0x00, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PA_EN",
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_PA_EN",
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
+			  ROULEUR_ANA_MBHC_RESULT_3, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_PULLDOWN_CTRL",
+			  0, 0, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ANC_DET_EN",
+			  SND_SOC_NOPM, 0x00, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_STATUS",
+			  ROULEUR_ANA_MBHC_FSM_STATUS, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
+			  ROULEUR_ANA_MBHC_CTL_2, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_STATUS",
+			  ROULEUR_ANA_MBHC_FSM_STATUS, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_GND",
+			  SND_SOC_NOPM, 0x00, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_GND",
+			  SND_SOC_NOPM, 0x00, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_DET_EN",
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x02, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_DET_EN",
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_STATUS",
+			  ROULEUR_DIG_SWR_INTR_STATUS_0, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_STATUS",
+			  ROULEUR_DIG_SWR_INTR_STATUS_0, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_EN",
+			  ROULEUR_ANA_MBHC_CTL_1, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_COMPLETE", ROULEUR_ANA_MBHC_FSM_STATUS,
+			  0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_TIMEOUT", ROULEUR_ANA_MBHC_FSM_STATUS,
+			  0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_RESULT", ROULEUR_ANA_MBHC_ADC_RESULT,
+			  0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB2_VOUT",
+			  ROULEUR_ANA_MICBIAS_LDO_1_SETTING, 0xF8, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_MODE",
+			  ROULEUR_ANA_MBHC_CTL_1, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_DETECTION_DONE",
+			  ROULEUR_ANA_MBHC_CTL_1, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_ISRC_EN",
+			  ROULEUR_ANA_MBHC_ZDET, 0x02, 1, 0),
+};
+
+static const struct wcd_mbhc_intr intr_ids = {
+	.mbhc_sw_intr =  ROULEUR_IRQ_MBHC_SW_DET,
+	.mbhc_btn_press_intr = ROULEUR_IRQ_MBHC_BUTTON_PRESS_DET,
+	.mbhc_btn_release_intr = ROULEUR_IRQ_MBHC_BUTTON_RELEASE_DET,
+	.mbhc_hs_ins_intr = ROULEUR_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	.mbhc_hs_rem_intr = ROULEUR_IRQ_MBHC_ELECT_INS_REM_DET,
+	.hph_left_ocp = ROULEUR_IRQ_HPHL_OCP_INT,
+	.hph_right_ocp = ROULEUR_IRQ_HPHR_OCP_INT,
+};
+
+struct rouleur_mbhc_zdet_param {
+	u16 ldo_ctl;
+	u16 noff;
+	u16 nshift;
+};
+
+static int rouleur_mbhc_request_irq(struct snd_soc_component *component,
+				  int irq, irq_handler_t handler,
+				  const char *name, void *data)
+{
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+
+	return wcd_request_irq(&rouleur->irq_info, irq, name, handler, data);
+}
+
+static void rouleur_mbhc_irq_control(struct snd_soc_component *component,
+				   int irq, bool enable)
+{
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+
+	if (enable)
+		wcd_enable_irq(&rouleur->irq_info, irq);
+	else
+		wcd_disable_irq(&rouleur->irq_info, irq);
+}
+
+static int rouleur_mbhc_free_irq(struct snd_soc_component *component,
+			       int irq, void *data)
+{
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+
+	wcd_free_irq(&rouleur->irq_info, irq, data);
+
+	return 0;
+}
+
+static void rouleur_mbhc_clk_setup(struct snd_soc_component *component,
+				 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1,
+				    0x80, 0x80);
+	else
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1,
+				    0x80, 0x00);
+}
+
+static int rouleur_mbhc_btn_to_num(struct snd_soc_component *component)
+{
+	return snd_soc_component_read32(component, ROULEUR_ANA_MBHC_RESULT_3) &
+				0x7;
+}
+
+static void rouleur_mbhc_mbhc_bias_control(struct snd_soc_component *component,
+					 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT,
+				    0x01, 0x01);
+	else
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT,
+				    0x01, 0x00);
+}
+
+static void rouleur_mbhc_program_btn_thr(struct snd_soc_component *component,
+				       s16 *btn_low, s16 *btn_high,
+				       int num_btn, bool is_micbias)
+{
+	int i;
+	int vth;
+
+	if (num_btn > WCD_MBHC_DEF_BUTTONS) {
+		dev_err(component->dev, "%s: invalid number of buttons: %d\n",
+			__func__, num_btn);
+		return;
+	}
+
+	for (i = 0; i < num_btn; i++) {
+		vth = ((btn_high[i] * 2) / 25) & 0x3F;
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1 + i,
+				0xFC, vth << 2);
+		dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",
+			__func__, i, btn_high[i], vth);
+	}
+}
+
+static bool rouleur_mbhc_lock_sleep(struct wcd_mbhc *mbhc, bool lock)
+{
+	struct snd_soc_component *component = mbhc->component;
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+
+	rouleur->wakeup((void *)rouleur, lock);
+	return true;
+}
+
+static int rouleur_mbhc_register_notifier(struct wcd_mbhc *mbhc,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct rouleur_mbhc *rouleur_mbhc;
+
+	rouleur_mbhc = container_of(mbhc, struct rouleur_mbhc, wcd_mbhc);
+
+	if (enable)
+		return blocking_notifier_chain_register(&rouleur_mbhc->notifier,
+							nblock);
+	else
+		return blocking_notifier_chain_unregister(
+				&rouleur_mbhc->notifier, nblock);
+}
+
+static bool rouleur_mbhc_micb_en_status(struct wcd_mbhc *mbhc, int micb_num)
+{
+	u8 val = 0;
+
+	if (micb_num == MIC_BIAS_2) {
+		val = ((snd_soc_component_read32(mbhc->component,
+				ROULEUR_ANA_MICBIAS_MICB_1_2_EN) & 0x04)
+				>> 2);
+		if (val == 0x01)
+			return true;
+	}
+	return false;
+}
+
+static bool rouleur_mbhc_hph_pa_on_status(struct snd_soc_component *component)
+{
+	return (snd_soc_component_read32(component, ROULEUR_ANA_HPHPA_PA_STATUS)
+					& 0xFF) ? true : false;
+}
+
+static void rouleur_mbhc_hph_l_pull_up_control(
+				struct snd_soc_component *component,
+				int pull_up_cur)
+{
+	/* Default pull up current to 2uA */
+	if (pull_up_cur < I_OFF || pull_up_cur > I_3P0_UA ||
+	    pull_up_cur == I_DEFAULT)
+		pull_up_cur = I_3P0_UA;
+
+	dev_dbg(component->dev, "%s: HS pull up current:%d\n",
+		__func__, pull_up_cur);
+
+	snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBHC_PLUG_DETECT_CTL,
+				0xC0, pull_up_cur << 6);
+}
+
+static int rouleur_mbhc_request_micbias(struct snd_soc_component *component,
+					int micb_num, int req)
+{
+	int ret = 0;
+
+	ret = rouleur_micbias_control(component, micb_num, req, false);
+
+	return ret;
+}
+
+static void rouleur_mbhc_micb_ramp_control(struct snd_soc_component *component,
+					   bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component,
+					ROULEUR_ANA_MBHC_MICB2_RAMP,
+					0x1C, 0x0C);
+		snd_soc_component_update_bits(component,
+					ROULEUR_ANA_MBHC_MICB2_RAMP,
+					0x80, 0x80);
+	} else {
+		snd_soc_component_update_bits(component,
+					ROULEUR_ANA_MBHC_MICB2_RAMP,
+					0x80, 0x00);
+		snd_soc_component_update_bits(component,
+					ROULEUR_ANA_MBHC_MICB2_RAMP,
+					0x1C, 0x00);
+	}
+}
+
+static struct firmware_cal *rouleur_get_hwdep_fw_cal(struct wcd_mbhc *mbhc,
+						   enum wcd_cal_type type)
+{
+	struct rouleur_mbhc *rouleur_mbhc;
+	struct firmware_cal *hwdep_cal;
+	struct snd_soc_component *component = mbhc->component;
+
+	rouleur_mbhc = container_of(mbhc, struct rouleur_mbhc, wcd_mbhc);
+
+	if (!component) {
+		pr_err("%s: NULL component pointer\n", __func__);
+		return NULL;
+	}
+	hwdep_cal = wcdcal_get_fw_cal(rouleur_mbhc->fw_data, type);
+	if (!hwdep_cal)
+		dev_err(component->dev, "%s: cal not sent by %d\n",
+			__func__, type);
+
+	return hwdep_cal;
+}
+
+static int rouleur_mbhc_micb_ctrl_threshold_mic(
+					struct snd_soc_component *component,
+					int micb_num, bool req_en)
+{
+	struct rouleur_pdata *pdata = dev_get_platdata(component->dev);
+	int rc, micb_mv;
+
+	if (micb_num != MIC_BIAS_2)
+		return -EINVAL;
+	/*
+	 * If device tree micbias level is already above the minimum
+	 * voltage needed to detect threshold microphone, then do
+	 * not change the micbias, just return.
+	 */
+	if (pdata->micbias.micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)
+		return 0;
+
+	micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : pdata->micbias.micb2_mv;
+
+	rc = rouleur_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
+
+	return rc;
+}
+
+static void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur,
+					   struct snd_soc_component *component,
+					   int32_t *zdet)
+{
+	int i;
+	int zcode = 0, zcode1 = 0, zdet_cal_result = 0, zdet_est_range = 0;
+	int noff = 0, ndac = 14;
+	int zdet_cal_coeff = 0, div_ratio = 0;
+	int num = 0, denom = 0;
+
+	/* Charge enable and wait for zcode to be updated */
+	regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x20);
+	for (i = 0; i < ROULEUR_ZDET_NUM_MEASUREMENTS; i++) {
+		regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode);
+		if (zcode & 0x80)
+			break;
+		usleep_range(200, 210);
+	}
+
+	/* If zcode updation is not complete, give additional 10ms */
+	if (!(zcode & 0x80))
+		usleep_range(10000, 10100);
+
+	regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode);
+	if (!(zcode & 0x80)) {
+		dev_dbg(rouleur->dev,
+			"%s: Impedance detect calculation error, zcode=0x%x\n",
+			__func__, zcode);
+		regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET,
+				   0x20, 0x00);
+		return;
+	}
+	zcode = zcode << 0x8;
+	zcode = zcode & 0x3FFF;
+	regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &zcode1);
+	zcode |= zcode1;
+
+	dev_dbg(rouleur->dev,
+		"%s: zcode: %d, zcode1: %d\n", __func__, zcode, zcode1);
+
+	/* Calculate calibration coefficient */
+	zdet_cal_result = (snd_soc_component_read32(component,
+				ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)) & 0x1F;
+	zdet_cal_coeff = ROULEUR_ZDET_C1 /
+			((ROULEUR_ZDET_C2 * zdet_cal_result) + ROULEUR_ZDET_C3);
+	/* Rload calculation */
+	zdet_est_range = (snd_soc_component_read32(component,
+			  ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT) & 0x60) >> 5;
+
+	dev_dbg(rouleur->dev,
+		"%s: zdet_cal_result: %d, zdet_cal_coeff: %d, zdet_est_range: %d\n",
+		__func__, zdet_cal_result, zdet_cal_coeff, zdet_est_range);
+	switch (zdet_est_range) {
+	case 0:
+	default:
+		noff = 0;
+		div_ratio = 320;
+		break;
+	case 1:
+		noff = 0;
+		div_ratio = 64;
+		break;
+	case 2:
+		noff = 4;
+		div_ratio = 64;
+		break;
+	case 3:
+		noff = 5;
+		div_ratio = 40;
+		break;
+	}
+
+	num = zdet_cal_coeff * ROULEUR_ZDET_RMAX;
+	denom = ((zcode * div_ratio * 100) - (1 << (ndac - noff)) * 1000);
+	dev_dbg(rouleur->dev,
+		"%s: num: %d, denom: %d\n", __func__, num, denom);
+	if (denom > 0)
+		*zdet = (int32_t) ((num / denom) * 1000);
+	else
+		*zdet = ROULEUR_ZDET_FLOATING_IMPEDANCE;
+
+	dev_dbg(rouleur->dev, "%s: z_val=%d(milliOhm)\n",
+		__func__, *zdet);
+	/* Start discharge */
+	regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00);
+}
+
+static void rouleur_mbhc_zdet_start(struct snd_soc_component *component,
+				 int32_t *zl, int32_t *zr)
+{
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+	int32_t zdet = 0;
+
+	if (!zl)
+		goto z_right;
+
+	/* HPHL pull down switch to force OFF */
+	regmap_update_bits(rouleur->regmap,
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x00);
+	/* Averaging enable for reliable results */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80);
+	/* ZDET left measurement enable */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET, 0x80, 0x80);
+	/* Calculate the left Rload result */
+	rouleur_mbhc_get_result_params(rouleur, component, &zdet);
+
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET, 0x80, 0x00);
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00);
+	regmap_update_bits(rouleur->regmap,
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x20);
+
+	*zl = zdet;
+
+z_right:
+	if (!zr)
+		return;
+	/* HPHR pull down switch to force OFF */
+	regmap_update_bits(rouleur->regmap,
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x00);
+	/* Averaging enable for reliable results */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80);
+	/* ZDET right measurement enable */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET, 0x40, 0x40);
+
+	/* Calculate the right Rload result */
+	rouleur_mbhc_get_result_params(rouleur, component, &zdet);
+
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET, 0x40, 0x00);
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00);
+	regmap_update_bits(rouleur->regmap,
+			  ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x08);
+
+	*zr = zdet;
+}
+
+static void rouleur_mbhc_impedance_fn(struct snd_soc_component *component,
+				      int32_t *z1L, int32_t *z1R,
+				      int32_t *zl, int32_t *zr)
+{
+	int i;
+	for (i = 0; i < IMPED_NUM_RETRY; i++) {
+		/* Start of left ch impedance calculation */
+		rouleur_mbhc_zdet_start(component, z1L, NULL);
+		if ((*z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+		    (*z1L > ROULEUR_ZDET_VAL_100K))
+			*zl = ROULEUR_ZDET_FLOATING_IMPEDANCE;
+		else
+			*zl = *z1L/1000;
+
+		/* Start of right ch impedance calculation */
+		rouleur_mbhc_zdet_start(component, NULL, z1R);
+		if ((*z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+		    (*z1R > ROULEUR_ZDET_VAL_100K))
+			*zr = ROULEUR_ZDET_FLOATING_IMPEDANCE;
+		else
+			*zr = *z1R/1000;
+	}
+
+	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
+		__func__, *zl);
+	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
+		__func__, *zr);
+}
+
+static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
+					  uint32_t *zr)
+{
+	struct snd_soc_component *component = mbhc->component;
+	struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
+	s16 reg0;
+	int32_t z1L, z1R, z1Ls;
+	int zMono, z_diff1, z_diff2;
+	bool is_fsm_disable = false;
+
+	WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
+
+	reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT);
+
+	if (reg0 & 0x80) {
+		is_fsm_disable = true;
+		regmap_update_bits(rouleur->regmap,
+				   ROULEUR_ANA_MBHC_ELECT, 0x80, 0x00);
+	}
+
+	/* Enable electrical bias */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT,
+				      0x01, 0x01);
+
+	/* Enable codec main bias */
+	rouleur_global_mbias_enable(component);
+
+	/* Enable RCO clock */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1,
+				      0x80, 0x80);
+
+	/* For NO-jack, disable L_DET_EN before Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(rouleur->regmap,
+				   ROULEUR_ANA_MBHC_MECH, 0x80, 0x00);
+
+	/* Turn off 100k pull down on HPHL */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_MECH, 0x01, 0x00);
+
+	/*
+	 * Disable surge protection before impedance detection.
+	 * This is done to give correct value for high impedance.
+	 */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
+					0xC0, 0x00);
+	/* 1ms delay needed after disable surge protection */
+	usleep_range(1000, 1010);
+
+	/*
+	 * Call impedance detection routine multiple times
+	 * in order to avoid wrong impedance values.
+	 */
+	rouleur_mbhc_impedance_fn(component, &z1L, &z1R, zl, zr);
+
+	/* Mono/stereo detection */
+	if ((*zl == ROULEUR_ZDET_FLOATING_IMPEDANCE) &&
+		(*zr == ROULEUR_ZDET_FLOATING_IMPEDANCE)) {
+		dev_dbg(component->dev,
+			"%s: plug type is invalid or extension cable\n",
+			__func__);
+		goto zdet_complete;
+	}
+	if ((*zl == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+	    (*zr == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+	    ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||
+	    ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {
+		dev_dbg(component->dev,
+			"%s: Mono plug type with one ch floating or shorted to GND\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_MONO;
+		goto zdet_complete;
+	}
+
+	z1Ls = z1L/1000;
+	/* Parallel of left Z and 20 ohm pull down resistor */
+	zMono = ((*zl) * 20) / ((*zl) + 20);
+	z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
+	z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
+	if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
+		dev_dbg(component->dev, "%s: stereo plug type detected\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+	} else {
+		dev_dbg(component->dev, "%s: MONO plug type detected\n",
+			__func__);
+		mbhc->hph_type = WCD_MBHC_HPH_MONO;
+	}
+
+zdet_complete:
+	/* Enable surge protection again after impedance detection */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
+	/* Turn on 100k pull down on HPHL */
+	regmap_update_bits(rouleur->regmap,
+			   ROULEUR_ANA_MBHC_MECH, 0x01, 0x01);
+
+	/* For NO-jack, re-enable L_DET_EN after Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(rouleur->regmap,
+				   ROULEUR_ANA_MBHC_MECH, 0x80, 0x80);
+
+	/* Restore electrical bias state */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, 0x01,
+				      reg0 >> 7);
+	if (is_fsm_disable)
+		regmap_update_bits(rouleur->regmap,
+				   ROULEUR_ANA_MBHC_ELECT, 0x80, 0x80);
+	rouleur_global_mbias_disable(component);
+}
+
+static void rouleur_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
+			bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MECH,
+				    0x02, 0x02);
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MECH,
+				    0x40, 0x40);
+	} else {
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MECH,
+				    0x40, 0x00);
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MECH,
+				    0x02, 0x00);
+	}
+}
+
+static void rouleur_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
+					  bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component,
+				    ROULEUR_ANA_HPHPA_CNP_CTL_2,
+				    0x30, 0x20);
+		snd_soc_component_update_bits(component,
+				    ROULEUR_ANA_HPHPA_CNP_CTL_2,
+				    0x0C, 0x08);
+	} else {
+		snd_soc_component_update_bits(component,
+				    ROULEUR_ANA_HPHPA_CNP_CTL_2,
+				    0x30, 0x00);
+		snd_soc_component_update_bits(component,
+				    ROULEUR_ANA_HPHPA_CNP_CTL_2,
+				    0x0C, 0x00);
+	}
+}
+
+static void rouleur_mbhc_moisture_config(struct wcd_mbhc *mbhc)
+{
+	struct snd_soc_component *component = mbhc->component;
+
+	if ((mbhc->moist_rref == R_OFF) ||
+	    (mbhc->mbhc_cfg->enable_usbc_analog)) {
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+				    0x0C, R_OFF << 2);
+		return;
+	}
+
+	/* Do not enable moisture detection if jack type is NC */
+	if (!mbhc->hphl_swh) {
+		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+			__func__);
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+				    0x0C, R_OFF << 2);
+		return;
+	}
+
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+			    0x0C, mbhc->moist_rref << 2);
+}
+
+static void rouleur_mbhc_moisture_detect_en(struct wcd_mbhc *mbhc, bool enable)
+{
+	struct snd_soc_component *component = mbhc->component;
+
+	if (enable)
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+					0x0C, mbhc->moist_rref << 2);
+	else
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+				    0x0C, R_OFF << 2);
+}
+
+static bool rouleur_mbhc_get_moisture_status(struct wcd_mbhc *mbhc)
+{
+	struct snd_soc_component *component = mbhc->component;
+	bool ret = false;
+
+	if ((mbhc->moist_rref == R_OFF) ||
+	    (mbhc->mbhc_cfg->enable_usbc_analog)) {
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+				    0x0C, R_OFF << 2);
+		goto done;
+	}
+
+	/* Do not enable moisture detection if jack type is NC */
+	if (!mbhc->hphl_swh) {
+		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+			__func__);
+		snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
+				    0x0C, R_OFF << 2);
+		goto done;
+	}
+
+	/* If moisture_en is already enabled, then skip to plug type
+	 * detection.
+	 */
+	if ((snd_soc_component_read32(component, ROULEUR_ANA_MBHC_CTL_2) &
+			0x0C))
+		goto done;
+
+	rouleur_mbhc_moisture_detect_en(mbhc, true);
+	/* Read moisture comparator status */
+	ret = ((snd_soc_component_read32(component, ROULEUR_ANA_MBHC_FSM_STATUS)
+				& 0x20) ? 0 : 1);
+
+done:
+	return ret;
+
+}
+
+static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+						  bool bcs_enable)
+{
+	if (bcs_enable)
+		rouleur_disable_bcs_before_slow_insert(mbhc->component, false);
+	else
+		rouleur_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
+static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb)
+{
+	u8 vout_ctl = 0;
+
+	/* Read MBHC Micbias (Mic Bias2) voltage */
+	WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
+
+	/* Formula for getting micbias from vout
+	 * micbias = 1.6V + VOUT_CTL * 50mV
+	 */
+	*mb = 1600 + (vout_ctl * 50);
+	pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb);
+}
+
+static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc,
+						bool az_enable)
+{
+	if (az_enable)
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x08);
+	else
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x00);
+
+}
+
+static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc,
+						bool surge_enable)
+{
+	if (surge_enable)
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
+	else
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_SURGE_EN, 0xC0, 0x00);
+
+}
+
+static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc)
+{
+	mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD;
+	mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD;
+
+	pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n",
+			__func__, mbhc->hphl_cross_conn_thr,
+			mbhc->hphr_cross_conn_thr);
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+	.request_irq = rouleur_mbhc_request_irq,
+	.irq_control = rouleur_mbhc_irq_control,
+	.free_irq = rouleur_mbhc_free_irq,
+	.clk_setup = rouleur_mbhc_clk_setup,
+	.map_btn_code_to_num = rouleur_mbhc_btn_to_num,
+	.mbhc_bias = rouleur_mbhc_mbhc_bias_control,
+	.set_btn_thr = rouleur_mbhc_program_btn_thr,
+	.lock_sleep = rouleur_mbhc_lock_sleep,
+	.register_notifier = rouleur_mbhc_register_notifier,
+	.micbias_enable_status = rouleur_mbhc_micb_en_status,
+	.hph_pa_on_status = rouleur_mbhc_hph_pa_on_status,
+	.hph_pull_up_control = rouleur_mbhc_hph_l_pull_up_control,
+	.mbhc_micbias_control = rouleur_mbhc_request_micbias,
+	.mbhc_micb_ramp_control = rouleur_mbhc_micb_ramp_control,
+	.get_hwdep_fw_cal = rouleur_get_hwdep_fw_cal,
+	.mbhc_micb_ctrl_thr_mic = rouleur_mbhc_micb_ctrl_threshold_mic,
+	.compute_impedance = rouleur_wcd_mbhc_calc_impedance,
+	.mbhc_gnd_det_ctrl = rouleur_mbhc_gnd_det_ctrl,
+	.hph_pull_down_ctrl = rouleur_mbhc_hph_pull_down_ctrl,
+	.mbhc_moisture_config = rouleur_mbhc_moisture_config,
+	.mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status,
+	.mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en,
+	.bcs_enable = rouleur_mbhc_bcs_enable,
+	.get_micbias_val = rouleur_mbhc_get_micbias_val,
+	.mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control,
+	.mbhc_surge_ctl = rouleur_mbhc_surge_control,
+	.update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr,
+};
+
+static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct rouleur_mbhc *rouleur_mbhc = rouleur_soc_get_mbhc(component);
+	struct wcd_mbhc *mbhc;
+
+	if (!rouleur_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mbhc = &rouleur_mbhc->wcd_mbhc;
+
+	ucontrol->value.integer.value[0] = (u32) mbhc->hph_type;
+	dev_dbg(component->dev, "%s: hph_type = %u\n", __func__,
+		mbhc->hph_type);
+
+	return 0;
+}
+
+static int rouleur_hph_impedance_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	uint32_t zl = 0, zr = 0;
+	bool hphr;
+	struct soc_multi_mixer_control *mc;
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct rouleur_mbhc *rouleur_mbhc = rouleur_soc_get_mbhc(component);
+
+	if (!rouleur_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+	hphr = mc->shift;
+	wcd_mbhc_get_impedance(&rouleur_mbhc->wcd_mbhc, &zl, &zr);
+	dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__,
+		zl, zr);
+	ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+	SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+		       rouleur_get_hph_type, NULL),
+};
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+		       rouleur_hph_impedance_get, NULL),
+	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+		       rouleur_hph_impedance_get, NULL),
+};
+
+/*
+ * rouleur_mbhc_get_impedance: get impedance of headphone
+ * left and right channels
+ * @rouleur_mbhc: handle to struct rouleur_mbhc *
+ * @zl: handle to left-ch impedance
+ * @zr: handle to right-ch impedance
+ * return 0 for success or error code in case of failure
+ */
+int rouleur_mbhc_get_impedance(struct rouleur_mbhc *rouleur_mbhc,
+			     uint32_t *zl, uint32_t *zr)
+{
+	if (!rouleur_mbhc) {
+		pr_err("%s: mbhc not initialized!\n", __func__);
+		return -EINVAL;
+	}
+	if (!zl || !zr) {
+		pr_err("%s: zl or zr null!\n", __func__);
+		return -EINVAL;
+	}
+
+	return wcd_mbhc_get_impedance(&rouleur_mbhc->wcd_mbhc, zl, zr);
+}
+EXPORT_SYMBOL(rouleur_mbhc_get_impedance);
+
+/*
+ * rouleur_mbhc_hs_detect: starts mbhc insertion/removal functionality
+ * @component: handle to snd_soc_component *
+ * @mbhc_cfg: handle to mbhc configuration structure
+ * return 0 if mbhc_start is success or error code in case of failure
+ */
+int rouleur_mbhc_hs_detect(struct snd_soc_component *component,
+			 struct wcd_mbhc_config *mbhc_cfg)
+{
+	struct rouleur_priv *rouleur = NULL;
+	struct rouleur_mbhc *rouleur_mbhc = NULL;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	rouleur = snd_soc_component_get_drvdata(component);
+	if (!rouleur) {
+		pr_err("%s: rouleur is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	rouleur_mbhc = rouleur->mbhc;
+	if (!rouleur_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	return wcd_mbhc_start(&rouleur_mbhc->wcd_mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL(rouleur_mbhc_hs_detect);
+
+/*
+ * rouleur_mbhc_hs_detect_exit: stop mbhc insertion/removal functionality
+ * @component: handle to snd_soc_component *
+ */
+void rouleur_mbhc_hs_detect_exit(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = NULL;
+	struct rouleur_mbhc *rouleur_mbhc = NULL;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return;
+	}
+
+	rouleur = snd_soc_component_get_drvdata(component);
+	if (!rouleur) {
+		pr_err("%s: rouleur is NULL\n", __func__);
+		return;
+	}
+
+	rouleur_mbhc = rouleur->mbhc;
+	if (!rouleur_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n",
+			__func__);
+		return;
+	}
+	wcd_mbhc_stop(&rouleur_mbhc->wcd_mbhc);
+}
+EXPORT_SYMBOL(rouleur_mbhc_hs_detect_exit);
+
+/*
+ * rouleur_mbhc_ssr_down: stop mbhc during
+ * rouleur subsystem restart
+ * @mbhc: pointer to rouleur_mbhc structure
+ * @component: handle to snd_soc_component *
+ */
+void rouleur_mbhc_ssr_down(struct rouleur_mbhc *mbhc,
+			   struct snd_soc_component *component)
+{
+	struct wcd_mbhc *wcd_mbhc = NULL;
+
+	if (!mbhc || !component)
+		return;
+
+	wcd_mbhc = &mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		dev_err(component->dev, "%s: wcd_mbhc is NULL\n", __func__);
+		return;
+	}
+
+	rouleur_mbhc_hs_detect_exit(component);
+	wcd_mbhc_deinit(wcd_mbhc);
+}
+EXPORT_SYMBOL(rouleur_mbhc_ssr_down);
+
+/*
+ * rouleur_mbhc_post_ssr_init: initialize mbhc for
+ * rouleur post subsystem restart
+ * @mbhc: poniter to rouleur_mbhc structure
+ * @component: handle to snd_soc_component *
+ *
+ * return 0 if mbhc_init is success or error code in case of failure
+ */
+int rouleur_mbhc_post_ssr_init(struct rouleur_mbhc *mbhc,
+			     struct snd_soc_component *component)
+{
+	int ret = 0;
+	struct wcd_mbhc *wcd_mbhc = NULL;
+
+	if (!mbhc || !component)
+		return -EINVAL;
+
+	wcd_mbhc = &mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MECH,
+				0x20, 0x20);
+	ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb, &intr_ids,
+			    wcd_mbhc_registers, ROULEUR_ZDET_SUPPORTED);
+	if (ret)
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+
+	return ret;
+}
+EXPORT_SYMBOL(rouleur_mbhc_post_ssr_init);
+
+/*
+ * rouleur_mbhc_init: initialize mbhc for rouleur
+ * @mbhc: poniter to rouleur_mbhc struct pointer to store the configs
+ * @component: handle to snd_soc_component *
+ * @fw_data: handle to firmware data
+ *
+ * return 0 if mbhc_init is success or error code in case of failure
+ */
+int rouleur_mbhc_init(struct rouleur_mbhc **mbhc,
+		      struct snd_soc_component *component,
+		      struct fw_info *fw_data)
+{
+	struct rouleur_mbhc *rouleur_mbhc = NULL;
+	struct wcd_mbhc *wcd_mbhc = NULL;
+	struct rouleur_pdata *pdata;
+	int ret = 0;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	rouleur_mbhc = devm_kzalloc(component->dev, sizeof(struct rouleur_mbhc),
+				    GFP_KERNEL);
+	if (!rouleur_mbhc)
+		return -ENOMEM;
+
+	rouleur_mbhc->fw_data = fw_data;
+	BLOCKING_INIT_NOTIFIER_HEAD(&rouleur_mbhc->notifier);
+	wcd_mbhc = &rouleur_mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+
+	/* Setting default mbhc detection logic to ADC */
+	wcd_mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
+
+	pdata = dev_get_platdata(component->dev);
+	if (!pdata) {
+		dev_err(component->dev, "%s: pdata pointer is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	wcd_mbhc->micb_mv = pdata->micbias.micb2_mv;
+
+	ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb,
+				&intr_ids, wcd_mbhc_registers,
+				ROULEUR_ZDET_SUPPORTED);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+		goto err;
+	}
+
+	(*mbhc) = rouleur_mbhc;
+	snd_soc_add_component_controls(component, impedance_detect_controls,
+				   ARRAY_SIZE(impedance_detect_controls));
+	snd_soc_add_component_controls(component, hph_type_detect_controls,
+				   ARRAY_SIZE(hph_type_detect_controls));
+
+	return 0;
+err:
+	devm_kfree(component->dev, rouleur_mbhc);
+	return ret;
+}
+EXPORT_SYMBOL(rouleur_mbhc_init);
+
+/*
+ * rouleur_mbhc_deinit: deinitialize mbhc for rouleur
+ * @component: handle to snd_soc_component *
+ */
+void rouleur_mbhc_deinit(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur;
+	struct rouleur_mbhc *rouleur_mbhc;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return;
+	}
+
+	rouleur = snd_soc_component_get_drvdata(component);
+	if (!rouleur) {
+		pr_err("%s: rouleur is NULL\n", __func__);
+		return;
+	}
+
+	rouleur_mbhc = rouleur->mbhc;
+	if (rouleur_mbhc) {
+		wcd_mbhc_deinit(&rouleur_mbhc->wcd_mbhc);
+		devm_kfree(component->dev, rouleur_mbhc);
+	}
+}
+EXPORT_SYMBOL(rouleur_mbhc_deinit);

+ 67 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-mbhc.h

@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+#ifndef __ROULEUR_MBHC_H__
+#define __ROULEUR_MBHC_H__
+#include <asoc/wcd-mbhc-v2.h>
+
+struct rouleur_mbhc {
+	struct wcd_mbhc wcd_mbhc;
+	struct blocking_notifier_head notifier;
+	struct fw_info *fw_data;
+};
+
+#if IS_ENABLED(CONFIG_SND_SOC_ROULEUR)
+extern int rouleur_mbhc_init(struct rouleur_mbhc **mbhc,
+			   struct snd_soc_component *component,
+			   struct fw_info *fw_data);
+extern void rouleur_mbhc_hs_detect_exit(struct snd_soc_component *component);
+extern int rouleur_mbhc_hs_detect(struct snd_soc_component *component,
+				struct wcd_mbhc_config *mbhc_cfg);
+extern void rouleur_mbhc_deinit(struct snd_soc_component *component);
+extern int rouleur_mbhc_post_ssr_init(struct rouleur_mbhc *mbhc,
+				    struct snd_soc_component *component);
+extern void rouleur_mbhc_ssr_down(struct rouleur_mbhc *mbhc,
+				    struct snd_soc_component *component);
+extern int rouleur_mbhc_get_impedance(struct rouleur_mbhc *rouleur_mbhc,
+				    uint32_t *zl, uint32_t *zr);
+#else
+static inline int rouleur_mbhc_init(struct rouleur_mbhc **mbhc,
+				  struct snd_soc_component *component,
+				  struct fw_info *fw_data)
+{
+	return 0;
+}
+static inline void rouleur_mbhc_hs_detect_exit(
+			struct snd_soc_component *component)
+{
+}
+static inline int rouleur_mbhc_hs_detect(struct snd_soc_component *component,
+				       struct wcd_mbhc_config *mbhc_cfg)
+{
+		return 0;
+}
+static inline void rouleur_mbhc_deinit(struct snd_soc_component *component)
+{
+}
+static inline int rouleur_mbhc_post_ssr_init(struct rouleur_mbhc *mbhc,
+					   struct snd_soc_component *component)
+{
+	return 0;
+}
+static inline void rouleur_mbhc_ssr_down(struct rouleur_mbhc *mbhc,
+					   struct snd_soc_component *component)
+{
+}
+static inline int rouleur_mbhc_get_impedance(struct rouleur_mbhc *rouleur_mbhc,
+					   uint32_t *zl, uint32_t *zr)
+{
+	if (zl)
+		*zl = 0;
+	if (zr)
+		*zr = 0;
+	return -EINVAL;
+}
+#endif
+
+#endif /* __ROULEUR_MBHC_H__ */

+ 126 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-registers.h

@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _ROULEUR_REGISTERS_H
+#define _ROULEUR_REGISTERS_H
+
+#define ROULEUR_ANA_BASE_ADDR 0x3000
+#define ROULEUR_DIG_BASE_ADDR 0x3400
+
+#define ROULEUR_REG(reg)  ((reg > ROULEUR_DIG_BASE_ADDR) ? \
+			   (reg - ROULEUR_DIG_BASE_ADDR) : \
+			   (reg - ROULEUR_ANA_BASE_ADDR))
+
+enum {
+	REG_NO_ACCESS,
+	RD_REG,
+	WR_REG,
+	RD_WR_REG
+};
+
+#define ROULEUR_ANA_MICBIAS_MICB_1_2_EN       (ROULEUR_ANA_BASE_ADDR+0x040)
+#define ROULEUR_ANA_MICBIAS_MICB_3_EN         (ROULEUR_ANA_BASE_ADDR+0x041)
+#define ROULEUR_ANA_MICBIAS_LDO_1_SETTING     (ROULEUR_ANA_BASE_ADDR+0x042)
+#define ROULEUR_ANA_MICBIAS_LDO_1_CTRL        (ROULEUR_ANA_BASE_ADDR+0x043)
+#define ROULEUR_ANA_TX_AMIC1                  (ROULEUR_ANA_BASE_ADDR+0x047)
+#define ROULEUR_ANA_TX_AMIC2                  (ROULEUR_ANA_BASE_ADDR+0x048)
+#define ROULEUR_ANA_MBHC_MECH                 (ROULEUR_ANA_BASE_ADDR+0x05A)
+#define ROULEUR_ANA_MBHC_ELECT                (ROULEUR_ANA_BASE_ADDR+0x05B)
+#define ROULEUR_ANA_MBHC_ZDET                 (ROULEUR_ANA_BASE_ADDR+0x05C)
+#define ROULEUR_ANA_MBHC_RESULT_1             (ROULEUR_ANA_BASE_ADDR+0x05D)
+#define ROULEUR_ANA_MBHC_RESULT_2             (ROULEUR_ANA_BASE_ADDR+0x05E)
+#define ROULEUR_ANA_MBHC_RESULT_3             (ROULEUR_ANA_BASE_ADDR+0x05F)
+#define ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1      (ROULEUR_ANA_BASE_ADDR+0x060)
+#define ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2      (ROULEUR_ANA_BASE_ADDR+0x061)
+#define ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3      (ROULEUR_ANA_BASE_ADDR+0x062)
+#define ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400    (ROULEUR_ANA_BASE_ADDR+0x063)
+#define ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400   (ROULEUR_ANA_BASE_ADDR+0x064)
+#define ROULEUR_ANA_MBHC_MICB2_RAMP           (ROULEUR_ANA_BASE_ADDR+0x065)
+#define ROULEUR_ANA_MBHC_CTL_1                (ROULEUR_ANA_BASE_ADDR+0x066)
+#define ROULEUR_ANA_MBHC_CTL_2                (ROULEUR_ANA_BASE_ADDR+0x067)
+#define ROULEUR_ANA_MBHC_PLUG_DETECT_CTL      (ROULEUR_ANA_BASE_ADDR+0x068)
+#define ROULEUR_ANA_MBHC_ZDET_ANA_CTL         (ROULEUR_ANA_BASE_ADDR+0x069)
+#define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL        (ROULEUR_ANA_BASE_ADDR+0x06A)
+#define ROULEUR_ANA_MBHC_FSM_STATUS           (ROULEUR_ANA_BASE_ADDR+0x06B)
+#define ROULEUR_ANA_MBHC_ADC_RESULT           (ROULEUR_ANA_BASE_ADDR+0x06C)
+#define ROULEUR_ANA_MBHC_CTL_CLK              (ROULEUR_ANA_BASE_ADDR+0x06D)
+#define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT    (ROULEUR_ANA_BASE_ADDR+0x072)
+#define ROULEUR_ANA_NCP_EN                    (ROULEUR_ANA_BASE_ADDR+0x077)
+#define ROULEUR_ANA_NCP_VCTRL                 (ROULEUR_ANA_BASE_ADDR+0x07C)
+#define ROULEUR_ANA_HPHPA_CNP_CTL_1           (ROULEUR_ANA_BASE_ADDR+0x083)
+#define ROULEUR_ANA_HPHPA_CNP_CTL_2           (ROULEUR_ANA_BASE_ADDR+0x084)
+#define ROULEUR_ANA_HPHPA_PA_STATUS           (ROULEUR_ANA_BASE_ADDR+0x087)
+#define ROULEUR_ANA_HPHPA_FSM_CLK             (ROULEUR_ANA_BASE_ADDR+0x088)
+#define ROULEUR_ANA_HPHPA_L_GAIN              (ROULEUR_ANA_BASE_ADDR+0x08B)
+#define ROULEUR_ANA_HPHPA_R_GAIN              (ROULEUR_ANA_BASE_ADDR+0x08C)
+#define ROULEUR_ANA_HPHPA_SPARE_CTL           (ROULEUR_ANA_BASE_ADDR+0x08E)
+#define ROULEUR_SWR_HPHPA_HD2                 (ROULEUR_ANA_BASE_ADDR+0x090)
+#define ROULEUR_ANA_SURGE_EN                  (ROULEUR_ANA_BASE_ADDR+0x097)
+#define ROULEUR_ANA_COMBOPA_CTL               (ROULEUR_ANA_BASE_ADDR+0x09B)
+#define ROULEUR_ANA_COMBOPA_CTL_4             (ROULEUR_ANA_BASE_ADDR+0x09F)
+#define ROULEUR_ANA_COMBOPA_CTL_5             (ROULEUR_ANA_BASE_ADDR+0x0A0)
+#define ROULEUR_ANA_RXLDO_CTL                 (ROULEUR_ANA_BASE_ADDR+0x0B2)
+#define ROULEUR_ANA_MBIAS_EN                  (ROULEUR_ANA_BASE_ADDR+0x0B4)
+
+#define ROULEUR_DIG_SWR_CHIP_ID0              (ROULEUR_DIG_BASE_ADDR+0x001)
+#define ROULEUR_DIG_SWR_CHIP_ID1              (ROULEUR_DIG_BASE_ADDR+0x002)
+#define ROULEUR_DIG_SWR_CHIP_ID2              (ROULEUR_DIG_BASE_ADDR+0x003)
+#define ROULEUR_DIG_SWR_CHIP_ID3              (ROULEUR_DIG_BASE_ADDR+0x004)
+#define ROULEUR_DIG_SWR_SWR_TX_CLK_RATE       (ROULEUR_DIG_BASE_ADDR+0x040)
+#define ROULEUR_DIG_SWR_CDC_RST_CTL           (ROULEUR_DIG_BASE_ADDR+0x041)
+#define ROULEUR_DIG_SWR_TOP_CLK_CFG           (ROULEUR_DIG_BASE_ADDR+0x042)
+#define ROULEUR_DIG_SWR_CDC_RX_CLK_CTL        (ROULEUR_DIG_BASE_ADDR+0x043)
+#define ROULEUR_DIG_SWR_CDC_TX_CLK_CTL        (ROULEUR_DIG_BASE_ADDR+0x044)
+#define ROULEUR_DIG_SWR_SWR_RST_EN            (ROULEUR_DIG_BASE_ADDR+0x045)
+#define ROULEUR_DIG_SWR_CDC_RX_RST            (ROULEUR_DIG_BASE_ADDR+0x047)
+#define ROULEUR_DIG_SWR_CDC_RX0_CTL           (ROULEUR_DIG_BASE_ADDR+0x048)
+#define ROULEUR_DIG_SWR_CDC_RX1_CTL           (ROULEUR_DIG_BASE_ADDR+0x049)
+#define ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1   (ROULEUR_DIG_BASE_ADDR+0x04B)
+#define ROULEUR_DIG_SWR_CDC_COMP_CTL_0        (ROULEUR_DIG_BASE_ADDR+0x04F)
+#define ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL      (ROULEUR_DIG_BASE_ADDR+0x052)
+#define ROULEUR_DIG_SWR_CDC_RX_GAIN_0         (ROULEUR_DIG_BASE_ADDR+0x053)
+#define ROULEUR_DIG_SWR_CDC_RX_GAIN_1         (ROULEUR_DIG_BASE_ADDR+0x054)
+#define ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL       (ROULEUR_DIG_BASE_ADDR+0x057)
+#define ROULEUR_DIG_SWR_CDC_TX0_CTL           (ROULEUR_DIG_BASE_ADDR+0x060)
+#define ROULEUR_DIG_SWR_CDC_TX1_CTL           (ROULEUR_DIG_BASE_ADDR+0x061)
+#define ROULEUR_DIG_SWR_CDC_TX_RST            (ROULEUR_DIG_BASE_ADDR+0x063)
+#define ROULEUR_DIG_SWR_CDC_REQ0_CTL          (ROULEUR_DIG_BASE_ADDR+0x064)
+#define ROULEUR_DIG_SWR_CDC_REQ1_CTL          (ROULEUR_DIG_BASE_ADDR+0x065)
+#define ROULEUR_DIG_SWR_CDC_RST               (ROULEUR_DIG_BASE_ADDR+0x067)
+#define ROULEUR_DIG_SWR_CDC_AMIC_CTL          (ROULEUR_DIG_BASE_ADDR+0x06A)
+#define ROULEUR_DIG_SWR_CDC_DMIC_CTL          (ROULEUR_DIG_BASE_ADDR+0x06B)
+#define ROULEUR_DIG_SWR_CDC_DMIC1_CTL         (ROULEUR_DIG_BASE_ADDR+0x06C)
+#define ROULEUR_DIG_SWR_CDC_DMIC1_RATE        (ROULEUR_DIG_BASE_ADDR+0x06D)
+#define ROULEUR_DIG_SWR_PDM_WD_CTL0           (ROULEUR_DIG_BASE_ADDR+0x070)
+#define ROULEUR_DIG_SWR_PDM_WD_CTL1           (ROULEUR_DIG_BASE_ADDR+0x071)
+#define ROULEUR_DIG_SWR_INTR_MODE             (ROULEUR_DIG_BASE_ADDR+0x080)
+#define ROULEUR_DIG_SWR_INTR_MASK_0           (ROULEUR_DIG_BASE_ADDR+0x081)
+#define ROULEUR_DIG_SWR_INTR_MASK_1           (ROULEUR_DIG_BASE_ADDR+0x082)
+#define ROULEUR_DIG_SWR_INTR_MASK_2           (ROULEUR_DIG_BASE_ADDR+0x083)
+#define ROULEUR_DIG_SWR_INTR_STATUS_0         (ROULEUR_DIG_BASE_ADDR+0x084)
+#define ROULEUR_DIG_SWR_INTR_STATUS_1         (ROULEUR_DIG_BASE_ADDR+0x085)
+#define ROULEUR_DIG_SWR_INTR_STATUS_2         (ROULEUR_DIG_BASE_ADDR+0x086)
+#define ROULEUR_DIG_SWR_INTR_CLEAR_0          (ROULEUR_DIG_BASE_ADDR+0x087)
+#define ROULEUR_DIG_SWR_INTR_CLEAR_1          (ROULEUR_DIG_BASE_ADDR+0x088)
+#define ROULEUR_DIG_SWR_INTR_CLEAR_2          (ROULEUR_DIG_BASE_ADDR+0x089)
+#define ROULEUR_DIG_SWR_INTR_LEVEL_0          (ROULEUR_DIG_BASE_ADDR+0x08A)
+#define ROULEUR_DIG_SWR_INTR_LEVEL_1          (ROULEUR_DIG_BASE_ADDR+0x08B)
+#define ROULEUR_DIG_SWR_INTR_LEVEL_2          (ROULEUR_DIG_BASE_ADDR+0x08C)
+#define ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL      (ROULEUR_DIG_BASE_ADDR+0x093)
+#define ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL      (ROULEUR_DIG_BASE_ADDR+0x094)
+#define ROULEUR_DIG_SWR_LOOP_BACK_MODE        (ROULEUR_DIG_BASE_ADDR+0x097)
+#define ROULEUR_DIG_SWR_DRIVE_STRENGTH_0      (ROULEUR_DIG_BASE_ADDR+0x0A0)
+#define ROULEUR_DIG_SWR_DIG_DEBUG_CTL         (ROULEUR_DIG_BASE_ADDR+0x0AB)
+#define ROULEUR_DIG_SWR_DIG_DEBUG_EN          (ROULEUR_DIG_BASE_ADDR+0x0AC)
+#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA0      (ROULEUR_DIG_BASE_ADDR+0x0B0)
+#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA1      (ROULEUR_DIG_BASE_ADDR+0x0B1)
+#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA2      (ROULEUR_DIG_BASE_ADDR+0x0B2)
+#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA3      (ROULEUR_DIG_BASE_ADDR+0x0B3)
+
+#define ROULEUR_ANALOG_REGISTERS_MAX_SIZE (ROULEUR_ANA_BASE_ADDR+0x0B5)
+#define ROULEUR_DIGITAL_REGISTERS_MAX_SIZE (ROULEUR_DIG_BASE_ADDR+0x0B4)
+#define ROULEUR_ANALOG_MAX_REGISTER (ROULEUR_ANALOG_REGISTERS_MAX_SIZE - 1)
+#define ROULEUR_DIGITAL_MAX_REGISTER (ROULEUR_DIGITAL_REGISTERS_MAX_SIZE - 1)
+#endif

+ 165 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-regmap.c

@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "rouleur-registers.h"
+
+extern const u8 rouleur_reg_access_analog[
+			ROULEUR_REG(ROULEUR_ANALOG_REGISTERS_MAX_SIZE)];
+extern const u8 rouleur_reg_access_digital[
+			ROULEUR_REG(ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)];
+
+static const struct reg_default rouleur_defaults[] = {
+	{ ROULEUR_ANA_MICBIAS_MICB_1_2_EN,        0x01 },
+	{ ROULEUR_ANA_MICBIAS_MICB_3_EN,          0x00 },
+	{ ROULEUR_ANA_MICBIAS_LDO_1_SETTING,      0x21 },
+	{ ROULEUR_ANA_MICBIAS_LDO_1_CTRL,         0x01 },
+	{ ROULEUR_ANA_TX_AMIC1,                   0x00 },
+	{ ROULEUR_ANA_TX_AMIC2,                   0x00 },
+	{ ROULEUR_ANA_MBHC_MECH,                  0x39 },
+	{ ROULEUR_ANA_MBHC_ELECT,                 0x08 },
+	{ ROULEUR_ANA_MBHC_ZDET,                  0x10 },
+	{ ROULEUR_ANA_MBHC_RESULT_1,              0x00 },
+	{ ROULEUR_ANA_MBHC_RESULT_2,              0x00 },
+	{ ROULEUR_ANA_MBHC_RESULT_3,              0x00 },
+	{ ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1,       0x00 },
+	{ ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2,       0x10 },
+	{ ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3,       0x20 },
+	{ ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400,     0x30 },
+	{ ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400,    0x40 },
+	{ ROULEUR_ANA_MBHC_MICB2_RAMP,            0x00 },
+	{ ROULEUR_ANA_MBHC_CTL_1,                 0x02 },
+	{ ROULEUR_ANA_MBHC_CTL_2,                 0x05 },
+	{ ROULEUR_ANA_MBHC_PLUG_DETECT_CTL,       0xE9 },
+	{ ROULEUR_ANA_MBHC_ZDET_ANA_CTL,          0x0F },
+	{ ROULEUR_ANA_MBHC_ZDET_RAMP_CTL,         0x00 },
+	{ ROULEUR_ANA_MBHC_FSM_STATUS,            0x00 },
+	{ ROULEUR_ANA_MBHC_ADC_RESULT,            0x00 },
+	{ ROULEUR_ANA_MBHC_CTL_CLK,               0x30 },
+	{ ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT,     0x00 },
+	{ ROULEUR_ANA_NCP_EN,                     0x00 },
+	{ ROULEUR_ANA_NCP_VCTRL,                  0xA7 },
+	{ ROULEUR_ANA_HPHPA_CNP_CTL_1,            0x54 },
+	{ ROULEUR_ANA_HPHPA_CNP_CTL_2,            0x2B },
+	{ ROULEUR_ANA_HPHPA_PA_STATUS,            0x00 },
+	{ ROULEUR_ANA_HPHPA_FSM_CLK,              0x12 },
+	{ ROULEUR_ANA_HPHPA_L_GAIN,               0x00 },
+	{ ROULEUR_ANA_HPHPA_R_GAIN,               0x00 },
+	{ ROULEUR_SWR_HPHPA_HD2,                  0x1B },
+	{ ROULEUR_ANA_HPHPA_SPARE_CTL,            0x02 },
+	{ ROULEUR_ANA_SURGE_EN,                   0x38 },
+	{ ROULEUR_ANA_COMBOPA_CTL,                0x35 },
+	{ ROULEUR_ANA_COMBOPA_CTL_4,              0x84 },
+	{ ROULEUR_ANA_COMBOPA_CTL_5,              0x05 },
+	{ ROULEUR_ANA_RXLDO_CTL,                  0x86 },
+	{ ROULEUR_ANA_MBIAS_EN,                   0x00 },
+	{ ROULEUR_DIG_SWR_CHIP_ID0,               0x00 },
+	{ ROULEUR_DIG_SWR_CHIP_ID1,               0x00 },
+	{ ROULEUR_DIG_SWR_CHIP_ID2,               0x0C },
+	{ ROULEUR_DIG_SWR_CHIP_ID3,               0x01 },
+	{ ROULEUR_DIG_SWR_SWR_TX_CLK_RATE,        0x00 },
+	{ ROULEUR_DIG_SWR_CDC_RST_CTL,            0x03 },
+	{ ROULEUR_DIG_SWR_TOP_CLK_CFG,            0x00 },
+	{ ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,         0x00 },
+	{ ROULEUR_DIG_SWR_CDC_TX_CLK_CTL,         0x33 },
+	{ ROULEUR_DIG_SWR_SWR_RST_EN,             0x00 },
+	{ ROULEUR_DIG_SWR_CDC_RX_RST,             0x00 },
+	{ ROULEUR_DIG_SWR_CDC_RX0_CTL,            0xFC },
+	{ ROULEUR_DIG_SWR_CDC_RX1_CTL,            0xFC },
+	{ ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1,    0x00 },
+	{ ROULEUR_DIG_SWR_CDC_COMP_CTL_0,         0x00 },
+	{ ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL,       0x66 },
+	{ ROULEUR_DIG_SWR_CDC_RX_GAIN_0,          0x55 },
+	{ ROULEUR_DIG_SWR_CDC_RX_GAIN_1,          0xA9 },
+	{ ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,        0x00 },
+	{ ROULEUR_DIG_SWR_CDC_TX0_CTL,            0x68 },
+	{ ROULEUR_DIG_SWR_CDC_TX1_CTL,            0x68 },
+	{ ROULEUR_DIG_SWR_CDC_TX_RST,             0x00 },
+	{ ROULEUR_DIG_SWR_CDC_REQ0_CTL,           0x01 },
+	{ ROULEUR_DIG_SWR_CDC_REQ1_CTL,           0x01 },
+	{ ROULEUR_DIG_SWR_CDC_RST,                0x00 },
+	{ ROULEUR_DIG_SWR_CDC_AMIC_CTL,           0x02 },
+	{ ROULEUR_DIG_SWR_CDC_DMIC_CTL,           0x00 },
+	{ ROULEUR_DIG_SWR_CDC_DMIC1_CTL,          0x00 },
+	{ ROULEUR_DIG_SWR_CDC_DMIC1_RATE,         0x01 },
+	{ ROULEUR_DIG_SWR_PDM_WD_CTL0,            0x00 },
+	{ ROULEUR_DIG_SWR_PDM_WD_CTL1,            0x00 },
+	{ ROULEUR_DIG_SWR_INTR_MODE,              0x00 },
+	{ ROULEUR_DIG_SWR_INTR_MASK_0,            0xFF },
+	{ ROULEUR_DIG_SWR_INTR_MASK_1,            0x7F },
+	{ ROULEUR_DIG_SWR_INTR_MASK_2,            0x0C },
+	{ ROULEUR_DIG_SWR_INTR_STATUS_0,          0x00 },
+	{ ROULEUR_DIG_SWR_INTR_STATUS_1,          0x00 },
+	{ ROULEUR_DIG_SWR_INTR_STATUS_2,          0x00 },
+	{ ROULEUR_DIG_SWR_INTR_CLEAR_0,           0x00 },
+	{ ROULEUR_DIG_SWR_INTR_CLEAR_1,           0x00 },
+	{ ROULEUR_DIG_SWR_INTR_CLEAR_2,           0x00 },
+	{ ROULEUR_DIG_SWR_INTR_LEVEL_0,           0x00 },
+	{ ROULEUR_DIG_SWR_INTR_LEVEL_1,           0x2A },
+	{ ROULEUR_DIG_SWR_INTR_LEVEL_2,           0x00 },
+	{ ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL,       0x00 },
+	{ ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL,       0x00 },
+	{ ROULEUR_DIG_SWR_LOOP_BACK_MODE,         0x00 },
+	{ ROULEUR_DIG_SWR_DRIVE_STRENGTH_0,       0x00 },
+	{ ROULEUR_DIG_SWR_DIG_DEBUG_CTL,          0x00 },
+	{ ROULEUR_DIG_SWR_DIG_DEBUG_EN,           0x00 },
+	{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA0,       0x55 },
+	{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA1,       0x55 },
+	{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA2,       0x55 },
+	{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA3,       0x01 },
+};
+
+static bool rouleur_readable_register(struct device *dev, unsigned int reg)
+{
+	if (reg > ROULEUR_ANA_BASE_ADDR && reg <
+				ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
+		return rouleur_reg_access_analog[ROULEUR_REG(reg)] & RD_REG;
+	if (reg > ROULEUR_DIG_BASE_ADDR && reg <
+				ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
+		return rouleur_reg_access_digital[ROULEUR_REG(reg)] & RD_REG;
+	return 0;
+}
+
+static bool rouleur_writeable_register(struct device *dev, unsigned int reg)
+{
+	if (reg > ROULEUR_ANA_BASE_ADDR && reg <
+					ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
+		return rouleur_reg_access_analog[ROULEUR_REG(reg)] & WR_REG;
+	if (reg > ROULEUR_DIG_BASE_ADDR && reg <
+					ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
+		return rouleur_reg_access_digital[ROULEUR_REG(reg)] & WR_REG;
+	return 0;
+}
+
+static bool rouleur_volatile_register(struct device *dev, unsigned int reg)
+{
+	if (reg > ROULEUR_ANA_BASE_ADDR && reg <
+					ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
+		if ((rouleur_reg_access_analog[ROULEUR_REG(reg)] & RD_REG)
+		    && !(rouleur_reg_access_analog[ROULEUR_REG(reg)] & WR_REG))
+			return true;
+	if (reg > ROULEUR_DIG_BASE_ADDR && reg <
+					ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
+		if ((rouleur_reg_access_digital[ROULEUR_REG(reg)] & RD_REG)
+		    && !(rouleur_reg_access_digital[ROULEUR_REG(reg)] & WR_REG))
+			return true;
+	return 0;
+}
+
+struct regmap_config rouleur_regmap_config = {
+	.name = "rouleur_csr",
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = rouleur_defaults,
+	.num_reg_defaults = ARRAY_SIZE(rouleur_defaults),
+	.max_register = ROULEUR_ANALOG_MAX_REGISTER +
+				ROULEUR_DIGITAL_MAX_REGISTER,
+	.readable_reg = rouleur_readable_register,
+	.writeable_reg = rouleur_writeable_register,
+	.volatile_reg = rouleur_volatile_register,
+	.can_multi_write = true,
+};

+ 112 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur-tables.c

@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include "rouleur-registers.h"
+
+const u8 rouleur_reg_access_analog[ROULEUR_REG(
+			ROULEUR_ANALOG_REGISTERS_MAX_SIZE)] = {
+	[ROULEUR_REG(ROULEUR_ANA_MICBIAS_MICB_1_2_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MICBIAS_MICB_3_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MICBIAS_LDO_1_SETTING)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MICBIAS_LDO_1_CTRL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_TX_AMIC1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_TX_AMIC2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_MECH)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ELECT)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_1)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_2)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_3)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_MICB2_RAMP)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_PLUG_DETECT_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_ANA_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_CLK)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_NCP_VCTRL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_FSM_CLK)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_L_GAIN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_R_GAIN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_HPHPA_SPARE_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_SWR_HPHPA_HD2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL_4)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL_5)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_RXLDO_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_MBIAS_EN)] = RD_WR_REG,
+};
+
+const u8 rouleur_reg_access_digital[ROULEUR_REG(
+			ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)] = {
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID0)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID1)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID2)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID3)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_SWR_TX_CLK_RATE)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RST_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_TOP_CLK_CFG)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_CLK_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_CLK_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_SWR_RST_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_RST)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX0_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX1_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_COMP_CTL_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX0_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX1_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_RST)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_REQ0_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_REQ1_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RST)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_AMIC_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC1_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC1_RATE)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_PDM_WD_CTL0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_PDM_WD_CTL1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MODE)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_0)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_1)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_2)] = RD_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_LOOP_BACK_MODE)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DRIVE_STRENGTH_0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DIG_DEBUG_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DIG_DEBUG_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA0)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA1)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA2)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA3)] = RD_WR_REG,
+};

+ 2819 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur.c

@@ -0,0 +1,2819 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_platform.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <soc/soundwire.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include "internal.h"
+#include "rouleur.h"
+#include <asoc/wcdcal-hwdep.h>
+#include "rouleur-registers.h"
+#include "pm2250-spmi.h"
+#include <asoc/msm-cdc-pinctrl.h>
+#include <dt-bindings/sound/audio-codec-port-types.h>
+#include <asoc/msm-cdc-supply.h>
+#include <linux/power_supply.h>
+#include "asoc/bolero-slave-internal.h"
+
+#define DRV_NAME "rouleur_codec"
+
+#define NUM_SWRS_DT_PARAMS 5
+
+#define ROULEUR_VERSION_1_0 1
+#define ROULEUR_VERSION_ENTRY_SIZE 32
+
+#define NUM_ATTEMPTS 5
+#define SOC_THRESHOLD_LEVEL 25
+#define LOW_SOC_MBIAS_REG_MIN_VOLTAGE 2850000
+
+#define FOUNDRY_ID_SEC 0x5
+
+enum {
+	CODEC_TX = 0,
+	CODEC_RX,
+};
+
+enum {
+	ALLOW_VPOS_DISABLE,
+	HPH_COMP_DELAY,
+	HPH_PA_DELAY,
+	AMIC2_BCS_ENABLE,
+	WCD_SUPPLIES_LPM_MODE,
+};
+
+/* TODO: Check on the step values */
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+
+static int rouleur_handle_post_irq(void *data);
+static int rouleur_reset(struct device *dev, int val);
+
+static const struct regmap_irq ROULEUR_IRQs[ROULEUR_NUM_IRQS] = {
+	REGMAP_IRQ_REG(ROULEUR_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_MBHC_SW_DET, 0, 0x10),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHR_OCP_INT, 0, 0x20),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHR_CNP_INT, 0, 0x40),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHL_OCP_INT, 0, 0x80),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHL_CNP_INT, 1, 0x01),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_EAR_CNP_INT, 1, 0x02),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_EAR_OCP_INT, 1, 0x04),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_LO_CNP_INT, 1, 0x08),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_LO_OCP_INT, 1, 0x10),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHL_PDM_WD_INT, 1, 0x20),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHR_PDM_WD_INT, 1, 0x40),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHL_SURGE_DET_INT, 2, 0x04),
+	REGMAP_IRQ_REG(ROULEUR_IRQ_HPHR_SURGE_DET_INT, 2, 0x08),
+};
+
+static struct regmap_irq_chip rouleur_regmap_irq_chip = {
+	.name = "rouleur",
+	.irqs = ROULEUR_IRQs,
+	.num_irqs = ARRAY_SIZE(ROULEUR_IRQs),
+	.num_regs = 3,
+	.status_base = ROULEUR_DIG_SWR_INTR_STATUS_0,
+	.mask_base = ROULEUR_DIG_SWR_INTR_MASK_0,
+	.ack_base = ROULEUR_DIG_SWR_INTR_CLEAR_0,
+	.use_ack = 1,
+	.type_base = ROULEUR_DIG_SWR_INTR_LEVEL_0,
+	.runtime_pm = false,
+	.handle_post_irq = rouleur_handle_post_irq,
+	.irq_drv_data = NULL,
+};
+
+static int rouleur_handle_post_irq(void *data)
+{
+	struct rouleur_priv *rouleur = data;
+	u32 status1 = 0, status2 = 0, status3 = 0;
+
+	regmap_read(rouleur->regmap, ROULEUR_DIG_SWR_INTR_STATUS_0, &status1);
+	regmap_read(rouleur->regmap, ROULEUR_DIG_SWR_INTR_STATUS_1, &status2);
+	regmap_read(rouleur->regmap, ROULEUR_DIG_SWR_INTR_STATUS_2, &status3);
+
+	rouleur->tx_swr_dev->slave_irq_pending =
+			((status1 || status2 || status3) ? true : false);
+
+	return IRQ_HANDLED;
+}
+
+static int rouleur_init_reg(struct snd_soc_component *component)
+{
+	/* Disable HPH OCP */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2,
+					0x03, 0x00);
+	/* Enable surge protection */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
+					0xC0, 0xC0);
+	/* Disable mic bias pull down */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_MICBIAS_MICB_1_2_EN,
+					0x01, 0x00);
+	return 0;
+}
+
+static int rouleur_set_port_params(struct snd_soc_component *component,
+				u8 slv_prt_type, u8 *port_id, u8 *num_ch,
+				u8 *ch_mask, u32 *ch_rate,
+				u8 *port_type, u8 path)
+{
+	int i, j;
+	u8 num_ports = 0;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT] = NULL;
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	switch (path) {
+	case CODEC_RX:
+		map = &rouleur->rx_port_mapping;
+		num_ports = rouleur->num_rx_ports;
+		break;
+	case CODEC_TX:
+		map = &rouleur->tx_port_mapping;
+		num_ports = rouleur->num_tx_ports;
+		break;
+	default:
+		dev_err(component->dev, "%s Invalid path: %d\n",
+			__func__, path);
+		return -EINVAL;
+	}
+
+	for (i = 0; i <= num_ports; i++) {
+		for (j = 0; j < MAX_CH_PER_PORT; j++) {
+			if ((*map)[i][j].slave_port_type == slv_prt_type)
+				goto found;
+		}
+	}
+
+	dev_err(component->dev, "%s Failed to find slave port for type %u\n",
+					__func__, slv_prt_type);
+	return -EINVAL;
+found:
+	*port_id = i;
+	*num_ch = (*map)[i][j].num_ch;
+	*ch_mask = (*map)[i][j].ch_mask;
+	*ch_rate = (*map)[i][j].ch_rate;
+	*port_type = (*map)[i][j].master_port_type;
+
+	return 0;
+}
+
+static int rouleur_parse_port_mapping(struct device *dev,
+			char *prop, u8 path)
+{
+	u32 *dt_array, map_size, map_length;
+	u32 port_num = 0, ch_mask, ch_rate, old_port_num = 0;
+	u32 slave_port_type, master_port_type;
+	u32 i, ch_iter = 0;
+	int ret = 0;
+	u8 *num_ports = NULL;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT] = NULL;
+	struct rouleur_priv *rouleur = dev_get_drvdata(dev);
+
+	switch (path) {
+	case CODEC_RX:
+		map = &rouleur->rx_port_mapping;
+		num_ports = &rouleur->num_rx_ports;
+		break;
+	case CODEC_TX:
+		map = &rouleur->tx_port_mapping;
+		num_ports = &rouleur->num_tx_ports;
+		break;
+	default:
+		dev_err(dev, "%s Invalid path: %d\n",
+			__func__, path);
+		return -EINVAL;
+	}
+
+	if (!of_find_property(dev->of_node, prop,
+				&map_size)) {
+		dev_err(dev, "missing port mapping prop %s\n", prop);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	map_length = map_size / (NUM_SWRS_DT_PARAMS * sizeof(u32));
+
+	dt_array = kzalloc(map_size, GFP_KERNEL);
+
+	if (!dt_array) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	ret = of_property_read_u32_array(dev->of_node, prop, dt_array,
+				NUM_SWRS_DT_PARAMS * map_length);
+	if (ret) {
+		dev_err(dev, "%s: Failed to read  port mapping from prop %s\n",
+					__func__, prop);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+
+	for (i = 0; i < map_length; i++) {
+		port_num = dt_array[NUM_SWRS_DT_PARAMS * i];
+		slave_port_type = dt_array[NUM_SWRS_DT_PARAMS * i + 1];
+		ch_mask = dt_array[NUM_SWRS_DT_PARAMS * i + 2];
+		ch_rate = dt_array[NUM_SWRS_DT_PARAMS * i + 3];
+		master_port_type = dt_array[NUM_SWRS_DT_PARAMS * i + 4];
+
+		if (port_num != old_port_num)
+			ch_iter = 0;
+
+		(*map)[port_num][ch_iter].slave_port_type = slave_port_type;
+		(*map)[port_num][ch_iter].ch_mask = ch_mask;
+		(*map)[port_num][ch_iter].master_port_type = master_port_type;
+		(*map)[port_num][ch_iter].num_ch = __sw_hweight8(ch_mask);
+		(*map)[port_num][ch_iter++].ch_rate = ch_rate;
+		old_port_num = port_num;
+	}
+	*num_ports = port_num;
+
+err_pdata_fail:
+	kfree(dt_array);
+err:
+	return ret;
+}
+
+static int rouleur_tx_connect_port(struct snd_soc_component *component,
+					u8 slv_port_type, u8 enable)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	u8 port_id;
+	u8 num_ch;
+	u8 ch_mask;
+	u32 ch_rate;
+	u8 port_type;
+	u8 num_port = 1;
+	int ret = 0;
+
+	ret = rouleur_set_port_params(component, slv_port_type, &port_id,
+				&num_ch, &ch_mask, &ch_rate,
+				&port_type, CODEC_TX);
+
+	if (ret) {
+		dev_err(rouleur->dev, "%s:Failed to set port params: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (enable)
+		ret = swr_connect_port(rouleur->tx_swr_dev, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					 &num_ch, &port_type);
+	else
+		ret = swr_disconnect_port(rouleur->tx_swr_dev, &port_id,
+					num_port, &ch_mask, &port_type);
+	return ret;
+
+}
+static int rouleur_rx_connect_port(struct snd_soc_component *component,
+					u8 slv_port_type, u8 enable)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	u8 port_id;
+	u8 num_ch;
+	u8 ch_mask;
+	u32 ch_rate;
+	u8 port_type;
+	u8 num_port = 1;
+	int ret = 0;
+
+	ret = rouleur_set_port_params(component, slv_port_type, &port_id,
+				&num_ch, &ch_mask, &ch_rate,
+				&port_type, CODEC_RX);
+
+	if (ret) {
+		dev_err(rouleur->dev, "%s:Failed to set port params: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (enable)
+		ret = swr_connect_port(rouleur->rx_swr_dev, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					&num_ch, &port_type);
+	else
+		ret = swr_disconnect_port(rouleur->rx_swr_dev, &port_id,
+					num_port, &ch_mask, &port_type);
+	return ret;
+}
+
+int rouleur_global_mbias_enable(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&rouleur->main_bias_lock);
+	if (rouleur->mbias_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBIAS_EN, 0x20, 0x20);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBIAS_EN, 0x10, 0x10);
+		usleep_range(1000, 1100);
+	}
+	rouleur->mbias_cnt++;
+	mutex_unlock(&rouleur->main_bias_lock);
+
+	return 0;
+}
+
+int rouleur_global_mbias_disable(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&rouleur->main_bias_lock);
+	if (rouleur->mbias_cnt == 0) {
+		dev_dbg(rouleur->dev, "%s:mbias already disabled\n", __func__);
+		mutex_unlock(&rouleur->main_bias_lock);
+		return 0;
+	}
+	rouleur->mbias_cnt--;
+	if (rouleur->mbias_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBIAS_EN, 0x10, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_MBIAS_EN, 0x20, 0x00);
+	}
+	mutex_unlock(&rouleur->main_bias_lock);
+
+	return 0;
+}
+
+static int rouleur_rx_clk_enable(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&rouleur->rx_clk_lock);
+	if (rouleur->rx_clk_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x10);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x20);
+		usleep_range(5000, 5100);
+		rouleur_global_mbias_enable(component);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_NCP_VCTRL, 0x07, 0x06);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_NCP_EN, 0x01, 0x01);
+		usleep_range(500, 510);
+	}
+	rouleur->rx_clk_cnt++;
+	mutex_unlock(&rouleur->rx_clk_lock);
+
+	return 0;
+}
+
+static int rouleur_rx_clk_disable(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&rouleur->rx_clk_lock);
+	if (rouleur->rx_clk_cnt == 0) {
+		dev_dbg(rouleur->dev, "%s:clk already disabled\n", __func__);
+		mutex_unlock(&rouleur->rx_clk_lock);
+		return 0;
+	}
+	rouleur->rx_clk_cnt--;
+	if (rouleur->rx_clk_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_NCP_EN, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00);
+		rouleur_global_mbias_disable(component);
+
+	}
+	mutex_unlock(&rouleur->rx_clk_lock);
+	return 0;
+}
+
+/*
+ * rouleur_soc_get_mbhc: get rouleur_mbhc handle of corresponding component
+ * @component: handle to snd_soc_component *
+ *
+ * return rouleur_mbhc handle or error code in case of failure
+ */
+struct rouleur_mbhc *rouleur_soc_get_mbhc(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur;
+
+	if (!component) {
+		pr_err("%s: Invalid params, NULL component\n", __func__);
+		return NULL;
+	}
+	rouleur = snd_soc_component_get_drvdata(component);
+
+	if (!rouleur) {
+		pr_err("%s: Invalid params, NULL tavil\n", __func__);
+		return NULL;
+	}
+
+	return rouleur->mbhc;
+}
+EXPORT_SYMBOL(rouleur_soc_get_mbhc);
+
+static int rouleur_codec_hphl_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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_CNP_CTL_1,
+				0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				ROULEUR_SWR_HPHPA_HD2,
+				0x38, 0x38);
+		set_bit(HPH_COMP_DELAY, &rouleur->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (rouleur->comp1_enable) {
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+				0x02, 0x02);
+
+			if (rouleur->comp2_enable)
+				snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x01, 0x01);
+			/*
+			 * 5ms sleep is required after COMP is enabled as per
+			 * HW requirement
+			 */
+			if (test_bit(HPH_COMP_DELAY, &rouleur->status_mask)) {
+				usleep_range(5000, 5100);
+				clear_bit(HPH_COMP_DELAY,
+					&rouleur->status_mask);
+			}
+		} else {
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x02, 0x00);
+		}
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX0_CTL,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x01);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX0_CTL,
+				0x80, 0x80);
+		if (rouleur->comp1_enable)
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x02, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static int rouleur_codec_hphr_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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_HPHPA_CNP_CTL_1,
+				0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				ROULEUR_SWR_HPHPA_HD2,
+				0x07, 0x07);
+		set_bit(HPH_COMP_DELAY, &rouleur->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (rouleur->comp2_enable) {
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+				0x01, 0x01);
+
+			if (rouleur->comp1_enable)
+				snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x02, 0x02);
+			/*
+			 * 5ms sleep is required after COMP is enabled as per
+			 * HW requirement
+			 */
+			if (test_bit(HPH_COMP_DELAY, &rouleur->status_mask)) {
+				usleep_range(5000, 5100);
+				clear_bit(HPH_COMP_DELAY,
+					&rouleur->status_mask);
+			}
+		} else {
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x01, 0x00);
+		}
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX1_CTL,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x02);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+			ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x08, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX1_CTL,
+				0x80, 0x80);
+		if (rouleur->comp2_enable)
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x01, 0x00);
+		break;
+
+	}
+
+	return 0;
+}
+
+static int rouleur_codec_ear_lo_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);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX0_CTL,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
+				0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x04);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX0_CTL,
+				0x80, 0x80);
+
+		break;
+	};
+	return 0;
+
+}
+
+static int rouleur_codec_enable_hphr_pa(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
+				    rouleur->rx_swr_dev->dev_num,
+				    true);
+
+		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		usleep_range(200, 210);
+		/* Enable HD2 Config for HPHR if foundry id is SEC */
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHR_HD2_ENABLE,
+						0x04);
+		snd_soc_component_update_bits(component,
+			ROULEUR_DIG_SWR_PDM_WD_CTL1,
+			0x03, 0x03);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/*
+		 * 5ms sleep is required after PA is enabled as per
+		 * HW requirement.
+		 */
+		if (test_bit(HPH_PA_DELAY, &rouleur->status_mask)) {
+			usleep_range(5000, 5100);
+			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		}
+
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10));
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHR_PDM_WD_INT);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wcd_disable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHR_PDM_WD_INT);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10 | 0x1));
+		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
+					     WCD_EVENT_PRE_HPHR_PA_OFF,
+					     &rouleur->mbhc->wcd_mbhc);
+		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/*
+		 * 5ms sleep is required after PA is disabled as per
+		 * HW requirement.
+		 */
+		if (test_bit(HPH_PA_DELAY, &rouleur->status_mask)) {
+
+			usleep_range(5000, 5100);
+			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		}
+
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHR_HD2_ENABLE,
+						0x00);
+		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
+					     WCD_EVENT_POST_HPHR_PA_OFF,
+					     &rouleur->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL1,
+				0x03, 0x00);
+		break;
+	};
+	return ret;
+}
+
+static int rouleur_codec_enable_hphl_pa(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
+				    rouleur->rx_swr_dev->dev_num,
+				    true);
+		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		usleep_range(200, 210);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x04);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL0,
+				0x03, 0x03);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/*
+		 * 5ms sleep is required after PA is enabled as per
+		 * HW requirement.
+		 */
+		if (test_bit(HPH_PA_DELAY, &rouleur->status_mask)) {
+			usleep_range(5000, 5100);
+			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		}
+
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wcd_disable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
+		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
+					     WCD_EVENT_PRE_HPHL_PA_OFF,
+					     &rouleur->mbhc->wcd_mbhc);
+		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/*
+		 * 5ms sleep is required after PA is disabled as per
+		 * HW requirement.
+		 */
+		if (test_bit(HPH_PA_DELAY, &rouleur->status_mask)) {
+			usleep_range(5000, 5100);
+			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
+		}
+
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x00);
+		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
+					     WCD_EVENT_POST_HPHL_PA_OFF,
+					     &rouleur->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component,
+			ROULEUR_DIG_SWR_PDM_WD_CTL0,
+			0x03, 0x00);
+
+		break;
+	};
+	return ret;
+}
+
+static int rouleur_codec_enable_ear_pa(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
+			    rouleur->rx_swr_dev->dev_num,
+			    true);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_5,
+				0x04, 0x00);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x0F);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x00);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x04);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL0,
+				0x03, 0x03);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x04);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wcd_disable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		usleep_range(5000, 5100);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL0,
+				0x03, 0x00);
+	};
+	return ret;
+}
+
+static int rouleur_codec_enable_lo_pa(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
+			    rouleur->rx_swr_dev->dev_num,
+			    true);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_5,
+				0x04, 0x00);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x0F);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x40);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL0,
+				0x03, 0x03);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x04);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wcd_disable_irq(&rouleur->irq_info,
+					ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x00);
+		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_PDM_WD_CTL0,
+				0x03, 0x00);
+	};
+	return ret;
+}
+
+static int rouleur_enable_rx1(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_rx_connect_port(component, HPH_L, true);
+		if (rouleur->comp1_enable)
+			rouleur_rx_connect_port(component, COMP_L, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rouleur_rx_connect_port(component, HPH_L, false);
+		if (rouleur->comp1_enable)
+			rouleur_rx_connect_port(component, COMP_L, false);
+		rouleur_rx_clk_disable(component);
+		break;
+	};
+	return 0;
+}
+
+static int rouleur_enable_rx2(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_rx_connect_port(component, HPH_R, true);
+		if (rouleur->comp2_enable)
+			rouleur_rx_connect_port(component, COMP_R, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rouleur_rx_connect_port(component, HPH_R, false);
+		if (rouleur->comp2_enable)
+			rouleur_rx_connect_port(component, COMP_R, false);
+		rouleur_rx_clk_disable(component);
+		break;
+	};
+
+	return 0;
+}
+
+static int rouleur_codec_enable_dmic(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	u16 dmic_clk_reg;
+	s32 *dmic_clk_cnt;
+	unsigned int dmic;
+	char *wname;
+	int ret = 0;
+
+	wname = strpbrk(w->name, "01");
+
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (dmic) {
+	case 0:
+	case 1:
+		dmic_clk_cnt = &(rouleur->dmic_0_1_clk_cnt);
+		dmic_clk_reg = ROULEUR_DIG_SWR_CDC_DMIC1_CTL;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	};
+	dev_dbg(component->dev, "%s: event %d DMIC%d dmic_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+			ROULEUR_DIG_SWR_CDC_AMIC_CTL, 0x02, 0x00);
+		snd_soc_component_update_bits(component,
+			dmic_clk_reg, 0x08, 0x08);
+		rouleur_tx_connect_port(component, DMIC0 + (w->shift), true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rouleur_tx_connect_port(component, DMIC0 + (w->shift), false);
+		snd_soc_component_update_bits(component,
+			dmic_clk_reg, 0x08, 0x00);
+		snd_soc_component_update_bits(component,
+			ROULEUR_DIG_SWR_CDC_AMIC_CTL, 0x02, 0x02);
+		break;
+
+	};
+	return 0;
+}
+
+static int rouleur_tx_swr_ctrl(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(rouleur->tx_swr_dev,
+		    rouleur->tx_swr_dev->dev_num,
+		    true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = swr_slvdev_datapath_control(rouleur->tx_swr_dev,
+		    rouleur->tx_swr_dev->dev_num,
+		    false);
+		break;
+	};
+
+	return ret;
+}
+
+static int rouleur_codec_enable_adc(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 rouleur_priv *rouleur =
+			snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable BCS for Headset mic */
+		if (w->shift == 1 && !(snd_soc_component_read32(component,
+				ROULEUR_ANA_TX_AMIC2) & 0x10)) {
+			rouleur_tx_connect_port(component, MBHC, true);
+			set_bit(AMIC2_BCS_ENABLE, &rouleur->status_mask);
+		}
+		rouleur_tx_connect_port(component, ADC1 + (w->shift), true);
+		rouleur_global_mbias_enable(component);
+		if (w->shift)
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1,
+				0x30, 0x30);
+		else
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1,
+				0x03, 0x03);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rouleur_tx_connect_port(component, ADC1 + (w->shift), false);
+		if (w->shift == 1 &&
+			test_bit(AMIC2_BCS_ENABLE, &rouleur->status_mask)) {
+			rouleur_tx_connect_port(component, MBHC, false);
+			clear_bit(AMIC2_BCS_ENABLE, &rouleur->status_mask);
+		}
+		if (w->shift)
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1,
+				0x30, 0x00);
+		else
+			snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1,
+				0x03, 0x00);
+		rouleur_global_mbias_disable(component);
+		break;
+	};
+
+	return 0;
+}
+
+/*
+ * rouleur_get_micb_vout_ctl_val: converts micbias from volts to register value
+ * @micb_mv: micbias in mv
+ *
+ * return register value converted
+ */
+int rouleur_get_micb_vout_ctl_val(u32 micb_mv)
+{
+	/* min micbias voltage is 1.6V and maximum is 2.85V */
+	if (micb_mv < 1600 || micb_mv > 2850) {
+		pr_err("%s: unsupported micbias voltage\n", __func__);
+		return -EINVAL;
+	}
+
+	return (micb_mv - 1600) / 50;
+}
+EXPORT_SYMBOL(rouleur_get_micb_vout_ctl_val);
+
+/*
+ * rouleur_mbhc_micb_adjust_voltage: adjust specific micbias voltage
+ * @component: handle to snd_soc_component *
+ * @req_volt: micbias voltage to be set
+ * @micb_num: micbias to be set, e.g. micbias1 or micbias2
+ *
+ * return 0 if adjustment is success or error code in case of failure
+ */
+int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+				   int req_volt, int micb_num)
+{
+	struct rouleur_priv *rouleur =
+			snd_soc_component_get_drvdata(component);
+	int cur_vout_ctl, req_vout_ctl;
+	int micb_reg, micb_val, micb_en;
+	int ret = 0;
+	int pullup_mask;
+
+	micb_reg = ROULEUR_ANA_MICBIAS_MICB_1_2_EN;
+	switch (micb_num) {
+	case MIC_BIAS_1:
+		micb_val = snd_soc_component_read32(component, micb_reg);
+		micb_en = (micb_val & 0x40) >> 6;
+		pullup_mask = 0x20;
+		break;
+	case MIC_BIAS_2:
+		micb_val = snd_soc_component_read32(component, micb_reg);
+		micb_en = (micb_val & 0x04) >> 2;
+		pullup_mask = 0x02;
+		break;
+	case MIC_BIAS_3:
+	default:
+		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
+			__func__, micb_num);
+		return -EINVAL;
+	}
+	mutex_lock(&rouleur->micb_lock);
+
+	/*
+	 * If requested micbias voltage is same as current micbias
+	 * voltage, then just return. Otherwise, adjust voltage as
+	 * per requested value. If micbias is already enabled, then
+	 * to avoid slow micbias ramp-up or down enable pull-up
+	 * momentarily, change the micbias value and then re-enable
+	 * micbias.
+	 */
+	cur_vout_ctl = (snd_soc_component_read32(component,
+				ROULEUR_ANA_MICBIAS_LDO_1_SETTING)) & 0xF8;
+	cur_vout_ctl = cur_vout_ctl >> 3;
+	req_vout_ctl = rouleur_get_micb_vout_ctl_val(req_volt);
+	if (req_vout_ctl < 0) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	if (cur_vout_ctl == req_vout_ctl) {
+		ret = 0;
+		goto exit;
+	}
+
+	dev_dbg(component->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
+		 __func__, micb_num, WCD_VOUT_CTL_TO_MICB(cur_vout_ctl),
+		 req_volt, micb_en);
+
+	if (micb_en == 0x1)
+		snd_soc_component_update_bits(component, micb_reg, pullup_mask,
+					      pullup_mask);
+
+	snd_soc_component_update_bits(component,
+		ROULEUR_ANA_MICBIAS_LDO_1_SETTING, 0xF8, req_vout_ctl << 3);
+
+	if (micb_en == 0x1) {
+		snd_soc_component_update_bits(component, micb_reg,
+					      pullup_mask, 0x00);
+		/*
+		 * Add 2ms delay as per HW requirement after enabling
+		 * micbias
+		 */
+		usleep_range(2000, 2100);
+	}
+exit:
+	mutex_unlock(&rouleur->micb_lock);
+	return ret;
+}
+EXPORT_SYMBOL(rouleur_mbhc_micb_adjust_voltage);
+
+int rouleur_micbias_control(struct snd_soc_component *component,
+				int micb_num, int req, bool is_dapm)
+{
+
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int micb_index = micb_num - 1;
+	u16 micb_reg;
+	int pre_off_event = 0, post_off_event = 0;
+	int post_on_event = 0, post_dapm_off = 0;
+	int post_dapm_on = 0;
+	u8 pullup_mask = 0, enable_mask = 0;
+	int ret = 0;
+
+	if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) {
+		dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n",
+			__func__, micb_index);
+		return -EINVAL;
+	}
+	switch (micb_num) {
+	case MIC_BIAS_1:
+		micb_reg = ROULEUR_ANA_MICBIAS_MICB_1_2_EN;
+		pullup_mask = 0x20;
+		enable_mask = 0x40;
+		break;
+	case MIC_BIAS_2:
+		micb_reg = ROULEUR_ANA_MICBIAS_MICB_1_2_EN;
+		pullup_mask = 0x02;
+		enable_mask = 0x04;
+		pre_off_event = WCD_EVENT_PRE_MICBIAS_2_OFF;
+		post_off_event = WCD_EVENT_POST_MICBIAS_2_OFF;
+		post_on_event = WCD_EVENT_POST_MICBIAS_2_ON;
+		post_dapm_on = WCD_EVENT_POST_DAPM_MICBIAS_2_ON;
+		post_dapm_off = WCD_EVENT_POST_DAPM_MICBIAS_2_OFF;
+		break;
+	case MIC_BIAS_3:
+		micb_reg = ROULEUR_ANA_MICBIAS_MICB_3_EN;
+		pullup_mask = 0x02;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
+			__func__, micb_num);
+		return -EINVAL;
+	};
+	mutex_lock(&rouleur->micb_lock);
+
+	switch (req) {
+	case MICB_PULLUP_ENABLE:
+		if (!rouleur->dev_up) {
+			dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
+				__func__, req);
+			ret = -ENODEV;
+			goto done;
+		}
+		rouleur->pullup_ref[micb_index]++;
+		if ((rouleur->pullup_ref[micb_index] == 1) &&
+		    (rouleur->micb_ref[micb_index] == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+				pullup_mask, pullup_mask);
+		break;
+	case MICB_PULLUP_DISABLE:
+		if (!rouleur->dev_up) {
+			dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
+				__func__, req);
+			ret = -ENODEV;
+			goto done;
+		}
+		if (rouleur->pullup_ref[micb_index] > 0)
+			rouleur->pullup_ref[micb_index]--;
+		if ((rouleur->pullup_ref[micb_index] == 0) &&
+		    (rouleur->micb_ref[micb_index] == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+				pullup_mask, 0x00);
+		break;
+	case MICB_ENABLE:
+		if (!rouleur->dev_up) {
+			dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
+				__func__, req);
+			ret = -ENODEV;
+			goto done;
+		}
+		rouleur->micb_ref[micb_index]++;
+		if (rouleur->micb_ref[micb_index] == 1) {
+			rouleur_global_mbias_enable(component);
+			snd_soc_component_update_bits(component,
+				micb_reg, enable_mask, enable_mask);
+			if (post_on_event)
+				blocking_notifier_call_chain(
+					&rouleur->mbhc->notifier, post_on_event,
+					&rouleur->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_on && rouleur->mbhc)
+			blocking_notifier_call_chain(
+				&rouleur->mbhc->notifier, post_dapm_on,
+				&rouleur->mbhc->wcd_mbhc);
+		break;
+	case MICB_DISABLE:
+		if (rouleur->micb_ref[micb_index] > 0)
+			rouleur->micb_ref[micb_index]--;
+		if (!rouleur->dev_up) {
+			dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
+				__func__, req);
+			ret = -ENODEV;
+			goto done;
+		}
+		if ((rouleur->micb_ref[micb_index] == 0) &&
+		    (rouleur->pullup_ref[micb_index] > 0)) {
+			snd_soc_component_update_bits(component, micb_reg,
+				pullup_mask, pullup_mask);
+                        snd_soc_component_update_bits(component, micb_reg,
+                                enable_mask, 0x00);
+			rouleur_global_mbias_disable(component);
+		} else if ((rouleur->micb_ref[micb_index] == 0) &&
+			   (rouleur->pullup_ref[micb_index] == 0)) {
+			if (pre_off_event && rouleur->mbhc)
+				blocking_notifier_call_chain(
+					&rouleur->mbhc->notifier, pre_off_event,
+					&rouleur->mbhc->wcd_mbhc);
+                        snd_soc_component_update_bits(component, micb_reg,
+                                enable_mask, 0x00);
+			rouleur_global_mbias_disable(component);
+			if (post_off_event && rouleur->mbhc)
+				blocking_notifier_call_chain(
+					&rouleur->mbhc->notifier,
+					post_off_event,
+					&rouleur->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_off && rouleur->mbhc)
+			blocking_notifier_call_chain(
+				&rouleur->mbhc->notifier, post_dapm_off,
+				&rouleur->mbhc->wcd_mbhc);
+		break;
+	};
+
+	dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
+		__func__, micb_num, rouleur->micb_ref[micb_index],
+		rouleur->pullup_ref[micb_index]);
+done:
+	mutex_unlock(&rouleur->micb_lock);
+	return 0;
+}
+EXPORT_SYMBOL(rouleur_micbias_control);
+
+void rouleur_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	if (rouleur->update_wcd_event) {
+		if (bcs_disable)
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			rouleur->update_wcd_event(rouleur->handle,
+						SLV_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
+static int rouleur_get_logical_addr(struct swr_device *swr_dev)
+{
+	int ret = 0;
+	uint8_t devnum = 0;
+	int num_retry = NUM_ATTEMPTS;
+
+	do {
+		ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
+		if (ret) {
+			dev_err(&swr_dev->dev,
+				"%s get devnum %d for dev addr %lx failed\n",
+				__func__, devnum, swr_dev->addr);
+			/* retry after 1ms */
+			usleep_range(1000, 1010);
+		}
+	} while (ret && --num_retry);
+	swr_dev->dev_num = devnum;
+	return 0;
+}
+
+static bool get_usbc_hs_status(struct snd_soc_component *component,
+			       struct wcd_mbhc_config *mbhc_cfg)
+{
+	if (mbhc_cfg->enable_usbc_analog) {
+		if (!(snd_soc_component_read32(component, ROULEUR_ANA_MBHC_MECH)
+			& 0x20))
+			return true;
+	}
+	return false;
+}
+
+static int rouleur_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	int ret = 0;
+	struct rouleur_priv *rouleur = dev_get_drvdata((struct device *)data);
+	struct snd_soc_component *component = rouleur->component;
+	struct wcd_mbhc *mbhc;
+
+	switch (event) {
+	case BOLERO_SLV_EVT_PA_OFF_PRE_SSR:
+		snd_soc_component_update_bits(component,
+					ROULEUR_ANA_HPHPA_CNP_CTL_2,
+					0xC0, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x40);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x80, 0x00);
+		break;
+	case BOLERO_SLV_EVT_SSR_DOWN:
+		rouleur->dev_up = false;
+		rouleur->mbhc->wcd_mbhc.deinit_in_progress = true;
+		mbhc = &rouleur->mbhc->wcd_mbhc;
+		rouleur->usbc_hs_status = get_usbc_hs_status(component,
+						mbhc->mbhc_cfg);
+		rouleur_mbhc_ssr_down(rouleur->mbhc, component);
+		rouleur_reset(rouleur->dev, 0x01);
+		break;
+	case BOLERO_SLV_EVT_SSR_UP:
+		rouleur_reset(rouleur->dev, 0x00);
+		/* allow reset to take effect */
+		usleep_range(10000, 10010);
+		rouleur_get_logical_addr(rouleur->tx_swr_dev);
+		rouleur_get_logical_addr(rouleur->rx_swr_dev);
+
+		rouleur_init_reg(component);
+		regcache_mark_dirty(rouleur->regmap);
+		regcache_sync(rouleur->regmap);
+		rouleur->dev_up = true;
+		/* Initialize MBHC module */
+		mbhc = &rouleur->mbhc->wcd_mbhc;
+		ret = rouleur_mbhc_post_ssr_init(rouleur->mbhc, component);
+		if (ret) {
+			dev_err(component->dev, "%s: mbhc initialization failed\n",
+				__func__);
+		} else {
+			rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg);
+			if (rouleur->usbc_hs_status)
+				mdelay(500);
+		}
+		rouleur->mbhc->wcd_mbhc.deinit_in_progress = false;
+		break;
+	default:
+		dev_err(component->dev, "%s: invalid event %d\n", __func__,
+			event);
+		break;
+	}
+	return 0;
+}
+
+static int __rouleur_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+					  int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Micbias LD0 enable not supported for MicBias 3*/
+		if (micb_num == MIC_BIAS_3)
+			rouleur_micbias_control(component, micb_num,
+				MICB_PULLUP_ENABLE, true);
+		else
+			rouleur_micbias_control(component, micb_num,
+				MICB_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (micb_num == MIC_BIAS_3)
+			rouleur_micbias_control(component, micb_num,
+				MICB_PULLUP_DISABLE, true);
+		else
+			rouleur_micbias_control(component, micb_num,
+				MICB_DISABLE, true);
+		break;
+	};
+
+	return 0;
+
+}
+
+static int rouleur_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *kcontrol,
+					int event)
+{
+	return __rouleur_codec_enable_micbias(w, event);
+}
+
+static int __rouleur_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+						 int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "VA MIC BIAS1", sizeof("VA MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "VA MIC BIAS2", sizeof("VA MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "VA MIC BIAS3", sizeof("VA MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rouleur_micbias_control(component, micb_num,
+					MICB_PULLUP_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* 1 msec delay as per HW requirement */
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rouleur_micbias_control(component, micb_num,
+					MICB_PULLUP_DISABLE, true);
+		break;
+	};
+
+	return 0;
+
+}
+
+static int rouleur_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+					       struct snd_kcontrol *kcontrol,
+					       int event)
+{
+	return __rouleur_codec_enable_micbias_pullup(w, event);
+}
+
+static int rouleur_get_compander(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	bool hphr;
+	struct soc_multi_mixer_control *mc;
+
+	mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+	hphr = mc->shift;
+
+	ucontrol->value.integer.value[0] = hphr ? rouleur->comp2_enable :
+						rouleur->comp1_enable;
+	return 0;
+}
+
+static int rouleur_set_compander(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+	bool hphr;
+	struct soc_multi_mixer_control *mc;
+
+	mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+	hphr = mc->shift;
+	if (hphr)
+		rouleur->comp2_enable = value;
+	else
+		rouleur->comp1_enable = value;
+
+	return 0;
+}
+
+static int rouleur_codec_enable_pa_vpos(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 rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	struct rouleur_pdata *pdata = NULL;
+	int ret = 0;
+
+	pdata = dev_get_platdata(rouleur->dev);
+
+	if (!pdata) {
+		dev_err(component->dev, "%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (test_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask)) {
+			dev_dbg(component->dev,
+				"%s: vpos already in enabled state\n",
+				__func__);
+			clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
+			return 0;
+		}
+		ret = msm_cdc_enable_ondemand_supply(rouleur->dev,
+						rouleur->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-pa-vpos");
+		if (ret == -EINVAL) {
+			dev_err(component->dev, "%s: pa vpos is not enabled\n",
+				__func__);
+			return ret;
+		}
+		clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
+		/*
+		 * 200us sleep is required after LDO15 is enabled as per
+		 * HW requirement
+		 */
+		usleep_range(200, 250);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		set_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
+		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
+				rouleur->rx_swr_dev->dev_num,
+				false);
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_kcontrol_new rouleur_snd_controls[] = {
+	SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0,
+		rouleur_get_compander, rouleur_set_compander),
+	SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0,
+		rouleur_get_compander, rouleur_set_compander),
+
+	SOC_SINGLE_TLV("HPHL Volume", ROULEUR_ANA_HPHPA_L_GAIN, 0, 20, 1,
+					line_gain),
+	SOC_SINGLE_TLV("HPHR Volume", ROULEUR_ANA_HPHPA_R_GAIN, 0, 20, 1,
+					line_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", ROULEUR_ANA_TX_AMIC1, 0, 8, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", ROULEUR_ANA_TX_AMIC2, 0, 8, 0,
+			analog_gain),
+};
+
+static const struct snd_kcontrol_new adc1_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new adc2_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic1_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic2_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new ear_rdac_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new lo_rdac_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new hphl_rdac_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new hphr_rdac_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const char * const adc2_mux_text[] = {
+	"INP2", "INP3"
+};
+
+static const struct soc_enum adc2_enum =
+	SOC_ENUM_SINGLE(ROULEUR_ANA_TX_AMIC2, 4,
+		ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
+
+
+static const struct snd_kcontrol_new tx_adc2_mux =
+	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
+
+
+static const struct snd_soc_dapm_widget rouleur_dapm_widgets[] = {
+
+	/*input widgets*/
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_INPUT("AMIC3"),
+	SND_SOC_DAPM_INPUT("IN1_HPHL"),
+	SND_SOC_DAPM_INPUT("IN2_HPHR"),
+
+	/*tx widgets*/
+	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0,
+				rouleur_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+				&tx_adc2_mux),
+
+	/*tx mixers*/
+	SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0,
+				adc1_switch, ARRAY_SIZE(adc1_switch),
+				rouleur_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0,
+				adc2_switch, ARRAY_SIZE(adc2_switch),
+				rouleur_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	/* micbias widgets*/
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("PA_VPOS", SND_SOC_NOPM, 0, 0,
+			     rouleur_codec_enable_pa_vpos,
+			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/*rx widgets*/
+	SND_SOC_DAPM_PGA_E("EAR PGA", ROULEUR_ANA_COMBOPA_CTL, 7, 0, NULL, 0,
+				rouleur_codec_enable_ear_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LO PGA", ROULEUR_ANA_COMBOPA_CTL, 7, 0, NULL, 0,
+				rouleur_codec_enable_lo_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("HPHL PGA", ROULEUR_ANA_HPHPA_CNP_CTL_2, 7, 0, NULL,
+				0, rouleur_codec_enable_hphl_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("HPHR PGA", ROULEUR_ANA_HPHPA_CNP_CTL_2, 6, 0, NULL,
+				0, rouleur_codec_enable_hphr_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,
+				rouleur_codec_hphl_dac_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0,
+				rouleur_codec_hphr_dac_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0,
+				rouleur_codec_ear_lo_dac_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0,
+				rouleur_enable_rx1, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0,
+				rouleur_enable_rx2, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	/* rx mixer widgets*/
+
+	SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0,
+			   ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)),
+	SND_SOC_DAPM_MIXER("LO_RDAC", SND_SOC_NOPM, 0, 0,
+			   lo_rdac_switch, ARRAY_SIZE(lo_rdac_switch)),
+	SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0,
+			   hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)),
+	SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0,
+			   hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)),
+
+	/*output widgets tx*/
+
+	SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),
+
+	/*output widgets rx*/
+	SND_SOC_DAPM_OUTPUT("EAR"),
+	SND_SOC_DAPM_OUTPUT("LO"),
+	SND_SOC_DAPM_OUTPUT("HPHL"),
+	SND_SOC_DAPM_OUTPUT("HPHR"),
+
+	/* micbias pull up widgets*/
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+				rouleur_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0,
+				rouleur_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/*tx mixer widgets*/
+	SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0,
+				0, dmic1_switch, ARRAY_SIZE(dmic1_switch),
+				rouleur_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0,
+				0, dmic2_switch, ARRAY_SIZE(dmic2_switch),
+				rouleur_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	/*output widgets*/
+	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route rouleur_audio_map[] = {
+	{"ADC1_OUTPUT", NULL, "ADC1_MIXER"},
+	{"ADC1_MIXER", "Switch", "ADC1"},
+	{"ADC1", NULL, "AMIC1"},
+
+	{"ADC2_OUTPUT", NULL, "ADC2_MIXER"},
+	{"ADC2_MIXER", "Switch", "ADC2"},
+	{"ADC2", NULL, "ADC2 MUX"},
+	{"ADC2 MUX", "INP3", "AMIC3"},
+	{"ADC2 MUX", "INP2", "AMIC2"},
+
+	{"IN1_HPHL", NULL, "PA_VPOS"},
+	{"RX1", NULL, "IN1_HPHL"},
+	{"RDAC1", NULL, "RX1"},
+	{"HPHL_RDAC", "Switch", "RDAC1"},
+	{"HPHL PGA", NULL, "HPHL_RDAC"},
+	{"HPHL", NULL, "HPHL PGA"},
+
+	{"IN2_HPHR", NULL, "PA_VPOS"},
+	{"RX2", NULL, "IN2_HPHR"},
+	{"RDAC2", NULL, "RX2"},
+	{"HPHR_RDAC", "Switch", "RDAC2"},
+	{"HPHR PGA", NULL, "HPHR_RDAC"},
+	{"HPHR", NULL, "HPHR PGA"},
+
+	{"RDAC3", NULL, "RX1"},
+	{"EAR_RDAC", "Switch", "RDAC3"},
+	{"EAR PGA", NULL, "EAR_RDAC"},
+	{"EAR", NULL, "EAR PGA"},
+
+	{"RDAC3", NULL, "RX1"},
+	{"LO_RDAC", "Switch", "RDAC3"},
+	{"LO PGA", NULL, "LO_RDAC"},
+	{"LO", NULL, "LO PGA"},
+
+	{"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"},
+	{"DMIC1_MIXER", "Switch", "DMIC1"},
+
+	{"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"},
+	{"DMIC2_MIXER", "Switch", "DMIC2"},
+};
+
+static ssize_t rouleur_version_read(struct snd_info_entry *entry,
+				   void *file_private_data,
+				   struct file *file,
+				   char __user *buf, size_t count,
+				   loff_t pos)
+{
+	struct rouleur_priv *priv;
+	char buffer[ROULEUR_VERSION_ENTRY_SIZE];
+	int len = 0;
+
+	priv = (struct rouleur_priv *) entry->private_data;
+	if (!priv) {
+		pr_err("%s: rouleur priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (priv->version) {
+	case ROULEUR_VERSION_1_0:
+		len = snprintf(buffer, sizeof(buffer), "ROULEUR_1_0\n");
+		break;
+	default:
+		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
+	}
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static struct snd_info_entry_ops rouleur_info_ops = {
+	.read = rouleur_version_read,
+};
+
+/*
+ * rouleur_info_create_codec_entry - creates rouleur module
+ * @codec_root: The parent directory
+ * @component: component instance
+ *
+ * Creates rouleur module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int rouleur_info_create_codec_entry(struct snd_info_entry *codec_root,
+				   struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct rouleur_priv *priv;
+	struct snd_soc_card *card;
+
+	if (!codec_root || !component)
+		return -EINVAL;
+
+	priv = snd_soc_component_get_drvdata(component);
+	if (priv->entry) {
+		dev_dbg(priv->dev,
+			"%s:rouleur module already created\n", __func__);
+		return 0;
+	}
+	card = component->card;
+	priv->entry = snd_info_create_subdir(codec_root->module,
+					     "rouleur", codec_root);
+	if (!priv->entry) {
+		dev_dbg(component->dev, "%s: failed to create rouleur entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+	version_entry = snd_info_create_card_entry(card->snd_card,
+						   "version",
+						   priv->entry);
+	if (!version_entry) {
+		dev_dbg(component->dev, "%s: failed to create rouleur version entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = priv;
+	version_entry->size = ROULEUR_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &rouleur_info_ops;
+
+	if (snd_info_register(version_entry) < 0) {
+		snd_info_free_entry(version_entry);
+		return -ENOMEM;
+	}
+	priv->version_entry = version_entry;
+
+	return 0;
+}
+EXPORT_SYMBOL(rouleur_info_create_codec_entry);
+
+static int rouleur_set_micbias_data(struct rouleur_priv *rouleur,
+			      struct rouleur_pdata *pdata)
+{
+	int vout_ctl = 0;
+	int rc = 0;
+
+	if (!pdata) {
+		dev_err(rouleur->dev, "%s: NULL pdata\n", __func__);
+		return -ENODEV;
+	}
+
+	/* set micbias voltage */
+	vout_ctl = rouleur_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
+	if (vout_ctl < 0) {
+		rc = -EINVAL;
+		goto done;
+	}
+	regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MICBIAS_LDO_1_SETTING,
+			   0xF8, vout_ctl << 3);
+done:
+	return rc;
+}
+
+static int rouleur_battery_supply_cb(struct notifier_block *nb,
+			unsigned long event, void *data)
+{
+	struct power_supply *psy = data;
+	struct rouleur_priv *rouleur =
+		container_of(nb, struct rouleur_priv, psy_nb);
+
+	if (strcmp(psy->desc->name, "battery"))
+		return NOTIFY_OK;
+	queue_work(system_freezable_wq, &rouleur->soc_eval_work);
+
+	return NOTIFY_OK;
+}
+
+static int rouleur_read_battery_soc(struct rouleur_priv *rouleur, int *soc_val)
+{
+	static struct power_supply *batt_psy;
+	union power_supply_propval ret = {0,};
+	int err = 0;
+
+	*soc_val = 100;
+	if (!batt_psy)
+		batt_psy = power_supply_get_by_name("battery");
+	if (batt_psy) {
+		err = power_supply_get_property(batt_psy,
+				POWER_SUPPLY_PROP_CAPACITY, &ret);
+		if (err) {
+			pr_err("%s: battery SoC read error:%d\n",
+				__func__, err);
+			return err;
+		}
+		*soc_val = ret.intval;
+	}
+	pr_debug("%s: soc:%d\n", __func__, *soc_val);
+
+	return err;
+}
+
+static void rouleur_evaluate_soc(struct work_struct *work)
+{
+	struct rouleur_priv *rouleur =
+		container_of(work, struct rouleur_priv, soc_eval_work);
+	int soc_val = 0, ret = 0;
+	struct rouleur_pdata *pdata = NULL;
+
+	pdata = dev_get_platdata(rouleur->dev);
+	if (!pdata) {
+		dev_err(rouleur->dev, "%s: pdata is NULL\n", __func__);
+		return;
+	}
+
+	if (rouleur_read_battery_soc(rouleur, &soc_val) < 0) {
+		dev_err(rouleur->dev, "%s unable to read battery SoC\n",
+			__func__);
+		return;
+	}
+
+	if (soc_val < SOC_THRESHOLD_LEVEL) {
+		dev_dbg(rouleur->dev,
+			"%s battery SoC less than threshold soc_val = %d\n",
+			__func__, soc_val);
+		/* Reduce PA Gain by 6DB for low SoC */
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+					SLV_BOLERO_EVT_RX_PA_GAIN_UPDATE,
+					true);
+		rouleur->low_soc = true;
+		ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
+						 rouleur->supplies,
+						 pdata->regulator,
+						 pdata->num_supplies,
+						 "cdc-vdd-mic-bias",
+						 LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
+						 true);
+		if (ret < 0)
+			dev_err(rouleur->dev,
+				"%s unable to set mbias min voltage\n",
+				__func__);
+	} else {
+		if (rouleur->low_soc == true) {
+			/* Reset PA Gain to default for normal SoC */
+			if (rouleur->update_wcd_event)
+				rouleur->update_wcd_event(rouleur->handle,
+					SLV_BOLERO_EVT_RX_PA_GAIN_UPDATE,
+					false);
+			ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
+						rouleur->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-mic-bias",
+						LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
+						false);
+			if (ret < 0)
+				dev_err(rouleur->dev,
+					"%s unable to set mbias min voltage\n",
+					__func__);
+			rouleur->low_soc = false;
+		}
+	}
+}
+
+static void rouleur_get_foundry_id(struct rouleur_priv *rouleur)
+{
+	int ret;
+
+	if (rouleur->foundry_id_reg == 0) {
+		pr_debug("%s: foundry id not defined\n", __func__);
+		return;
+	}
+
+	ret = pm2250_spmi_read(rouleur->spmi_dev,
+				rouleur->foundry_id_reg, &rouleur->foundry_id);
+	if (ret == 0)
+		pr_debug("%s: rouleur foundry id = %x\n", rouleur->foundry_id,
+			 __func__);
+	else
+		pr_debug("%s: rouleur error in spmi read ret = %d\n",
+			 __func__, ret);
+}
+
+static int rouleur_soc_codec_probe(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm =
+			snd_soc_component_get_dapm(component);
+	int ret = -EINVAL;
+
+	dev_info(component->dev, "%s()\n", __func__);
+	rouleur = snd_soc_component_get_drvdata(component);
+
+	if (!rouleur)
+		return -EINVAL;
+
+	rouleur->component = component;
+	snd_soc_component_init_regmap(component, rouleur->regmap);
+
+	rouleur->fw_data = devm_kzalloc(component->dev,
+					sizeof(*(rouleur->fw_data)),
+					GFP_KERNEL);
+	if (!rouleur->fw_data) {
+		dev_err(component->dev, "Failed to allocate fw_data\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	set_bit(WCD9XXX_MBHC_CAL, rouleur->fw_data->cal_bit);
+	ret = wcd_cal_create_hwdep(rouleur->fw_data,
+				   WCD9XXX_CODEC_HWDEP_NODE, component);
+
+	if (ret < 0) {
+		dev_err(component->dev, "%s hwdep failed %d\n", __func__, ret);
+		goto done;
+	}
+
+	ret = rouleur_mbhc_init(&rouleur->mbhc, component, rouleur->fw_data);
+	if (ret) {
+		pr_err("%s: mbhc initialization failed\n", __func__);
+		goto done;
+	}
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+	snd_soc_dapm_ignore_suspend(dapm, "IN1_HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "IN2_HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC1_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC2_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "EAR");
+	snd_soc_dapm_ignore_suspend(dapm, "LO");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC1_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC2_OUTPUT");
+	snd_soc_dapm_sync(dapm);
+
+	rouleur_init_reg(component);
+	/* Get rouleur foundry id */
+	rouleur_get_foundry_id(rouleur);
+
+	rouleur->version = ROULEUR_VERSION_1_0;
+       /* Register event notifier */
+	rouleur->nblock.notifier_call = rouleur_event_notify;
+	if (rouleur->register_notifier) {
+		ret = rouleur->register_notifier(rouleur->handle,
+						&rouleur->nblock,
+						true);
+		if (ret) {
+			dev_err(component->dev,
+				"%s: Failed to register notifier %d\n",
+				__func__, ret);
+			return ret;
+		}
+	}
+	rouleur->low_soc = false;
+	rouleur->dev_up = true;
+	/* Register notifier to change gain based on state of charge */
+	INIT_WORK(&rouleur->soc_eval_work, rouleur_evaluate_soc);
+	rouleur->psy_nb.notifier_call = rouleur_battery_supply_cb;
+	if (power_supply_reg_notifier(&rouleur->psy_nb) < 0)
+		dev_dbg(rouleur->dev,
+			"%s: could not register pwr supply notifier\n",
+			__func__);
+	queue_work(system_freezable_wq, &rouleur->soc_eval_work);
+done:
+	return ret;
+}
+
+static void rouleur_soc_codec_remove(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	if (!rouleur)
+		return;
+
+	if (rouleur->register_notifier)
+		rouleur->register_notifier(rouleur->handle,
+						&rouleur->nblock,
+						false);
+}
+
+static int rouleur_soc_codec_suspend(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	if (!rouleur)
+		return 0;
+	rouleur->dapm_bias_off = true;
+	return 0;
+}
+
+static int rouleur_soc_codec_resume(struct snd_soc_component *component)
+{
+	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
+
+	if (!rouleur)
+		return 0;
+	rouleur->dapm_bias_off = false;
+	return 0;
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_rouleur = {
+	.name = DRV_NAME,
+	.probe = rouleur_soc_codec_probe,
+	.remove = rouleur_soc_codec_remove,
+	.controls = rouleur_snd_controls,
+	.num_controls = ARRAY_SIZE(rouleur_snd_controls),
+	.dapm_widgets = rouleur_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rouleur_dapm_widgets),
+	.dapm_routes = rouleur_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(rouleur_audio_map),
+	.suspend = rouleur_soc_codec_suspend,
+	.resume = rouleur_soc_codec_resume,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int rouleur_suspend(struct device *dev)
+{
+	struct rouleur_priv *rouleur = NULL;
+	int ret = 0;
+	struct rouleur_pdata *pdata = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	rouleur = dev_get_drvdata(dev);
+	if (!rouleur)
+		return -EINVAL;
+
+	pdata = dev_get_platdata(rouleur->dev);
+
+	if (!pdata) {
+		dev_err(dev, "%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (test_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask)) {
+		ret = msm_cdc_disable_ondemand_supply(rouleur->dev,
+						rouleur->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-pa-vpos");
+		if (ret == -EINVAL) {
+			dev_err(dev, "%s: pa vpos is not disabled\n",
+				__func__);
+			return 0;
+		}
+		clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
+	}
+	if (rouleur->dapm_bias_off) {
+		 msm_cdc_set_supplies_lpm_mode(rouleur->dev,
+					      rouleur->supplies,
+					      pdata->regulator,
+					      pdata->num_supplies,
+					      true);
+		set_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask);
+	}
+	return 0;
+}
+
+static int rouleur_resume(struct device *dev)
+{
+	struct rouleur_priv *rouleur = NULL;
+	struct rouleur_pdata *pdata = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	rouleur = dev_get_drvdata(dev);
+	if (!rouleur)
+		return -EINVAL;
+
+	pdata = dev_get_platdata(rouleur->dev);
+
+	if (!pdata) {
+		dev_err(dev, "%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (test_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask)) {
+		msm_cdc_set_supplies_lpm_mode(rouleur->dev,
+						rouleur->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						false);
+		clear_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask);
+	}
+
+	return 0;
+}
+#endif
+
+static int rouleur_reset(struct device *dev, int reset_val)
+{
+	struct rouleur_priv *rouleur = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	rouleur = dev_get_drvdata(dev);
+	if (!rouleur)
+		return -EINVAL;
+
+	pm2250_spmi_write(rouleur->spmi_dev, rouleur->reset_reg, reset_val);
+
+	return 0;
+}
+
+static int rouleur_read_of_property_u32(struct device *dev, const char *name,
+					u32 *val)
+{
+	int rc = 0;
+
+	rc = of_property_read_u32(dev->of_node, name, val);
+	if (rc)
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, name, dev->of_node->full_name);
+
+	return rc;
+}
+
+static void rouleur_dt_parse_micbias_info(struct device *dev,
+					  struct rouleur_micbias_setting *mb)
+{
+	u32 prop_val = 0;
+	int rc = 0;
+
+	/* MB1 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias1-mv",
+				    NULL)) {
+		rc = rouleur_read_of_property_u32(dev,
+						  "qcom,cdc-micbias1-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb1_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias1 DT property not found\n",
+			__func__);
+	}
+
+	/* MB2 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias2-mv",
+				    NULL)) {
+		rc = rouleur_read_of_property_u32(dev,
+						  "qcom,cdc-micbias2-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb2_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias2 DT property not found\n",
+			__func__);
+	}
+
+	/* MB3 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias3-mv",
+				    NULL)) {
+		rc = rouleur_read_of_property_u32(dev,
+						  "qcom,cdc-micbias3-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb3_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias3 DT property not found\n",
+			__func__);
+	}
+}
+
+struct rouleur_pdata *rouleur_populate_dt_data(struct device *dev)
+{
+	struct rouleur_pdata *pdata = NULL;
+	u32 reg;
+	int ret = 0;
+
+	pdata = kzalloc(sizeof(struct rouleur_pdata),
+				GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	pdata->spmi_np = of_parse_phandle(dev->of_node,
+					"qcom,pmic-spmi-node", 0);
+	if (!pdata->spmi_np) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+				__func__, "qcom,pmic-spmi-node",
+				dev->of_node->full_name);
+		kfree(pdata);
+		return NULL;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "qcom,wcd-reset-reg", &reg);
+	if (ret) {
+		dev_err(dev, "%s: Failed to obtain reset reg value %d\n",
+			__func__, ret);
+		kfree(pdata);
+		return NULL;
+	}
+	pdata->reset_reg = reg;
+
+	if (of_property_read_u32(dev->of_node, "qcom,foundry-id-reg", &reg))
+		dev_dbg(dev, "%s: Failed to obtain foundry id\n",
+			__func__);
+	else
+		pdata->foundry_id_reg = reg;
+
+	/* Parse power supplies */
+	msm_cdc_get_power_supplies(dev, &pdata->regulator,
+				   &pdata->num_supplies);
+	if (!pdata->regulator || (pdata->num_supplies <= 0)) {
+		dev_err(dev, "%s: no power supplies defined for codec\n",
+			__func__);
+		kfree(pdata);
+		return NULL;
+	}
+
+	pdata->rx_slave = of_parse_phandle(dev->of_node, "qcom,rx-slave", 0);
+	pdata->tx_slave = of_parse_phandle(dev->of_node, "qcom,tx-slave", 0);
+	rouleur_dt_parse_micbias_info(dev, &pdata->micbias);
+
+	return pdata;
+}
+
+static int rouleur_wakeup(void *handle, bool enable)
+{
+	struct rouleur_priv *priv;
+
+	if (!handle) {
+		pr_err("%s: NULL handle\n", __func__);
+		return -EINVAL;
+	}
+	priv = (struct rouleur_priv *)handle;
+	if (!priv->tx_swr_dev) {
+		pr_err("%s: tx swr dev is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		return swr_device_wakeup_vote(priv->tx_swr_dev);
+	else
+		return swr_device_wakeup_unvote(priv->tx_swr_dev);
+}
+
+static irqreturn_t rouleur_wd_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: Watchdog interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static int rouleur_bind(struct device *dev)
+{
+	int ret = 0, i = 0;
+	struct rouleur_priv *rouleur = NULL;
+	struct rouleur_pdata *pdata = NULL;
+	struct wcd_ctrl_platform_data *plat_data = NULL;
+	struct platform_device *pdev = NULL;
+
+	rouleur = kzalloc(sizeof(struct rouleur_priv), GFP_KERNEL);
+	if (!rouleur)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, rouleur);
+
+	pdata = rouleur_populate_dt_data(dev);
+	if (!pdata) {
+		dev_err(dev, "%s: Fail to obtain platform data\n", __func__);
+		kfree(rouleur);
+		return -EINVAL;
+	}
+	rouleur->dev = dev;
+	rouleur->dev->platform_data = pdata;
+	pdev = of_find_device_by_node(pdata->spmi_np);
+	if (!pdev) {
+		dev_err(dev, "%s: platform device from SPMI node is NULL\n",
+				__func__);
+		ret = -EINVAL;
+		goto err_bind_all;
+	}
+
+	rouleur->spmi_dev = &pdev->dev;
+	rouleur->reset_reg = pdata->reset_reg;
+	rouleur->foundry_id_reg = pdata->foundry_id_reg;
+	ret = msm_cdc_init_supplies(dev, &rouleur->supplies,
+				    pdata->regulator, pdata->num_supplies);
+	if (!rouleur->supplies) {
+		dev_err(dev, "%s: Cannot init wcd supplies\n",
+			__func__);
+		goto err_bind_all;
+	}
+
+	plat_data = dev_get_platdata(dev->parent);
+	if (!plat_data) {
+		dev_err(dev, "%s: platform data from parent is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_bind_all;
+	}
+	rouleur->handle = (void *)plat_data->handle;
+	if (!rouleur->handle) {
+		dev_err(dev, "%s: handle is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err_bind_all;
+	}
+	rouleur->update_wcd_event = plat_data->update_wcd_event;
+	if (!rouleur->update_wcd_event) {
+		dev_err(dev, "%s: update_wcd_event api is null!\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_bind_all;
+	}
+	rouleur->register_notifier = plat_data->register_notifier;
+	if (!rouleur->register_notifier) {
+		dev_err(dev, "%s: register_notifier api is null!\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_bind_all;
+	}
+
+	ret = msm_cdc_enable_static_supplies(dev, rouleur->supplies,
+					     pdata->regulator,
+					     pdata->num_supplies);
+	if (ret) {
+		dev_err(dev, "%s: wcd static supply enable failed!\n",
+			__func__);
+		goto err_bind_all;
+	}
+
+	rouleur_reset(dev, 0x01);
+	usleep_range(20, 30);
+	rouleur_reset(dev, 0x00);
+	/*
+	 * Add 5msec delay to provide sufficient time for
+	 * soundwire auto enumeration of slave devices as
+	 * as per HW requirement.
+	 */
+	usleep_range(5000, 5010);
+	rouleur->wakeup = rouleur_wakeup;
+
+	ret = component_bind_all(dev, rouleur);
+	if (ret) {
+		dev_err(dev, "%s: Slave bind failed, ret = %d\n",
+			__func__, ret);
+		goto err_bind_all;
+	}
+
+	ret = rouleur_parse_port_mapping(dev, "qcom,rx_swr_ch_map", CODEC_RX);
+	ret |= rouleur_parse_port_mapping(dev, "qcom,tx_swr_ch_map", CODEC_TX);
+
+	if (ret) {
+		dev_err(dev, "Failed to read port mapping\n");
+		goto err;
+	}
+
+	rouleur->rx_swr_dev = get_matching_swr_slave_device(pdata->rx_slave);
+	if (!rouleur->rx_swr_dev) {
+		dev_err(dev, "%s: Could not find RX swr slave device\n",
+			 __func__);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	rouleur->tx_swr_dev = get_matching_swr_slave_device(pdata->tx_slave);
+	if (!rouleur->tx_swr_dev) {
+		dev_err(dev, "%s: Could not find TX swr slave device\n",
+			__func__);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	rouleur->regmap = devm_regmap_init_swr(rouleur->tx_swr_dev,
+					       &rouleur_regmap_config);
+	if (!rouleur->regmap) {
+		dev_err(dev, "%s: Regmap init failed\n",
+				__func__);
+		goto err;
+	}
+
+	/* Set all interupts as edge triggered */
+	for (i = 0; i < rouleur_regmap_irq_chip.num_regs; i++)
+		regmap_write(rouleur->regmap,
+			     (ROULEUR_DIG_SWR_INTR_LEVEL_0 + i), 0);
+
+	rouleur_regmap_irq_chip.irq_drv_data = rouleur;
+	rouleur->irq_info.wcd_regmap_irq_chip = &rouleur_regmap_irq_chip;
+	rouleur->irq_info.codec_name = "rouleur";
+	rouleur->irq_info.regmap = rouleur->regmap;
+	rouleur->irq_info.dev = dev;
+	ret = wcd_irq_init(&rouleur->irq_info, &rouleur->virq);
+
+	if (ret) {
+		dev_err(dev, "%s: IRQ init failed: %d\n",
+			__func__, ret);
+		goto err;
+	}
+	rouleur->tx_swr_dev->slave_irq = rouleur->virq;
+
+	mutex_init(&rouleur->micb_lock);
+	mutex_init(&rouleur->main_bias_lock);
+	mutex_init(&rouleur->rx_clk_lock);
+
+	ret = rouleur_set_micbias_data(rouleur, pdata);
+	if (ret < 0) {
+		dev_err(dev, "%s: bad micbias pdata\n", __func__);
+		goto err_irq;
+	}
+
+	/* Request for watchdog interrupt */
+	wcd_request_irq(&rouleur->irq_info, ROULEUR_IRQ_HPHR_PDM_WD_INT,
+			"HPHR PDM WD INT", rouleur_wd_handle_irq, NULL);
+	wcd_request_irq(&rouleur->irq_info, ROULEUR_IRQ_HPHL_PDM_WD_INT,
+			"HPHL PDM WD INT", rouleur_wd_handle_irq, NULL);
+	/* Disable watchdog interrupt for HPH */
+	wcd_disable_irq(&rouleur->irq_info, ROULEUR_IRQ_HPHR_PDM_WD_INT);
+	wcd_disable_irq(&rouleur->irq_info, ROULEUR_IRQ_HPHL_PDM_WD_INT);
+
+	ret = snd_soc_register_component(dev, &soc_codec_dev_rouleur,
+				     NULL, 0);
+	if (ret) {
+		dev_err(dev, "%s: Codec registration failed\n",
+				__func__);
+		goto err_irq;
+	}
+
+	return ret;
+err_irq:
+	wcd_irq_exit(&rouleur->irq_info, rouleur->virq);
+	mutex_destroy(&rouleur->micb_lock);
+	mutex_destroy(&rouleur->main_bias_lock);
+	mutex_destroy(&rouleur->rx_clk_lock);
+err:
+	component_unbind_all(dev, rouleur);
+err_bind_all:
+	dev_set_drvdata(dev, NULL);
+	kfree(pdata);
+	kfree(rouleur);
+	return ret;
+}
+
+static void rouleur_unbind(struct device *dev)
+{
+	struct rouleur_priv *rouleur = dev_get_drvdata(dev);
+	struct rouleur_pdata *pdata = dev_get_platdata(rouleur->dev);
+
+	wcd_irq_exit(&rouleur->irq_info, rouleur->virq);
+	snd_soc_unregister_component(dev);
+	component_unbind_all(dev, rouleur);
+	mutex_destroy(&rouleur->micb_lock);
+	mutex_destroy(&rouleur->main_bias_lock);
+	mutex_destroy(&rouleur->rx_clk_lock);
+	dev_set_drvdata(dev, NULL);
+	kfree(pdata);
+	kfree(rouleur);
+}
+
+static const struct of_device_id rouleur_dt_match[] = {
+	{ .compatible = "qcom,rouleur-codec" , .data = "rouleur" },
+	{}
+};
+
+static const struct component_master_ops rouleur_comp_ops = {
+	.bind   = rouleur_bind,
+	.unbind = rouleur_unbind,
+};
+
+static int rouleur_compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static void rouleur_release_of(struct device *dev, void *data)
+{
+	of_node_put(data);
+}
+
+static int rouleur_add_slave_components(struct device *dev,
+				struct component_match **matchptr)
+{
+	struct device_node *np, *rx_node, *tx_node;
+
+	np = dev->of_node;
+
+	rx_node = of_parse_phandle(np, "qcom,rx-slave", 0);
+	if (!rx_node) {
+		dev_err(dev, "%s: Rx-slave node not defined\n", __func__);
+		return -ENODEV;
+	}
+	of_node_get(rx_node);
+	component_match_add_release(dev, matchptr,
+			rouleur_release_of,
+			rouleur_compare_of,
+			rx_node);
+
+	tx_node = of_parse_phandle(np, "qcom,tx-slave", 0);
+	if (!tx_node) {
+		dev_err(dev, "%s: Tx-slave node not defined\n", __func__);
+			return -ENODEV;
+	}
+	of_node_get(tx_node);
+	component_match_add_release(dev, matchptr,
+			rouleur_release_of,
+			rouleur_compare_of,
+			tx_node);
+	return 0;
+}
+
+static int rouleur_probe(struct platform_device *pdev)
+{
+	struct component_match *match = NULL;
+	int ret;
+
+	ret = rouleur_add_slave_components(&pdev->dev, &match);
+	if (ret)
+		return ret;
+
+	return component_master_add_with_match(&pdev->dev,
+					&rouleur_comp_ops, match);
+}
+
+static int rouleur_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &rouleur_comp_ops);
+	dev_set_drvdata(&pdev->dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static const struct dev_pm_ops rouleur_dev_pm_ops = {
+	.suspend_late = rouleur_suspend,
+	.resume_early = rouleur_resume
+};
+#endif
+
+static struct platform_driver rouleur_codec_driver = {
+	.probe = rouleur_probe,
+	.remove = rouleur_remove,
+	.driver = {
+		.name = "rouleur_codec",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(rouleur_dt_match),
+#ifdef CONFIG_PM_SLEEP
+		.pm = &rouleur_dev_pm_ops,
+#endif
+		.suppress_bind_attrs = true,
+	},
+};
+
+module_platform_driver(rouleur_codec_driver);
+MODULE_DESCRIPTION("Rouleur Codec driver");
+MODULE_LICENSE("GPL v2");
+

+ 19 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur.h

@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _ROULEUR_H
+#define _ROULEUR_H
+
+#ifdef CONFIG_SND_SOC_ROULEUR
+extern int rouleur_info_create_codec_entry(struct snd_info_entry *codec_root,
+				    struct snd_soc_component *component);
+#else
+extern int rouleur_info_create_codec_entry(struct snd_info_entry *codec_root,
+				    struct snd_soc_component *component)
+{
+	return 0;
+}
+#endif /* CONFIG_SND_SOC_ROULEUR */
+
+#endif

+ 444 - 0
qcom/opensource/audio-kernel/asoc/codecs/rouleur/rouleur_slave.c

@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <soc/soundwire.h>
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#define SWR_SLV_MAX_REG_ADDR    0x2009
+#define SWR_SLV_START_REG_ADDR  0x40
+#define SWR_SLV_MAX_BUF_LEN     20
+#define BYTES_PER_LINE          12
+#define SWR_SLV_RD_BUF_LEN      8
+#define SWR_SLV_WR_BUF_LEN      32
+#define SWR_SLV_MAX_DEVICES     2
+#endif /* CONFIG_DEBUG_FS */
+
+struct rouleur_slave_priv {
+	struct swr_device *swr_slave;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_rouleur_dent;
+	struct dentry *debugfs_peek;
+	struct dentry *debugfs_poke;
+	struct dentry *debugfs_reg_dump;
+	unsigned int read_data;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int get_parameters(char *buf, u32 *param1, int num_of_par)
+{
+	char *token = NULL;
+	int base = 0, cnt = 0;
+
+	token = strsep(&buf, " ");
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtou32(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else {
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static bool is_swr_slv_reg_readable(int reg)
+{
+	int ret = true;
+
+	if (((reg > 0x46) && (reg < 0x4A)) ||
+	    ((reg > 0x4A) && (reg < 0x50)) ||
+	    ((reg > 0x55) && (reg < 0xD0)) ||
+	    ((reg > 0xD0) && (reg < 0xE0)) ||
+	    ((reg > 0xE0) && (reg < 0xF0)) ||
+	    ((reg > 0xF0) && (reg < 0x100)) ||
+	    ((reg > 0x105) && (reg < 0x120)) ||
+	    ((reg > 0x205) && (reg < 0x220)) ||
+	    ((reg > 0x305) && (reg < 0x320)) ||
+	    ((reg > 0x405) && (reg < 0x420)) ||
+	    ((reg > 0x128) && (reg < 0x130)) ||
+	    ((reg > 0x228) && (reg < 0x230)) ||
+	    ((reg > 0x328) && (reg < 0x330)) ||
+	    ((reg > 0x428) && (reg < 0x430)) ||
+	    ((reg > 0x138) && (reg < 0x205)) ||
+	    ((reg > 0x238) && (reg < 0x305)) ||
+	    ((reg > 0x338) && (reg < 0x405)) ||
+	    ((reg > 0x405) && (reg < 0xF00)) ||
+	    ((reg > 0xF05) && (reg < 0xF20)) ||
+	    ((reg > 0xF25) && (reg < 0xF30)) ||
+	    ((reg > 0xF35) && (reg < 0x2000)))
+		ret = false;
+
+	return ret;
+}
+
+static ssize_t rouleur_swrslave_reg_show(struct swr_device *pdev,
+					char __user *ubuf,
+					size_t count, loff_t *ppos)
+{
+	int i, reg_val, len;
+	ssize_t total = 0;
+	char tmp_buf[SWR_SLV_MAX_BUF_LEN];
+
+	if (!ubuf || !ppos)
+		return 0;
+
+	for (i = (((int) *ppos/BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR);
+		i <= SWR_SLV_MAX_REG_ADDR; i++) {
+		if (!is_swr_slv_reg_readable(i))
+			continue;
+		swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
+		len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
+			       (reg_val & 0xFF));
+		if (len < 0) {
+			pr_err("%s: fail to fill the buffer\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		if (((total + len) >= count - 1) || (len < 0))
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			pr_err("%s: fail to copy reg dump\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		total += len;
+		*ppos += len;
+	}
+
+copy_err:
+	*ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE;
+	return total;
+}
+
+static ssize_t codec_debug_dump(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct swr_device *pdev;
+
+	if (!count || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	return rouleur_swrslave_reg_show(pdev, ubuf, count, ppos);
+}
+
+static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_RD_BUF_LEN];
+	struct swr_device *pdev = NULL;
+	struct rouleur_slave_priv *rouleur_slave = NULL;
+
+	if (!count || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	rouleur_slave = swr_get_dev_data(pdev);
+	if (!rouleur_slave)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	snprintf(lbuf, sizeof(lbuf), "0x%x\n",
+			(rouleur_slave->read_data & 0xFF));
+
+	return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+					       strnlen(lbuf, 7));
+}
+
+static ssize_t codec_debug_peek_write(struct file *file,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_WR_BUF_LEN];
+	int rc = 0;
+	u32 param[5];
+	struct swr_device *pdev = NULL;
+	struct rouleur_slave_priv *rouleur_slave = NULL;
+
+	if (!cnt || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	rouleur_slave = swr_get_dev_data(pdev);
+	if (!rouleur_slave)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	rc = get_parameters(lbuf, param, 1);
+	if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)))
+		return -EINVAL;
+	swr_read(pdev, pdev->dev_num, param[0], &rouleur_slave->read_data, 1);
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static ssize_t codec_debug_write(struct file *file,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_WR_BUF_LEN];
+	int rc = 0;
+	u32 param[5];
+	struct swr_device *pdev;
+
+	if (!file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	rc = get_parameters(lbuf, param, 2);
+	if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) &&
+		(param[1] <= 0xFF) && (rc == 0)))
+		return -EINVAL;
+	swr_write(pdev, pdev->dev_num, param[0], &param[1]);
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static const struct file_operations codec_debug_write_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+};
+
+static const struct file_operations codec_debug_read_ops = {
+	.open = codec_debug_open,
+	.read = codec_debug_read,
+	.write = codec_debug_peek_write,
+};
+
+static const struct file_operations codec_debug_dump_ops = {
+	.open = codec_debug_open,
+	.read = codec_debug_dump,
+};
+#endif
+
+static int rouleur_slave_bind(struct device *dev,
+				struct device *master, void *data)
+{
+	int ret = 0;
+	uint8_t devnum = 0;
+	struct swr_device *pdev = to_swr_device(dev);
+
+	if (pdev == NULL) {
+		dev_err(dev, "%s: pdev is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"%s get devnum %d for dev addr %lx failed\n",
+				__func__, devnum, pdev->addr);
+		swr_remove_device(pdev);
+		return ret;
+	}
+	pdev->dev_num = devnum;
+
+	return ret;
+}
+
+static void rouleur_slave_unbind(struct device *dev,
+				struct device *master, void *data)
+{
+	struct rouleur_slave_priv *rouleur_slave = NULL;
+	struct swr_device *pdev = to_swr_device(dev);
+
+	if (pdev == NULL) {
+		dev_err(dev, "%s: pdev is NULL\n", __func__);
+		return;
+	}
+
+	rouleur_slave = swr_get_dev_data(pdev);
+	if (!rouleur_slave) {
+		dev_err(&pdev->dev, "%s: rouleur_slave is NULL\n", __func__);
+		return;
+	}
+
+}
+
+static const struct swr_device_id rouleur_swr_id[] = {
+	{"rouleur-slave", 0},
+	{}
+};
+
+static const struct of_device_id rouleur_swr_dt_match[] = {
+	{
+		.compatible = "qcom,rouleur-slave",
+	},
+	{}
+};
+
+static const struct component_ops rouleur_slave_comp_ops = {
+	.bind   = rouleur_slave_bind,
+	.unbind = rouleur_slave_unbind,
+};
+
+static int rouleur_swr_up(struct swr_device *pdev)
+{
+	return 0;
+}
+
+static int rouleur_swr_down(struct swr_device *pdev)
+{
+	return 0;
+}
+
+static int rouleur_swr_reset(struct swr_device *pdev)
+{
+	return 0;
+}
+
+static int rouleur_swr_probe(struct swr_device *pdev)
+{
+	struct rouleur_slave_priv *rouleur_slave = NULL;
+
+	rouleur_slave = devm_kzalloc(&pdev->dev,
+				sizeof(struct rouleur_slave_priv), GFP_KERNEL);
+	if (!rouleur_slave)
+		return -ENOMEM;
+
+	swr_set_dev_data(pdev, rouleur_slave);
+
+	rouleur_slave->swr_slave = pdev;
+#ifdef CONFIG_DEBUG_FS
+	if (!rouleur_slave->debugfs_rouleur_dent) {
+		rouleur_slave->debugfs_rouleur_dent = debugfs_create_dir(
+						dev_name(&pdev->dev), 0);
+		if (!IS_ERR(rouleur_slave->debugfs_rouleur_dent)) {
+			rouleur_slave->debugfs_peek =
+					debugfs_create_file("swrslave_peek",
+					S_IFREG | 0444,
+					rouleur_slave->debugfs_rouleur_dent,
+					(void *) pdev,
+					&codec_debug_read_ops);
+
+			rouleur_slave->debugfs_poke =
+					debugfs_create_file("swrslave_poke",
+					S_IFREG | 0444,
+					rouleur_slave->debugfs_rouleur_dent,
+					(void *) pdev,
+					&codec_debug_write_ops);
+
+			rouleur_slave->debugfs_reg_dump =
+					debugfs_create_file(
+					"swrslave_reg_dump",
+					S_IFREG | 0444,
+					rouleur_slave->debugfs_rouleur_dent,
+					(void *) pdev,
+					&codec_debug_dump_ops);
+                }
+        }
+#endif
+	return component_add(&pdev->dev, &rouleur_slave_comp_ops);
+}
+
+static int rouleur_swr_remove(struct swr_device *pdev)
+{
+#ifdef CONFIG_DEBUG_FS
+	struct rouleur_slave_priv *rouleur_slave = swr_get_dev_data(pdev);
+
+	if (rouleur_slave) {
+		debugfs_remove_recursive(rouleur_slave->debugfs_rouleur_dent);
+		rouleur_slave->debugfs_rouleur_dent = NULL;
+	}
+#endif
+	component_del(&pdev->dev, &rouleur_slave_comp_ops);
+	swr_set_dev_data(pdev, NULL);
+	swr_remove_device(pdev);
+	return 0;
+}
+
+static struct swr_driver rouleur_slave_driver = {
+	.driver = {
+		.name = "rouleur-slave",
+		.owner = THIS_MODULE,
+		.of_match_table = rouleur_swr_dt_match,
+	},
+	.probe = rouleur_swr_probe,
+	.remove = rouleur_swr_remove,
+	.id_table = rouleur_swr_id,
+	.device_up = rouleur_swr_up,
+	.device_down = rouleur_swr_down,
+	.reset_device = rouleur_swr_reset,
+};
+
+static int __init rouleur_slave_init(void)
+{
+	return swr_driver_register(&rouleur_slave_driver);
+}
+
+static void __exit rouleur_slave_exit(void)
+{
+	swr_driver_unregister(&rouleur_slave_driver);
+}
+
+module_init(rouleur_slave_init);
+module_exit(rouleur_slave_exit);
+
+MODULE_DESCRIPTION("Rouleur Swr Slave driver");
+MODULE_LICENSE("GPL v2");

+ 937 - 0
qcom/opensource/audio-kernel/asoc/codecs/swr-dmic.c

@@ -0,0 +1,937 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/debugfs.h>
+#include <soc/soundwire.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <asoc/msm-cdc-supply.h>
+#include <bindings/audio-codec-port-types.h>
+#ifdef CONFIG_SND_SOC_WCD939X
+#include "wcd939x/wcd939x.h"
+#else
+#include "wcd938x/wcd938x.h"
+#endif
+#include "swr-dmic.h"
+
+#define NUM_ATTEMPTS 5
+#define SWRS_SCP_CONTROL    0x44
+
+#define MAX_NAME_LEN 40
+
+static int swr_master_channel_map[] = {
+	ZERO,
+	SWRM_TX_PCM_OUT,
+	SWRM_TX1_CH1,
+	SWRM_TX1_CH2,
+	SWRM_TX1_CH3,
+	SWRM_TX1_CH4,
+	SWRM_TX2_CH1,
+	SWRM_TX2_CH2,
+	SWRM_TX2_CH3,
+	SWRM_TX2_CH4,
+	SWRM_TX3_CH1,
+	SWRM_TX3_CH2,
+	SWRM_TX3_CH3,
+	SWRM_TX3_CH4,
+	SWRM_TX_PCM_IN,
+};
+
+/*
+ * Private data Structure for swr-dmic. All parameters related to
+ * external mic codec needs to be defined here.
+ */
+struct swr_dmic_priv {
+	struct device *dev;
+	struct swr_device *swr_slave;
+	struct snd_soc_component *component;
+	struct snd_soc_component_driver *driver;
+	struct snd_soc_dai_driver *dai_driver;
+	struct snd_soc_component *supply_component;
+	u32 micb_num;
+	struct device_node *wcd_handle;
+	bool is_wcd_supply;
+	int is_en_supply;
+	u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
+	struct swr_port_params tx_port_params[SWR_UC_MAX][SWR_DMIC_MAX_PORTS];
+	struct swr_dev_frame_config swr_tx_port_params[SWR_UC_MAX];
+	struct notifier_block nblock;
+};
+
+const char *codec_name_list[] = {
+	"swr-dmic.01",
+	"swr-dmic.02",
+	"swr-dmic.03",
+	"swr-dmic.04",
+};
+
+const char *dai_name_list[] = {
+	"swr_dmic_tx0",
+	"swr_dmic_tx1",
+	"swr_dmic_tx2",
+	"swr_dmic_tx3",
+};
+
+const char *aif_name_list[] = {
+	"SWR_DMIC_AIF0 Capture",
+	"SWR_DMIC_AIF1 Capture",
+	"SWR_DMIC_AIF2 Capture",
+	"SWR_DMIC_AIF3 Capture",
+};
+
+static int swr_dmic_reset(struct swr_device *pdev);
+static int swr_dmic_up(struct swr_device *pdev);
+static int swr_dmic_down(struct swr_device *pdev);
+static int swr_dmic_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data);
+
+static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname,
+				      unsigned int *port_idx)
+{
+	u8 port_type;
+
+	if (strnstr(wname, "HIFI", strlen(wname)))
+		port_type = SWR_DMIC_HIFI_PORT;
+	else if (strnstr(wname, "LP", strlen(wname)))
+		port_type = SWR_DMIC_LP_PORT;
+	else
+		return -EINVAL;
+
+	*port_idx = port_type;
+	return 0;
+}
+
+static inline int swr_dmic_get_master_port_val(int port)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(swr_master_channel_map); i++)
+		if (port == swr_master_channel_map[i])
+			return i;
+	return 0;
+}
+
+static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct swr_dmic_priv *swr_dmic = NULL;
+	int ret = 0;
+	unsigned int slave_port_idx = SWR_DMIC_MAX_PORTS;
+
+	if (NULL == component) {
+		pr_err_ratelimited("%s: swr dmic component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	swr_dmic = snd_soc_component_get_drvdata(component);
+	if (NULL == swr_dmic) {
+		pr_err_ratelimited("%s: swr_dmic_priv is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = swr_dmic_tx_get_slave_port_type_idx(kcontrol->id.name,
+							&slave_port_idx);
+	if (ret) {
+		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
+		return ret;
+	}
+
+	if (slave_port_idx >= SWR_DMIC_MAX_PORTS) {
+		pr_err_ratelimited("%s: invalid slave port id\n", __func__);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] =
+			swr_dmic_get_master_port_val(
+				swr_dmic->tx_master_port_map[slave_port_idx]);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+			__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct swr_dmic_priv *swr_dmic = NULL;
+	int ret = 0;
+	unsigned int slave_port_idx = SWR_DMIC_MAX_PORTS;
+	unsigned int idx = 0;
+
+	if (NULL == component) {
+		pr_err_ratelimited("%s: swr dmic component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	swr_dmic = snd_soc_component_get_drvdata(component);
+	if (NULL == swr_dmic) {
+		pr_err_ratelimited("%s: swr_dmic_priv is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	ret  = swr_dmic_tx_get_slave_port_type_idx(kcontrol->id.name,
+							&slave_port_idx);
+	if (ret) {
+		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
+		return ret;
+	}
+
+	if (slave_port_idx >= SWR_DMIC_MAX_PORTS) {
+		pr_err_ratelimited("%s: invalid slave port id\n", __func__);
+		return -EINVAL;
+	}
+
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx < 0 || idx >= ARRAY_SIZE(swr_master_channel_map))
+		return -EINVAL;
+
+	swr_dmic->tx_master_port_map[slave_port_idx] =
+			swr_master_channel_map[idx];
+	dev_dbg(component->dev, "%s: slv port id: %d, master_port_type: %d\n",
+		__func__, slave_port_idx,
+		swr_dmic->tx_master_port_map[slave_port_idx]);
+
+	return 0;
+}
+
+static int swr_dmic_port_enable(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol, int event)
+{
+	int ret = 0;
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	struct swr_dmic_priv *swr_dmic =
+			snd_soc_component_get_drvdata(component);
+
+	u8 ch_mask = 0x01; /* only DpnChannelEN1 register is available */
+	u8 num_port = 1;
+	u8 port_id = w->shift;
+	u8 port_type = swr_dmic->tx_master_port_map[port_id];
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		ret = swr_slvdev_datapath_control(swr_dmic->swr_slave,
+			swr_dmic->swr_slave->dev_num, true);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		ret = swr_disconnect_port(swr_dmic->swr_slave,
+				&port_id, num_port, &ch_mask, &port_type);
+		break;
+	};
+
+	return ret;
+}
+
+static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol, int event)
+{
+	int ret = 0;
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	struct swr_dmic_priv *swr_dmic =
+			snd_soc_component_get_drvdata(component);
+
+	u8 num_ch = 1;
+	u8 ch_mask = 0x01; /* only DpnChannelEN1 register is available */
+	u32 ch_rate = SWR_CLK_RATE_4P8MHZ;
+	u8 num_port = 1;
+	u8 port_type = 0;
+	u8 port_id = w->shift;
+
+	if (port_id >= SWR_DMIC_MAX_PORTS)
+	{
+		dev_err_ratelimited(component->dev, "%s: invalid port id: %d\n",
+			__func__, port_id);
+		return -EINVAL;
+	}
+
+	/*
+	 * Port 1 is high quality / 2.4 or 3.072 Mbps
+	 * Port 2 is listen low power / 0.6 or 0.768 Mbps
+	 */
+	if (port_id == SWR_DMIC_HIFI_PORT)
+		ch_rate = SWR_CLK_RATE_2P4MHZ;
+	else
+		ch_rate = SWR_CLK_RATE_0P6MHZ;
+
+	port_type = swr_dmic->tx_master_port_map[port_id];
+
+	dev_dbg(component->dev, "%s port_type: %d event: %d\n", __func__,
+		port_type, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_connect_port(swr_dmic->swr_slave, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					&num_ch, &port_type);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = swr_slvdev_datapath_control(swr_dmic->swr_slave,
+			swr_dmic->swr_slave->dev_num, false);
+		break;
+	};
+
+	return ret;
+}
+
+/* qcom,swr-tx-port-params = <OFFSET1_VAL0 LANE1>, <OFFSET1_VAL5 LANE0>, *UC0*
+			<OFFSET1_VAL0 LANE1>, <OFFSET1_VAL2 LANE0>, *UC1*
+			<OFFSET1_VAL1 LANE0>, <OFFSET1_VAL1 LANE0>, *UC2*
+			<OFFSET1_VAL1 LANE0>, <OFFSET1_VAL1 LANE0>, *UC3 */
+static int swr_dmic_parse_port_params(struct device *dev,
+				      char *prop)
+{
+	int i, j;
+	u32 *dt_array, map_size, max_uc;
+	int ret = 0;
+	u32 cnt = 0;
+	struct swr_port_params (*map)[SWR_UC_MAX][SWR_DMIC_MAX_PORTS];
+	struct swr_dev_frame_config (*map_uc)[SWR_UC_MAX];
+	struct swr_dmic_priv *swr_dmic = dev_get_drvdata(dev);
+
+	map = &swr_dmic->tx_port_params;
+	map_uc = &swr_dmic->swr_tx_port_params;
+
+	if (!of_find_property(dev->of_node, prop,
+				&map_size)) {
+		dev_err(dev, "missing port mapping prop %s\n", prop);
+		ret = -EINVAL;
+		goto err_port_map;
+	}
+
+	max_uc = map_size / (SWR_DMIC_MAX_PORTS * SWR_PORT_PARAMS * sizeof(u32));
+
+	if (max_uc != SWR_UC_MAX) {
+		dev_err(dev,
+			"%s:port params not provided for all usecases\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_port_map;
+	}
+	dt_array = kzalloc(map_size, GFP_KERNEL);
+
+	if (!dt_array) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+	ret = of_property_read_u32_array(dev->of_node, prop, dt_array,
+				SWR_DMIC_MAX_PORTS * SWR_PORT_PARAMS * max_uc);
+	if (ret) {
+		dev_err(dev, "%s: Failed to read  port mapping from prop %s\n",
+					__func__, prop);
+		goto err_pdata_fail;
+	}
+
+	for (i = 0; i < max_uc; i++) {
+		for (j = 0; j < SWR_DMIC_MAX_PORTS; j++) {
+			cnt = (i * SWR_DMIC_MAX_PORTS + j) * SWR_PORT_PARAMS;
+			(*map)[i][j].offset1 = dt_array[cnt];
+			(*map)[i][j].lane_ctrl = dt_array[cnt + 1];
+			dev_err(dev, "%s: port %d, uc: %d, offset1:%d, lane: %d\n",
+				__func__, j, i, dt_array[cnt], dt_array[cnt + 1]);
+		}
+		(*map_uc)[i].pp = &(*map)[i][0];
+	}
+	kfree(dt_array);
+	return 0;
+
+err_pdata_fail:
+	kfree(dt_array);
+err_alloc:
+err_port_map:
+	return ret;
+}
+
+static const char * const tx_master_port_text[] = {
+	"ZERO", "SWRM_PCM_OUT", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3",
+	"SWRM_TX1_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3",
+	"SWRM_TX2_CH4", "SWRM_TX3_CH1", "SWRM_TX3_CH2", "SWRM_TX3_CH3",
+	"SWRM_TX3_CH4", "SWRM_PCM_IN",
+};
+
+static const struct soc_enum tx_master_port_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tx_master_port_text),
+				tx_master_port_text);
+
+static const struct snd_kcontrol_new swr_dmic_snd_controls[] = {
+	SOC_ENUM_EXT("HIFI PortMap", tx_master_port_enum,
+		swr_dmic_tx_master_port_get, swr_dmic_tx_master_port_put),
+	SOC_ENUM_EXT("LP PortMap", tx_master_port_enum,
+		swr_dmic_tx_master_port_get, swr_dmic_tx_master_port_put),
+};
+
+static const struct snd_kcontrol_new dmic_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new va_dmic_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM,
+			SWR_DMIC_HIFI_PORT, 0,
+			dmic_switch, ARRAY_SIZE(dmic_switch), dmic_swr_ctrl,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_VA_MIXER", SND_SOC_NOPM,
+			SWR_DMIC_LP_PORT, 0,
+			va_dmic_switch, ARRAY_SIZE(va_dmic_switch), dmic_swr_ctrl,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("SWR_DMIC"),
+	SND_SOC_DAPM_INPUT("VA_SWR_DMIC"),
+
+	SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM,
+				SWR_DMIC_HIFI_PORT, 0, NULL, 0,
+				swr_dmic_port_enable,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_OUT_DRV_E("SMIC_VA_PORT_EN", SND_SOC_NOPM,
+				SWR_DMIC_LP_PORT, 0, NULL, 0,
+				swr_dmic_port_enable,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_OUTPUT("SWR_DMIC_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("SWR_DMIC_VA_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
+	{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
+	{"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"},
+	{"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"},
+	{"SWR_DMIC_VA_MIXER", "Switch", "VA_SWR_DMIC"},
+	{"SMIC_VA_PORT_EN", NULL, "SWR_DMIC_VA_MIXER"},
+	{"SWR_DMIC_VA_OUTPUT", NULL, "SMIC_VA_PORT_EN"},
+};
+
+static int swr_dmic_codec_probe(struct snd_soc_component *component)
+{
+	struct swr_dmic_priv *swr_dmic =
+			snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm =
+			snd_soc_component_get_dapm(component);
+	char w_name[MAX_NAME_LEN];
+
+	if (!swr_dmic)
+		return -EINVAL;
+
+	swr_dmic->component = component;
+	if (!component->name_prefix) {
+		dev_err(component->dev, "%s: component prefix is NULL\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " ", sizeof(w_name));
+	strlcat(w_name, swr_dmic->dai_driver->capture.stream_name,
+				sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR_DMIC", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SMIC_PORT_EN", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR_DMIC_OUTPUT", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " VA_SWR_DMIC", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SMIC_VA_PORT_EN", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR_DMIC_VA_OUTPUT", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	snd_soc_dapm_sync(dapm);
+
+	swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
+#ifdef CONFIG_SND_SOC_WCD939X
+	wcd939x_swr_dmic_register_notifier(swr_dmic->supply_component,
+					&swr_dmic->nblock, true);
+#else
+	wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
+					&swr_dmic->nblock, true);
+#endif
+
+	return 0;
+}
+
+static void swr_dmic_codec_remove(struct snd_soc_component *component)
+{
+	struct swr_dmic_priv *swr_dmic =
+			snd_soc_component_get_drvdata(component);
+
+	swr_dmic->component = NULL;
+	return;
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_swr_dmic = {
+	.name = NULL,
+	.probe = swr_dmic_codec_probe,
+	.remove = swr_dmic_codec_remove,
+	.controls = swr_dmic_snd_controls,
+	.num_controls = ARRAY_SIZE(swr_dmic_snd_controls),
+	.dapm_widgets = swr_dmic_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(swr_dmic_dapm_widgets),
+	.dapm_routes = swr_dmic_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(swr_dmic_audio_map),
+};
+
+static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable)
+{
+	int rc = 0;
+	int micb_num = swr_dmic->micb_num;
+	struct snd_soc_component *component = swr_dmic->supply_component;
+
+	if (!component) {
+		pr_err_ratelimited("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+	dev_dbg(component->dev, "%s: supply %d micbias: %d enable: %d\n",
+		__func__, swr_dmic->is_en_supply, micb_num, enable);
+
+	if (enable)
+#ifdef CONFIG_SND_SOC_WCD939X
+		rc = wcd939x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_PRE_PMU, micb_num);
+#else
+		rc = wcd938x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_PRE_PMU, micb_num);
+#endif
+	else
+#ifdef CONFIG_SND_SOC_WCD939X
+		rc = wcd939x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_POST_PMD, micb_num);
+#else
+		rc = wcd938x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_POST_PMD, micb_num);
+#endif
+	return rc;
+}
+
+static int swr_dmic_parse_supply(struct device_node *np,
+				struct swr_dmic_priv *swr_dmic)
+{
+	struct platform_device *pdev = NULL;
+
+	if (!np || !swr_dmic)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev)
+		return -EINVAL;
+
+	swr_dmic->supply_component = snd_soc_lookup_component(&pdev->dev, NULL);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver swr_dmic_dai[] = {
+	{
+		.name = "",
+		.id = 0,
+		.capture = {
+			.stream_name = "",
+			.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),
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE |
+				SNDRV_PCM_FMTBIT_S32_LE),
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+	},
+};
+
+static int swr_dmic_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	int ret = 0;
+	struct swr_dmic_priv *swr_dmic = container_of(block,
+					struct swr_dmic_priv,
+					nblock);
+	switch (event) {
+#ifdef CONFIG_SND_SOC_WCD939X
+	case WCD939X_EVT_SSR_DOWN:
+#else
+	case WCD938X_EVT_SSR_DOWN:
+#endif
+		ret = swr_dmic_down(swr_dmic->swr_slave);
+		break;
+#ifdef CONFIG_SND_SOC_WCD939X
+	case WCD939X_EVT_SSR_UP:
+#else
+	case WCD938X_EVT_SSR_UP:
+#endif
+		ret = swr_dmic_up(swr_dmic->swr_slave);
+		if (!ret)
+			ret = swr_dmic_reset(swr_dmic->swr_slave);
+		break;
+	}
+
+	return ret;
+}
+
+static int swr_dmic_probe(struct swr_device *pdev)
+{
+	int ret = 0;
+	int i = 0;
+	u8 swr_devnum = 0;
+	int dev_index = -1;
+	struct swr_dmic_priv *swr_dmic = NULL;
+	const char *swr_dmic_codec_name_of = NULL;
+	struct snd_soc_component *component = NULL;
+	int num_retry = NUM_ATTEMPTS;
+
+	swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv),
+			    GFP_KERNEL);
+	if (!swr_dmic)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-dmic-supply",
+				&swr_dmic->micb_num);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
+		__func__, "qcom,swr-dmic-supply",
+		pdev->dev.of_node->full_name);
+		goto err;
+	}
+	swr_dmic->wcd_handle = of_parse_phandle(pdev->dev.of_node,
+						"qcom,wcd-handle", 0);
+	if (!swr_dmic->wcd_handle) {
+		dev_dbg(&pdev->dev, "%s: no wcd handle listed\n",
+			__func__);
+		swr_dmic->is_wcd_supply = false;
+	} else {
+		swr_dmic_parse_supply(swr_dmic->wcd_handle, swr_dmic);
+		swr_dmic->is_wcd_supply = true;
+	}
+
+	if (swr_dmic->is_wcd_supply) {
+		ret = enable_wcd_codec_supply(swr_dmic, true);
+		if (ret) {
+			ret = -EPROBE_DEFER;
+			swr_dmic->is_wcd_supply = false;
+			swr_dmic->wcd_handle = NULL;
+			goto err;
+		}
+		++swr_dmic->is_en_supply;
+	}
+
+	swr_set_dev_data(pdev, swr_dmic);
+
+	swr_dmic->swr_slave = pdev;
+
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,codec-name",
+				&swr_dmic_codec_name_of);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
+		__func__, "qcom,codec-name",
+		pdev->dev.of_node->full_name);
+		goto dev_err;
+	}
+
+	ret = swr_dmic_parse_port_params(&pdev->dev, "qcom,swr-tx-port-params");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Parsing %s failed in node %s\n",
+			__func__, "qcom,swr-tx-port-params",
+			pdev->dev.of_node->full_name);
+		goto dev_err;
+	}
+
+	/*
+	 * Add 5msec delay to provide sufficient time for
+	 * soundwire auto enumeration of slave devices as
+	 * as per HW requirement.
+	 */
+	usleep_range(5000, 5010);
+	do {
+		/* Add delay for soundwire enumeration */
+		usleep_range(100, 110);
+		ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum);
+	} while (ret && --num_retry);
+
+	if (ret) {
+		dev_info(&pdev->dev,
+			"%s get devnum %d for dev addr %llx failed\n",
+			__func__, swr_devnum, pdev->addr);
+		ret = -EPROBE_DEFER;
+
+		if (swr_dmic->is_en_supply == 1) {
+			enable_wcd_codec_supply(swr_dmic, false);
+			--swr_dmic->is_en_supply;
+		}
+		swr_dmic->is_wcd_supply = false;
+		swr_dmic->wcd_handle = NULL;
+		goto err;
+	}
+	pdev->dev_num = swr_devnum;
+	swr_init_port_params(pdev, SWR_DMIC_MAX_PORTS,
+			     swr_dmic->swr_tx_port_params);
+
+	swr_dmic->driver = devm_kzalloc(&pdev->dev,
+			sizeof(struct snd_soc_component_driver), GFP_KERNEL);
+	if (!swr_dmic->driver) {
+		ret = -ENOMEM;
+		goto dev_err;
+	}
+
+	memcpy(swr_dmic->driver, &soc_codec_dev_swr_dmic,
+			sizeof(struct snd_soc_component_driver));
+
+	for (i = 0; i < ARRAY_SIZE(codec_name_list); i++) {
+		if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) {
+			dev_index = i;
+			break;
+		}
+	}
+
+	if (dev_index < 0) {
+		ret = -EINVAL;
+		goto dev_err;
+	}
+
+	swr_dmic->driver->name = codec_name_list[dev_index];
+
+	swr_dmic->dai_driver = devm_kzalloc(&pdev->dev,
+			sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
+	if (!swr_dmic->dai_driver) {
+		ret = -ENOMEM;
+		goto dev_err;
+	}
+
+	memcpy(swr_dmic->dai_driver, swr_dmic_dai,
+			sizeof(struct snd_soc_dai_driver));
+	swr_dmic->dai_driver->id = dev_index;
+	swr_dmic->dai_driver->name = dai_name_list[dev_index];
+	swr_dmic->dai_driver->capture.stream_name = aif_name_list[dev_index];
+
+	/* Number of DAI's used is 1 */
+	ret = snd_soc_register_component(&pdev->dev, swr_dmic->driver,
+				swr_dmic->dai_driver, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Codec registration failed\n",
+			__func__);
+		goto dev_err;
+	}
+
+	component = snd_soc_lookup_component(&pdev->dev,
+						swr_dmic->driver->name);
+	if (!component) {
+		dev_err(&pdev->dev, "%s: could not find swr_dmic component\n",
+			__func__);
+		goto dev_err;
+	}
+	swr_dmic->component = component;
+
+	return 0;
+
+dev_err:
+	if (swr_dmic->is_en_supply == 1) {
+		enable_wcd_codec_supply(swr_dmic, false);
+		--swr_dmic->is_en_supply;
+	}
+	swr_dmic->is_wcd_supply = false;
+	swr_dmic->wcd_handle = NULL;
+	swr_remove_device(pdev);
+err:
+	return ret;
+}
+
+static int swr_dmic_remove(struct swr_device *pdev)
+{
+	struct swr_dmic_priv *swr_dmic;
+
+	swr_dmic = swr_get_dev_data(pdev);
+	if (!swr_dmic) {
+		dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (swr_dmic->is_en_supply == 1) {
+		enable_wcd_codec_supply(swr_dmic, false);
+		--swr_dmic->is_en_supply;
+	}
+	snd_soc_unregister_component(&pdev->dev);
+	swr_set_dev_data(pdev, NULL);
+	return 0;
+}
+
+static int swr_dmic_up(struct swr_device *pdev)
+{
+	int ret = 0;
+	struct swr_dmic_priv *swr_dmic;
+
+	swr_dmic = swr_get_dev_data(pdev);
+	if (!swr_dmic) {
+		dev_err_ratelimited(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	++swr_dmic->is_en_supply;
+	if (swr_dmic->is_en_supply == 1)
+		ret = enable_wcd_codec_supply(swr_dmic, true);
+
+	return ret;
+}
+
+static int swr_dmic_down(struct swr_device *pdev)
+{
+	struct swr_dmic_priv *swr_dmic;
+	int ret = 0;
+
+	swr_dmic = swr_get_dev_data(pdev);
+	if (!swr_dmic) {
+		dev_err_ratelimited(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "%s: is_en_supply: %d\n",
+		__func__, swr_dmic->is_en_supply);
+	--swr_dmic->is_en_supply;
+	if (swr_dmic->is_en_supply < 0) {
+		dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n",
+			__func__, swr_dmic->is_en_supply);
+		swr_dmic->is_en_supply = 0;
+		goto done;
+	}
+	if (!swr_dmic->is_en_supply)
+		enable_wcd_codec_supply(swr_dmic, false);
+
+done:
+	return ret;
+}
+
+static int swr_dmic_reset(struct swr_device *pdev)
+{
+	struct swr_dmic_priv *swr_dmic;
+	u8 retry = NUM_ATTEMPTS;
+	u8 devnum = 0;
+
+	swr_dmic = swr_get_dev_data(pdev);
+	if (!swr_dmic) {
+		dev_err_ratelimited(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
+		/* Retry after 1 msec delay */
+		usleep_range(1000, 1100);
+	}
+	pdev->dev_num = devnum;
+	dev_dbg(&pdev->dev, "%s: devnum: %d\n", __func__, devnum);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int swr_dmic_suspend(struct device *dev)
+{
+	dev_dbg(dev, "%s: system suspend\n", __func__);
+	return 0;
+}
+
+static int swr_dmic_resume(struct device *dev)
+{
+	struct swr_dmic_priv *swr_dmic = swr_get_dev_data(to_swr_device(dev));
+
+	if (!swr_dmic) {
+		dev_err_ratelimited(dev, "%s: swr_dmic private data is NULL\n", __func__);
+		return -EINVAL;
+	}
+	dev_dbg(dev, "%s: system resume\n", __func__);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops swr_dmic_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(swr_dmic_suspend, swr_dmic_resume)
+};
+
+static const struct swr_device_id swr_dmic_id[] = {
+	{"swr-dmic", 0},
+	{}
+};
+
+static const struct of_device_id swr_dmic_dt_match[] = {
+	{
+		.compatible = "qcom,swr-dmic",
+	},
+	{}
+};
+
+static struct swr_driver swr_dmic_driver = {
+	.driver = {
+		.name = "swr-dmic",
+		.owner = THIS_MODULE,
+		.pm = &swr_dmic_pm_ops,
+		.of_match_table = swr_dmic_dt_match,
+	},
+	.probe = swr_dmic_probe,
+	.remove = swr_dmic_remove,
+	.id_table = swr_dmic_id,
+};
+
+static int __init swr_dmic_init(void)
+{
+	return swr_driver_register(&swr_dmic_driver);
+}
+
+static void __exit swr_dmic_exit(void)
+{
+	swr_driver_unregister(&swr_dmic_driver);
+}
+
+module_init(swr_dmic_init);
+module_exit(swr_dmic_exit);
+
+MODULE_DESCRIPTION("SWR DMIC driver");
+MODULE_LICENSE("GPL v2");

+ 17 - 0
qcom/opensource/audio-kernel/asoc/codecs/swr-dmic.h

@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _SWR_DMIC_H
+#define _SWR_DMIC_H
+
+#include <sound/soc.h>
+#include <sound/info.h>
+
+enum {
+	SWR_DMIC_HIFI_PORT = 0,
+	SWR_DMIC_LP_PORT,
+	SWR_DMIC_MAX_PORTS,
+};
+
+#endif /* _SWR_DMIC_H */

Vissa filer visades inte eftersom för många filer har ändrats