فهرست منبع

ASoC: wcd938x: Add support for wcd938x codec

WCD938x codec is a soundwire based codec that supports AMICs, DMICs,
Headphones, Ear and Aux paths. Add support to enable all device
paths of wcd938x codec.

Change-Id: I81b5e603ef73afba74b8d2274012752f9ca5cb6f
Signed-off-by: Sudheer Papothi <[email protected]>
Sudheer Papothi 6 سال پیش
والد
کامیت
c9443c282a

+ 7 - 0
Android.mk

@@ -35,3 +35,10 @@ include $(MY_LOCAL_PATH)/asoc/codecs/bolero/Android.mk
 $(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wcd937x/Module.symvers)
 include $(MY_LOCAL_PATH)/asoc/codecs/wcd937x/Android.mk
 endif
+
+ifeq ($(call is-board-platform-in-list, kona),true)
+$(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/bolero/Module.symvers)
+include $(MY_LOCAL_PATH)/asoc/codecs/bolero/Android.mk
+$(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wcd938x/Module.symvers)
+include $(MY_LOCAL_PATH)/asoc/codecs/wcd938x/Android.mk
+endif

+ 57 - 0
asoc/codecs/wcd938x/Android.mk

@@ -0,0 +1,57 @@
+# Android makefile for audio kernel modules
+
+# Assume no targets will be supported
+
+# Check if this driver needs be built for current target
+ifeq ($(call is-board-platform,kona),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_KONA=m
+endif
+
+AUDIO_CHIPSET := audio
+# Build/Package only in case of supported target
+ifeq ($(call is-board-platform-in-list,kona),true)
+
+LOCAL_PATH := $(call my-dir)
+
+# This makefile is only for DLKM
+ifneq ($(findstring vendor,$(LOCAL_PATH)),)
+
+ifneq ($(findstring opensource,$(LOCAL_PATH)),)
+	AUDIO_BLD_DIR := $(shell pwd)/vendor/qcom/opensource/audio-kernel
+endif # opensource
+
+DLKM_DIR := $(TOP)/device/qcom/common/dlkm
+
+# Build audio.ko as $(AUDIO_CHIPSET)_audio.ko
+###########################################################
+# 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=wcd938x_dlkm
+KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
+KBUILD_OPTIONS += $(AUDIO_SELECT)
+
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE              := $(AUDIO_CHIPSET)_wcd938x.ko
+LOCAL_MODULE_KBUILD_NAME  := wcd938x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/AndroidKernelModule.mk
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE              := $(AUDIO_CHIPSET)_wcd938x_slave.ko
+LOCAL_MODULE_KBUILD_NAME  := wcd938x_slave_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/AndroidKernelModule.mk
+###########################################################
+
+endif # DLKM check
+endif # supported target check

+ 112 - 0
asoc/codecs/wcd938x/Kbuild

@@ -0,0 +1,112 @@
+# 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-4.19
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_KONA), y)
+		include $(AUDIO_ROOT)/config/konaauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/konaautoconf.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)
+
+############ WCD938X ############
+
+# for WCD938X Codec
+ifdef CONFIG_SND_SOC_WCD938X
+	WCD938X_OBJS += wcd938x.o
+	WCD938X_OBJS += wcd938x-regmap.o
+	WCD938X_OBJS += wcd938x-tables.o
+	WCD938X_OBJS += wcd938x-mbhc.o
+endif
+
+ifdef CONFIG_SND_SOC_WCD938X_SLAVE
+	WCD938X_SLAVE_OBJS += wcd938x-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_WCD938X) += wcd938x_dlkm.o
+wcd938x_dlkm-y := $(WCD938X_OBJS)
+
+obj-$(CONFIG_SND_SOC_WCD938X_SLAVE) += wcd938x_slave_dlkm.o
+wcd938x_slave_dlkm-y := $(WCD938X_SLAVE_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

+ 182 - 0
asoc/codecs/wcd938x/internal.h

@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _WCD938X_INTERNAL_H
+#define _WCD938X_INTERNAL_H
+
+#include <asoc/wcd-mbhc-v2.h>
+#include <asoc/wcd-irq.h>
+#include "wcd938x-mbhc.h"
+
+#define WCD938X_MAX_MICBIAS 4
+
+/* Convert from vout ctl to micbias voltage in mV */
+#define  WCD_VOUT_CTL_TO_MICB(v)  (1000 + v * 50)
+#define MAX_PORT 8
+#define MAX_CH_PER_PORT 8
+
+enum {
+	TX_HDR12 = 0,
+	TX_HDR34,
+	TX_HDR_MAX,
+};
+
+extern struct regmap_config wcd938x_regmap_config;
+
+struct codec_port_info {
+	u32 slave_port_type;
+	u32 master_port_type;
+	u32 ch_mask;
+	u32 num_ch;
+	u32 ch_rate;
+};
+
+struct wcd938x_priv {
+	struct device *dev;
+
+	int variant;
+	struct snd_soc_component *component;
+	struct device_node *rst_np;
+	struct regmap *regmap;
+
+	struct swr_device *rx_swr_dev;
+	struct swr_device *tx_swr_dev;
+
+	s32 micb_ref[WCD938X_MAX_MICBIAS];
+	s32 pullup_ref[WCD938X_MAX_MICBIAS];
+
+	struct fw_info *fw_data;
+	struct device_node *wcd_rst_np;
+
+	struct mutex micb_lock;
+	s32 dmic_0_1_clk_cnt;
+	s32 dmic_2_3_clk_cnt;
+	s32 dmic_4_5_clk_cnt;
+	s32 dmic_6_7_clk_cnt;
+	int hdr_en[TX_HDR_MAX];
+	/* class h specific info */
+	struct wcd_clsh_cdc_info clsh_info;
+	/* mbhc module */
+	struct wcd938x_mbhc *mbhc;
+
+	u32 hph_mode;
+	bool comp1_enable;
+	bool comp2_enable;
+
+	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);
+	u32 version;
+	/* Entry for version info */
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+};
+
+struct wcd938x_micbias_setting {
+	u8 ldoh_v;
+	u32 cfilt1_mv;
+	u32 micb1_mv;
+	u32 micb2_mv;
+	u32 micb3_mv;
+	u32 micb4_mv;
+	u8 bias1_cfilt_sel;
+};
+
+struct wcd938x_pdata {
+	struct device_node *rst_np;
+	struct device_node *rx_slave;
+	struct device_node *tx_slave;
+	struct wcd938x_micbias_setting micbias;
+
+	struct cdc_regulator *regulator;
+	int num_supplies;
+};
+
+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 {
+	BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
+	BOLERO_WCD_EVT_PA_OFF_PRE_SSR,
+	BOLERO_WCD_EVT_SSR_DOWN,
+	BOLERO_WCD_EVT_SSR_UP,
+	BOLERO_WCD_EVT_CLK_NOTIFY,
+};
+
+enum {
+	WCD_BOLERO_EVT_RX_MUTE = 1,	/* for RX mute/unmute */
+	WCD_BOLERO_EVT_IMPED_TRUE,	/* for imped true */
+	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
+};
+
+enum {
+	/* INTR_CTRL_INT_MASK_0 */
+	WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
+	WCD938X_IRQ_MBHC_BUTTON_PRESS_DET,
+	WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,
+	WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	WCD938X_IRQ_MBHC_SW_DET,
+	WCD938X_IRQ_HPHR_OCP_INT,
+	WCD938X_IRQ_HPHR_CNP_INT,
+	WCD938X_IRQ_HPHL_OCP_INT,
+
+	/* INTR_CTRL_INT_MASK_1 */
+	WCD938X_IRQ_HPHL_CNP_INT,
+	WCD938X_IRQ_EAR_CNP_INT,
+	WCD938X_IRQ_EAR_SCD_INT,
+	WCD938X_IRQ_AUX_CNP_INT,
+	WCD938X_IRQ_AUX_SCD_INT,
+	WCD938X_IRQ_HPHL_PDM_WD_INT,
+	WCD938X_IRQ_HPHR_PDM_WD_INT,
+	WCD938X_IRQ_AUX_PDM_WD_INT,
+
+	/* INTR_CTRL_INT_MASK_2 */
+	WCD938X_IRQ_LDORT_SCD_INT,
+	WCD938X_IRQ_MBHC_MOISTURE_INT,
+	WCD938X_IRQ_HPHL_SURGE_DET_INT,
+	WCD938X_IRQ_HPHR_SURGE_DET_INT,
+	WCD938X_NUM_IRQS,
+};
+
+extern struct wcd938x_mbhc *wcd938x_soc_get_mbhc(
+				struct snd_soc_component *component);
+extern int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+					int volt, int micb_num);
+extern int wcd938x_get_micb_vout_ctl_val(u32 micb_mv);
+extern int wcd938x_micbias_control(struct snd_soc_component *component,
+			int micb_num, int req, bool is_dapm);
+extern int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root,
+				    struct snd_soc_component *component);
+#endif /* _WCD938X_INTERNAL_H */

+ 1082 - 0
asoc/codecs/wcd938x/wcd938x-mbhc.c

@@ -0,0 +1,1082 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 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 <asoc/wcdcal-hwdep.h>
+#include <asoc/wcd-mbhc-v2-api.h>
+#include "wcd938x-registers.h"
+#include "internal.h"
+
+#define WCD938X_ZDET_SUPPORTED          true
+/* Z value defined in milliohm */
+#define WCD938X_ZDET_VAL_32             32000
+#define WCD938X_ZDET_VAL_400            400000
+#define WCD938X_ZDET_VAL_1200           1200000
+#define WCD938X_ZDET_VAL_100K           100000000
+/* Z floating defined in ohms */
+#define WCD938X_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE
+
+#define WCD938X_ZDET_NUM_MEASUREMENTS   900
+#define WCD938X_MBHC_GET_C1(c)          ((c & 0xC000) >> 14)
+#define WCD938X_MBHC_GET_X1(x)          (x & 0x3FFF)
+/* Z value compared in milliOhm */
+#define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000))
+#define WCD938X_MBHC_ZDET_CONST         (86 * 16384)
+#define WCD938X_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",
+			  WCD938X_ANA_MBHC_MECH, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_DET_EN",
+			  WCD938X_ANA_MBHC_MECH, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MECH_DETECTION_TYPE",
+			  WCD938X_ANA_MBHC_MECH, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_CLAMP_CTL",
+			  WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_DETECTION_TYPE",
+			  WCD938X_ANA_MBHC_ELECT, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_CTRL",
+			  WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL",
+			  WCD938X_ANA_MBHC_MECH, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PLUG_TYPE",
+			  WCD938X_ANA_MBHC_MECH, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_GND_PLUG_TYPE",
+			  WCD938X_ANA_MBHC_MECH, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SW_HPH_LP_100K_TO_GND",
+			  WCD938X_ANA_MBHC_MECH, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_SCHMT_ISRC",
+			  WCD938X_ANA_MBHC_ELECT, 0x06, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_EN",
+			  WCD938X_ANA_MBHC_ELECT, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_INSREM_DBNC",
+			  WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_DBNC",
+			  WCD938X_MBHC_NEW_CTL_1, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_VREF",
+			  WCD938X_MBHC_NEW_CTL_2, 0x03, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HS_COMP_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_IN2P_CLAMP_STATE",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MIC_SCHMT_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_SCHMT_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_SCHMT_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_OCP_FSM_EN",
+			  WCD938X_HPH_OCP_CTL, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0x07, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_BTN_ISRC_CTL",
+			  WCD938X_ANA_MBHC_ELECT, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
+			  WCD938X_ANA_MBHC_RESULT_3, 0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
+			  WCD938X_ANA_MICB2, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
+			  WCD938X_HPH_CNP_WG_TIME, 0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
+			  WCD938X_ANA_HPH, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PA_EN",
+			  WCD938X_ANA_HPH, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPH_PA_EN",
+			  WCD938X_ANA_HPH, 0xC0, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
+			  WCD938X_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",
+			  WCD938X_MBHC_CTL_BCS, 0x02, 1, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_FSM_STATUS",
+			  WCD938X_MBHC_NEW_FSM_STATUS, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
+			  WCD938X_MBHC_NEW_CTL_2, 0x70, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_STATUS",
+			  WCD938X_MBHC_NEW_FSM_STATUS, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_GND",
+			  WCD938X_HPH_PA_CTL2, 0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_GND",
+			  WCD938X_HPH_PA_CTL2, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_DET_EN",
+			  WCD938X_HPH_L_TEST, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_DET_EN",
+			  WCD938X_HPH_R_TEST, 0x01, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_STATUS",
+			  WCD938X_DIGITAL_INTR_STATUS_0, 0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_STATUS",
+			  WCD938X_DIGITAL_INTR_STATUS_0, 0x20, 5, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_EN",
+			  WCD938X_MBHC_NEW_CTL_1, 0x08, 3, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_COMPLETE", WCD938X_MBHC_NEW_FSM_STATUS,
+			  0x40, 6, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_TIMEOUT", WCD938X_MBHC_NEW_FSM_STATUS,
+			  0x80, 7, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_RESULT", WCD938X_MBHC_NEW_ADC_RESULT,
+			  0xFF, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_MICB2_VOUT", WCD938X_ANA_MICB2, 0x3F, 0, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ADC_MODE",
+			  WCD938X_MBHC_NEW_CTL_1, 0x10, 4, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_DETECTION_DONE",
+			  WCD938X_MBHC_NEW_CTL_1, 0x04, 2, 0),
+	WCD_MBHC_REGISTER("WCD_MBHC_ELECT_ISRC_EN",
+			  WCD938X_ANA_MBHC_ZDET, 0x02, 1, 0),
+};
+
+static const struct wcd_mbhc_intr intr_ids = {
+	.mbhc_sw_intr =  WCD938X_IRQ_MBHC_SW_DET,
+	.mbhc_btn_press_intr = WCD938X_IRQ_MBHC_BUTTON_PRESS_DET,
+	.mbhc_btn_release_intr = WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET,
+	.mbhc_hs_ins_intr = WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	.mbhc_hs_rem_intr = WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,
+	.hph_left_ocp = WCD938X_IRQ_HPHL_OCP_INT,
+	.hph_right_ocp = WCD938X_IRQ_HPHR_OCP_INT,
+};
+
+struct wcd938x_mbhc_zdet_param {
+	u16 ldo_ctl;
+	u16 noff;
+	u16 nshift;
+	u16 btn5;
+	u16 btn6;
+	u16 btn7;
+};
+
+static int wcd938x_mbhc_request_irq(struct snd_soc_component *component,
+				  int irq, irq_handler_t handler,
+				  const char *name, void *data)
+{
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(component->dev);
+
+	return wcd_request_irq(&wcd938x->irq_info, irq, name, handler, data);
+}
+
+static void wcd938x_mbhc_irq_control(struct snd_soc_component *component,
+				   int irq, bool enable)
+{
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(component->dev);
+
+	if (enable)
+		wcd_enable_irq(&wcd938x->irq_info, irq);
+	else
+		wcd_disable_irq(&wcd938x->irq_info, irq);
+}
+
+static int wcd938x_mbhc_free_irq(struct snd_soc_component *component,
+			       int irq, void *data)
+{
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(component->dev);
+
+	wcd_free_irq(&wcd938x->irq_info, irq, data);
+
+	return 0;
+}
+
+static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component,
+				 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_CTL_1,
+				    0x80, 0x80);
+	else
+		snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_CTL_1,
+				    0x80, 0x00);
+}
+
+static int wcd938x_mbhc_btn_to_num(struct snd_soc_component *component)
+{
+	return snd_soc_component_read32(component, WCD938X_ANA_MBHC_RESULT_3) & 0x7;
+}
+
+static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component,
+					 bool enable)
+{
+	if (enable)
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_ELECT,
+				    0x01, 0x01);
+	else
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_ELECT,
+				    0x01, 0x00);
+}
+
+static void wcd938x_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, WCD938X_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 wcd938x_mbhc_lock_sleep(struct wcd_mbhc *mbhc, bool lock)
+{
+	return true;
+}
+
+static int wcd938x_mbhc_register_notifier(struct wcd_mbhc *mbhc,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct wcd938x_mbhc *wcd938x_mbhc;
+
+	wcd938x_mbhc = container_of(mbhc, struct wcd938x_mbhc, wcd_mbhc);
+
+	if (enable)
+		return blocking_notifier_chain_register(&wcd938x_mbhc->notifier,
+							nblock);
+	else
+		return blocking_notifier_chain_unregister(
+				&wcd938x_mbhc->notifier, nblock);
+}
+
+static bool wcd938x_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,
+								WCD938X_ANA_MICB2) & 0xC0)
+			>> 6);
+		if (val == 0x01)
+			return true;
+	}
+	return false;
+}
+
+static bool wcd938x_mbhc_hph_pa_on_status(struct snd_soc_component *component)
+{
+	return (snd_soc_component_read32(component, WCD938X_ANA_HPH) & 0xC0) ?
+									true : false;
+}
+
+static void wcd938x_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,
+				WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,
+			    0x1F, pull_up_cur);
+}
+
+static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component,
+					int micb_num, int req)
+{
+	int ret = 0;
+
+	ret = wcd938x_micbias_control(component, micb_num, req, false);
+
+	return ret;
+}
+
+static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component,
+					   bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, WCD938X_ANA_MICB2_RAMP,
+				    0x1C, 0x0C);
+		snd_soc_component_update_bits(component, WCD938X_ANA_MICB2_RAMP,
+				    0x80, 0x80);
+	} else {
+		snd_soc_component_update_bits(component, WCD938X_ANA_MICB2_RAMP,
+				    0x80, 0x00);
+		snd_soc_component_update_bits(component, WCD938X_ANA_MICB2_RAMP,
+				    0x1C, 0x00);
+	}
+}
+
+static struct firmware_cal *wcd938x_get_hwdep_fw_cal(struct wcd_mbhc *mbhc,
+						   enum wcd_cal_type type)
+{
+	struct wcd938x_mbhc *wcd938x_mbhc;
+	struct firmware_cal *hwdep_cal;
+	struct snd_soc_component *component = mbhc->component;
+
+	wcd938x_mbhc = container_of(mbhc, struct wcd938x_mbhc, wcd_mbhc);
+
+	if (!component) {
+		pr_err("%s: NULL component pointer\n", __func__);
+		return NULL;
+	}
+	hwdep_cal = wcdcal_get_fw_cal(wcd938x_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 wcd938x_mbhc_micb_ctrl_threshold_mic(
+							struct snd_soc_component *component,
+							int micb_num, bool req_en)
+{
+	struct wcd938x_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 = wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
+
+	return rc;
+}
+
+static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
+						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(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20);
+	for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) {
+		regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val);
+		if (val & 0x80)
+			break;
+	}
+	val = val << 0x8;
+	regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1);
+	val |= val1;
+	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00);
+	x1 = WCD938X_MBHC_GET_X1(val);
+	c1 = WCD938X_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(wcd938x->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 = (WCD938X_MBHC_ZDET_CONST * 1000) / denom;
+	else if (x1 < minCode_param[noff])
+		*zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
+
+	dev_dbg(wcd938x->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_read(wcd938x->regmap,
+				 WCD938X_ANA_MBHC_RESULT_1, &val);
+		regmap_read(wcd938x->regmap,
+				 WCD938X_ANA_MBHC_RESULT_2, &val1);
+		val = val << 0x08;
+		val |= val1;
+		x1 = WCD938X_MBHC_GET_X1(val);
+		i++;
+		if (i == WCD938X_ZDET_NUM_MEASUREMENTS)
+			break;
+	}
+}
+
+static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
+				 struct wcd938x_mbhc_zdet_param *zdet_param,
+				 int32_t *zl, int32_t *zr, s16 *d1_a)
+{
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(component->dev);
+	int32_t zdet = 0;
+
+	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+				0x70, zdet_param->ldo_ctl << 4);
+	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5, 0xFC,
+			    zdet_param->btn5);
+	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6, 0xFC,
+			    zdet_param->btn6);
+	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7, 0xFC,
+			    zdet_param->btn7);
+	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+				0x0F, zdet_param->noff);
+	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL,
+				0x0F, zdet_param->nshift);
+
+	if (!zl)
+		goto z_right;
+	/* Start impedance measurement for HPH_L */
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
+	dev_dbg(wcd938x->dev, "%s: ramp for HPH_L, noff = %d\n",
+		__func__, zdet_param->noff);
+	wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
+
+	*zl = zdet;
+
+z_right:
+	if (!zr)
+		return;
+	/* Start impedance measurement for HPH_R */
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
+	dev_dbg(wcd938x->dev, "%s: ramp for HPH_R, noff = %d\n",
+		__func__, zdet_param->noff);
+	wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
+
+	*zr = zdet;
+}
+
+static inline void wcd938x_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 < (WCD938X_ZDET_VAL_400/1000))
+		q1 = snd_soc_component_read32(component,
+			WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));
+	else
+		q1 = snd_soc_component_read32(component,
+			WCD938X_DIGITAL_EFUSE_REG_24 + (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 wcd938x_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
+					  uint32_t *zr)
+{
+	struct snd_soc_component *component = mbhc->component;
+	struct wcd938x_priv *wcd938x = 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 wcd938x_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 wcd938x_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, WCD938X_ANA_MBHC_BTN5);
+	reg1 = snd_soc_component_read32(component, WCD938X_ANA_MBHC_BTN6);
+	reg2 = snd_soc_component_read32(component, WCD938X_ANA_MBHC_BTN7);
+	reg3 = snd_soc_component_read32(component, WCD938X_MBHC_CTL_CLK);
+	reg4 = snd_soc_component_read32(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL);
+
+	if (snd_soc_component_read32(component, WCD938X_ANA_MBHC_ELECT) & 0x80) {
+		is_fsm_disable = true;
+		regmap_update_bits(wcd938x->regmap,
+				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x00);
+	}
+
+	/* For NO-jack, disable L_DET_EN before Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(wcd938x->regmap,
+				   WCD938X_ANA_MBHC_MECH, 0x80, 0x00);
+
+	/* Turn off 100k pull down on HPHL */
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_MECH, 0x01, 0x00);
+
+	/* First get impedance on Left */
+	d1 = d1_a[1];
+	zdet_param_ptr = &zdet_param[1];
+	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+	if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
+		goto left_ch_impedance;
+
+	/* Second ramp for left ch */
+	if (z1L < WCD938X_ZDET_VAL_32) {
+		zdet_param_ptr = &zdet_param[0];
+		d1 = d1_a[0];
+	} else if ((z1L > WCD938X_ZDET_VAL_400) &&
+		  (z1L <= WCD938X_ZDET_VAL_1200)) {
+		zdet_param_ptr = &zdet_param[2];
+		d1 = d1_a[2];
+	} else if (z1L > WCD938X_ZDET_VAL_1200) {
+		zdet_param_ptr = &zdet_param[3];
+		d1 = d1_a[3];
+	}
+	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+left_ch_impedance:
+	if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+		(z1L > WCD938X_ZDET_VAL_100K)) {
+		*zl = WCD938X_ZDET_FLOATING_IMPEDANCE;
+		zdet_param_ptr = &zdet_param[1];
+		d1 = d1_a[1];
+	} else {
+		*zl = z1L/1000;
+		wcd938x_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 */
+	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+	if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
+		if (((z1R > WCD938X_ZDET_VAL_1200) &&
+			(zdet_param_ptr->noff == 0x6)) ||
+			((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE))
+			goto right_ch_impedance;
+		/* Second ramp for right ch */
+		if (z1R < WCD938X_ZDET_VAL_32) {
+			zdet_param_ptr = &zdet_param[0];
+			d1 = d1_a[0];
+		} else if ((z1R > WCD938X_ZDET_VAL_400) &&
+			(z1R <= WCD938X_ZDET_VAL_1200)) {
+			zdet_param_ptr = &zdet_param[2];
+			d1 = d1_a[2];
+		} else if (z1R > WCD938X_ZDET_VAL_1200) {
+			zdet_param_ptr = &zdet_param[3];
+			d1 = d1_a[3];
+		}
+		wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+	}
+right_ch_impedance:
+	if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+		(z1R > WCD938X_ZDET_VAL_100K)) {
+		*zr = WCD938X_ZDET_FLOATING_IMPEDANCE;
+	} else {
+		*zr = z1R/1000;
+		wcd938x_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 == WCD938X_ZDET_FLOATING_IMPEDANCE) &&
+		(*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) {
+		dev_dbg(component->dev,
+			"%s: plug type is invalid or extension cable\n",
+			__func__);
+		goto zdet_complete;
+	}
+	if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+	    (*zr == WCD938X_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, WCD938X_HPH_R_ATEST, 0x02, 0x02);
+	snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2, 0x40, 0x01);
+	if (*zl < (WCD938X_ZDET_VAL_32/1000))
+		wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);
+	else
+		wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);
+	snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2, 0x40, 0x00);
+	snd_soc_component_update_bits(component, WCD938X_HPH_R_ATEST, 0x02, 0x00);
+	z1Ls /= 1000;
+	wcd938x_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, WCD938X_ANA_MBHC_BTN5, reg0);
+	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1);
+	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2);
+	/* Turn on 100k pull down on HPHL */
+	regmap_update_bits(wcd938x->regmap,
+			   WCD938X_ANA_MBHC_MECH, 0x01, 0x01);
+
+	/* For NO-jack, re-enable L_DET_EN after Z-det measurements */
+	if (mbhc->hphl_swh)
+		regmap_update_bits(wcd938x->regmap,
+				   WCD938X_ANA_MBHC_MECH, 0x80, 0x80);
+
+	snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4);
+	snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3);
+	if (is_fsm_disable)
+		regmap_update_bits(wcd938x->regmap,
+				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x80);
+}
+
+static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
+			bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_MECH,
+				    0x02, 0x02);
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_MECH,
+				    0x40, 0x40);
+	} else {
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_MECH,
+				    0x40, 0x00);
+		snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_MECH,
+				    0x02, 0x00);
+	}
+}
+
+static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
+					  bool enable)
+{
+	if (enable) {
+		snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2,
+				    0x40, 0x40);
+		snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2,
+				    0x10, 0x10);
+	} else {
+		snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2,
+				    0x40, 0x00);
+		snd_soc_component_update_bits(component, WCD938X_HPH_PA_CTL2,
+				    0x10, 0x00);
+	}
+}
+
+static void wcd938x_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, WCD938X_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, WCD938X_MBHC_NEW_CTL_2,
+				    0x0C, R_OFF << 2);
+		return;
+	}
+
+	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_CTL_2,
+			    0x0C, mbhc->moist_rref << 2);
+}
+
+static void wcd938x_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, WCD938X_MBHC_NEW_CTL_2,
+					0x0C, mbhc->moist_rref << 2);
+	else
+		snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_CTL_2,
+				    0x0C, R_OFF << 2);
+}
+
+static bool wcd938x_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, WCD938X_MBHC_NEW_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, WCD938X_MBHC_NEW_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, WCD938X_MBHC_NEW_CTL_2) & 0x0C))
+		goto done;
+
+	wcd938x_mbhc_moisture_detect_en(mbhc, true);
+	/* Read moisture comparator status */
+	ret = ((snd_soc_component_read32(component, WCD938X_MBHC_NEW_FSM_STATUS)
+				& 0x20) ? 0 : 1);
+
+done:
+	return ret;
+
+}
+
+static void wcd938x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc,
+						bool enable)
+{
+	struct snd_soc_component *component = mbhc->component;
+
+	snd_soc_component_update_bits(component,
+			WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
+			0x04, (enable << 2));
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+	.request_irq = wcd938x_mbhc_request_irq,
+	.irq_control = wcd938x_mbhc_irq_control,
+	.free_irq = wcd938x_mbhc_free_irq,
+	.clk_setup = wcd938x_mbhc_clk_setup,
+	.map_btn_code_to_num = wcd938x_mbhc_btn_to_num,
+	.mbhc_bias = wcd938x_mbhc_mbhc_bias_control,
+	.set_btn_thr = wcd938x_mbhc_program_btn_thr,
+	.lock_sleep = wcd938x_mbhc_lock_sleep,
+	.register_notifier = wcd938x_mbhc_register_notifier,
+	.micbias_enable_status = wcd938x_mbhc_micb_en_status,
+	.hph_pa_on_status = wcd938x_mbhc_hph_pa_on_status,
+	.hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control,
+	.mbhc_micbias_control = wcd938x_mbhc_request_micbias,
+	.mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control,
+	.get_hwdep_fw_cal = wcd938x_get_hwdep_fw_cal,
+	.mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic,
+	.compute_impedance = wcd938x_wcd_mbhc_calc_impedance,
+	.mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl,
+	.hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl,
+	.mbhc_moisture_config = wcd938x_mbhc_moisture_config,
+	.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
+	.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
+	.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+};
+
+static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_mbhc *wcd938x_mbhc = wcd938x_soc_get_mbhc(component);
+	struct wcd_mbhc *mbhc;
+
+	if (!wcd938x_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n", __func__);
+		return -EINVAL;
+	}
+
+	mbhc = &wcd938x_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 wcd938x_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 wcd938x_mbhc *wcd938x_mbhc = wcd938x_soc_get_mbhc(component);
+
+	if (!wcd938x_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(&wcd938x_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,
+		       wcd938x_get_hph_type, NULL),
+};
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+		       wcd938x_hph_impedance_get, NULL),
+	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+		       wcd938x_hph_impedance_get, NULL),
+};
+
+/*
+ * wcd938x_mbhc_get_impedance: get impedance of headphone
+ * left and right channels
+ * @wcd938x_mbhc: handle to struct wcd938x_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 wcd938x_mbhc_get_impedance(struct wcd938x_mbhc *wcd938x_mbhc,
+			     uint32_t *zl, uint32_t *zr)
+{
+	if (!wcd938x_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(&wcd938x_mbhc->wcd_mbhc, zl, zr);
+}
+EXPORT_SYMBOL(wcd938x_mbhc_get_impedance);
+
+/*
+ * wcd938x_mbhc_hs_detect: starts mbhc insertion/removal functionality
+ * @codec: 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 wcd938x_mbhc_hs_detect(struct snd_soc_component *component,
+			 struct wcd_mbhc_config *mbhc_cfg)
+{
+	struct wcd938x_priv *wcd938x = NULL;
+	struct wcd938x_mbhc *wcd938x_mbhc = NULL;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x = snd_soc_component_get_drvdata(component);
+	if (!wcd938x) {
+		pr_err("%s: wcd938x is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x_mbhc = wcd938x->mbhc;
+	if (!wcd938x_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n", __func__);
+		return -EINVAL;
+	}
+
+	return wcd_mbhc_start(&wcd938x_mbhc->wcd_mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL(wcd938x_mbhc_hs_detect);
+
+/*
+ * wcd938x_mbhc_hs_detect_exit: stop mbhc insertion/removal functionality
+ * @component: handle to snd_soc_component *
+ */
+void wcd938x_mbhc_hs_detect_exit(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x = NULL;
+	struct wcd938x_mbhc *wcd938x_mbhc = NULL;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return;
+	}
+
+	wcd938x = snd_soc_component_get_drvdata(component);
+	if (!wcd938x) {
+		pr_err("%s: wcd938x is NULL\n", __func__);
+		return;
+	}
+
+	wcd938x_mbhc = wcd938x->mbhc;
+	if (!wcd938x_mbhc) {
+		dev_err(component->dev, "%s: mbhc not initialized!\n", __func__);
+		return;
+	}
+	wcd_mbhc_stop(&wcd938x_mbhc->wcd_mbhc);
+}
+EXPORT_SYMBOL(wcd938x_mbhc_hs_detect_exit);
+
+/*
+ * wcd938x_mbhc_post_ssr_init: initialize mbhc for
+ * wcd938x post subsystem restart
+ * @mbhc: poniter to wcd938x_mbhc structure
+ * @component: handle to snd_soc_component *
+ *
+ * return 0 if mbhc_init is success or error code in case of failure
+ */
+int wcd938x_mbhc_post_ssr_init(struct wcd938x_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;
+	}
+
+	wcd_mbhc_deinit(wcd_mbhc);
+	ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb, &intr_ids,
+			    wcd_mbhc_registers, WCD938X_ZDET_SUPPORTED);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+		goto done;
+	}
+
+done:
+	return ret;
+}
+EXPORT_SYMBOL(wcd938x_mbhc_post_ssr_init);
+
+/*
+ * wcd938x_mbhc_init: initialize mbhc for wcd938x
+ * @mbhc: poniter to wcd938x_mbhc struct pointer to store the configs
+ * @codec: 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 wcd938x_mbhc_init(struct wcd938x_mbhc **mbhc,
+				struct snd_soc_component *component,
+				struct fw_info *fw_data)
+{
+	struct wcd938x_mbhc *wcd938x_mbhc = NULL;
+	struct wcd_mbhc *wcd_mbhc = NULL;
+	int ret = 0;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x_mbhc = devm_kzalloc(component->dev, sizeof(struct wcd938x_mbhc),
+				    GFP_KERNEL);
+	if (!wcd938x_mbhc)
+		return -ENOMEM;
+
+	wcd938x_mbhc->fw_data = fw_data;
+	BLOCKING_INIT_NOTIFIER_HEAD(&wcd938x_mbhc->notifier);
+	wcd_mbhc = &wcd938x_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,
+				WCD938X_ZDET_SUPPORTED);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc initialization failed\n",
+			__func__);
+		goto err;
+	}
+
+	(*mbhc) = wcd938x_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, wcd938x_mbhc);
+	return ret;
+}
+EXPORT_SYMBOL(wcd938x_mbhc_init);
+
+/*
+ * wcd938x_mbhc_deinit: deinitialize mbhc for wcd938x
+ * @codec: handle to snd_soc_component *
+ */
+void wcd938x_mbhc_deinit(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x;
+	struct wcd938x_mbhc *wcd938x_mbhc;
+
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return;
+	}
+
+	wcd938x = snd_soc_component_get_drvdata(component);
+	if (!wcd938x) {
+		pr_err("%s: wcd938x is NULL\n", __func__);
+		return;
+	}
+
+	wcd938x_mbhc = wcd938x->mbhc;
+	if (wcd938x_mbhc) {
+		wcd_mbhc_deinit(&wcd938x_mbhc->wcd_mbhc);
+		devm_kfree(component->dev, wcd938x_mbhc);
+	}
+}
+EXPORT_SYMBOL(wcd938x_mbhc_deinit);

+ 63 - 0
asoc/codecs/wcd938x/wcd938x-mbhc.h

@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+#ifndef __WCD938X_MBHC_H__
+#define __WCD938X_MBHC_H__
+#include <asoc/wcd-mbhc-v2.h>
+
+struct wcd938x_mbhc {
+	struct wcd_mbhc wcd_mbhc;
+	struct blocking_notifier_head notifier;
+	struct fw_info *fw_data;
+};
+
+#if IS_ENABLED(CONFIG_SND_SOC_WCD938X)
+extern int wcd938x_mbhc_init(struct wcd938x_mbhc **mbhc,
+			   struct snd_soc_component *component,
+			   struct fw_info *fw_data);
+extern void wcd938x_mbhc_hs_detect_exit(struct snd_soc_component *component);
+extern int wcd938x_mbhc_hs_detect(struct snd_soc_component *component,
+				struct wcd_mbhc_config *mbhc_cfg);
+extern void wcd938x_mbhc_deinit(struct snd_soc_component *component);
+extern int wcd938x_mbhc_post_ssr_init(struct wcd938x_mbhc *mbhc,
+				    struct snd_soc_component *component);
+extern int wcd938x_mbhc_get_impedance(struct wcd938x_mbhc *wcd938x_mbhc,
+				    uint32_t *zl, uint32_t *zr);
+#else
+static inline int wcd938x_mbhc_init(struct wcd938x_mbhc **mbhc,
+				  struct snd_soc_component *component,
+				  struct fw_info *fw_data)
+{
+	return 0;
+}
+static inline void wcd938x_mbhc_hs_detect_exit(
+					struct snd_soc_component *component)
+{
+}
+static inline int wcd938x_mbhc_hs_detect(struct snd_soc_component *component,
+				       struct wcd_mbhc_config *mbhc_cfg)
+{
+		return 0;
+}
+static inline void wcd938x_mbhc_deinit(struct snd_soc_component *component)
+{
+}
+static inline int wcd938x_mbhc_post_ssr_init(struct wcd938x_mbhc *mbhc,
+					   struct snd_soc_component *component)
+{
+	return 0;
+}
+
+static inline int wcd938x_mbhc_get_impedance(struct wcd938x_mbhc *wcd938x_mbhc,
+					   uint32_t *zl, uint32_t *zr)
+{
+	if (zl)
+		*zl = 0;
+	if (zr)
+		*zr = 0;
+	return -EINVAL;
+}
+#endif
+
+#endif /* __WCD938X_MBHC_H__ */

+ 502 - 0
asoc/codecs/wcd938x/wcd938x-registers.h

@@ -0,0 +1,502 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _WCD938X_REGISTERS_H
+#define _WCD938X_REGISTERS_H
+
+#define WCD938X_BASE_ADDRESS 0x3000
+#define WCD938X_REG(reg)  (reg - WCD938X_BASE_ADDRESS)
+
+enum {
+    REG_NO_ACCESS,
+    RD_REG,
+    WR_REG,
+    RD_WR_REG
+};
+
+
+#define WCD938X_ANA_PAGE_REGISTER               (WCD938X_BASE_ADDRESS + 0x0000)
+#define WCD938X_ANA_BIAS                        (WCD938X_BASE_ADDRESS + 0x0001)
+#define WCD938X_ANA_RX_SUPPLIES                 (WCD938X_BASE_ADDRESS + 0x0008)
+#define WCD938X_ANA_HPH                         (WCD938X_BASE_ADDRESS + 0x0009)
+#define WCD938X_ANA_EAR                         (WCD938X_BASE_ADDRESS + 0x000A)
+#define WCD938X_ANA_EAR_COMPANDER_CTL           (WCD938X_BASE_ADDRESS + 0x000B)
+#define WCD938X_ANA_TX_CH1                      (WCD938X_BASE_ADDRESS + 0x000E)
+#define WCD938X_ANA_TX_CH2                      (WCD938X_BASE_ADDRESS + 0x000F)
+#define WCD938X_ANA_TX_CH3                      (WCD938X_BASE_ADDRESS + 0x0010)
+#define WCD938X_ANA_TX_CH4                      (WCD938X_BASE_ADDRESS + 0x0011)
+#define WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC    (WCD938X_BASE_ADDRESS + 0x0012)
+#define WCD938X_ANA_MICB3_DSP_EN_LOGIC          (WCD938X_BASE_ADDRESS + 0x0013)
+#define WCD938X_ANA_MBHC_MECH                   (WCD938X_BASE_ADDRESS + 0x0014)
+#define WCD938X_ANA_MBHC_ELECT                  (WCD938X_BASE_ADDRESS + 0x0015)
+#define WCD938X_ANA_MBHC_ZDET                   (WCD938X_BASE_ADDRESS + 0x0016)
+#define WCD938X_ANA_MBHC_RESULT_1               (WCD938X_BASE_ADDRESS + 0x0017)
+#define WCD938X_ANA_MBHC_RESULT_2               (WCD938X_BASE_ADDRESS + 0x0018)
+#define WCD938X_ANA_MBHC_RESULT_3               (WCD938X_BASE_ADDRESS + 0x0019)
+#define WCD938X_ANA_MBHC_BTN0                   (WCD938X_BASE_ADDRESS + 0x001A)
+#define WCD938X_ANA_MBHC_BTN1                   (WCD938X_BASE_ADDRESS + 0x001B)
+#define WCD938X_ANA_MBHC_BTN2                   (WCD938X_BASE_ADDRESS + 0x001C)
+#define WCD938X_ANA_MBHC_BTN3                   (WCD938X_BASE_ADDRESS + 0x001D)
+#define WCD938X_ANA_MBHC_BTN4                   (WCD938X_BASE_ADDRESS + 0x001E)
+#define WCD938X_ANA_MBHC_BTN5                   (WCD938X_BASE_ADDRESS + 0x001F)
+#define WCD938X_ANA_MBHC_BTN6                   (WCD938X_BASE_ADDRESS + 0x0020)
+#define WCD938X_ANA_MBHC_BTN7                   (WCD938X_BASE_ADDRESS + 0x0021)
+#define WCD938X_ANA_MICB1                       (WCD938X_BASE_ADDRESS + 0x0022)
+#define WCD938X_ANA_MICB2                       (WCD938X_BASE_ADDRESS + 0x0023)
+#define WCD938X_ANA_MICB2_RAMP                  (WCD938X_BASE_ADDRESS + 0x0024)
+#define WCD938X_ANA_MICB3                       (WCD938X_BASE_ADDRESS + 0x0025)
+#define WCD938X_ANA_MICB4                       (WCD938X_BASE_ADDRESS + 0x0026)
+#define WCD938X_BIAS_CTL                        (WCD938X_BASE_ADDRESS + 0x0028)
+#define WCD938X_BIAS_VBG_FINE_ADJ               (WCD938X_BASE_ADDRESS + 0x0029)
+#define WCD938X_LDOL_VDDCX_ADJUST               (WCD938X_BASE_ADDRESS + 0x0040)
+#define WCD938X_LDOL_DISABLE_LDOL               (WCD938X_BASE_ADDRESS + 0x0041)
+#define WCD938X_MBHC_CTL_CLK                    (WCD938X_BASE_ADDRESS + 0x0056)
+#define WCD938X_MBHC_CTL_ANA                    (WCD938X_BASE_ADDRESS + 0x0057)
+#define WCD938X_MBHC_CTL_SPARE_1                (WCD938X_BASE_ADDRESS + 0x0058)
+#define WCD938X_MBHC_CTL_SPARE_2                (WCD938X_BASE_ADDRESS + 0x0059)
+#define WCD938X_MBHC_CTL_BCS                    (WCD938X_BASE_ADDRESS + 0x005A)
+#define WCD938X_MBHC_MOISTURE_DET_FSM_STATUS    (WCD938X_BASE_ADDRESS + 0x005B)
+#define WCD938X_MBHC_TEST_CTL                   (WCD938X_BASE_ADDRESS + 0x005C)
+#define WCD938X_LDOH_MODE                       (WCD938X_BASE_ADDRESS + 0x0067)
+#define WCD938X_LDOH_BIAS                       (WCD938X_BASE_ADDRESS + 0x0068)
+#define WCD938X_LDOH_STB_LOADS                  (WCD938X_BASE_ADDRESS + 0x0069)
+#define WCD938X_LDOH_SLOWRAMP                   (WCD938X_BASE_ADDRESS + 0x006A)
+#define WCD938X_MICB1_TEST_CTL_1                (WCD938X_BASE_ADDRESS + 0x006B)
+#define WCD938X_MICB1_TEST_CTL_2                (WCD938X_BASE_ADDRESS + 0x006C)
+#define WCD938X_MICB1_TEST_CTL_3                (WCD938X_BASE_ADDRESS + 0x006D)
+#define WCD938X_MICB2_TEST_CTL_1                (WCD938X_BASE_ADDRESS + 0x006E)
+#define WCD938X_MICB2_TEST_CTL_2                (WCD938X_BASE_ADDRESS + 0x006F)
+#define WCD938X_MICB2_TEST_CTL_3                (WCD938X_BASE_ADDRESS + 0x0070)
+#define WCD938X_MICB3_TEST_CTL_1                (WCD938X_BASE_ADDRESS + 0x0071)
+#define WCD938X_MICB3_TEST_CTL_2                (WCD938X_BASE_ADDRESS + 0x0072)
+#define WCD938X_MICB3_TEST_CTL_3                (WCD938X_BASE_ADDRESS + 0x0073)
+#define WCD938X_MICB4_TEST_CTL_1                (WCD938X_BASE_ADDRESS + 0x0074)
+#define WCD938X_MICB4_TEST_CTL_2                (WCD938X_BASE_ADDRESS + 0x0075)
+#define WCD938X_MICB4_TEST_CTL_3                (WCD938X_BASE_ADDRESS + 0x0076)
+#define WCD938X_TX_COM_ADC_VCM                  (WCD938X_BASE_ADDRESS + 0x0077)
+#define WCD938X_TX_COM_BIAS_ATEST               (WCD938X_BASE_ADDRESS + 0x0078)
+#define WCD938X_TX_COM_SPARE1                   (WCD938X_BASE_ADDRESS + 0x0079)
+#define WCD938X_TX_COM_SPARE2                   (WCD938X_BASE_ADDRESS + 0x007A)
+#define WCD938X_TX_COM_TXFE_DIV_CTL             (WCD938X_BASE_ADDRESS + 0x007B)
+#define WCD938X_TX_COM_TXFE_DIV_START           (WCD938X_BASE_ADDRESS + 0x007C)
+#define WCD938X_TX_COM_SPARE3                   (WCD938X_BASE_ADDRESS + 0x007D)
+#define WCD938X_TX_COM_SPARE4                   (WCD938X_BASE_ADDRESS + 0x007E)
+#define WCD938X_TX_1_2_TEST_EN                  (WCD938X_BASE_ADDRESS + 0x007F)
+#define WCD938X_TX_1_2_ADC_IB                   (WCD938X_BASE_ADDRESS + 0x0080)
+#define WCD938X_TX_1_2_ATEST_REFCTL             (WCD938X_BASE_ADDRESS + 0x0081)
+#define WCD938X_TX_1_2_TEST_CTL                 (WCD938X_BASE_ADDRESS + 0x0082)
+#define WCD938X_TX_1_2_TEST_BLK_EN1             (WCD938X_BASE_ADDRESS + 0x0083)
+#define WCD938X_TX_1_2_TXFE1_CLKDIV             (WCD938X_BASE_ADDRESS + 0x0084)
+#define WCD938X_TX_1_2_SAR2_ERR                 (WCD938X_BASE_ADDRESS + 0x0085)
+#define WCD938X_TX_1_2_SAR1_ERR                 (WCD938X_BASE_ADDRESS + 0x0086)
+#define WCD938X_TX_3_4_TEST_EN                  (WCD938X_BASE_ADDRESS + 0x0087)
+#define WCD938X_TX_3_4_ADC_IB                   (WCD938X_BASE_ADDRESS + 0x0088)
+#define WCD938X_TX_3_4_ATEST_REFCTL             (WCD938X_BASE_ADDRESS + 0x0089)
+#define WCD938X_TX_3_4_TEST_CTL                 (WCD938X_BASE_ADDRESS + 0x008A)
+#define WCD938X_TX_3_4_TEST_BLK_EN3             (WCD938X_BASE_ADDRESS + 0x008B)
+#define WCD938X_TX_3_4_TXFE3_CLKDIV             (WCD938X_BASE_ADDRESS + 0x008C)
+#define WCD938X_TX_3_4_SAR4_ERR                 (WCD938X_BASE_ADDRESS + 0x008D)
+#define WCD938X_TX_3_4_SAR3_ERR                 (WCD938X_BASE_ADDRESS + 0x008E)
+#define WCD938X_TX_3_4_TEST_BLK_EN2             (WCD938X_BASE_ADDRESS + 0x008F)
+#define WCD938X_TX_3_4_TXFE2_CLKDIV             (WCD938X_BASE_ADDRESS + 0x0090)
+#define WCD938X_TX_3_4_SPARE1                   (WCD938X_BASE_ADDRESS + 0x0091)
+#define WCD938X_TX_3_4_TEST_BLK_EN4             (WCD938X_BASE_ADDRESS + 0x0092)
+#define WCD938X_TX_3_4_TXFE4_CLKDIV             (WCD938X_BASE_ADDRESS + 0x0093)
+#define WCD938X_TX_3_4_SPARE2                   (WCD938X_BASE_ADDRESS + 0x0094)
+#define WCD938X_CLASSH_MODE_1                   (WCD938X_BASE_ADDRESS + 0x0097)
+#define WCD938X_CLASSH_MODE_2                   (WCD938X_BASE_ADDRESS + 0x0098)
+#define WCD938X_CLASSH_MODE_3                   (WCD938X_BASE_ADDRESS + 0x0099)
+#define WCD938X_CLASSH_CTRL_VCL_1               (WCD938X_BASE_ADDRESS + 0x009A)
+#define WCD938X_CLASSH_CTRL_VCL_2               (WCD938X_BASE_ADDRESS + 0x009B)
+#define WCD938X_CLASSH_CTRL_CCL_1               (WCD938X_BASE_ADDRESS + 0x009C)
+#define WCD938X_CLASSH_CTRL_CCL_2               (WCD938X_BASE_ADDRESS + 0x009D)
+#define WCD938X_CLASSH_CTRL_CCL_3               (WCD938X_BASE_ADDRESS + 0x009E)
+#define WCD938X_CLASSH_CTRL_CCL_4               (WCD938X_BASE_ADDRESS + 0x009F)
+#define WCD938X_CLASSH_CTRL_CCL_5               (WCD938X_BASE_ADDRESS + 0x00A0)
+#define WCD938X_CLASSH_BUCK_TMUX_A_D            (WCD938X_BASE_ADDRESS + 0x00A1)
+#define WCD938X_CLASSH_BUCK_SW_DRV_CNTL         (WCD938X_BASE_ADDRESS + 0x00A2)
+#define WCD938X_CLASSH_SPARE                    (WCD938X_BASE_ADDRESS + 0x00A3)
+#define WCD938X_FLYBACK_EN                      (WCD938X_BASE_ADDRESS + 0x00A4)
+#define WCD938X_FLYBACK_VNEG_CTRL_1             (WCD938X_BASE_ADDRESS + 0x00A5)
+#define WCD938X_FLYBACK_VNEG_CTRL_2             (WCD938X_BASE_ADDRESS + 0x00A6)
+#define WCD938X_FLYBACK_VNEG_CTRL_3             (WCD938X_BASE_ADDRESS + 0x00A7)
+#define WCD938X_FLYBACK_VNEG_CTRL_4             (WCD938X_BASE_ADDRESS + 0x00A8)
+#define WCD938X_FLYBACK_VNEG_CTRL_5             (WCD938X_BASE_ADDRESS + 0x00A9)
+#define WCD938X_FLYBACK_VNEG_CTRL_6             (WCD938X_BASE_ADDRESS + 0x00AA)
+#define WCD938X_FLYBACK_VNEG_CTRL_7             (WCD938X_BASE_ADDRESS + 0x00AB)
+#define WCD938X_FLYBACK_VNEG_CTRL_8             (WCD938X_BASE_ADDRESS + 0x00AC)
+#define WCD938X_FLYBACK_VNEG_CTRL_9             (WCD938X_BASE_ADDRESS + 0x00AD)
+#define WCD938X_FLYBACK_VNEGDAC_CTRL_1          (WCD938X_BASE_ADDRESS + 0x00AE)
+#define WCD938X_FLYBACK_VNEGDAC_CTRL_2          (WCD938X_BASE_ADDRESS + 0x00AF)
+#define WCD938X_FLYBACK_VNEGDAC_CTRL_3          (WCD938X_BASE_ADDRESS + 0x00B0)
+#define WCD938X_FLYBACK_CTRL_1                  (WCD938X_BASE_ADDRESS + 0x00B1)
+#define WCD938X_FLYBACK_TEST_CTL                (WCD938X_BASE_ADDRESS + 0x00B2)
+#define WCD938X_RX_AUX_SW_CTL                   (WCD938X_BASE_ADDRESS + 0x00B3)
+#define WCD938X_RX_PA_AUX_IN_CONN               (WCD938X_BASE_ADDRESS + 0x00B4)
+#define WCD938X_RX_TIMER_DIV                    (WCD938X_BASE_ADDRESS + 0x00B5)
+#define WCD938X_RX_OCP_CTL                      (WCD938X_BASE_ADDRESS + 0x00B6)
+#define WCD938X_RX_OCP_COUNT                    (WCD938X_BASE_ADDRESS + 0x00B7)
+#define WCD938X_RX_BIAS_EAR_DAC                 (WCD938X_BASE_ADDRESS + 0x00B8)
+#define WCD938X_RX_BIAS_EAR_AMP                 (WCD938X_BASE_ADDRESS + 0x00B9)
+#define WCD938X_RX_BIAS_HPH_LDO                 (WCD938X_BASE_ADDRESS + 0x00BA)
+#define WCD938X_RX_BIAS_HPH_PA                  (WCD938X_BASE_ADDRESS + 0x00BB)
+#define WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2       (WCD938X_BASE_ADDRESS + 0x00BC)
+#define WCD938X_RX_BIAS_HPH_RDAC_LDO            (WCD938X_BASE_ADDRESS + 0x00BD)
+#define WCD938X_RX_BIAS_HPH_CNP1                (WCD938X_BASE_ADDRESS + 0x00BE)
+#define WCD938X_RX_BIAS_HPH_LOWPOWER            (WCD938X_BASE_ADDRESS + 0x00BF)
+#define WCD938X_RX_BIAS_AUX_DAC                 (WCD938X_BASE_ADDRESS + 0x00C0)
+#define WCD938X_RX_BIAS_AUX_AMP                 (WCD938X_BASE_ADDRESS + 0x00C1)
+#define WCD938X_RX_BIAS_VNEGDAC_BLEEDER         (WCD938X_BASE_ADDRESS + 0x00C2)
+#define WCD938X_RX_BIAS_MISC                    (WCD938X_BASE_ADDRESS + 0x00C3)
+#define WCD938X_RX_BIAS_BUCK_RST                (WCD938X_BASE_ADDRESS + 0x00C4)
+#define WCD938X_RX_BIAS_BUCK_VREF_ERRAMP        (WCD938X_BASE_ADDRESS + 0x00C5)
+#define WCD938X_RX_BIAS_FLYB_ERRAMP             (WCD938X_BASE_ADDRESS + 0x00C6)
+#define WCD938X_RX_BIAS_FLYB_BUFF               (WCD938X_BASE_ADDRESS + 0x00C7)
+#define WCD938X_RX_BIAS_FLYB_MID_RST            (WCD938X_BASE_ADDRESS + 0x00C8)
+#define WCD938X_HPH_L_STATUS                    (WCD938X_BASE_ADDRESS + 0x00C9)
+#define WCD938X_HPH_R_STATUS                    (WCD938X_BASE_ADDRESS + 0x00CA)
+#define WCD938X_HPH_CNP_EN                      (WCD938X_BASE_ADDRESS + 0x00CB)
+#define WCD938X_HPH_CNP_WG_CTL                  (WCD938X_BASE_ADDRESS + 0x00CC)
+#define WCD938X_HPH_CNP_WG_TIME                 (WCD938X_BASE_ADDRESS + 0x00CD)
+#define WCD938X_HPH_OCP_CTL                     (WCD938X_BASE_ADDRESS + 0x00CE)
+#define WCD938X_HPH_AUTO_CHOP                   (WCD938X_BASE_ADDRESS + 0x00CF)
+#define WCD938X_HPH_CHOP_CTL                    (WCD938X_BASE_ADDRESS + 0x00D0)
+#define WCD938X_HPH_PA_CTL1                     (WCD938X_BASE_ADDRESS + 0x00D1)
+#define WCD938X_HPH_PA_CTL2                     (WCD938X_BASE_ADDRESS + 0x00D2)
+#define WCD938X_HPH_L_EN                        (WCD938X_BASE_ADDRESS + 0x00D3)
+#define WCD938X_HPH_L_TEST                      (WCD938X_BASE_ADDRESS + 0x00D4)
+#define WCD938X_HPH_L_ATEST                     (WCD938X_BASE_ADDRESS + 0x00D5)
+#define WCD938X_HPH_R_EN                        (WCD938X_BASE_ADDRESS + 0x00D6)
+#define WCD938X_HPH_R_TEST                      (WCD938X_BASE_ADDRESS + 0x00D7)
+#define WCD938X_HPH_R_ATEST                     (WCD938X_BASE_ADDRESS + 0x00D8)
+#define WCD938X_HPH_RDAC_CLK_CTL1               (WCD938X_BASE_ADDRESS + 0x00D9)
+#define WCD938X_HPH_RDAC_CLK_CTL2               (WCD938X_BASE_ADDRESS + 0x00DA)
+#define WCD938X_HPH_RDAC_LDO_CTL                (WCD938X_BASE_ADDRESS + 0x00DB)
+#define WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL        (WCD938X_BASE_ADDRESS + 0x00DC)
+#define WCD938X_HPH_REFBUFF_UHQA_CTL            (WCD938X_BASE_ADDRESS + 0x00DD)
+#define WCD938X_HPH_REFBUFF_LP_CTL              (WCD938X_BASE_ADDRESS + 0x00DE)
+#define WCD938X_HPH_L_DAC_CTL                   (WCD938X_BASE_ADDRESS + 0x00DF)
+#define WCD938X_HPH_R_DAC_CTL                   (WCD938X_BASE_ADDRESS + 0x00E0)
+#define WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL  (WCD938X_BASE_ADDRESS + 0x00E1)
+#define WCD938X_HPH_SURGE_HPHLR_SURGE_EN        (WCD938X_BASE_ADDRESS + 0x00E2)
+#define WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1     (WCD938X_BASE_ADDRESS + 0x00E3)
+#define WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS    (WCD938X_BASE_ADDRESS + 0x00E4)
+#define WCD938X_EAR_EAR_EN_REG                  (WCD938X_BASE_ADDRESS + 0x00E9)
+#define WCD938X_EAR_EAR_PA_CON                  (WCD938X_BASE_ADDRESS + 0x00EA)
+#define WCD938X_EAR_EAR_SP_CON                  (WCD938X_BASE_ADDRESS + 0x00EB)
+#define WCD938X_EAR_EAR_DAC_CON                 (WCD938X_BASE_ADDRESS + 0x00EC)
+#define WCD938X_EAR_EAR_CNP_FSM_CON             (WCD938X_BASE_ADDRESS + 0x00ED)
+#define WCD938X_EAR_TEST_CTL                    (WCD938X_BASE_ADDRESS + 0x00EE)
+#define WCD938X_EAR_STATUS_REG_1                (WCD938X_BASE_ADDRESS + 0x00EF)
+#define WCD938X_EAR_STATUS_REG_2                (WCD938X_BASE_ADDRESS + 0x00F0)
+#define WCD938X_ANA_NEW_PAGE_REGISTER           (WCD938X_BASE_ADDRESS + 0x0100)
+#define WCD938X_HPH_NEW_ANA_HPH2                (WCD938X_BASE_ADDRESS + 0x0101)
+#define WCD938X_HPH_NEW_ANA_HPH3                (WCD938X_BASE_ADDRESS + 0x0102)
+#define WCD938X_SLEEP_CTL                       (WCD938X_BASE_ADDRESS + 0x0103)
+#define WCD938X_SLEEP_WATCHDOG_CTL              (WCD938X_BASE_ADDRESS + 0x0104)
+#define WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL    (WCD938X_BASE_ADDRESS + 0x011F)
+#define WCD938X_MBHC_NEW_CTL_1                  (WCD938X_BASE_ADDRESS + 0x0120)
+#define WCD938X_MBHC_NEW_CTL_2                  (WCD938X_BASE_ADDRESS + 0x0121)
+#define WCD938X_MBHC_NEW_PLUG_DETECT_CTL        (WCD938X_BASE_ADDRESS + 0x0122)
+#define WCD938X_MBHC_NEW_ZDET_ANA_CTL           (WCD938X_BASE_ADDRESS + 0x0123)
+#define WCD938X_MBHC_NEW_ZDET_RAMP_CTL          (WCD938X_BASE_ADDRESS + 0x0124)
+#define WCD938X_MBHC_NEW_FSM_STATUS             (WCD938X_BASE_ADDRESS + 0x0125)
+#define WCD938X_MBHC_NEW_ADC_RESULT             (WCD938X_BASE_ADDRESS + 0x0126)
+#define WCD938X_TX_NEW_AMIC_MUX_CFG             (WCD938X_BASE_ADDRESS + 0x0127)
+#define WCD938X_AUX_AUXPA                       (WCD938X_BASE_ADDRESS + 0x0128)
+#define WCD938X_LDORXTX_MODE                    (WCD938X_BASE_ADDRESS + 0x0129)
+#define WCD938X_LDORXTX_CONFIG                  (WCD938X_BASE_ADDRESS + 0x012A)
+#define WCD938X_DIE_CRACK_DIE_CRK_DET_EN        (WCD938X_BASE_ADDRESS + 0x012C)
+#define WCD938X_DIE_CRACK_DIE_CRK_DET_OUT       (WCD938X_BASE_ADDRESS + 0x012D)
+#define WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL       (WCD938X_BASE_ADDRESS + 0x0132)
+#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L      (WCD938X_BASE_ADDRESS + 0x0133)
+#define WCD938X_HPH_NEW_INT_RDAC_VREF_CTL       (WCD938X_BASE_ADDRESS + 0x0134)
+#define WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL   (WCD938X_BASE_ADDRESS + 0x0135)
+#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R      (WCD938X_BASE_ADDRESS + 0x0136)
+#define WCD938X_HPH_NEW_INT_PA_MISC1            (WCD938X_BASE_ADDRESS + 0x0137)
+#define WCD938X_HPH_NEW_INT_PA_MISC2            (WCD938X_BASE_ADDRESS + 0x0138)
+#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC        (WCD938X_BASE_ADDRESS + 0x0139)
+#define WCD938X_HPH_NEW_INT_HPH_TIMER1          (WCD938X_BASE_ADDRESS + 0x013A)
+#define WCD938X_HPH_NEW_INT_HPH_TIMER2          (WCD938X_BASE_ADDRESS + 0x013B)
+#define WCD938X_HPH_NEW_INT_HPH_TIMER3          (WCD938X_BASE_ADDRESS + 0x013C)
+#define WCD938X_HPH_NEW_INT_HPH_TIMER4          (WCD938X_BASE_ADDRESS + 0x013D)
+#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC2       (WCD938X_BASE_ADDRESS + 0x013E)
+#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC3       (WCD938X_BASE_ADDRESS + 0x013F)
+#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW  (WCD938X_BASE_ADDRESS + 0x0140)
+#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW  (WCD938X_BASE_ADDRESS + 0x0141)
+#define WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI (WCD938X_BASE_ADDRESS + 0x0145)
+#define WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP    (WCD938X_BASE_ADDRESS + 0x0146)
+#define WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP      (WCD938X_BASE_ADDRESS + 0x0147)
+#define WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL  \
+                                                (WCD938X_BASE_ADDRESS + 0x01AF)
+#define WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL \
+                                                (WCD938X_BASE_ADDRESS + 0x01B0)
+#define WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT   (WCD938X_BASE_ADDRESS + 0x01B1)
+#define WCD938X_MBHC_NEW_INT_SPARE_2            (WCD938X_BASE_ADDRESS + 0x01B2)
+#define WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON     (WCD938X_BASE_ADDRESS + 0x01B7)
+#define WCD938X_EAR_INT_NEW_CNP_VCM_CON1        (WCD938X_BASE_ADDRESS + 0x01B8)
+#define WCD938X_EAR_INT_NEW_CNP_VCM_CON2        (WCD938X_BASE_ADDRESS + 0x01B9)
+#define WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS    (WCD938X_BASE_ADDRESS + 0x01BA)
+#define WCD938X_AUX_INT_EN_REG                  (WCD938X_BASE_ADDRESS + 0x01BD)
+#define WCD938X_AUX_INT_PA_CTRL                 (WCD938X_BASE_ADDRESS + 0x01BE)
+#define WCD938X_AUX_INT_SP_CTRL                 (WCD938X_BASE_ADDRESS + 0x01BF)
+#define WCD938X_AUX_INT_DAC_CTRL                (WCD938X_BASE_ADDRESS + 0x01C0)
+#define WCD938X_AUX_INT_CLK_CTRL                (WCD938X_BASE_ADDRESS + 0x01C1)
+#define WCD938X_AUX_INT_TEST_CTRL               (WCD938X_BASE_ADDRESS + 0x01C2)
+#define WCD938X_AUX_INT_STATUS_REG              (WCD938X_BASE_ADDRESS + 0x01C3)
+#define WCD938X_AUX_INT_MISC                    (WCD938X_BASE_ADDRESS + 0x01C4)
+#define WCD938X_LDORXTX_INT_BIAS                (WCD938X_BASE_ADDRESS + 0x01C5)
+#define WCD938X_LDORXTX_INT_STB_LOADS_DTEST     (WCD938X_BASE_ADDRESS + 0x01C6)
+#define WCD938X_LDORXTX_INT_TEST0               (WCD938X_BASE_ADDRESS + 0x01C7)
+#define WCD938X_LDORXTX_INT_STARTUP_TIMER       (WCD938X_BASE_ADDRESS + 0x01C8)
+#define WCD938X_LDORXTX_INT_TEST1               (WCD938X_BASE_ADDRESS + 0x01C9)
+#define WCD938X_LDORXTX_INT_STATUS              (WCD938X_BASE_ADDRESS + 0x01CA)
+#define WCD938X_SLEEP_INT_WATCHDOG_CTL_1        (WCD938X_BASE_ADDRESS + 0x01D0)
+#define WCD938X_SLEEP_INT_WATCHDOG_CTL_2        (WCD938X_BASE_ADDRESS + 0x01D1)
+#define WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1  (WCD938X_BASE_ADDRESS + 0x01D3)
+#define WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2  (WCD938X_BASE_ADDRESS + 0x01D4)
+#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2  (WCD938X_BASE_ADDRESS + 0x01D5)
+#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1  (WCD938X_BASE_ADDRESS + 0x01D6)
+#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0  (WCD938X_BASE_ADDRESS + 0x01D7)
+#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M \
+                                                (WCD938X_BASE_ADDRESS + 0x01D8)
+#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M \
+                                                (WCD938X_BASE_ADDRESS + 0x01D9)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1 \
+                                                (WCD938X_BASE_ADDRESS + 0x01DA)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0 \
+                                                (WCD938X_BASE_ADDRESS + 0x01DB)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP \
+                                                (WCD938X_BASE_ADDRESS + 0x01DC)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1 \
+                                                (WCD938X_BASE_ADDRESS + 0x01DD)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0 \
+                                                (WCD938X_BASE_ADDRESS + 0x01DE)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP \
+                                                (WCD938X_BASE_ADDRESS + 0x01DF)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0 \
+                                                (WCD938X_BASE_ADDRESS + 0x01E0)
+#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP \
+                                                (WCD938X_BASE_ADDRESS + 0x01E1)
+#define WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1 \
+                                                (WCD938X_BASE_ADDRESS + 0x01E2)
+#define WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP \
+                                                (WCD938X_BASE_ADDRESS + 0x01E3)
+#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L2     (WCD938X_BASE_ADDRESS + 0x01E4)
+#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L1     (WCD938X_BASE_ADDRESS + 0x01E5)
+#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L0     (WCD938X_BASE_ADDRESS + 0x01E6)
+#define WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP    (WCD938X_BASE_ADDRESS + 0x01E7)
+#define WCD938X_DIGITAL_PAGE_REGISTER           (WCD938X_BASE_ADDRESS + 0x0400)
+#define WCD938X_DIGITAL_CHIP_ID0                (WCD938X_BASE_ADDRESS + 0x0401)
+#define WCD938X_DIGITAL_CHIP_ID1                (WCD938X_BASE_ADDRESS + 0x0402)
+#define WCD938X_DIGITAL_CHIP_ID2                (WCD938X_BASE_ADDRESS + 0x0403)
+#define WCD938X_DIGITAL_CHIP_ID3                (WCD938X_BASE_ADDRESS + 0x0404)
+#define WCD938X_DIGITAL_SWR_TX_CLK_RATE         (WCD938X_BASE_ADDRESS + 0x0405)
+#define WCD938X_DIGITAL_CDC_RST_CTL             (WCD938X_BASE_ADDRESS + 0x0406)
+#define WCD938X_DIGITAL_TOP_CLK_CFG             (WCD938X_BASE_ADDRESS + 0x0407)
+#define WCD938X_DIGITAL_CDC_ANA_CLK_CTL         (WCD938X_BASE_ADDRESS + 0x0408)
+#define WCD938X_DIGITAL_CDC_DIG_CLK_CTL         (WCD938X_BASE_ADDRESS + 0x0409)
+#define WCD938X_DIGITAL_SWR_RST_EN              (WCD938X_BASE_ADDRESS + 0x040A)
+#define WCD938X_DIGITAL_CDC_PATH_MODE           (WCD938X_BASE_ADDRESS + 0x040B)
+#define WCD938X_DIGITAL_CDC_RX_RST              (WCD938X_BASE_ADDRESS + 0x040C)
+#define WCD938X_DIGITAL_CDC_RX0_CTL             (WCD938X_BASE_ADDRESS + 0x040D)
+#define WCD938X_DIGITAL_CDC_RX1_CTL             (WCD938X_BASE_ADDRESS + 0x040E)
+#define WCD938X_DIGITAL_CDC_RX2_CTL             (WCD938X_BASE_ADDRESS + 0x040F)
+#define WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1     (WCD938X_BASE_ADDRESS + 0x0410)
+#define WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3     (WCD938X_BASE_ADDRESS + 0x0411)
+#define WCD938X_DIGITAL_CDC_COMP_CTL_0          (WCD938X_BASE_ADDRESS + 0x0414)
+#define WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL      (WCD938X_BASE_ADDRESS + 0x0417)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A1_0        (WCD938X_BASE_ADDRESS + 0x0418)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A1_1        (WCD938X_BASE_ADDRESS + 0x0419)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A2_0        (WCD938X_BASE_ADDRESS + 0x041A)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A2_1        (WCD938X_BASE_ADDRESS + 0x041B)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A3_0        (WCD938X_BASE_ADDRESS + 0x041C)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A3_1        (WCD938X_BASE_ADDRESS + 0x041D)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A4_0        (WCD938X_BASE_ADDRESS + 0x041E)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A4_1        (WCD938X_BASE_ADDRESS + 0x041F)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A5_0        (WCD938X_BASE_ADDRESS + 0x0420)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A5_1        (WCD938X_BASE_ADDRESS + 0x0421)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A6_0        (WCD938X_BASE_ADDRESS + 0x0422)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_A7_0        (WCD938X_BASE_ADDRESS + 0x0423)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_C_0         (WCD938X_BASE_ADDRESS + 0x0424)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_C_1         (WCD938X_BASE_ADDRESS + 0x0425)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_C_2         (WCD938X_BASE_ADDRESS + 0x0426)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_C_3         (WCD938X_BASE_ADDRESS + 0x0427)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R1          (WCD938X_BASE_ADDRESS + 0x0428)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R2          (WCD938X_BASE_ADDRESS + 0x0429)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R3          (WCD938X_BASE_ADDRESS + 0x042A)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R4          (WCD938X_BASE_ADDRESS + 0x042B)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R5          (WCD938X_BASE_ADDRESS + 0x042C)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R6          (WCD938X_BASE_ADDRESS + 0x042D)
+#define WCD938X_DIGITAL_CDC_HPH_DSM_R7          (WCD938X_BASE_ADDRESS + 0x042E)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A1_0        (WCD938X_BASE_ADDRESS + 0x042F)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A1_1        (WCD938X_BASE_ADDRESS + 0x0430)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A2_0        (WCD938X_BASE_ADDRESS + 0x0431)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A2_1        (WCD938X_BASE_ADDRESS + 0x0432)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A3_0        (WCD938X_BASE_ADDRESS + 0x0433)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A3_1        (WCD938X_BASE_ADDRESS + 0x0434)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A4_0        (WCD938X_BASE_ADDRESS + 0x0435)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A4_1        (WCD938X_BASE_ADDRESS + 0x0436)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A5_0        (WCD938X_BASE_ADDRESS + 0x0437)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A5_1        (WCD938X_BASE_ADDRESS + 0x0438)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A6_0        (WCD938X_BASE_ADDRESS + 0x0439)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_A7_0        (WCD938X_BASE_ADDRESS + 0x043A)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_C_0         (WCD938X_BASE_ADDRESS + 0x043B)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_C_1         (WCD938X_BASE_ADDRESS + 0x043C)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_C_2         (WCD938X_BASE_ADDRESS + 0x043D)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_C_3         (WCD938X_BASE_ADDRESS + 0x043E)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R1          (WCD938X_BASE_ADDRESS + 0x043F)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R2          (WCD938X_BASE_ADDRESS + 0x0440)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R3          (WCD938X_BASE_ADDRESS + 0x0441)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R4          (WCD938X_BASE_ADDRESS + 0x0442)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R5          (WCD938X_BASE_ADDRESS + 0x0443)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R6          (WCD938X_BASE_ADDRESS + 0x0444)
+#define WCD938X_DIGITAL_CDC_AUX_DSM_R7          (WCD938X_BASE_ADDRESS + 0x0445)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0       (WCD938X_BASE_ADDRESS + 0x0446)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1       (WCD938X_BASE_ADDRESS + 0x0447)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0      (WCD938X_BASE_ADDRESS + 0x0448)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1      (WCD938X_BASE_ADDRESS + 0x0449)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2      (WCD938X_BASE_ADDRESS + 0x044A)
+#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0      (WCD938X_BASE_ADDRESS + 0x044B)
+#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1      (WCD938X_BASE_ADDRESS + 0x044C)
+#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2      (WCD938X_BASE_ADDRESS + 0x044D)
+#define WCD938X_DIGITAL_CDC_HPH_GAIN_CTL        (WCD938X_BASE_ADDRESS + 0x044E)
+#define WCD938X_DIGITAL_CDC_AUX_GAIN_CTL        (WCD938X_BASE_ADDRESS + 0x044F)
+#define WCD938X_DIGITAL_CDC_EAR_PATH_CTL        (WCD938X_BASE_ADDRESS + 0x0450)
+#define WCD938X_DIGITAL_CDC_SWR_CLH             (WCD938X_BASE_ADDRESS + 0x0451)
+#define WCD938X_DIGITAL_SWR_CLH_BYP             (WCD938X_BASE_ADDRESS + 0x0452)
+#define WCD938X_DIGITAL_CDC_TX0_CTL             (WCD938X_BASE_ADDRESS + 0x0453)
+#define WCD938X_DIGITAL_CDC_TX1_CTL             (WCD938X_BASE_ADDRESS + 0x0454)
+#define WCD938X_DIGITAL_CDC_TX2_CTL             (WCD938X_BASE_ADDRESS + 0x0455)
+#define WCD938X_DIGITAL_CDC_TX_RST              (WCD938X_BASE_ADDRESS + 0x0456)
+#define WCD938X_DIGITAL_CDC_REQ_CTL             (WCD938X_BASE_ADDRESS + 0x0457)
+#define WCD938X_DIGITAL_CDC_RST                 (WCD938X_BASE_ADDRESS + 0x0458)
+#define WCD938X_DIGITAL_CDC_AMIC_CTL            (WCD938X_BASE_ADDRESS + 0x045A)
+#define WCD938X_DIGITAL_CDC_DMIC_CTL            (WCD938X_BASE_ADDRESS + 0x045B)
+#define WCD938X_DIGITAL_CDC_DMIC1_CTL           (WCD938X_BASE_ADDRESS + 0x045C)
+#define WCD938X_DIGITAL_CDC_DMIC2_CTL           (WCD938X_BASE_ADDRESS + 0x045D)
+#define WCD938X_DIGITAL_CDC_DMIC3_CTL           (WCD938X_BASE_ADDRESS + 0x045E)
+#define WCD938X_DIGITAL_CDC_DMIC4_CTL           (WCD938X_BASE_ADDRESS + 0x045F)
+#define WCD938X_DIGITAL_EFUSE_PRG_CTL           (WCD938X_BASE_ADDRESS + 0x0460)
+#define WCD938X_DIGITAL_EFUSE_CTL               (WCD938X_BASE_ADDRESS + 0x0461)
+#define WCD938X_DIGITAL_CDC_DMIC_RATE_1_2       (WCD938X_BASE_ADDRESS + 0x0462)
+#define WCD938X_DIGITAL_CDC_DMIC_RATE_3_4       (WCD938X_BASE_ADDRESS + 0x0463)
+#define WCD938X_DIGITAL_PDM_WD_CTL0             (WCD938X_BASE_ADDRESS + 0x0465)
+#define WCD938X_DIGITAL_PDM_WD_CTL1             (WCD938X_BASE_ADDRESS + 0x0466)
+#define WCD938X_DIGITAL_PDM_WD_CTL2             (WCD938X_BASE_ADDRESS + 0x0467)
+#define WCD938X_DIGITAL_INTR_MODE               (WCD938X_BASE_ADDRESS + 0x046A)
+#define WCD938X_DIGITAL_INTR_MASK_0             (WCD938X_BASE_ADDRESS + 0x046B)
+#define WCD938X_DIGITAL_INTR_MASK_1             (WCD938X_BASE_ADDRESS + 0x046C)
+#define WCD938X_DIGITAL_INTR_MASK_2             (WCD938X_BASE_ADDRESS + 0x046D)
+#define WCD938X_DIGITAL_INTR_STATUS_0           (WCD938X_BASE_ADDRESS + 0x046E)
+#define WCD938X_DIGITAL_INTR_STATUS_1           (WCD938X_BASE_ADDRESS + 0x046F)
+#define WCD938X_DIGITAL_INTR_STATUS_2           (WCD938X_BASE_ADDRESS + 0x0470)
+#define WCD938X_DIGITAL_INTR_CLEAR_0            (WCD938X_BASE_ADDRESS + 0x0471)
+#define WCD938X_DIGITAL_INTR_CLEAR_1            (WCD938X_BASE_ADDRESS + 0x0472)
+#define WCD938X_DIGITAL_INTR_CLEAR_2            (WCD938X_BASE_ADDRESS + 0x0473)
+#define WCD938X_DIGITAL_INTR_LEVEL_0            (WCD938X_BASE_ADDRESS + 0x0474)
+#define WCD938X_DIGITAL_INTR_LEVEL_1            (WCD938X_BASE_ADDRESS + 0x0475)
+#define WCD938X_DIGITAL_INTR_LEVEL_2            (WCD938X_BASE_ADDRESS + 0x0476)
+#define WCD938X_DIGITAL_INTR_SET_0              (WCD938X_BASE_ADDRESS + 0x0477)
+#define WCD938X_DIGITAL_INTR_SET_1              (WCD938X_BASE_ADDRESS + 0x0478)
+#define WCD938X_DIGITAL_INTR_SET_2              (WCD938X_BASE_ADDRESS + 0x0479)
+#define WCD938X_DIGITAL_INTR_TEST_0             (WCD938X_BASE_ADDRESS + 0x047A)
+#define WCD938X_DIGITAL_INTR_TEST_1             (WCD938X_BASE_ADDRESS + 0x047B)
+#define WCD938X_DIGITAL_INTR_TEST_2             (WCD938X_BASE_ADDRESS + 0x047C)
+#define WCD938X_DIGITAL_TX_MODE_DBG_EN          (WCD938X_BASE_ADDRESS + 0x047F)
+#define WCD938X_DIGITAL_TX_MODE_DBG_0_1         (WCD938X_BASE_ADDRESS + 0x0480)
+#define WCD938X_DIGITAL_TX_MODE_DBG_2_3         (WCD938X_BASE_ADDRESS + 0x0481)
+#define WCD938X_DIGITAL_LB_IN_SEL_CTL           (WCD938X_BASE_ADDRESS + 0x0482)
+#define WCD938X_DIGITAL_LOOP_BACK_MODE          (WCD938X_BASE_ADDRESS + 0x0483)
+#define WCD938X_DIGITAL_SWR_DAC_TEST            (WCD938X_BASE_ADDRESS + 0x0484)
+#define WCD938X_DIGITAL_SWR_HM_TEST_RX_0        (WCD938X_BASE_ADDRESS + 0x0485)
+#define WCD938X_DIGITAL_SWR_HM_TEST_TX_0        (WCD938X_BASE_ADDRESS + 0x0486)
+#define WCD938X_DIGITAL_SWR_HM_TEST_RX_1        (WCD938X_BASE_ADDRESS + 0x0487)
+#define WCD938X_DIGITAL_SWR_HM_TEST_TX_1        (WCD938X_BASE_ADDRESS + 0x0488)
+#define WCD938X_DIGITAL_SWR_HM_TEST_TX_2        (WCD938X_BASE_ADDRESS + 0x0489)
+#define WCD938X_DIGITAL_SWR_HM_TEST_0           (WCD938X_BASE_ADDRESS + 0x048A)
+#define WCD938X_DIGITAL_SWR_HM_TEST_1           (WCD938X_BASE_ADDRESS + 0x048B)
+#define WCD938X_DIGITAL_PAD_CTL_SWR_0           (WCD938X_BASE_ADDRESS + 0x048C)
+#define WCD938X_DIGITAL_PAD_CTL_SWR_1           (WCD938X_BASE_ADDRESS + 0x048D)
+#define WCD938X_DIGITAL_I2C_CTL                 (WCD938X_BASE_ADDRESS + 0x048E)
+#define WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE   (WCD938X_BASE_ADDRESS + 0x048F)
+#define WCD938X_DIGITAL_EFUSE_TEST_CTL_0        (WCD938X_BASE_ADDRESS + 0x0490)
+#define WCD938X_DIGITAL_EFUSE_TEST_CTL_1        (WCD938X_BASE_ADDRESS + 0x0491)
+#define WCD938X_DIGITAL_EFUSE_T_DATA_0          (WCD938X_BASE_ADDRESS + 0x0492)
+#define WCD938X_DIGITAL_EFUSE_T_DATA_1          (WCD938X_BASE_ADDRESS + 0x0493)
+#define WCD938X_DIGITAL_PAD_CTL_PDM_RX0         (WCD938X_BASE_ADDRESS + 0x0494)
+#define WCD938X_DIGITAL_PAD_CTL_PDM_RX1         (WCD938X_BASE_ADDRESS + 0x0495)
+#define WCD938X_DIGITAL_PAD_CTL_PDM_TX0         (WCD938X_BASE_ADDRESS + 0x0496)
+#define WCD938X_DIGITAL_PAD_CTL_PDM_TX1         (WCD938X_BASE_ADDRESS + 0x0497)
+#define WCD938X_DIGITAL_PAD_CTL_PDM_TX2         (WCD938X_BASE_ADDRESS + 0x0498)
+#define WCD938X_DIGITAL_PAD_INP_DIS_0           (WCD938X_BASE_ADDRESS + 0x0499)
+#define WCD938X_DIGITAL_PAD_INP_DIS_1           (WCD938X_BASE_ADDRESS + 0x049A)
+#define WCD938X_DIGITAL_DRIVE_STRENGTH_0        (WCD938X_BASE_ADDRESS + 0x049B)
+#define WCD938X_DIGITAL_DRIVE_STRENGTH_1        (WCD938X_BASE_ADDRESS + 0x049C)
+#define WCD938X_DIGITAL_DRIVE_STRENGTH_2        (WCD938X_BASE_ADDRESS + 0x049D)
+#define WCD938X_DIGITAL_RX_DATA_EDGE_CTL        (WCD938X_BASE_ADDRESS + 0x049E)
+#define WCD938X_DIGITAL_TX_DATA_EDGE_CTL        (WCD938X_BASE_ADDRESS + 0x049F)
+#define WCD938X_DIGITAL_GPIO_MODE               (WCD938X_BASE_ADDRESS + 0x04A0)
+#define WCD938X_DIGITAL_PIN_CTL_OE              (WCD938X_BASE_ADDRESS + 0x04A1)
+#define WCD938X_DIGITAL_PIN_CTL_DATA_0          (WCD938X_BASE_ADDRESS + 0x04A2)
+#define WCD938X_DIGITAL_PIN_CTL_DATA_1          (WCD938X_BASE_ADDRESS + 0x04A3)
+#define WCD938X_DIGITAL_PIN_STATUS_0            (WCD938X_BASE_ADDRESS + 0x04A4)
+#define WCD938X_DIGITAL_PIN_STATUS_1            (WCD938X_BASE_ADDRESS + 0x04A5)
+#define WCD938X_DIGITAL_DIG_DEBUG_CTL           (WCD938X_BASE_ADDRESS + 0x04A6)
+#define WCD938X_DIGITAL_DIG_DEBUG_EN            (WCD938X_BASE_ADDRESS + 0x04A7)
+#define WCD938X_DIGITAL_ANA_CSR_DBG_ADD         (WCD938X_BASE_ADDRESS + 0x04A8)
+#define WCD938X_DIGITAL_ANA_CSR_DBG_CTL         (WCD938X_BASE_ADDRESS + 0x04A9)
+#define WCD938X_DIGITAL_SSP_DBG                 (WCD938X_BASE_ADDRESS + 0x04AA)
+#define WCD938X_DIGITAL_MODE_STATUS_0           (WCD938X_BASE_ADDRESS + 0x04AB)
+#define WCD938X_DIGITAL_MODE_STATUS_1           (WCD938X_BASE_ADDRESS + 0x04AC)
+#define WCD938X_DIGITAL_SPARE_0                 (WCD938X_BASE_ADDRESS + 0x04AD)
+#define WCD938X_DIGITAL_SPARE_1                 (WCD938X_BASE_ADDRESS + 0x04AE)
+#define WCD938X_DIGITAL_SPARE_2                 (WCD938X_BASE_ADDRESS + 0x04AF)
+#define WCD938X_DIGITAL_EFUSE_REG_0             (WCD938X_BASE_ADDRESS + 0x04B0)
+#define WCD938X_DIGITAL_EFUSE_REG_1             (WCD938X_BASE_ADDRESS + 0x04B1)
+#define WCD938X_DIGITAL_EFUSE_REG_2             (WCD938X_BASE_ADDRESS + 0x04B2)
+#define WCD938X_DIGITAL_EFUSE_REG_3             (WCD938X_BASE_ADDRESS + 0x04B3)
+#define WCD938X_DIGITAL_EFUSE_REG_4             (WCD938X_BASE_ADDRESS + 0x04B4)
+#define WCD938X_DIGITAL_EFUSE_REG_5             (WCD938X_BASE_ADDRESS + 0x04B5)
+#define WCD938X_DIGITAL_EFUSE_REG_6             (WCD938X_BASE_ADDRESS + 0x04B6)
+#define WCD938X_DIGITAL_EFUSE_REG_7             (WCD938X_BASE_ADDRESS + 0x04B7)
+#define WCD938X_DIGITAL_EFUSE_REG_8             (WCD938X_BASE_ADDRESS + 0x04B8)
+#define WCD938X_DIGITAL_EFUSE_REG_9             (WCD938X_BASE_ADDRESS + 0x04B9)
+#define WCD938X_DIGITAL_EFUSE_REG_10            (WCD938X_BASE_ADDRESS + 0x04BA)
+#define WCD938X_DIGITAL_EFUSE_REG_11            (WCD938X_BASE_ADDRESS + 0x04BB)
+#define WCD938X_DIGITAL_EFUSE_REG_12            (WCD938X_BASE_ADDRESS + 0x04BC)
+#define WCD938X_DIGITAL_EFUSE_REG_13            (WCD938X_BASE_ADDRESS + 0x04BD)
+#define WCD938X_DIGITAL_EFUSE_REG_14            (WCD938X_BASE_ADDRESS + 0x04BE)
+#define WCD938X_DIGITAL_EFUSE_REG_15            (WCD938X_BASE_ADDRESS + 0x04BF)
+#define WCD938X_DIGITAL_EFUSE_REG_16            (WCD938X_BASE_ADDRESS + 0x04C0)
+#define WCD938X_DIGITAL_EFUSE_REG_17            (WCD938X_BASE_ADDRESS + 0x04C1)
+#define WCD938X_DIGITAL_EFUSE_REG_18            (WCD938X_BASE_ADDRESS + 0x04C2)
+#define WCD938X_DIGITAL_EFUSE_REG_19            (WCD938X_BASE_ADDRESS + 0x04C3)
+#define WCD938X_DIGITAL_EFUSE_REG_20            (WCD938X_BASE_ADDRESS + 0x04C4)
+#define WCD938X_DIGITAL_EFUSE_REG_21            (WCD938X_BASE_ADDRESS + 0x04C5)
+#define WCD938X_DIGITAL_EFUSE_REG_22            (WCD938X_BASE_ADDRESS + 0x04C6)
+#define WCD938X_DIGITAL_EFUSE_REG_23            (WCD938X_BASE_ADDRESS + 0x04C7)
+#define WCD938X_DIGITAL_EFUSE_REG_24            (WCD938X_BASE_ADDRESS + 0x04C8)
+#define WCD938X_DIGITAL_EFUSE_REG_25            (WCD938X_BASE_ADDRESS + 0x04C9)
+#define WCD938X_DIGITAL_EFUSE_REG_26            (WCD938X_BASE_ADDRESS + 0x04CA)
+#define WCD938X_DIGITAL_EFUSE_REG_27            (WCD938X_BASE_ADDRESS + 0x04CB)
+#define WCD938X_DIGITAL_EFUSE_REG_28            (WCD938X_BASE_ADDRESS + 0x04CC)
+#define WCD938X_DIGITAL_EFUSE_REG_29            (WCD938X_BASE_ADDRESS + 0x04CD)
+#define WCD938X_DIGITAL_EFUSE_REG_30            (WCD938X_BASE_ADDRESS + 0x04CE)
+#define WCD938X_DIGITAL_EFUSE_REG_31            (WCD938X_BASE_ADDRESS + 0x04CF)
+#define WCD938X_DIGITAL_TX_REQ_FB_CTL_0         (WCD938X_BASE_ADDRESS + 0x04D0)
+#define WCD938X_DIGITAL_TX_REQ_FB_CTL_1         (WCD938X_BASE_ADDRESS + 0x04D1)
+#define WCD938X_DIGITAL_TX_REQ_FB_CTL_2         (WCD938X_BASE_ADDRESS + 0x04D2)
+#define WCD938X_DIGITAL_TX_REQ_FB_CTL_3         (WCD938X_BASE_ADDRESS + 0x04D3)
+#define WCD938X_DIGITAL_TX_REQ_FB_CTL_4         (WCD938X_BASE_ADDRESS + 0x04D4)
+#define WCD938X_DIGITAL_DEM_BYPASS_DATA0        (WCD938X_BASE_ADDRESS + 0x04D5)
+#define WCD938X_DIGITAL_DEM_BYPASS_DATA1        (WCD938X_BASE_ADDRESS + 0x04D6)
+#define WCD938X_DIGITAL_DEM_BYPASS_DATA2        (WCD938X_BASE_ADDRESS + 0x04D7)
+#define WCD938X_DIGITAL_DEM_BYPASS_DATA3        (WCD938X_BASE_ADDRESS + 0x04D8)
+
+#define WCD938X_REGISTERS_MAX_SIZE (WCD938X_DIGITAL_DEM_BYPASS_DATA3 + 1)
+#define WCD938X_MAX_REGISTER (WCD938X_REGISTERS_MAX_SIZE - 1)
+
+#endif /*_WCD938X_REGISTERS_H*/

+ 513 - 0
asoc/codecs/wcd938x/wcd938x-regmap.c

@@ -0,0 +1,513 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wcd938x-registers.h"
+
+extern const u8 wcd938x_reg_access[WCD938X_REGISTERS_MAX_SIZE];
+
+static const struct reg_default wcd938x_defaults[] = {
+	{WCD938X_ANA_PAGE_REGISTER,                            0x00},
+	{WCD938X_ANA_BIAS,                                     0x00},
+	{WCD938X_ANA_RX_SUPPLIES,                              0x00},
+	{WCD938X_ANA_HPH,                                      0x0C},
+	{WCD938X_ANA_EAR,                                      0x00},
+	{WCD938X_ANA_EAR_COMPANDER_CTL,                        0x02},
+	{WCD938X_ANA_TX_CH1,                                   0x20},
+	{WCD938X_ANA_TX_CH2,                                   0x00},
+	{WCD938X_ANA_TX_CH3,                                   0x20},
+	{WCD938X_ANA_TX_CH4,                                   0x00},
+	{WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC,                 0x00},
+	{WCD938X_ANA_MICB3_DSP_EN_LOGIC,                       0x00},
+	{WCD938X_ANA_MBHC_MECH,                                0x39},
+	{WCD938X_ANA_MBHC_ELECT,                               0x08},
+	{WCD938X_ANA_MBHC_ZDET,                                0x00},
+	{WCD938X_ANA_MBHC_RESULT_1,                            0x00},
+	{WCD938X_ANA_MBHC_RESULT_2,                            0x00},
+	{WCD938X_ANA_MBHC_RESULT_3,                            0x00},
+	{WCD938X_ANA_MBHC_BTN0,                                0x00},
+	{WCD938X_ANA_MBHC_BTN1,                                0x10},
+	{WCD938X_ANA_MBHC_BTN2,                                0x20},
+	{WCD938X_ANA_MBHC_BTN3,                                0x30},
+	{WCD938X_ANA_MBHC_BTN4,                                0x40},
+	{WCD938X_ANA_MBHC_BTN5,                                0x50},
+	{WCD938X_ANA_MBHC_BTN6,                                0x60},
+	{WCD938X_ANA_MBHC_BTN7,                                0x70},
+	{WCD938X_ANA_MICB1,                                    0x10},
+	{WCD938X_ANA_MICB2,                                    0x10},
+	{WCD938X_ANA_MICB2_RAMP,                               0x00},
+	{WCD938X_ANA_MICB3,                                    0x10},
+	{WCD938X_ANA_MICB4,                                    0x10},
+	{WCD938X_BIAS_CTL,                                     0x2A},
+	{WCD938X_BIAS_VBG_FINE_ADJ,                            0x55},
+	{WCD938X_LDOL_VDDCX_ADJUST,                            0x01},
+	{WCD938X_LDOL_DISABLE_LDOL,                            0x00},
+	{WCD938X_MBHC_CTL_CLK,                                 0x00},
+	{WCD938X_MBHC_CTL_ANA,                                 0x00},
+	{WCD938X_MBHC_CTL_SPARE_1,                             0x00},
+	{WCD938X_MBHC_CTL_SPARE_2,                             0x00},
+	{WCD938X_MBHC_CTL_BCS,                                 0x00},
+	{WCD938X_MBHC_MOISTURE_DET_FSM_STATUS,                 0x00},
+	{WCD938X_MBHC_TEST_CTL,                                0x00},
+	{WCD938X_LDOH_MODE,                                    0x2B},
+	{WCD938X_LDOH_BIAS,                                    0x68},
+	{WCD938X_LDOH_STB_LOADS,                               0x00},
+	{WCD938X_LDOH_SLOWRAMP,                                0x50},
+	{WCD938X_MICB1_TEST_CTL_1,                             0x1A},
+	{WCD938X_MICB1_TEST_CTL_2,                             0x00},
+	{WCD938X_MICB1_TEST_CTL_3,                             0xA4},
+	{WCD938X_MICB2_TEST_CTL_1,                             0x1A},
+	{WCD938X_MICB2_TEST_CTL_2,                             0x00},
+	{WCD938X_MICB2_TEST_CTL_3,                             0x24},
+	{WCD938X_MICB3_TEST_CTL_1,                             0x1A},
+	{WCD938X_MICB3_TEST_CTL_2,                             0x00},
+	{WCD938X_MICB3_TEST_CTL_3,                             0xA4},
+	{WCD938X_MICB4_TEST_CTL_1,                             0x1A},
+	{WCD938X_MICB4_TEST_CTL_2,                             0x00},
+	{WCD938X_MICB4_TEST_CTL_3,                             0xA4},
+	{WCD938X_TX_COM_ADC_VCM,                               0x39},
+	{WCD938X_TX_COM_BIAS_ATEST,                            0xE0},
+	{WCD938X_TX_COM_SPARE1,                                0x00},
+	{WCD938X_TX_COM_SPARE2,                                0x00},
+	{WCD938X_TX_COM_TXFE_DIV_CTL,                          0x22},
+	{WCD938X_TX_COM_TXFE_DIV_START,                        0x00},
+	{WCD938X_TX_COM_SPARE3,                                0x00},
+	{WCD938X_TX_COM_SPARE4,                                0x00},
+	{WCD938X_TX_1_2_TEST_EN,                               0xCC},
+	{WCD938X_TX_1_2_ADC_IB,                                0xE9},
+	{WCD938X_TX_1_2_ATEST_REFCTL,                          0x0A},
+	{WCD938X_TX_1_2_TEST_CTL,                              0x38},
+	{WCD938X_TX_1_2_TEST_BLK_EN1,                          0xFF},
+	{WCD938X_TX_1_2_TXFE1_CLKDIV,                          0x00},
+	{WCD938X_TX_1_2_SAR2_ERR,                              0x00},
+	{WCD938X_TX_1_2_SAR1_ERR,                              0x00},
+	{WCD938X_TX_3_4_TEST_EN,                               0xCC},
+	{WCD938X_TX_3_4_ADC_IB,                                0xE9},
+	{WCD938X_TX_3_4_ATEST_REFCTL,                          0x0A},
+	{WCD938X_TX_3_4_TEST_CTL,                              0x38},
+	{WCD938X_TX_3_4_TEST_BLK_EN3,                          0xFF},
+	{WCD938X_TX_3_4_TXFE3_CLKDIV,                          0x00},
+	{WCD938X_TX_3_4_SAR4_ERR,                              0x00},
+	{WCD938X_TX_3_4_SAR3_ERR,                              0x00},
+	{WCD938X_TX_3_4_TEST_BLK_EN2,                          0xFB},
+	{WCD938X_TX_3_4_TXFE2_CLKDIV,                          0x00},
+	{WCD938X_TX_3_4_SPARE1,                                0x00},
+	{WCD938X_TX_3_4_TEST_BLK_EN4,                          0xFB},
+	{WCD938X_TX_3_4_TXFE4_CLKDIV,                          0x00},
+	{WCD938X_TX_3_4_SPARE2,                                0x00},
+	{WCD938X_CLASSH_MODE_1,                                0x40},
+	{WCD938X_CLASSH_MODE_2,                                0x3A},
+	{WCD938X_CLASSH_MODE_3,                                0x00},
+	{WCD938X_CLASSH_CTRL_VCL_1,                            0x70},
+	{WCD938X_CLASSH_CTRL_VCL_2,                            0x82},
+	{WCD938X_CLASSH_CTRL_CCL_1,                            0x31},
+	{WCD938X_CLASSH_CTRL_CCL_2,                            0x80},
+	{WCD938X_CLASSH_CTRL_CCL_3,                            0x80},
+	{WCD938X_CLASSH_CTRL_CCL_4,                            0x51},
+	{WCD938X_CLASSH_CTRL_CCL_5,                            0x00},
+	{WCD938X_CLASSH_BUCK_TMUX_A_D,                         0x00},
+	{WCD938X_CLASSH_BUCK_SW_DRV_CNTL,                      0x77},
+	{WCD938X_CLASSH_SPARE,                                 0x00},
+	{WCD938X_FLYBACK_EN,                                   0x4E},
+	{WCD938X_FLYBACK_VNEG_CTRL_1,                          0x0B},
+	{WCD938X_FLYBACK_VNEG_CTRL_2,                          0x45},
+	{WCD938X_FLYBACK_VNEG_CTRL_3,                          0x74},
+	{WCD938X_FLYBACK_VNEG_CTRL_4,                          0x7F},
+	{WCD938X_FLYBACK_VNEG_CTRL_5,                          0x83},
+	{WCD938X_FLYBACK_VNEG_CTRL_6,                          0x98},
+	{WCD938X_FLYBACK_VNEG_CTRL_7,                          0xA9},
+	{WCD938X_FLYBACK_VNEG_CTRL_8,                          0x68},
+	{WCD938X_FLYBACK_VNEG_CTRL_9,                          0x64},
+	{WCD938X_FLYBACK_VNEGDAC_CTRL_1,                       0xED},
+	{WCD938X_FLYBACK_VNEGDAC_CTRL_2,                       0xF0},
+	{WCD938X_FLYBACK_VNEGDAC_CTRL_3,                       0xA6},
+	{WCD938X_FLYBACK_CTRL_1,                               0x65},
+	{WCD938X_FLYBACK_TEST_CTL,                             0x00},
+	{WCD938X_RX_AUX_SW_CTL,                                0x00},
+	{WCD938X_RX_PA_AUX_IN_CONN,                            0x01},
+	{WCD938X_RX_TIMER_DIV,                                 0x32},
+	{WCD938X_RX_OCP_CTL,                                   0x1F},
+	{WCD938X_RX_OCP_COUNT,                                 0x77},
+	{WCD938X_RX_BIAS_EAR_DAC,                              0xA0},
+	{WCD938X_RX_BIAS_EAR_AMP,                              0xAA},
+	{WCD938X_RX_BIAS_HPH_LDO,                              0xA9},
+	{WCD938X_RX_BIAS_HPH_PA,                               0xAA},
+	{WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2,                    0x8A},
+	{WCD938X_RX_BIAS_HPH_RDAC_LDO,                         0x88},
+	{WCD938X_RX_BIAS_HPH_CNP1,                             0x82},
+	{WCD938X_RX_BIAS_HPH_LOWPOWER,                         0x82},
+	{WCD938X_RX_BIAS_AUX_DAC,                              0xA0},
+	{WCD938X_RX_BIAS_AUX_AMP,                              0xAA},
+	{WCD938X_RX_BIAS_VNEGDAC_BLEEDER,                      0x50},
+	{WCD938X_RX_BIAS_MISC,                                 0x00},
+	{WCD938X_RX_BIAS_BUCK_RST,                             0x08},
+	{WCD938X_RX_BIAS_BUCK_VREF_ERRAMP,                     0x44},
+	{WCD938X_RX_BIAS_FLYB_ERRAMP,                          0x40},
+	{WCD938X_RX_BIAS_FLYB_BUFF,                            0xAA},
+	{WCD938X_RX_BIAS_FLYB_MID_RST,                         0x14},
+	{WCD938X_HPH_L_STATUS,                                 0x04},
+	{WCD938X_HPH_R_STATUS,                                 0x04},
+	{WCD938X_HPH_CNP_EN,                                   0x80},
+	{WCD938X_HPH_CNP_WG_CTL,                               0x9A},
+	{WCD938X_HPH_CNP_WG_TIME,                              0x14},
+	{WCD938X_HPH_OCP_CTL,                                  0x28},
+	{WCD938X_HPH_AUTO_CHOP,                                0x16},
+	{WCD938X_HPH_CHOP_CTL,                                 0x83},
+	{WCD938X_HPH_PA_CTL1,                                  0x46},
+	{WCD938X_HPH_PA_CTL2,                                  0x50},
+	{WCD938X_HPH_L_EN,                                     0x80},
+	{WCD938X_HPH_L_TEST,                                   0xE0},
+	{WCD938X_HPH_L_ATEST,                                  0x50},
+	{WCD938X_HPH_R_EN,                                     0x80},
+	{WCD938X_HPH_R_TEST,                                   0xE0},
+	{WCD938X_HPH_R_ATEST,                                  0x54},
+	{WCD938X_HPH_RDAC_CLK_CTL1,                            0x99},
+	{WCD938X_HPH_RDAC_CLK_CTL2,                            0x9B},
+	{WCD938X_HPH_RDAC_LDO_CTL,                             0x33},
+	{WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL,                     0x00},
+	{WCD938X_HPH_REFBUFF_UHQA_CTL,                         0x68},
+	{WCD938X_HPH_REFBUFF_LP_CTL,                           0x0E},
+	{WCD938X_HPH_L_DAC_CTL,                                0x20},
+	{WCD938X_HPH_R_DAC_CTL,                                0x20},
+	{WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL,               0x55},
+	{WCD938X_HPH_SURGE_HPHLR_SURGE_EN,                     0x19},
+	{WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1,                  0xA0},
+	{WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS,                 0x00},
+	{WCD938X_EAR_EAR_EN_REG,                               0x22},
+	{WCD938X_EAR_EAR_PA_CON,                               0x44},
+	{WCD938X_EAR_EAR_SP_CON,                               0xDB},
+	{WCD938X_EAR_EAR_DAC_CON,                              0x80},
+	{WCD938X_EAR_EAR_CNP_FSM_CON,                          0xB2},
+	{WCD938X_EAR_TEST_CTL,                                 0x00},
+	{WCD938X_EAR_STATUS_REG_1,                             0x00},
+	{WCD938X_EAR_STATUS_REG_2,                             0x08},
+	{WCD938X_ANA_NEW_PAGE_REGISTER,                        0x00},
+	{WCD938X_HPH_NEW_ANA_HPH2,                             0x00},
+	{WCD938X_HPH_NEW_ANA_HPH3,                             0x00},
+	{WCD938X_SLEEP_CTL,                                    0x16},
+	{WCD938X_SLEEP_WATCHDOG_CTL,                           0x00},
+	{WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL,                 0x00},
+	{WCD938X_MBHC_NEW_CTL_1,                               0x02},
+	{WCD938X_MBHC_NEW_CTL_2,                               0x05},
+	{WCD938X_MBHC_NEW_PLUG_DETECT_CTL,                     0xE9},
+	{WCD938X_MBHC_NEW_ZDET_ANA_CTL,                        0x0F},
+	{WCD938X_MBHC_NEW_ZDET_RAMP_CTL,                       0x00},
+	{WCD938X_MBHC_NEW_FSM_STATUS,                          0x00},
+	{WCD938X_MBHC_NEW_ADC_RESULT,                          0x00},
+	{WCD938X_TX_NEW_AMIC_MUX_CFG,                          0x00},
+	{WCD938X_AUX_AUXPA,                                    0x00},
+	{WCD938X_LDORXTX_MODE,                                 0x0C},
+	{WCD938X_LDORXTX_CONFIG,                               0x10},
+	{WCD938X_DIE_CRACK_DIE_CRK_DET_EN,                     0x00},
+	{WCD938X_DIE_CRACK_DIE_CRK_DET_OUT,                    0x00},
+	{WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL,                    0x40},
+	{WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L,                   0x81},
+	{WCD938X_HPH_NEW_INT_RDAC_VREF_CTL,                    0x10},
+	{WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL,                0x00},
+	{WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,                   0x81},
+	{WCD938X_HPH_NEW_INT_PA_MISC1,                         0x22},
+	{WCD938X_HPH_NEW_INT_PA_MISC2,                         0x00},
+	{WCD938X_HPH_NEW_INT_PA_RDAC_MISC,                     0x00},
+	{WCD938X_HPH_NEW_INT_HPH_TIMER1,                       0xFE},
+	{WCD938X_HPH_NEW_INT_HPH_TIMER2,                       0x02},
+	{WCD938X_HPH_NEW_INT_HPH_TIMER3,                       0x4E},
+	{WCD938X_HPH_NEW_INT_HPH_TIMER4,                       0x54},
+	{WCD938X_HPH_NEW_INT_PA_RDAC_MISC2,                    0x00},
+	{WCD938X_HPH_NEW_INT_PA_RDAC_MISC3,                    0x00},
+	{WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW,               0x90},
+	{WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW,               0x90},
+	{WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI,              0x62},
+	{WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP,                 0x01},
+	{WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP,                   0x11},
+	{WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL,            0x57},
+	{WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,       0x01},
+	{WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,                0x00},
+	{WCD938X_MBHC_NEW_INT_SPARE_2,                         0x00},
+	{WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON,                  0xA8},
+	{WCD938X_EAR_INT_NEW_CNP_VCM_CON1,                     0x42},
+	{WCD938X_EAR_INT_NEW_CNP_VCM_CON2,                     0x22},
+	{WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS,                 0x00},
+	{WCD938X_AUX_INT_EN_REG,                               0x00},
+	{WCD938X_AUX_INT_PA_CTRL,                              0x06},
+	{WCD938X_AUX_INT_SP_CTRL,                              0xD2},
+	{WCD938X_AUX_INT_DAC_CTRL,                             0x80},
+	{WCD938X_AUX_INT_CLK_CTRL,                             0x50},
+	{WCD938X_AUX_INT_TEST_CTRL,                            0x00},
+	{WCD938X_AUX_INT_STATUS_REG,                           0x00},
+	{WCD938X_AUX_INT_MISC,                                 0x00},
+	{WCD938X_LDORXTX_INT_BIAS,                             0x6E},
+	{WCD938X_LDORXTX_INT_STB_LOADS_DTEST,                  0x50},
+	{WCD938X_LDORXTX_INT_TEST0,                            0x1C},
+	{WCD938X_LDORXTX_INT_STARTUP_TIMER,                    0xFF},
+	{WCD938X_LDORXTX_INT_TEST1,                            0x1F},
+	{WCD938X_LDORXTX_INT_STATUS,                           0x00},
+	{WCD938X_SLEEP_INT_WATCHDOG_CTL_1,                     0x0A},
+	{WCD938X_SLEEP_INT_WATCHDOG_CTL_2,                     0x0A},
+	{WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1,               0x02},
+	{WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2,               0x60},
+	{WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2,               0xFF},
+	{WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1,               0x7F},
+	{WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0,               0x3F},
+	{WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M,          0x1F},
+	{WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M,          0x0F},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1,          0xD7},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0,            0xC8},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP,           0xC6},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1,      0xD5},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0,        0xCA},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP,       0x05},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0,    0xA5},
+	{WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP,       0x13},
+	{WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1,             0x88},
+	{WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP,            0x42},
+	{WCD938X_TX_COM_NEW_INT_TXADC_INT_L2,                  0xFF},
+	{WCD938X_TX_COM_NEW_INT_TXADC_INT_L1,                  0x64},
+	{WCD938X_TX_COM_NEW_INT_TXADC_INT_L0,                  0x64},
+	{WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP,                 0x77},
+	{WCD938X_DIGITAL_PAGE_REGISTER,                        0x00},
+	{WCD938X_DIGITAL_CHIP_ID0,                             0x00},
+	{WCD938X_DIGITAL_CHIP_ID1,                             0x00},
+	{WCD938X_DIGITAL_CHIP_ID2,                             0x0D},
+	{WCD938X_DIGITAL_CHIP_ID3,                             0x01},
+	{WCD938X_DIGITAL_SWR_TX_CLK_RATE,                      0x00},
+	{WCD938X_DIGITAL_CDC_RST_CTL,                          0x03},
+	{WCD938X_DIGITAL_TOP_CLK_CFG,                          0x00},
+	{WCD938X_DIGITAL_CDC_ANA_CLK_CTL,                      0x00},
+	{WCD938X_DIGITAL_CDC_DIG_CLK_CTL,                      0xF0},
+	{WCD938X_DIGITAL_SWR_RST_EN,                           0x00},
+	{WCD938X_DIGITAL_CDC_PATH_MODE,                        0x55},
+	{WCD938X_DIGITAL_CDC_RX_RST,                           0x00},
+	{WCD938X_DIGITAL_CDC_RX0_CTL,                          0xFC},
+	{WCD938X_DIGITAL_CDC_RX1_CTL,                          0xFC},
+	{WCD938X_DIGITAL_CDC_RX2_CTL,                          0xFC},
+	{WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,                  0x00},
+	{WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,                  0x00},
+	{WCD938X_DIGITAL_CDC_COMP_CTL_0,                       0x00},
+	{WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL,                   0x1E},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A1_0,                     0x00},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A1_1,                     0x01},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A2_0,                     0x63},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A2_1,                     0x04},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A3_0,                     0xAC},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A3_1,                     0x04},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A4_0,                     0x1A},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A4_1,                     0x03},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A5_0,                     0xBC},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A5_1,                     0x02},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A6_0,                     0xC7},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_A7_0,                     0xF8},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_C_0,                      0x47},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_C_1,                      0x43},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_C_2,                      0xB1},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_C_3,                      0x17},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R1,                       0x4D},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R2,                       0x29},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R3,                       0x34},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R4,                       0x59},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R5,                       0x66},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R6,                       0x87},
+	{WCD938X_DIGITAL_CDC_HPH_DSM_R7,                       0x64},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A1_0,                     0x00},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A1_1,                     0x01},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A2_0,                     0x96},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A2_1,                     0x09},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A3_0,                     0xAB},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A3_1,                     0x05},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A4_0,                     0x1C},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A4_1,                     0x02},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A5_0,                     0x17},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A5_1,                     0x02},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A6_0,                     0xAA},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_A7_0,                     0xE3},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_C_0,                      0x69},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_C_1,                      0x54},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_C_2,                      0x02},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_C_3,                      0x15},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R1,                       0xA4},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R2,                       0xB5},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R3,                       0x86},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R4,                       0x85},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R5,                       0xAA},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R6,                       0xE2},
+	{WCD938X_DIGITAL_CDC_AUX_DSM_R7,                       0x62},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0,                    0x55},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1,                    0xA9},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0,                   0x3D},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1,                   0x2E},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2,                   0x01},
+	{WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0,                   0x00},
+	{WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1,                   0xFC},
+	{WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2,                   0x01},
+	{WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,                     0x00},
+	{WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,                     0x00},
+	{WCD938X_DIGITAL_CDC_EAR_PATH_CTL,                     0x00},
+	{WCD938X_DIGITAL_CDC_SWR_CLH,                          0x00},
+	{WCD938X_DIGITAL_SWR_CLH_BYP,                          0x00},
+	{WCD938X_DIGITAL_CDC_TX0_CTL,                          0x68},
+	{WCD938X_DIGITAL_CDC_TX1_CTL,                          0x68},
+	{WCD938X_DIGITAL_CDC_TX2_CTL,                          0x68},
+	{WCD938X_DIGITAL_CDC_TX_RST,                           0x00},
+	{WCD938X_DIGITAL_CDC_REQ_CTL,                          0x01},
+	{WCD938X_DIGITAL_CDC_RST,                              0x00},
+	{WCD938X_DIGITAL_CDC_AMIC_CTL,                         0x0F},
+	{WCD938X_DIGITAL_CDC_DMIC_CTL,                         0x04},
+	{WCD938X_DIGITAL_CDC_DMIC1_CTL,                        0x01},
+	{WCD938X_DIGITAL_CDC_DMIC2_CTL,                        0x01},
+	{WCD938X_DIGITAL_CDC_DMIC3_CTL,                        0x01},
+	{WCD938X_DIGITAL_CDC_DMIC4_CTL,                        0x01},
+	{WCD938X_DIGITAL_EFUSE_PRG_CTL,                        0x00},
+	{WCD938X_DIGITAL_EFUSE_CTL,                            0x2B},
+	{WCD938X_DIGITAL_CDC_DMIC_RATE_1_2,                    0x11},
+	{WCD938X_DIGITAL_CDC_DMIC_RATE_3_4,                    0x11},
+	{WCD938X_DIGITAL_PDM_WD_CTL0,                          0x00},
+	{WCD938X_DIGITAL_PDM_WD_CTL1,                          0x00},
+	{WCD938X_DIGITAL_PDM_WD_CTL2,                          0x00},
+	{WCD938X_DIGITAL_INTR_MODE,                            0x00},
+	{WCD938X_DIGITAL_INTR_MASK_0,                          0xFF},
+	{WCD938X_DIGITAL_INTR_MASK_1,                          0xFF},
+	{WCD938X_DIGITAL_INTR_MASK_2,                          0x3F},
+	{WCD938X_DIGITAL_INTR_STATUS_0,                        0x00},
+	{WCD938X_DIGITAL_INTR_STATUS_1,                        0x00},
+	{WCD938X_DIGITAL_INTR_STATUS_2,                        0x00},
+	{WCD938X_DIGITAL_INTR_CLEAR_0,                         0x00},
+	{WCD938X_DIGITAL_INTR_CLEAR_1,                         0x00},
+	{WCD938X_DIGITAL_INTR_CLEAR_2,                         0x00},
+	{WCD938X_DIGITAL_INTR_LEVEL_0,                         0x00},
+	{WCD938X_DIGITAL_INTR_LEVEL_1,                         0x00},
+	{WCD938X_DIGITAL_INTR_LEVEL_2,                         0x00},
+	{WCD938X_DIGITAL_INTR_SET_0,                           0x00},
+	{WCD938X_DIGITAL_INTR_SET_1,                           0x00},
+	{WCD938X_DIGITAL_INTR_SET_2,                           0x00},
+	{WCD938X_DIGITAL_INTR_TEST_0,                          0x00},
+	{WCD938X_DIGITAL_INTR_TEST_1,                          0x00},
+	{WCD938X_DIGITAL_INTR_TEST_2,                          0x00},
+	{WCD938X_DIGITAL_TX_MODE_DBG_EN,                       0x00},
+	{WCD938X_DIGITAL_TX_MODE_DBG_0_1,                      0x00},
+	{WCD938X_DIGITAL_TX_MODE_DBG_2_3,                      0x00},
+	{WCD938X_DIGITAL_LB_IN_SEL_CTL,                        0x00},
+	{WCD938X_DIGITAL_LOOP_BACK_MODE,                       0x00},
+	{WCD938X_DIGITAL_SWR_DAC_TEST,                         0x00},
+	{WCD938X_DIGITAL_SWR_HM_TEST_RX_0,                     0x40},
+	{WCD938X_DIGITAL_SWR_HM_TEST_TX_0,                     0x40},
+	{WCD938X_DIGITAL_SWR_HM_TEST_RX_1,                     0x00},
+	{WCD938X_DIGITAL_SWR_HM_TEST_TX_1,                     0x00},
+	{WCD938X_DIGITAL_SWR_HM_TEST_TX_2,                     0x00},
+	{WCD938X_DIGITAL_SWR_HM_TEST_0,                        0x00},
+	{WCD938X_DIGITAL_SWR_HM_TEST_1,                        0x00},
+	{WCD938X_DIGITAL_PAD_CTL_SWR_0,                        0x8F},
+	{WCD938X_DIGITAL_PAD_CTL_SWR_1,                        0x06},
+	{WCD938X_DIGITAL_I2C_CTL,                              0x00},
+	{WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE,                0x00},
+	{WCD938X_DIGITAL_EFUSE_TEST_CTL_0,                     0x00},
+	{WCD938X_DIGITAL_EFUSE_TEST_CTL_1,                     0x00},
+	{WCD938X_DIGITAL_EFUSE_T_DATA_0,                       0x00},
+	{WCD938X_DIGITAL_EFUSE_T_DATA_1,                       0x00},
+	{WCD938X_DIGITAL_PAD_CTL_PDM_RX0,                      0xF1},
+	{WCD938X_DIGITAL_PAD_CTL_PDM_RX1,                      0xF1},
+	{WCD938X_DIGITAL_PAD_CTL_PDM_TX0,                      0xF1},
+	{WCD938X_DIGITAL_PAD_CTL_PDM_TX1,                      0xF1},
+	{WCD938X_DIGITAL_PAD_CTL_PDM_TX2,                      0xF1},
+	{WCD938X_DIGITAL_PAD_INP_DIS_0,                        0x00},
+	{WCD938X_DIGITAL_PAD_INP_DIS_1,                        0x00},
+	{WCD938X_DIGITAL_DRIVE_STRENGTH_0,                     0x00},
+	{WCD938X_DIGITAL_DRIVE_STRENGTH_1,                     0x00},
+	{WCD938X_DIGITAL_DRIVE_STRENGTH_2,                     0x00},
+	{WCD938X_DIGITAL_RX_DATA_EDGE_CTL,                     0x1F},
+	{WCD938X_DIGITAL_TX_DATA_EDGE_CTL,                     0x80},
+	{WCD938X_DIGITAL_GPIO_MODE,                            0x00},
+	{WCD938X_DIGITAL_PIN_CTL_OE,                           0x00},
+	{WCD938X_DIGITAL_PIN_CTL_DATA_0,                       0x00},
+	{WCD938X_DIGITAL_PIN_CTL_DATA_1,                       0x00},
+	{WCD938X_DIGITAL_PIN_STATUS_0,                         0x00},
+	{WCD938X_DIGITAL_PIN_STATUS_1,                         0x00},
+	{WCD938X_DIGITAL_DIG_DEBUG_CTL,                        0x00},
+	{WCD938X_DIGITAL_DIG_DEBUG_EN,                         0x00},
+	{WCD938X_DIGITAL_ANA_CSR_DBG_ADD,                      0x00},
+	{WCD938X_DIGITAL_ANA_CSR_DBG_CTL,                      0x48},
+	{WCD938X_DIGITAL_SSP_DBG,                              0x00},
+	{WCD938X_DIGITAL_MODE_STATUS_0,                        0x00},
+	{WCD938X_DIGITAL_MODE_STATUS_1,                        0x00},
+	{WCD938X_DIGITAL_SPARE_0,                              0x00},
+	{WCD938X_DIGITAL_SPARE_1,                              0x00},
+	{WCD938X_DIGITAL_SPARE_2,                              0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_0,                          0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_1,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_2,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_3,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_4,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_5,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_6,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_7,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_8,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_9,                          0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_10,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_11,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_12,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_13,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_14,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_15,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_16,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_17,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_18,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_19,                         0xFF},
+	{WCD938X_DIGITAL_EFUSE_REG_20,                         0x0E},
+	{WCD938X_DIGITAL_EFUSE_REG_21,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_22,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_23,                         0xF8},
+	{WCD938X_DIGITAL_EFUSE_REG_24,                         0x16},
+	{WCD938X_DIGITAL_EFUSE_REG_25,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_26,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_27,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_28,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_29,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_30,                         0x00},
+	{WCD938X_DIGITAL_EFUSE_REG_31,                         0x00},
+	{WCD938X_DIGITAL_TX_REQ_FB_CTL_0,                      0x88},
+	{WCD938X_DIGITAL_TX_REQ_FB_CTL_1,                      0x88},
+	{WCD938X_DIGITAL_TX_REQ_FB_CTL_2,                      0x88},
+	{WCD938X_DIGITAL_TX_REQ_FB_CTL_3,                      0x88},
+	{WCD938X_DIGITAL_TX_REQ_FB_CTL_4,                      0x88},
+	{WCD938X_DIGITAL_DEM_BYPASS_DATA0,                     0x55},
+	{WCD938X_DIGITAL_DEM_BYPASS_DATA1,                     0x55},
+	{WCD938X_DIGITAL_DEM_BYPASS_DATA2,                     0x55},
+	{WCD938X_DIGITAL_DEM_BYPASS_DATA3,                     0x01},
+};
+
+static bool wcd938x_readable_register(struct device *dev, unsigned int reg)
+{
+	if(reg <= WCD938X_BASE_ADDRESS)
+		return 0;
+	return wcd938x_reg_access[WCD938X_REG(reg)] & RD_REG;
+}
+
+static bool wcd938x_writeable_register(struct device *dev, unsigned int reg)
+{
+	if(reg <= WCD938X_BASE_ADDRESS)
+		return 0;
+	return wcd938x_reg_access[WCD938X_REG(reg)] & WR_REG;
+}
+
+static bool wcd938x_volatile_register(struct device *dev, unsigned int reg)
+{
+	if(reg <= WCD938X_BASE_ADDRESS)
+		return 0;
+	return (wcd938x_reg_access[WCD938X_REG(reg)] & RD_REG)
+		& ~(wcd938x_reg_access[WCD938X_REG(reg)] & WR_REG);
+}
+
+struct regmap_config wcd938x_regmap_config = {
+	.name = "wcd938x_csr",
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wcd938x_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wcd938x_defaults),
+	.max_register = WCD938X_MAX_REGISTER,
+	.readable_reg = wcd938x_readable_register,
+	.writeable_reg = wcd938x_writeable_register,
+	.volatile_reg = wcd938x_volatile_register,
+	.can_multi_write = true,
+};

+ 117 - 0
asoc/codecs/wcd938x/wcd938x-slave.c

@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018, 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>
+
+struct wcd938x_slave_priv {
+	struct swr_device *swr_slave;
+};
+
+static int wcd938x_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);
+
+	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);
+		return ret;
+	}
+	pdev->dev_num = devnum;
+
+	return ret;
+}
+
+static void wcd938x_slave_unbind(struct device *dev,
+				struct device *master, void *data)
+{
+	struct wcd938x_slave_priv *wcd938x_slave = NULL;
+	struct swr_device *pdev = to_swr_device(dev);
+
+	wcd938x_slave = swr_get_dev_data(pdev);
+	if (!wcd938x_slave) {
+		dev_err(&pdev->dev, "%s: wcd938x_slave is NULL\n", __func__);
+		return;
+	}
+}
+
+static const struct swr_device_id wcd938x_swr_id[] = {
+	{"wcd938x-slave", 0},
+	{}
+};
+
+static const struct of_device_id wcd938x_swr_dt_match[] = {
+	{
+		.compatible = "qcom,wcd938x-slave",
+	},
+	{}
+};
+
+static const struct component_ops wcd938x_slave_comp_ops = {
+	.bind   = wcd938x_slave_bind,
+	.unbind = wcd938x_slave_unbind,
+};
+
+static int wcd938x_swr_probe(struct swr_device *pdev)
+{
+	struct wcd938x_slave_priv *wcd938x_slave = NULL;
+
+	wcd938x_slave = devm_kzalloc(&pdev->dev,
+				sizeof(struct wcd938x_slave_priv), GFP_KERNEL);
+	if (!wcd938x_slave)
+		return -ENOMEM;
+
+	swr_set_dev_data(pdev, wcd938x_slave);
+
+	wcd938x_slave->swr_slave = pdev;
+
+	return component_add(&pdev->dev, &wcd938x_slave_comp_ops);
+}
+
+static int wcd938x_swr_remove(struct swr_device *pdev)
+{
+	component_del(&pdev->dev, &wcd938x_slave_comp_ops);
+	swr_set_dev_data(pdev, NULL);
+	swr_remove_device(pdev);
+
+	return 0;
+}
+
+static struct swr_driver wcd938x_slave_driver = {
+	.driver = {
+		.name = "wcd938x-slave",
+		.owner = THIS_MODULE,
+		.of_match_table = wcd938x_swr_dt_match,
+	},
+	.probe = wcd938x_swr_probe,
+	.remove = wcd938x_swr_remove,
+	.id_table = wcd938x_swr_id,
+};
+
+static int __init wcd938x_slave_init(void)
+{
+	return swr_driver_register(&wcd938x_slave_driver);
+}
+
+static void __exit wcd938x_slave_exit(void)
+{
+	swr_driver_unregister(&wcd938x_slave_driver);
+}
+
+module_init(wcd938x_slave_init);
+module_exit(wcd938x_slave_exit);
+
+MODULE_DESCRIPTION("WCD938X Swr Slave driver");
+MODULE_LICENSE("GPL v2");

+ 474 - 0
asoc/codecs/wcd938x/wcd938x-tables.c

@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018 , The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include "wcd938x-registers.h"
+
+const u8 wcd938x_reg_access[WCD938X_REG(WCD938X_REGISTERS_MAX_SIZE)] = {
+	[WCD938X_REG(WCD938X_ANA_PAGE_REGISTER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_BIAS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_RX_SUPPLIES)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_HPH)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_EAR)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_EAR_COMPANDER_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_TX_CH1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_TX_CH2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_TX_CH3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_TX_CH4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB3_DSP_EN_LOGIC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_MECH)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_ELECT)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_ZDET)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_RESULT_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_RESULT_2)] = RD_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_RESULT_3)] = RD_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN5)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN6)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MBHC_BTN7)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB2_RAMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_ANA_MICB4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_BIAS_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_BIAS_VBG_FINE_ADJ)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOL_VDDCX_ADJUST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOL_DISABLE_LDOL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_CTL_CLK)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_CTL_ANA)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_CTL_SPARE_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_CTL_SPARE_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_CTL_BCS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_MOISTURE_DET_FSM_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_MBHC_TEST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOH_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOH_BIAS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOH_STB_LOADS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDOH_SLOWRAMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB1_TEST_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB1_TEST_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB1_TEST_CTL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB2_TEST_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB2_TEST_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB2_TEST_CTL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB3_TEST_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB3_TEST_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB3_TEST_CTL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB4_TEST_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB4_TEST_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MICB4_TEST_CTL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_ADC_VCM)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_BIAS_ATEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_SPARE1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_SPARE2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_TXFE_DIV_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_TXFE_DIV_START)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_SPARE3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_SPARE4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_TEST_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_ADC_IB)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_ATEST_REFCTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_TEST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_TEST_BLK_EN1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_TXFE1_CLKDIV)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_SAR2_ERR)] = RD_REG,
+	[WCD938X_REG(WCD938X_TX_1_2_SAR1_ERR)] = RD_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TEST_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_ADC_IB)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_ATEST_REFCTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TEST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TEST_BLK_EN3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TXFE3_CLKDIV)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_SAR4_ERR)] = RD_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_SAR3_ERR)] = RD_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TEST_BLK_EN2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TXFE2_CLKDIV)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_SPARE1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TEST_BLK_EN4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_TXFE4_CLKDIV)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_3_4_SPARE2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_MODE_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_MODE_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_MODE_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_VCL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_VCL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_CCL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_CCL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_CCL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_CCL_4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_CTRL_CCL_5)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_BUCK_TMUX_A_D)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_BUCK_SW_DRV_CNTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_CLASSH_SPARE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_5)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_6)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_7)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_8)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEG_CTRL_9)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEGDAC_CTRL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEGDAC_CTRL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_VNEGDAC_CTRL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_CTRL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_FLYBACK_TEST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_AUX_SW_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_PA_AUX_IN_CONN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_TIMER_DIV)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_OCP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_OCP_COUNT)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_EAR_DAC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_EAR_AMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_LDO)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_PA)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_RDAC_LDO)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_CNP1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_HPH_LOWPOWER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_AUX_DAC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_AUX_AMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_VNEGDAC_BLEEDER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_MISC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_BUCK_RST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_BUCK_VREF_ERRAMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_FLYB_ERRAMP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_FLYB_BUFF)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_BIAS_FLYB_MID_RST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_L_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_HPH_R_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_HPH_CNP_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_CNP_WG_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_CNP_WG_TIME)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_OCP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_AUTO_CHOP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_CHOP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_PA_CTL1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_PA_CTL2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_L_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_L_TEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_L_ATEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_R_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_R_TEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_R_ATEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_RDAC_CLK_CTL1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_RDAC_CLK_CTL2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_RDAC_LDO_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_REFBUFF_UHQA_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_REFBUFF_LP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_L_DAC_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_R_DAC_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_SURGE_HPHLR_SURGE_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_EAR_EAR_EN_REG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_EAR_PA_CON)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_EAR_SP_CON)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_EAR_DAC_CON)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_EAR_CNP_FSM_CON)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_TEST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_STATUS_REG_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_EAR_STATUS_REG_2)] = RD_REG,
+	[WCD938X_REG(WCD938X_ANA_NEW_PAGE_REGISTER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_ANA_HPH2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_ANA_HPH3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_SLEEP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_SLEEP_WATCHDOG_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_PLUG_DETECT_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_ZDET_ANA_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_ZDET_RAMP_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_FSM_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_ADC_RESULT)] = RD_REG,
+	[WCD938X_REG(WCD938X_TX_NEW_AMIC_MUX_CFG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_AUXPA)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_CONFIG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIE_CRACK_DIE_CRK_DET_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIE_CRACK_DIE_CRK_DET_OUT)] = RD_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_VREF_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_PA_MISC1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_PA_MISC2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_PA_RDAC_MISC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_HPH_TIMER1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_HPH_TIMER2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_HPH_TIMER3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_HPH_TIMER4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_PA_RDAC_MISC2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_PA_RDAC_MISC3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_MBHC_NEW_INT_SPARE_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_INT_NEW_CNP_VCM_CON1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_INT_NEW_CNP_VCM_CON2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_EN_REG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_PA_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_SP_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_DAC_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_CLK_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_TEST_CTRL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_STATUS_REG)] = RD_REG,
+	[WCD938X_REG(WCD938X_AUX_INT_MISC)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_BIAS)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_STB_LOADS_DTEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_TEST0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_STARTUP_TIMER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_TEST1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_LDORXTX_INT_STATUS)] = RD_REG,
+	[WCD938X_REG(WCD938X_SLEEP_INT_WATCHDOG_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_SLEEP_INT_WATCHDOG_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0)]=RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_INT_L2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_INT_L1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_INT_L0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAGE_REGISTER)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CHIP_ID0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CHIP_ID1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CHIP_ID2)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CHIP_ID3)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_TX_CLK_RATE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RST_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TOP_CLK_CFG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_ANA_CLK_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DIG_CLK_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_RST_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_PATH_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RX_RST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RX0_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RX1_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RX2_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_COMP_CTL_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A1_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A1_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A2_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A2_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A3_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A3_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A4_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A4_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A5_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A5_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A6_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_A7_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_C_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_C_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_C_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_C_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R5)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R6)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_DSM_R7)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A1_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A1_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A2_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A2_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A3_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A3_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A4_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A4_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A5_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A5_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A6_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_A7_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_C_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_C_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_C_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_C_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R5)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R6)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_DSM_R7)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_HPH_GAIN_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AUX_GAIN_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_EAR_PATH_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_SWR_CLH)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_CLH_BYP)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX0_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX1_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX2_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX_RST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_REQ_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_RST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_AMIC_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC1_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC2_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC3_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC4_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_PRG_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC_RATE_1_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_DMIC_RATE_3_4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PDM_WD_CTL0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PDM_WD_CTL1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PDM_WD_CTL2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_MASK_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_MASK_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_MASK_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_STATUS_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_STATUS_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_STATUS_2)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_CLEAR_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_CLEAR_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_CLEAR_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_LEVEL_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_LEVEL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_LEVEL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_SET_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_SET_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_SET_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_TEST_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_TEST_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_INTR_TEST_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_MODE_DBG_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_MODE_DBG_0_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_MODE_DBG_2_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_LB_IN_SEL_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_LOOP_BACK_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_DAC_TEST)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_RX_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_TX_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_RX_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_TX_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_TX_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SWR_HM_TEST_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_SWR_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_SWR_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_I2C_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_TEST_CTL_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_TEST_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_T_DATA_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_T_DATA_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_PDM_RX0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_PDM_RX1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_PDM_TX0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_PDM_TX1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_CTL_PDM_TX2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_INP_DIS_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PAD_INP_DIS_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DRIVE_STRENGTH_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DRIVE_STRENGTH_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DRIVE_STRENGTH_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_RX_DATA_EDGE_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_DATA_EDGE_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_GPIO_MODE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PIN_CTL_OE)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PIN_CTL_DATA_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PIN_CTL_DATA_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PIN_STATUS_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_PIN_STATUS_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DIG_DEBUG_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DIG_DEBUG_EN)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_ANA_CSR_DBG_ADD)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_ANA_CSR_DBG_CTL)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SSP_DBG)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_MODE_STATUS_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_MODE_STATUS_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SPARE_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SPARE_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_SPARE_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_0)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_1)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_2)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_3)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_4)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_5)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_6)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_7)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_8)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_9)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_10)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_11)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_12)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_13)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_14)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_15)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_16)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_17)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_18)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_19)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_20)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_21)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_22)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_23)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_24)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_25)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_26)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_27)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_28)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_29)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_30)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_EFUSE_REG_31)] = RD_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_REQ_FB_CTL_0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_REQ_FB_CTL_1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_REQ_FB_CTL_2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_REQ_FB_CTL_3)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_TX_REQ_FB_CTL_4)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DEM_BYPASS_DATA0)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DEM_BYPASS_DATA1)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DEM_BYPASS_DATA2)] = RD_WR_REG,
+	[WCD938X_REG(WCD938X_DIGITAL_DEM_BYPASS_DATA3)] = RD_WR_REG,
+};

+ 2704 - 0
asoc/codecs/wcd938x/wcd938x.c

@@ -0,0 +1,2704 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018, 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 <sound/soc.h>
+#include <sound/tlv.h>
+#include <soc/soundwire.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asoc/wcdcal-hwdep.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <asoc/msm-cdc-supply.h>
+#include <dt-bindings/sound/audio-codec-port-types.h>
+
+#include "internal.h"
+#include "wcd938x-registers.h"
+
+#define WCD938X_DRV_NAME "wcd938x_codec"
+#define NUM_SWRS_DT_PARAMS 5
+
+#define WCD938X_VERSION_1_0 1
+#define WCD938X_VERSION_ENTRY_SIZE 32
+
+enum {
+	WCD9380 = 0,
+	WCD9385,
+	WCD9385FX,
+};
+
+enum {
+	CODEC_TX = 0,
+	CODEC_RX,
+};
+
+enum {
+	ALLOW_BUCK_DISABLE,
+	HPH_COMP_DELAY,
+	HPH_PA_DELAY,
+};
+
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+
+static int wcd938x_handle_post_irq(void *data);
+static int wcd938x_reset(struct device *dev);
+static int wcd938x_reset_low(struct device *dev);
+
+static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = {
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02),
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04),
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08),
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_SW_DET, 0, 0x10),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_OCP_INT, 0, 0x20),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_CNP_INT, 0, 0x40),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_OCP_INT, 0, 0x80),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_CNP_INT, 1, 0x01),
+	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_CNP_INT, 1, 0x02),
+	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_SCD_INT, 1, 0x04),
+	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_CNP_INT, 1, 0x08),
+	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_SCD_INT, 1, 0x10),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_PDM_WD_INT, 1, 0x20),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_PDM_WD_INT, 1, 0x40),
+	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_PDM_WD_INT, 1, 0x80),
+	REGMAP_IRQ_REG(WCD938X_IRQ_LDORT_SCD_INT, 2, 0x01),
+	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_MOISTURE_INT, 2, 0x02),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_SURGE_DET_INT, 2, 0x04),
+	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08),
+};
+
+static struct regmap_irq_chip wcd938x_regmap_irq_chip = {
+	.name = "wcd938x",
+	.irqs = wcd938x_irqs,
+	.num_irqs = ARRAY_SIZE(wcd938x_irqs),
+	.num_regs = 3,
+	.status_base = WCD938X_DIGITAL_INTR_STATUS_0,
+	.mask_base = WCD938X_DIGITAL_INTR_MASK_0,
+	.type_base = WCD938X_DIGITAL_INTR_LEVEL_0,
+	.ack_base = WCD938X_DIGITAL_INTR_CLEAR_0,
+	.use_ack = 1,
+	.clear_ack = 1,
+	.runtime_pm = true,
+	.handle_post_irq = wcd938x_handle_post_irq,
+	.irq_drv_data = NULL,
+};
+
+static int wcd938x_handle_post_irq(void *data)
+{
+	struct wcd938x_priv *wcd938x = data;
+	u32 sts1 = 0, sts2 = 0, sts3 = 0;
+
+	regmap_read(wcd938x->regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1);
+	regmap_read(wcd938x->regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2);
+	regmap_read(wcd938x->regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3);
+
+	wcd938x->tx_swr_dev->slave_irq_pending =
+			((sts1 || sts2 || sts3) ? true : false);
+
+	return IRQ_HANDLED;
+}
+
+static int wcd938x_init_reg(struct snd_soc_component *component)
+{
+	snd_soc_component_update_bits(component, WCD938X_SLEEP_CTL, 0x0E, 0x0E);
+	snd_soc_component_update_bits(component, WCD938X_SLEEP_CTL, 0x80, 0x80);
+	/* 1 msec delay as per HW requirement */
+	usleep_range(1000, 1010);
+	snd_soc_component_update_bits(component, WCD938X_SLEEP_CTL, 0x40, 0x40);
+	/* 1 msec delay as per HW requirement */
+	usleep_range(1000, 1010);
+	snd_soc_component_update_bits(component, WCD938X_LDORXTX_CONFIG,
+								0x10, 0x00);
+	snd_soc_component_update_bits(component, WCD938X_BIAS_VBG_FINE_ADJ,
+								0xF0, 0x80);
+	snd_soc_component_update_bits(component, WCD938X_ANA_BIAS, 0x80, 0x80);
+	snd_soc_component_update_bits(component, WCD938X_ANA_BIAS, 0x40, 0x40);
+	/* 10 msec delay as per HW requirement */
+	usleep_range(10000, 10010);
+	snd_soc_component_update_bits(component, WCD938X_ANA_BIAS, 0x40, 0x00);
+	snd_soc_component_update_bits(component, WCD938X_HPH_OCP_CTL,
+								0xFF, 0x3A);
+	snd_soc_component_update_bits(component, WCD938X_RX_OCP_CTL,
+								0x0F, 0x02);
+	snd_soc_component_update_bits(component, WCD938X_HPH_R_TEST,
+								0x01, 0x01);
+	snd_soc_component_update_bits(component, WCD938X_HPH_L_TEST,
+								0x01, 0x01);
+
+	return 0;
+}
+
+static int wcd938x_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;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	switch (path) {
+	case CODEC_RX:
+		map = &wcd938x->rx_port_mapping;
+		num_ports = wcd938x->num_rx_ports;
+		break;
+	case CODEC_TX:
+		map = &wcd938x->tx_port_mapping;
+		num_ports = wcd938x->num_tx_ports;
+		break;
+	}
+
+	for (i = 0; i <= num_ports; i++) {
+		for (j = 0; j < MAX_CH_PER_PORT; j++) {
+			if ((*map)[i][j].port_type == slv_prt_type)
+				goto found;
+		}
+	}
+found:
+	if (i > num_ports || j == MAX_CH_PER_PORT) {
+		dev_err(component->dev, "%s Failed to find slave port for type %u\n",
+						__func__, slv_prt_type);
+		return -EINVAL;
+	}
+	*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 wcd938x_parse_port_mapping(struct device *dev,
+			char *prop, u8 path)
+{
+	u32 *dt_array, map_size, map_length;
+	u32 port_num, 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;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
+
+	switch (path) {
+	case CODEC_RX:
+		map = &wcd938x->rx_port_mapping;
+		num_ports = &wcd938x->num_rx_ports;
+		break;
+	case CODEC_TX:
+		map = &wcd938x->tx_port_mapping;
+		num_ports = &wcd938x->num_tx_ports;
+		break;
+	}
+
+	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;
+	}
+
+	map_length = map_size / (NUM_SWRS_DT_PARAMS * sizeof(u32));
+
+	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,
+				NUM_SWRS_DT_PARAMS * map_length);
+	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 < 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].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;
+	kfree(dt_array);
+	return 0;
+
+err_pdata_fail:
+	kfree(dt_array);
+err_alloc:
+err_port_map:
+	return ret;
+}
+
+static int wcd938x_tx_connect_port(struct snd_soc_component *component,
+					u8 slv_port_type, u8 enable)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	u8 port_id, num_ch, ch_mask, port_type;
+	u32 ch_rate;
+	u8 num_port = 1;
+	int ret = 0;
+
+	ret = wcd938x_set_port_params(component, slv_port_type, &port_id,
+				&num_ch, &ch_mask, &ch_rate,
+				&port_type, CODEC_TX);
+
+	if (ret)
+		return ret;
+
+	if (enable)
+		ret = swr_connect_port(wcd938x->tx_swr_dev, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					 &num_ch, &port_type);
+	else
+		ret = swr_disconnect_port(wcd938x->tx_swr_dev, &port_id,
+					num_port, &ch_mask, &port_type);
+	return ret;
+
+}
+static int wcd938x_rx_connect_port(struct snd_soc_component *component,
+					u8 slv_port_type, u8 enable)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	u8 port_id, num_ch, ch_mask, port_type;
+	u32 ch_rate;
+	u8 num_port = 1;
+	int ret = 0;
+
+	ret = wcd938x_set_port_params(component, slv_port_type, &port_id,
+				&num_ch, &ch_mask, &ch_rate,
+				&port_type, CODEC_RX);
+
+	if (ret)
+		return ret;
+
+	if (enable)
+		ret = swr_connect_port(wcd938x->rx_swr_dev, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					&num_ch, &port_type);
+	else
+		ret = swr_disconnect_port(wcd938x->rx_swr_dev, &port_id,
+					num_port, &ch_mask, &port_type);
+	return ret;
+}
+
+static int wcd938x_rx_clk_enable(struct snd_soc_component *component)
+{
+
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (wcd938x->rx_clk_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_RX_SUPPLIES, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_RX0_CTL, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_RX1_CTL, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_RX2_CTL, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x02);
+	}
+	wcd938x->rx_clk_cnt++;
+
+	return 0;
+}
+
+static int wcd938x_rx_clk_disable(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	wcd938x->rx_clk_cnt--;
+	if (wcd938x->rx_clk_cnt == 0) {
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_RX_SUPPLIES, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_RX_SUPPLIES, 0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_RX_SUPPLIES, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x00);
+	}
+	return 0;
+}
+
+/*
+ * wcd938x_soc_get_mbhc: get wcd938x_mbhc handle of corresponding component
+ * @component: handle to snd_soc_component *
+ *
+ * return wcd938x_mbhc handle or error code in case of failure
+ */
+struct wcd938x_mbhc *wcd938x_soc_get_mbhc(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x;
+
+	if (!component) {
+		pr_err("%s: Invalid params, NULL component\n", __func__);
+		return NULL;
+	}
+	wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd938x) {
+		pr_err("%s: wcd938x is NULL\n", __func__);
+		return NULL;
+	}
+
+	return wcd938x->mbhc;
+}
+EXPORT_SYMBOL(wcd938x_soc_get_mbhc);
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_RDAC_CLK_CTL1, 0x80, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x0F, 0x02);
+		if (wcd938x->comp1_enable) {
+			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
+			/* 5msec compander delay as per HW requirement */
+			if (!wcd938x->comp2_enable ||
+				(snd_soc_component_read(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x01))
+			usleep_range(5000, 5010);
+			snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00);
+		} else {
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0,
+					0x02, 0x00);
+			snd_soc_component_update_bits(component,
+					WCD938X_HPH_L_EN, 0x20, 0x20);
+
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,
+			0x0F, 0x01);
+		break;
+	}
+
+	return 0;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_RDAC_CLK_CTL1, 0x80, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x0F, 0x02);
+		if (wcd938x->comp2_enable) {
+			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x01, 0x01);
+			/* 5msec compander delay as per HW requirement */
+			if (!wcd938x->comp1_enable ||
+				(snd_soc_component_read(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x02))
+				usleep_range(5000, 5010);
+			snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00);
+		} else {
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0,
+					0x01, 0x00);
+			snd_soc_component_update_bits(component,
+					WCD938X_HPH_R_EN, 0x20, 0x20);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,
+			0x0F, 0x01);
+		break;
+	}
+
+	return 0;
+}
+
+static int wcd938x_codec_ear_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
+		/* 5 msec delay as per HW requirement */
+		usleep_range(5000, 5010);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_PRE_DAC,
+			     WCD_CLSH_STATE_EAR,
+			     wcd938x->hph_mode);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		break;
+	};
+	return 0;
+
+}
+
+static int wcd938x_codec_aux_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_clk_enable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 0x01, 0x01);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_PRE_DAC,
+			     WCD_CLSH_STATE_AUX,
+			     wcd938x->hph_mode);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_rx_clk_disable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x04, 0x00);
+		break;
+	};
+	return ret;
+
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+	int hph_mode = wcd938x->hph_mode;
+
+	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(wcd938x->rx_swr_dev,
+				    wcd938x->rx_swr_dev->dev_num,
+				    true);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_PRE_DAC,
+			     WCD_CLSH_STATE_HPHR,
+			     hph_mode);
+		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
+					      0x10, 0x10);
+		/* 100 usec delay as per HW requirement */
+		usleep_range(100, 110);
+		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/*
+		 * 7ms sleep is required if compander is enabled as per
+		 * HW requirement. If compander is disabled, then
+		 * 20ms delay is required.
+		 */
+		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
+			if (!wcd938x->comp2_enable)
+				usleep_range(20000, 20100);
+			else
+				usleep_range(7000, 7100);
+			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		}
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02);
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+			snd_soc_component_update_bits(component,
+					WCD938X_ANA_RX_SUPPLIES, 0x02, 0x02);
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10 | 0x1));
+		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+					     WCD_EVENT_PRE_HPHR_PA_OFF,
+					     &wcd938x->mbhc->wcd_mbhc);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 7 msec delay as per HW requirement */
+		usleep_range(7000, 7010);
+		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+					     WCD_EVENT_POST_HPHR_PA_OFF,
+					     &wcd938x->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
+						0x10, 0x00);
+		wcd_cls_h_fsm(component, &wcd93x->clsh_info,
+			     WCD_CLSH_EVENT_POST_PA,
+			     WCD_CLSH_STATE_HPHR,
+			     hph_mode);
+		break;
+	};
+	return ret;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+	int hph_mode = wcd938x->hph_mode;
+
+	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(wcd938x->rx_swr_dev,
+				    wcd938x->rx_swr_dev->dev_num,
+				    true);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_PRE_DAC,
+			     WCD_CLSH_STATE_HPHL,
+			     hph_mode);
+		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
+						0x20, 0x20);
+		/* 100 usec delay as per HW requirement */
+		usleep_range(100, 110);
+		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/*
+		 * 7ms sleep is required if compander is enabled as per
+		 * HW requirement. If compander is disabled, then
+		 * 20ms delay is required.
+		 */
+		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
+			if (!wcd938x->comp1_enable)
+				usleep_range(20000, 20100);
+			else
+				usleep_range(7000, 7100);
+			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		}
+		snd_soc_component_update_bits(component,
+				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02);
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+			snd_soc_component_update_bits(component,
+					WCD938X_ANA_RX_SUPPLIES, 0x02, 0x02);
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
+		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+					     WCD_EVENT_PRE_HPHL_PA_OFF,
+					     &wcd938x->mbhc->wcd_mbhc);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 7 msec delay as per HW requirement */
+		usleep_range(7000, 7010);
+		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+					     WCD_EVENT_POST_HPHL_PA_OFF,
+					     &wcd938x->mbhc->wcd_mbhc);
+		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
+						0x20, 0x00);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_POST_PA,
+			     WCD_CLSH_STATE_HPHL,
+			     hph_mode);
+		break;
+	};
+	return ret;
+}
+
+static int wcd938x_codec_enable_aux_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int hph_mode = wcd938x->hph_mode;
+	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(wcd938x->rx_swr_dev,
+			    wcd938x->rx_swr_dev->dev_num,
+			    true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* 1 msec delay as per HW requirement */
+		usleep_range(1000, 1010);
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+			snd_soc_component_update_bits(component,
+					WCD938X_ANA_RX_SUPPLIES,
+					0x20, 0x20);
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX3 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX3 << 0x10 | 0x1));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 1 msec delay as per HW requirement */
+		usleep_range(1000, 1010);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_POST_PA,
+			     WCD_CLSH_STATE_AUX,
+			     hph_mode);
+		break;
+	};
+	return ret;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int hph_mode = wcd938x->hph_mode;
+	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(wcd938x->rx_swr_dev,
+			    wcd938x->rx_swr_dev->dev_num,
+			    true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* 6 msec delay as per HW requirement */
+		usleep_range(6000, 6010);
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+			snd_soc_component_update_bits(component,
+					WCD938X_ANA_RX_SUPPLIES,
+					0x02, 0x02);
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd938x->update_wcd_event)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* 7 msec delay as per HW requirement */
+		usleep_range(7000, 7010);
+		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
+			     WCD_CLSH_EVENT_POST_PA,
+			     WCD_CLSH_STATE_EAR,
+			     hph_mode);
+		break;
+	};
+	return ret;
+}
+
+static int wcd938x_enable_clsh(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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int mode = wcd938x->hph_mode;
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	if (mode == CLS_H_LOHIFI || mode == CLS_H_ULP ||
+		mode == CLS_H_HIFI || mode == CLS_H_LP) {
+		wcd938x_rx_connect_port(component, CLSH,
+				SND_SOC_DAPM_EVENT_ON(event));
+	}
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		ret = swr_slvdev_datapath_control(
+				wcd938x->rx_swr_dev,
+				wcd938x->rx_swr_dev->dev_num,
+				false);
+	return ret;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_connect_port(component, HPH_L, true);
+		if (wcd938x->comp1_enable)
+			wcd938x_rx_connect_port(component, COMP_L, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_rx_connect_port(component, HPH_L, false);
+		if (wcd938x->comp1_enable)
+			wcd938x_rx_connect_port(component, COMP_L, false);
+		wcd938x_rx_clk_disable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
+				0x01, 0x00);
+		break;
+	};
+
+	return 0;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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:
+		wcd938x_rx_connect_port(component, HPH_R, true);
+		if (wcd938x->comp2_enable)
+			wcd938x_rx_connect_port(component, COMP_R, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_rx_connect_port(component, HPH_R, false);
+		if (wcd938x->comp2_enable)
+			wcd938x_rx_connect_port(component, COMP_R, false);
+		wcd938x_rx_clk_disable(component);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
+				0x02, 0x00);
+		break;
+	};
+
+	return 0;
+}
+
+static int wcd938x_enable_rx3(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:
+		wcd938x_rx_connect_port(component, LO, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_rx_connect_port(component, LO, false);
+		/* 6 msec delay as per HW requirement */
+		usleep_range(6000, 6010);
+		wcd938x_rx_clk_disable(component);
+		snd_soc_component_update_bits(component,
+			WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x04, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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, "012345");
+
+	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 = &(wcd938x->dmic_0_1_clk_cnt);
+		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_CTL;
+		break;
+	case 2:
+	case 3:
+		dmic_clk_cnt = &(wcd938x->dmic_2_3_clk_cnt);
+		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;
+		break;
+	case 4:
+	case 5:
+		dmic_clk_cnt = &(wcd938x->dmic_4_5_clk_cnt);
+		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC2_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,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+						dmic_clk_reg, 0x07, 0x02);
+		snd_soc_component_update_bits(component,
+						dmic_clk_reg, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+						dmic_clk_reg, 0x70, 0x20);
+		wcd938x_tx_connect_port(component, DMIC0 + (w->shift), true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_tx_connect_port(component, DMIC0 + (w->shift), false);
+		break;
+
+	};
+	return 0;
+}
+
+/*
+ * wcd938x_get_micb_vout_ctl_val: converts micbias from volts to register value
+ * @micb_mv: micbias in mv
+ *
+ * return register value converted
+ */
+int wcd938x_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(wcd938x_get_micb_vout_ctl_val);
+
+/*
+ * wcd938x_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 wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+				   int req_volt, int micb_num)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int cur_vout_ctl, req_vout_ctl;
+	int micb_reg, micb_val, micb_en;
+	int ret = 0;
+
+	switch (micb_num) {
+	case MIC_BIAS_1:
+		micb_reg = WCD938X_ANA_MICB1;
+		break;
+	case MIC_BIAS_2:
+		micb_reg = WCD938X_ANA_MICB2;
+		break;
+	case MIC_BIAS_3:
+		micb_reg = WCD938X_ANA_MICB3;
+		break;
+	case MIC_BIAS_4:
+		micb_reg = WCD938X_ANA_MICB4;
+		break;
+	default:
+		return -EINVAL;
+	}
+	mutex_lock(&wcd938x->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 = wcd938x_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, 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(&wcd938x->micb_lock);
+	return ret;
+}
+EXPORT_SYMBOL(wcd938x_mbhc_micb_adjust_voltage);
+
+static int wcd938x_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+		    wcd938x->tx_swr_dev->dev_num,
+		    true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+		    wcd938x->tx_swr_dev->dev_num,
+		    false);
+		break;
+	};
+
+	return ret;
+}
+
+static int wcd938x_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);
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+		wcd938x_tx_connect_port(component, ADC1 + (w->shift), true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x_tx_connect_port(component, ADC1 + (w->shift), false);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00);
+		break;
+	};
+
+	return 0;
+}
+
+static int wcd938x_enable_req(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:
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x40, 0x40);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x20, 0x20);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x30, 0x30);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH1, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x20, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH1, 0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_TX_CH2, 0x80, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x10, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00);
+		break;
+	};
+	return 0;
+}
+
+int wcd938x_micbias_control(struct snd_soc_component *component,
+				int micb_num, int req, bool is_dapm)
+{
+
+	struct wcd938x_priv *wcd938x = 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;
+
+	if ((micb_index < 0) || (micb_index > WCD938X_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 = WCD938X_ANA_MICB1;
+		break;
+	case MIC_BIAS_2:
+		micb_reg = WCD938X_ANA_MICB2;
+		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 = WCD938X_ANA_MICB3;
+		break;
+	case MIC_BIAS_4:
+		micb_reg = WCD938X_ANA_MICB4;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
+			__func__, micb_num);
+		return -EINVAL;
+	};
+	mutex_lock(&wcd938x->micb_lock);
+
+	switch (req) {
+	case MICB_PULLUP_ENABLE:
+		wcd938x->pullup_ref[micb_index]++;
+		if ((wcd938x->pullup_ref[micb_index] == 1) &&
+		    (wcd938x->micb_ref[micb_index] == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+							0xC0, 0x80);
+		break;
+	case MICB_PULLUP_DISABLE:
+		if (wcd938x->pullup_ref[micb_index] > 0)
+			wcd938x->pullup_ref[micb_index]--;
+		if ((wcd938x->pullup_ref[micb_index] == 0) &&
+		    (wcd938x->micb_ref[micb_index] == 0))
+			snd_soc_component_update_bits(component, micb_reg,
+							0xC0, 0x00);
+		break;
+	case MICB_ENABLE:
+		wcd938x->micb_ref[micb_index]++;
+		if (wcd938x->micb_ref[micb_index] == 1) {
+			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0);
+			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+			snd_soc_component_update_bits(component,
+				WCD938X_MICB1_TEST_CTL_2, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				WCD938X_MICB2_TEST_CTL_2, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				WCD938X_MICB3_TEST_CTL_2, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+				micb_reg, 0xC0, 0x40);
+			if (post_on_event)
+				blocking_notifier_call_chain(
+						&wcd938x->mbhc->notifier,
+						post_on_event,
+						&wcd938x->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_on && wcd938x->mbhc)
+			blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+						     post_dapm_on,
+						     &wcd938x->mbhc->wcd_mbhc);
+		break;
+	case MICB_DISABLE:
+		if (wcd938x->micb_ref[micb_index] > 0)
+			wcd938x->micb_ref[micb_index]--;
+		if ((wcd938x->micb_ref[micb_index] == 0) &&
+		    (wcd938x->pullup_ref[micb_index] > 0))
+			snd_soc_component_update_bits(component, micb_reg,
+							0xC0, 0x80);
+		else if ((wcd938x->micb_ref[micb_index] == 0) &&
+			 (wcd938x->pullup_ref[micb_index] == 0)) {
+			if (pre_off_event && wcd938x->mbhc)
+				blocking_notifier_call_chain(
+						&wcd938x->mbhc->notifier,
+						pre_off_event,
+						&wcd938x->mbhc->wcd_mbhc);
+			snd_soc_component_update_bits(component, micb_reg,
+							0xC0, 0x00);
+			if (post_off_event && wcd938x->mbhc)
+				blocking_notifier_call_chain(
+						&wcd938x->mbhc->notifier,
+						post_off_event,
+						&wcd938x->mbhc->wcd_mbhc);
+		}
+		if (is_dapm && post_dapm_off && wcd938x->mbhc)
+			blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
+						post_dapm_off,
+						&wcd938x->mbhc->wcd_mbhc);
+		break;
+	};
+
+	dev_dbg(component->dev,
+		"%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
+		__func__, micb_num, wcd938x->micb_ref[micb_index],
+		wcd938x->pullup_ref[micb_index]);
+	mutex_unlock(&wcd938x->micb_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd938x_micbias_control);
+
+static int wcd938x_get_logical_addr(struct swr_device *swr_dev)
+{
+	int ret = 0;
+	uint8_t devnum = 0;
+
+	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);
+		swr_remove_device(swr_dev);
+		return ret;
+	}
+	swr_dev->dev_num = devnum;
+	return 0;
+}
+
+static int wcd938x_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	u16 amic;
+	u16 mask = 0x40, reg = 0x0;
+	int ret = 0;
+	struct wcd938x_priv *wcd938x = dev_get_drvdata((struct device *)data);
+	struct snd_soc_component *component = wcd938x->component;
+	struct wcd_mbhc *mbhc;
+
+	switch (event) {
+	case BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR:
+		amic = (val >> 0x10);
+		if (amic == 0x1 || amic == 0x2)
+			reg = WCD938X_ANA_TX_CH2;
+		else if (amic == 0x3)
+			reg = WCD938X_ANA_TX_CH3_HPF;
+		else
+			return 0;
+		if (amic == 0x2)
+			mask = 0x20;
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		break;
+	case BOLERO_WCD_EVT_PA_OFF_PRE_SSR:
+		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
+					0xC0, 0x00);
+		snd_soc_component_update_bits(component, WCD938X_ANA_EAR,
+					0x80, 0x00);
+		snd_soc_component_update_bits(component, WCD938X_AUX_AUXPA,
+					0x80, 0x00);
+		break;
+	case BOLERO_WCD_EVT_SSR_DOWN:
+		wcd938x_reset_low(wcd938x->dev);
+		break;
+	case BOLERO_WCD_EVT_SSR_UP:
+		wcd938x_reset(wcd938x->dev);
+		wcd938x_get_logical_addr(wcd938x->tx_swr_dev);
+		wcd938x_get_logical_addr(wcd938x->rx_swr_dev);
+		regcache_mark_dirty(wcd938x->regmap);
+		regcache_sync(wcd938x->regmap);
+		/* Initialize MBHC module */
+		mbhc = &wcd938x->mbhc->wcd_mbhc;
+		ret = wcd938x_mbhc_post_ssr_init(wcd938x->mbhc, component);
+		if (ret) {
+			dev_err(component->dev, "%s: mbhc initialization failed\n",
+				__func__);
+		} else {
+			wcd938x_mbhc_hs_detect(component, mbhc->mbhc_cfg);
+		}
+		break;
+	case BOLERO_WCD_EVT_CLK_NOTIFY:
+		snd_soc_update_bits(codec, WCD938X_DIGITAL_TOP_CLK_CFG, 0x06,
+				    ((val >> 0x10) << 0x01));
+		break;
+	default:
+		dev_dbg(component->dev, "%s: invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
+static int __wcd938x_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 if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4")))
+		micb_num = MIC_BIAS_4;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd938x_micbias_control(component, micb_num,
+						MICB_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:
+		wcd938x_micbias_control(component, micb_num,
+						MICB_DISABLE, true);
+		break;
+	};
+
+	return 0;
+
+}
+
+static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *kcontrol,
+					int event)
+{
+	return __wcd938x_codec_enable_micbias(w, event);
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wcd938x->hph_mode;
+	return 0;
+}
+
+static int wcd938x_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 wcd938x_priv *wcd938x = 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_info(component->dev,
+			"%s:Invalid HPH Mode, default to class_AB\n",
+			__func__);
+		mode_val = 3; /* enum will be updated later */
+	}
+	wcd938x->hph_mode = mode_val;
+	return 0;
+}
+
+static int wcd938x_get_compander(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_priv *wcd938x = 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 ? wcd938x->comp2_enable :
+						wcd938x->comp1_enable;
+	return 0;
+}
+
+static int wcd938x_set_compander(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_priv *wcd938x = 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)
+		wcd938x->comp2_enable = value;
+	else
+		wcd938x->comp1_enable = value;
+
+	return 0;
+}
+
+static int wcd938x_codec_enable_vdd_buck(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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	struct wcd938x_pdata *pdata = NULL;
+	int ret = 0;
+
+	pdata = dev_get_platdata(wcd938x->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:
+		ret = msm_cdc_enable_ondemand_supply(wcd938x->dev,
+						wcd938x->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-buck");
+		if (ret == -EINVAL) {
+			dev_err(component->dev, "%s: vdd buck is not enabled\n",
+				__func__);
+			return ret;
+		}
+		/*
+		 * 200us sleep is required after LDO15 is enabled as per
+		 * HW requirement
+		 */
+		usleep_range(200, 250);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = msm_cdc_disable_ondemand_supply(wcd938x->dev,
+						wcd938x->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-buck");
+		if (ret == -EINVAL) {
+			dev_err(dev, "%s: vdd buck is not disabled\n",
+				__func__);
+			return 0;
+		}
+		break;
+	}
+	return 0;
+}
+
+static int wcd938x_tx_hdr_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int hdr = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] = wcd938x->hdr_en[hdr];
+
+	return 0;
+}
+
+static int wcd938x_tx_hdr_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int hdr = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+	int val = ucontrol->value.integer.value[0];
+	u8 mask = 0;
+
+	wcd938x->hdr_en[hdr] = val;
+
+	switch(val) {
+	case TX_HDR12:
+		mask = (1 << 4);
+		val = (val << 4);
+		break;
+	case TX_HDR34:
+		mask = (1 << 3);
+		val = (val << 3);
+		break;
+	default:
+		dev_err(component->dev, "%s: unknown HDR input: %d\n",
+			__func__, hdr);
+		break;
+	}
+
+	if (mask)
+		snd_soc_component_update_bits(component,
+					WCD938X_TX_NEW_AMIC_MUX_CFG, mask, 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 const struct snd_kcontrol_new wcd938x_snd_controls[] = {
+	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
+		wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
+
+	SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0,
+		wcd938x_get_compander, wcd938x_set_compander),
+	SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0,
+		wcd938x_get_compander, wcd938x_set_compander),
+
+	SOC_SINGLE_EXT("TX HDR12", SND_SOC_NOPM, TX_HDR12, 1, 0,
+		wcd938x_tx_hdr_get, wcd938x_tx_hdr_put),
+
+	SOC_SINGLE_EXT("TX HDR34", SND_SOC_NOPM, TX_HDR34, 1, 0,
+		wcd938x_tx_hdr_get, wcd938x_tx_hdr_put),
+
+	SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 20, 1, line_gain),
+	SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 20, 1, line_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", WCD938X_ANA_TX_CH2, 0, 20, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", WCD938X_ANA_TX_CH3, 0, 20, 0,
+			analog_gain),
+	SOC_SINGLE_TLV("ADC4 Volume", WCD938X_ANA_TX_CH4, 0, 20, 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 adc3_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new adc4_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 dmic3_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic4_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic5_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic6_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic7_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new dmic8_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 aux_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(WCD938X_TX_NEW_AMIC_MUX_CFG, 7,
+		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 char * const adc3_mux_text[] = {
+	"INP4", "INP6"
+};
+
+static const struct soc_enum adc3_enum =
+	SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 6,
+		ARRAY_SIZE(adc3_mux_text), adc3_mux_text);
+
+static const struct snd_kcontrol_new tx_adc3_mux =
+	SOC_DAPM_ENUM("ADC3 MUX Mux", adc3_enum);
+
+static const char * const adc4_mux_text[] = {
+	"INP5", "INP7"
+};
+
+static const struct soc_enum adc4_enum =
+	SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 5,
+		ARRAY_SIZE(adc4_mux_text), adc4_mux_text);
+
+static const struct snd_kcontrol_new tx_adc4_mux =
+	SOC_DAPM_ENUM("ADC4 MUX Mux", adc4_enum);
+
+static const char * const rdac3_mux_text[] = {
+	"RX1", "RX3"
+};
+
+static const struct soc_enum rdac3_enum =
+	SOC_ENUM_SINGLE(WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0,
+		ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text);
+
+static const struct snd_kcontrol_new rx_rdac3_mux =
+	SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum);
+
+static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
+
+	/*input widgets*/
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_INPUT("AMIC3"),
+	SND_SOC_DAPM_INPUT("AMIC4"),
+	SND_SOC_DAPM_INPUT("AMIC5"),
+	SND_SOC_DAPM_INPUT("AMIC6"),
+	SND_SOC_DAPM_INPUT("AMIC7"),
+	SND_SOC_DAPM_INPUT("IN1_HPHL"),
+	SND_SOC_DAPM_INPUT("IN2_HPHR"),
+	SND_SOC_DAPM_INPUT("IN3_AUX"),
+
+	/*tx widgets*/
+	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
+				wcd938x_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 0, 1,
+				wcd938x_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 0, 2,
+				wcd938x_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC4", NULL, SND_SOC_NOPM, 0, 3,
+				wcd938x_codec_enable_adc,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 1,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 2,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 3,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 4,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 5,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC7", NULL, SND_SOC_NOPM, 0, 6,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC8", NULL, SND_SOC_NOPM, 0, 7,
+				wcd938x_codec_enable_dmic,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0,
+				NULL, 0, wcd938x_enable_req,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 0, 0,
+				NULL, 0, wcd938x_enable_req,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 0, 0,
+				NULL, 0, wcd938x_enable_req,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC4 REQ", SND_SOC_NOPM, 0, 0,
+				NULL, 0, wcd938x_enable_req,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+				&tx_adc2_mux),
+	SND_SOC_DAPM_MUX("ADC3 MUX", SND_SOC_NOPM, 0, 0,
+				&tx_adc3_mux),
+	SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0,
+				&tx_adc4_mux),
+
+	/*tx mixers*/
+	SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0,
+				adc1_switch, ARRAY_SIZE(adc1_switch),
+				wcd938x_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),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch,
+				ARRAY_SIZE(adc3_switch), wcd938x_tx_swr_ctrl,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("ADC4_MIXER", SND_SOC_NOPM, 0, 0, adc4_switch,
+				ARRAY_SIZE(adc4_switch), wcd938x_tx_swr_ctrl,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0,
+				0, dmic1_switch, ARRAY_SIZE(dmic1_switch),
+				wcd938x_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),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0,
+				0, dmic3_switch, ARRAY_SIZE(dmic3_switch),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0,
+				0, dmic4_switch, ARRAY_SIZE(dmic4_switch),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0,
+				0, dmic5_switch, ARRAY_SIZE(dmic5_switch),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0,
+				0, dmic6_switch, ARRAY_SIZE(dmic6_switch),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC7_MIXER", SND_SOC_NOPM, 0,
+				0, dmic7_switch, ARRAY_SIZE(dmic7_switch),
+				wcd938x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("DMIC8_MIXER", SND_SOC_NOPM, 0,
+				0, dmic8_switch, ARRAY_SIZE(dmic8_switch),
+				wcd938x_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,
+				wcd938x_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,
+				wcd938x_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,
+				wcd938x_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4", SND_SOC_NOPM, 0, 0,
+				wcd938x_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0,
+			     wcd938x_codec_enable_vdd_buck,
+			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0,
+			     wcd938x_enable_clsh,
+			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/*rx widgets*/
+	SND_SOC_DAPM_PGA_E("EAR PGA", WCD938X_ANA_EAR, 7, 0, NULL, 0,
+				wcd938x_codec_enable_ear_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("AUX PGA", WCD938X_AUX_AUXPA, 7, 0, NULL, 0,
+				wcd938x_codec_enable_aux_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("HPHL PGA", WCD938X_ANA_HPH, 7, 0, NULL, 0,
+				wcd938x_codec_enable_hphl_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("HPHR PGA", WCD938X_ANA_HPH, 6, 0, NULL, 0,
+				wcd938x_codec_enable_hphr_pa,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,
+				wcd938x_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,
+				wcd938x_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,
+				wcd938x_codec_ear_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("RDAC4", NULL, SND_SOC_NOPM, 0, 0,
+				wcd938x_codec_aux_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_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),
+
+	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0,
+				wcd938x_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,
+				wcd938x_enable_rx2, SND_SOC_DAPM_PRE_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0,
+				wcd938x_enable_rx3, 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("AUX_RDAC", SND_SOC_NOPM, 0, 0,
+			   aux_rdac_switch, ARRAY_SIZE(aux_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"),
+	SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("ADC4_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC7_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("DMIC8_OUTPUT"),
+
+	/*output widgets rx*/
+	SND_SOC_DAPM_OUTPUT("EAR"),
+	SND_SOC_DAPM_OUTPUT("AUX"),
+	SND_SOC_DAPM_OUTPUT("HPHL"),
+	SND_SOC_DAPM_OUTPUT("HPHR"),
+};
+
+static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
+
+	{"ADC1_OUTPUT", NULL, "ADC1_MIXER"},
+	{"ADC1_MIXER", "Switch", "ADC1 REQ"},
+	{"ADC1 REQ", NULL, "ADC1"},
+	{"ADC1", NULL, "AMIC1"},
+
+	{"ADC2_OUTPUT", NULL, "ADC2_MIXER"},
+	{"ADC2_MIXER", "Switch", "ADC2 REQ"},
+	{"ADC2 REQ", NULL, "ADC2"},
+	{"ADC2", NULL, "ADC2 MUX"},
+	{"ADC2 MUX", "INP3", "AMIC3"},
+	{"ADC2 MUX", "INP2", "AMIC2"},
+
+	{"ADC3_OUTPUT", NULL, "ADC3_MIXER"},
+	{"ADC3_MIXER", "Switch", "ADC3 REQ"},
+	{"ADC3 REQ", NULL, "ADC3"},
+	{"ADC3", NULL, "ADC3 MUX"},
+	{"ADC3 MUX", "INP4", "AMIC4"},
+	{"ADC3 MUX", "INP6", "AMIC6"},
+
+	{"ADC4_OUTPUT", NULL, "ADC4_MIXER"},
+	{"ADC4_MIXER", "Switch", "ADC4 REQ"},
+	{"ADC4 REQ", NULL, "ADC4"},
+	{"ADC4", NULL, "ADC4 MUX"},
+	{"ADC4 MUX", "INP5", "AMIC5"},
+	{"ADC4 MUX", "INP7", "AMIC7"},
+
+	{"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"},
+	{"DMIC1_MIXER", "Switch", "DMIC1"},
+
+	{"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"},
+	{"DMIC2_MIXER", "Switch", "DMIC2"},
+
+	{"DMIC3_OUTPUT", NULL, "DMIC3_MIXER"},
+	{"DMIC3_MIXER", "Switch", "DMIC3"},
+
+	{"DMIC4_OUTPUT", NULL, "DMIC4_MIXER"},
+	{"DMIC4_MIXER", "Switch", "DMIC4"},
+
+	{"DMIC5_OUTPUT", NULL, "DMIC5_MIXER"},
+	{"DMIC5_MIXER", "Switch", "DMIC5"},
+
+	{"DMIC6_OUTPUT", NULL, "DMIC6_MIXER"},
+	{"DMIC6_MIXER", "Switch", "DMIC6"},
+
+	{"DMIC7_OUTPUT", NULL, "DMIC7_MIXER"},
+	{"DMIC7_MIXER", "Switch", "DMIC7"},
+
+	{"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"},
+	{"DMIC8_MIXER", "Switch", "DMIC8"},
+
+	{"IN1_HPHL", NULL, "VDD_BUCK"},
+	{"IN1_HPHL", NULL, "CLS_H_PORT"},
+	{"RX1", NULL, "IN1_HPHL"},
+	{"RDAC1", NULL, "RX1"},
+	{"HPHL_RDAC", "Switch", "RDAC1"},
+	{"HPHL PGA", NULL, "HPHL_RDAC"},
+	{"HPHL", NULL, "HPHL PGA"},
+
+	{"IN2_HPHR", NULL, "VDD_BUCK"},
+	{"IN2_HPHR", NULL, "CLS_H_PORT"},
+	{"RX2", NULL, "IN2_HPHR"},
+	{"RDAC2", NULL, "RX2"},
+	{"HPHR_RDAC", "Switch", "RDAC2"},
+	{"HPHR PGA", NULL, "HPHR_RDAC"},
+	{"HPHR", NULL, "HPHR PGA"},
+
+	{"IN3_AUX", NULL, "VDD_BUCK"},
+	{"IN3_AUX", NULL, "CLS_H_PORT"},
+	{"RX3", NULL, "IN3_AUX"},
+	{"RDAC4", NULL, "RX3"},
+	{"AUX_RDAC", "Switch", "RDAC4"},
+	{"AUX PGA", NULL, "AUX_RDAC"},
+	{"AUX", NULL, "AUX PGA"},
+
+	{"RDAC3_MUX", "RX3", "RX3"},
+	{"RDAC3_MUX", "RX1", "RX1"},
+	{"RDAC3", NULL, "RDAC3_MUX"},
+	{"EAR_RDAC", "Switch", "RDAC3"},
+	{"EAR PGA", NULL, "EAR_RDAC"},
+	{"EAR", NULL, "EAR PGA"},
+};
+
+static ssize_t wcd938x_version_read(struct snd_info_entry *entry,
+				   void *file_private_data,
+				   struct file *file,
+				   char __user *buf, size_t count,
+				   loff_t pos)
+{
+	struct wcd938x_priv *priv;
+	char buffer[WCD938X_VERSION_ENTRY_SIZE];
+	int len = 0;
+
+	priv = (struct wcd938x_priv *) entry->private_data;
+	if (!priv) {
+		pr_err("%s: wcd938x priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (priv->version) {
+	case WCD938X_VERSION_1_0:
+		len = snprintf(buffer, sizeof(buffer), "WCD938X_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 wcd938x_info_ops = {
+	.read = wcd938x_version_read,
+};
+
+/*
+ * wcd938x_info_create_codec_entry - creates wcd938x module
+ * @codec_root: The parent directory
+ * @component: component instance
+ *
+ * Creates wcd938x module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root,
+				   struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct wcd938x_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:wcd938x module already created\n", __func__);
+		return 0;
+	}
+	card = component->card;
+	priv->entry = snd_info_create_subdir(codec_root->module,
+					     "wcd938x", codec_root);
+	if (!priv->entry) {
+		dev_dbg(component->dev, "%s: failed to create wcd938x 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 wcd938x version entry\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = priv;
+	version_entry->size = WCD938X_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &wcd938x_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(wcd938x_info_create_codec_entry);
+
+static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int variant;
+	int ret = -EINVAL;
+
+	dev_info(component->dev, "%s()\n", __func__);
+	wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd938x)
+		return -EINVAL;
+
+	wcd938x->component = component;
+	snd_soc_component_init_regmap(component, wcd938x->regmap);
+
+	variant = (snd_soc_component_read32(component,
+			WCD938X_DIGITAL_EFUSE_REG_0) & 0x1E) >> 1;
+	wcd938x->variant = variant;
+
+	wcd938x->fw_data = devm_kzalloc(component->dev,
+					sizeof(*(wcd938x->fw_data)),
+					GFP_KERNEL);
+	if (!wcd938x->fw_data) {
+		dev_err(component->dev, "Failed to allocate fw_data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	set_bit(WCD9XXX_MBHC_CAL, wcd938x->fw_data->cal_bit);
+	ret = wcd_cal_create_hwdep(wcd938x->fw_data,
+				   WCD9XXX_CODEC_HWDEP_NODE, component);
+
+	if (ret < 0) {
+		dev_err(component->dev, "%s hwdep failed %d\n", __func__, ret);
+		goto err_hwdep;
+	}
+
+	ret = wcd938x_mbhc_init(&wcd938x->mbhc, component, wcd938x->fw_data);
+	if (ret) {
+		pr_err("%s: mbhc initialization failed\n", __func__);
+		goto err_hwdep;
+	}
+
+	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_ignore_suspend(dapm, "AMIC5");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC6");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC7");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC1_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC2_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC3_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC4_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC5_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC6_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC7_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "DMIC8_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC1_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC2_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC3_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "ADC4_OUTPUT");
+	snd_soc_dapm_ignore_suspend(dapm, "IN1_HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "IN2_HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "IN3_AUX");
+	snd_soc_dapm_ignore_suspend(dapm, "EAR");
+	snd_soc_dapm_ignore_suspend(dapm, "AUX");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+	snd_soc_dapm_sync(dapm);
+
+	wcd_cls_h_init(&wcd938x->clsh_info);
+	wcd938x_init_reg(component);
+
+	wcd938x->version = WCD938X_VERSION_1_0;
+       /* Register event notifier */
+	wcd938x->nblock.notifier_call = wcd938x_event_notify;
+	if (wcd938x->register_notifier) {
+		ret = wcd938x->register_notifier(wcd938x->handle,
+						&wcd938x->nblock,
+						true);
+		if (ret) {
+			dev_err(component->dev,
+				"%s: Failed to register notifier %d\n",
+				__func__, ret);
+			return ret;
+		}
+	}
+	return ret;
+
+err_hwdep:
+	wcd938x->fw_data = NULL;
+
+err:
+	return ret;
+}
+
+static void wcd938x_soc_codec_remove(struct snd_soc_component *component)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd938x) {
+		dev_err(component->dev, "%s: wcd938x is already NULL\n",
+			__func__);
+		return;
+	}
+	if (wcd938x->register_notifier)
+		wcd938x->register_notifier(wcd938x->handle,
+						&wcd938x->nblock,
+						false);
+}
+
+static struct snd_soc_component_driver soc_codec_dev_wcd938x = {
+	.name = WCD938X_DRV_NAME,
+	.probe = wcd938x_soc_codec_probe,
+	.remove = wcd938x_soc_codec_remove,
+	.controls = wcd938x_snd_controls,
+	.num_controls = ARRAY_SIZE(wcd938x_snd_controls),
+	.dapm_widgets = wcd938x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),
+	.dapm_routes = wcd938x_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),
+};
+
+static int wcd938x_reset(struct device *dev)
+{
+	struct wcd938x_priv *wcd938x = NULL;
+	int rc = 0;
+	int value = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd938x = dev_get_drvdata(dev);
+	if (!wcd938x)
+		return -EINVAL;
+
+	if (!wcd938x->rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	value = msm_cdc_pinctrl_get_state(wcd938x->rst_np);
+	if (value > 0)
+		return 0;
+
+	rc = msm_cdc_pinctrl_select_sleep_state(wcd938x->rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd sleep state request fail!\n",
+				__func__);
+		return rc;
+	}
+	/* 20us sleep required after pulling the reset gpio to LOW */
+	usleep_range(20, 30);
+
+	rc = msm_cdc_pinctrl_select_active_state(wcd938x->rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd active state request fail!\n",
+				__func__);
+		return rc;
+	}
+	/* 20us sleep required after pulling the reset gpio to HIGH */
+	usleep_range(20, 30);
+
+	return rc;
+}
+
+static int wcd938x_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 wcd938x_dt_parse_micbias_info(struct device *dev,
+					  struct wcd938x_micbias_setting *mb)
+{
+	u32 prop_val = 0;
+	int rc = 0;
+
+	/* MB1 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias1-mv",
+				    NULL)) {
+		rc = wcd938x_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 = wcd938x_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 = wcd938x_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__);
+	}
+}
+
+static int wcd938x_reset_low(struct device *dev)
+{
+	struct wcd938x_priv *wcd938x = NULL;
+	int rc = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd938x = dev_get_drvdata(dev);
+	if (!wcd938x)
+		return -EINVAL;
+
+	if (!wcd938x->rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	rc = msm_cdc_pinctrl_select_sleep_state(wcd938x->rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd sleep state request fail!\n",
+				__func__);
+		return rc;
+	}
+	/* 20us sleep required after pulling the reset gpio to LOW */
+	usleep_range(20, 30);
+
+	return rc;
+}
+
+struct wcd938x_pdata *wcd938x_populate_dt_data(struct device *dev)
+{
+	struct wcd938x_pdata *pdata = NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(struct wcd938x_pdata),
+				GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	pdata->rst_np = of_parse_phandle(dev->of_node,
+			"qcom,wcd-rst-gpio-node", 0);
+
+	if (!pdata->rst_np) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+				__func__, "qcom,wcd-rst-gpio-node",
+				dev->of_node->full_name);
+		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__);
+		return NULL;
+	}
+
+	pdata->rx_slave = of_parse_phandle(dev->of_node, "qcom,rx-swr-slave", 0);
+	pdata->tx_slave = of_parse_phandle(dev->of_node, "qcom,tx-swr-slave", 0);
+
+	wcd938x_dt_parse_micbias_info(dev, &pdata->micbias);
+
+	return pdata;
+}
+
+static int wcd938x_bind(struct device *dev)
+{
+	int ret = 0, i = 0;
+	struct wcd938x_pdata *pdata = dev_get_platdata(dev);
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
+
+	/*
+	 * Add 5msec delay to provide sufficient time for
+	 * soundwire auto enumeration of slave devices as
+	 * as per HW requirement.
+	 */
+	usleep_range(5000, 5010);
+
+	ret = component_bind_all(dev, wcd938x);
+	if (ret) {
+		dev_err(dev, "%s: Slave bind failed, ret = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	wcd938x->rx_swr_dev = get_matching_swr_slave_device(pdata->rx_slave);
+	if (!wcd938x->rx_swr_dev) {
+		dev_err(dev, "%s: Could not find RX swr slave device\n",
+			 __func__);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	wcd938x->tx_swr_dev = get_matching_swr_slave_device(pdata->tx_slave);
+	if (!wcd938x->tx_swr_dev) {
+		dev_err(dev, "%s: Could not find TX swr slave device\n",
+			__func__);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	wcd938x->regmap = devm_regmap_init_swr(wcd938x->tx_swr_dev,
+					       &wcd938x_regmap_config);
+	if (!wcd938x->regmap) {
+		dev_err(dev, "%s: Regmap init failed\n",
+				__func__);
+		goto err;
+	}
+
+	/* Set all interupts as edge triggered */
+	for (i = 0; i < wcd938x_regmap_irq_chip.num_regs; i++)
+		regmap_write(wcd938x->regmap,
+			     (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);
+
+	wcd938x_regmap_irq_chip.irq_drv_data = wcd938x;
+	wcd938x->irq_info.wcd_regmap_irq_chip = &wcd938x_regmap_irq_chip;
+	wcd938x->irq_info.codec_name = "WCD938X";
+	wcd938x->irq_info.regmap = wcd938x->regmap;
+	wcd938x->irq_info.dev = dev;
+	ret = wcd_irq_init(&wcd938x->irq_info, &wcd938x->virq);
+
+	if (ret) {
+		dev_err(wcd938x->dev, "%s: IRQ init failed: %d\n",
+			__func__, ret);
+		goto err;
+	}
+	wcd938x->tx_swr_dev->slave_irq = wcd938x->virq;
+
+	ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x,
+				     NULL, 0);
+	if (ret) {
+		dev_err(dev, "%s: Codec registration failed\n",
+				__func__);
+		goto err_irq;
+	}
+
+	return ret;
+err_irq:
+	wcd_irq_exit(&wcd938x->irq_info, wcd938x->virq);
+err:
+	component_unbind_all(dev, wcd938x);
+	return ret;
+}
+
+static void wcd938x_unbind(struct device *dev)
+{
+	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
+
+	wcd_irq_exit(&wcd938x->irq_info, wcd938x->virq);
+	snd_soc_unregister_component(dev);
+	component_unbind_all(dev, wcd938x);
+}
+
+static const struct of_device_id wcd938x_dt_match[] = {
+	{ .compatible = "qcom,wcd938x-codec" },
+	{}
+};
+
+static const struct component_master_ops wcd938x_comp_ops = {
+	.bind   = wcd938x_bind,
+	.unbind = wcd938x_unbind,
+};
+
+static int wcd938x_compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static void wcd938x_release_of(struct device *dev, void *data)
+{
+	of_node_put(data);
+}
+
+static int wcd938x_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-swr-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,
+			wcd938x_release_of,
+			wcd938x_compare_of,
+			rx_node);
+
+	tx_node = of_parse_phandle(np, "qcom,tx-swr-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,
+			wcd938x_release_of,
+			wcd938x_compare_of,
+			tx_node);
+	return 0;
+}
+
+static int wcd938x_probe(struct platform_device *pdev)
+{
+	struct component_match *match = NULL;
+	struct wcd938x_priv *wcd938x = NULL;
+	struct wcd938x_pdata *pdata = NULL;
+	int ret;
+
+	wcd938x = devm_kzalloc(&pdev->dev, sizeof(struct wcd938x_priv),
+				GFP_KERNEL);
+	if (!wcd938x)
+		return -ENOMEM;
+
+	dev_set_drvdata(&pdev->dev, wcd938x);
+
+	pdata = wcd938x_populate_dt_data(&pdev->dev);
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: Fail to obtain platform data\n", __func__);
+		return -EINVAL;
+	}
+	dev->platform_data = pdata;
+
+	wcd938x->rst_np = pdata->rst_np;
+	ret = msm_cdc_init_supplies(&pdev->dev, &wcd938x->supplies,
+				    pdata->regulator, pdata->num_supplies);
+	if (!wcd938x->supplies) {
+		dev_err(&pdev->dev, "%s: Cannot init wcd supplies\n",
+			__func__);
+		return ret;
+	}
+
+	wcd938x->handle = (void *)pdata->handle;
+	if (!wcd938x->handle) {
+		dev_err(dev, "%s: handle is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x->update_wcd_event = pdata->update_wcd_event;
+	if (!wcd938x->update_wcd_event) {
+		dev_err(dev, "%s: update_wcd_event api is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd938x->register_notifier = pdata->register_notifier;
+	if (!wcd938x->register_notifier) {
+		dev_err(dev, "%s: register_notifier api is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = msm_cdc_enable_static_supplies(&pdev->dev, wcd938x->supplies,
+					     pdata->regulator,
+					     pdata->num_supplies);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: wcd static supply enable failed!\n",
+			__func__);
+		return ret;
+	}
+
+	ret = wcd938x_parse_port_mapping(&pdev->dev, "qcom,rx_swr_ch_map",
+					CODEC_RX);
+	ret |= wcd938x_parse_port_mapping(&pdev->dev, "qcom,tx_swr_ch_map",
+					CODEC_TX);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to read port mapping\n");
+		goto err;
+	}
+
+	ret = wcd938x_add_slave_components(&pdev->dev, &match);
+	if (ret)
+		goto err;
+
+	wcd938x_reset(dev);
+
+	return component_master_add_with_match(&pdev->dev,
+					&wcd938x_comp_ops, match);
+
+err:
+	return ret;
+}
+
+static int wcd938x_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &wcd938x_comp_ops);
+	dev_set_drvdata(&pdev->dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int wcd938x_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int wcd938x_resume(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops wcd938x_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		wcd938x_suspend,
+		wcd938x_resume
+	)
+};
+#endif
+
+static struct platform_driver wcd938x_codec_driver = {
+	.probe = wcd938x_probe,
+	.remove = wcd938x_remove,
+	.driver = {
+		.name = "wcd938x_codec",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(wcd938x_dt_match),
+#ifdef CONFIG_PM_SLEEP
+		.pm = &wcd938x_dev_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(wcd938x_codec_driver);
+MODULE_DESCRIPTION("WCD938X Codec driver");
+MODULE_LICENSE("GPL v2");