diff --git a/asoc/codecs/wsa883x/Android.mk b/asoc/codecs/wsa883x/Android.mk new file mode 100644 index 0000000000..66056e8c44 --- /dev/null +++ b/asoc/codecs/wsa883x/Android.mk @@ -0,0 +1,49 @@ +# 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,lahaina),true) +AUDIO_SELECT := CONFIG_SND_SOC_LAHAINA=m +endif + +AUDIO_CHIPSET := audio +# Build/Package only in case of supported target +ifeq ($(call is-board-platform-in-list,lahaina),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 _audio.ko as LOCAL_MODULE. +# This means we need to rename the module to _audio.ko +# after audio.ko is built. +KBUILD_OPTIONS += MODNAME=wsa883x_dlkm +KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) +KBUILD_OPTIONS += $(AUDIO_SELECT) + +########################################################### +include $(CLEAR_VARS) +LOCAL_MODULE := $(AUDIO_CHIPSET)_wsa883x.ko +LOCAL_MODULE_KBUILD_NAME := wsa883x_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 diff --git a/asoc/codecs/wsa883x/Kbuild b/asoc/codecs/wsa883x/Kbuild new file mode 100644 index 0000000000..4eb844af51 --- /dev/null +++ b/asoc/codecs/wsa883x/Kbuild @@ -0,0 +1,103 @@ +# 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_LAHAINA), y) + include $(AUDIO_ROOT)/config/lahainaauto.conf + INCS += -include $(AUDIO_ROOT)/config/lahainaautoconf.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) + +############ WSA883X ############ + +# for WSA883X Codec +ifdef CONFIG_SND_SOC_WSA883X + WSA883X_OBJS += wsa883x.o + WSA883X_OBJS += wsa883x-regmap.o + WSA883X_OBJS += wsa883x-tables.o + WSA883X_OBJS += wsa883x-temp-sensor.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_WSA883X) += wsa883x_dlkm.o +wsa883x_dlkm-y := $(WSA883X_OBJS) + +# inject some build related information +DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h new file mode 100644 index 0000000000..3f99f78065 --- /dev/null +++ b/asoc/codecs/wsa883x/internal.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef WSA883X_INTERNAL_H +#define WSA883X_INTERNAL_H + +#include "wsa883x.h" +#include "wsa883x-registers.h" + +#ifdef CONFIG_DEBUG_FS +#include +#include + +#define SWR_SLV_MAX_REG_ADDR 0x2009 +#define SWR_SLV_START_REG_ADDR 0x40 +#define SWR_SLV_MAX_BUF_LEN 20 +#define BYTES_PER_LINE 12 +#define SWR_SLV_RD_BUF_LEN 8 +#define SWR_SLV_WR_BUF_LEN 32 +#define SWR_SLV_MAX_DEVICES 2 +#endif /* CONFIG_DEBUG_FS */ + +#define WSA883X_DRV_NAME "wsa883x-codec" +#define WSA883X_NUM_RETRY 5 + +#define WSA883X_VERSION_ENTRY_SIZE 27 + +enum { + G_18DB = 0, + G_16P5DB, + G_15DB, + G_13P5DB, + G_12DB, + G_10P5DB, + G_9DB, + G_7P5DB, + G_6DB, + G_4P5DB, + G_3DB, + G_1P5DB, + G_0DB, +}; + +enum { + DISABLE = 0, + ENABLE, +}; + +enum { + SWR_DAC_PORT, + SWR_COMP_PORT, + SWR_BOOST_PORT, + SWR_VISENSE_PORT, +}; + +struct swr_port { + u8 port_id; + u8 ch_mask; + u32 ch_rate; + u8 num_ch; + u8 port_type; +}; + +enum { + WSA883X_DEV_DOWN, + WSA883X_DEV_UP, + WSA883X_DEV_READY, +}; + +extern struct regmap_config wsa883x_regmap_config; + +/* + * Private data Structure for wsa883x. All parameters related to + * WSA883X codec needs to be defined here. + */ +struct wsa883x_priv { + struct regmap *regmap; + struct device *dev; + struct swr_device *swr_slave; + struct snd_soc_component *component; + bool comp_enable; + bool boost_enable; + bool visense_enable; + u8 pa_gain; + struct swr_port port[WSA883X_MAX_SWR_PORTS]; + int pd_gpio; + struct wsa883x_tz_priv tz_pdata; + int bg_cnt; + int clk_cnt; + int version; + struct mutex bg_lock; + struct mutex res_lock; + struct mutex temp_lock; + struct snd_info_entry *entry; + struct snd_info_entry *version_entry; + int state; + struct delayed_work ocp_ctl_work; + struct device_node *wsa_rst_np; + int pa_mute; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_dent; + struct dentry *debugfs_peek; + struct dentry *debugfs_poke; + struct dentry *debugfs_reg_dump; + unsigned int read_data; +#endif +}; + +static int32_t wsa883x_resource_acquire(struct snd_soc_component *component, + bool enable); +#endif /* WSA883X_INTERNAL_H */ diff --git a/asoc/codecs/wsa883x/wsa883x-registers.h b/asoc/codecs/wsa883x/wsa883x-registers.h new file mode 100644 index 0000000000..7e518d2fd0 --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x-registers.h @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef WSA883X_REGISTERS_H +#define WSA883X_REGISTERS_H + +#define WSA883X_BASE 0x3000 +#define WSA883X_REG(reg) (reg - WSA883X_BASE) + +enum { + REG_NO_ACCESS, + RD_REG, + WR_REG, + RD_WR_REG, +}; + +#define WSA883X_ANA_BG_TSADC_BASE (WSA883X_BASE+0x00000000) +#define WSA883X_REF_CTRL (WSA883X_ANA_BG_TSADC_BASE+0x0000) +#define WSA883X_TEST_CTL_0 (WSA883X_ANA_BG_TSADC_BASE+0x0001) +#define WSA883X_BIAS_0 (WSA883X_ANA_BG_TSADC_BASE+0x0002) +#define WSA883X_OP_CTL (WSA883X_ANA_BG_TSADC_BASE+0x0003) +#define WSA883X_IREF_CTL (WSA883X_ANA_BG_TSADC_BASE+0x0004) +#define WSA883X_ISENS_CTL (WSA883X_ANA_BG_TSADC_BASE+0x0005) +#define WSA883X_CLK_CTL (WSA883X_ANA_BG_TSADC_BASE+0x0006) +#define WSA883X_TEST_CTL_1 (WSA883X_ANA_BG_TSADC_BASE+0x0007) +#define WSA883X_BIAS_1 (WSA883X_ANA_BG_TSADC_BASE+0x0008) +#define WSA883X_ADC_CTL (WSA883X_ANA_BG_TSADC_BASE+0x0009) +#define WSA883X_DOUT_MSB (WSA883X_ANA_BG_TSADC_BASE+0x000A) +#define WSA883X_DOUT_LSB (WSA883X_ANA_BG_TSADC_BASE+0x000B) +#define WSA883X_VBAT_SNS (WSA883X_ANA_BG_TSADC_BASE+0x000C) +#define WSA883X_ITRIM_CODE (WSA883X_ANA_BG_TSADC_BASE+0x000D) + +#define WSA883X_ANA_IVSENSE_BASE (WSA883X_BASE+0x0000000F) +#define WSA883X_EN (WSA883X_ANA_IVSENSE_BASE+0x0000) +#define WSA883X_OVERRIDE1 (WSA883X_ANA_IVSENSE_BASE+0x0001) +#define WSA883X_OVERRIDE2 (WSA883X_ANA_IVSENSE_BASE+0x0002) +#define WSA883X_VSENSE1 (WSA883X_ANA_IVSENSE_BASE+0x0003) +#define WSA883X_ISENSE1 (WSA883X_ANA_IVSENSE_BASE+0x0004) +#define WSA883X_ISENSE2 (WSA883X_ANA_IVSENSE_BASE+0x0005) +#define WSA883X_ISENSE_CAL (WSA883X_ANA_IVSENSE_BASE+0x0006) +#define WSA883X_MISC (WSA883X_ANA_IVSENSE_BASE+0x0007) +#define WSA883X_ADC_0 (WSA883X_ANA_IVSENSE_BASE+0x0008) +#define WSA883X_ADC_1 (WSA883X_ANA_IVSENSE_BASE+0x0009) +#define WSA883X_ADC_2 (WSA883X_ANA_IVSENSE_BASE+0x000A) +#define WSA883X_ADC_3 (WSA883X_ANA_IVSENSE_BASE+0x000B) +#define WSA883X_ADC_4 (WSA883X_ANA_IVSENSE_BASE+0x000C) +#define WSA883X_ADC_5 (WSA883X_ANA_IVSENSE_BASE+0x000D) +#define WSA883X_ADC_6 (WSA883X_ANA_IVSENSE_BASE+0x000E) +#define WSA883X_ADC_7 (WSA883X_ANA_IVSENSE_BASE+0x000F) +#define WSA883X_STATUS (WSA883X_ANA_IVSENSE_BASE+0x0010) + +#define WSA883X_ANA_SPK_TOP_BASE (WSA883X_BASE+0x00000025) +#define WSA883X_DAC_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE+0x0000) +#define WSA883X_DAC_EN_DEBUG_REG (WSA883X_ANA_SPK_TOP_BASE+0x0001) +#define WSA883X_DAC_OPAMP_BIAS1_REG (WSA883X_ANA_SPK_TOP_BASE+0x0002) +#define WSA883X_DAC_OPAMP_BIAS2_REG (WSA883X_ANA_SPK_TOP_BASE+0x0003) +#define WSA883X_DAC_VCM_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE+0x0004) +#define WSA883X_DAC_VOLTAGE_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE+0x0005) +#define WSA883X_ATEST1_REG (WSA883X_ANA_SPK_TOP_BASE+0x0006) +#define WSA883X_ATEST2_REG (WSA883X_ANA_SPK_TOP_BASE+0x0007) +#define WSA883X_SPKR_TOP_BIAS_REG1 (WSA883X_ANA_SPK_TOP_BASE+0x0008) +#define WSA883X_SPKR_TOP_BIAS_REG2 (WSA883X_ANA_SPK_TOP_BASE+0x0009) +#define WSA883X_SPKR_TOP_BIAS_REG3 (WSA883X_ANA_SPK_TOP_BASE+0x000A) +#define WSA883X_SPKR_TOP_BIAS_REG4 (WSA883X_ANA_SPK_TOP_BASE+0x000B) +#define WSA883X_SPKR_CLIP_DET_REG (WSA883X_ANA_SPK_TOP_BASE+0x000C) +#define WSA883X_SPKR_DRV_LF_BLK_EN (WSA883X_ANA_SPK_TOP_BASE+0x000D) +#define WSA883X_SPKR_DRV_LF_EN (WSA883X_ANA_SPK_TOP_BASE+0x000E) +#define WSA883X_SPKR_DRV_LF_MASK_DCC_CTL (WSA883X_ANA_SPK_TOP_BASE+0x000F) +#define WSA883X_SPKR_DRV_LF_MISC_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0010) +#define WSA883X_SPKR_DRV_LF_REG_GAIN (WSA883X_ANA_SPK_TOP_BASE+0x0011) +#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL1 (WSA883X_ANA_SPK_TOP_BASE+0x0012) +#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0013) +#define WSA883X_SPKR_PWM_CLK_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0014) +#define WSA883X_SPKR_PDRV_HS_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0015) +#define WSA883X_SPKR_PDRV_LS_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0016) +#define WSA883X_SPKR_PWRSTG_DBG (WSA883X_ANA_SPK_TOP_BASE+0x0017) +#define WSA883X_SPKR_OCP_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0018) +#define WSA883X_SPKR_BBM_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0019) +#define WSA883X_PA_STATUS0 (WSA883X_ANA_SPK_TOP_BASE+0x001A) +#define WSA883X_PA_STATUS1 (WSA883X_ANA_SPK_TOP_BASE+0x001B) +#define WSA883X_PA_STATUS2 (WSA883X_ANA_SPK_TOP_BASE+0x001C) + +#define WSA883X_ANA_BOOST_BASE (WSA883X_BASE+0x00000045) +#define WSA883X_EN_CTRL (WSA883X_ANA_BOOST_BASE+0x0000) +#define WSA883X_CURRENT_LIMIT (WSA883X_ANA_BOOST_BASE+0x0001) +#define WSA883X_IBIAS1 (WSA883X_ANA_BOOST_BASE+0x0002) +#define WSA883X_IBIAS2 (WSA883X_ANA_BOOST_BASE+0x0003) +#define WSA883X_IBIAS3 (WSA883X_ANA_BOOST_BASE+0x0004) +#define WSA883X_LDO_PROG (WSA883X_ANA_BOOST_BASE+0x0005) +#define WSA883X_STABILITY_CTRL1 (WSA883X_ANA_BOOST_BASE+0x0006) +#define WSA883X_STABILITY_CTRL2 (WSA883X_ANA_BOOST_BASE+0x0007) +#define WSA883X_PWRSTAGE_CTRL1 (WSA883X_ANA_BOOST_BASE+0x0008) +#define WSA883X_PWRSTAGE_CTRL2 (WSA883X_ANA_BOOST_BASE+0x0009) +#define WSA883X_UVLO (WSA883X_ANA_BOOST_BASE+0x000A) +#define WSA883X_SEQUENCE_CTRL (WSA883X_ANA_BOOST_BASE+0x000B) +#define WSA883X_ZX_CTRL_1 (WSA883X_ANA_BOOST_BASE+0x000C) +#define WSA883X_ZX_CTRL_2 (WSA883X_ANA_BOOST_BASE+0x000D) +#define WSA883X_MISC1 (WSA883X_ANA_BOOST_BASE+0x000E) +#define WSA883X_MISC2 (WSA883X_ANA_BOOST_BASE+0x000F) +#define WSA883X_GMAMP_SUP1 (WSA883X_ANA_BOOST_BASE+0x0010) +#define WSA883X_PWRSTAGE_CTRL3 (WSA883X_ANA_BOOST_BASE+0x0011) +#define WSA883X_PRSTAGE_CTRL4 (WSA883X_ANA_BOOST_BASE+0x0012) +#define WSA883X_SPARE1 (WSA883X_ANA_BOOST_BASE+0x0013) + +#define WSA883X_ANA_PON_LDOL_BASE (WSA883X_BASE+0x00000059) +#define WSA883X_PON_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0000) +#define WSA883X_PON_CLT_1 (WSA883X_ANA_PON_LDOL_BASE+0x0001) +#define WSA883X_PON_CTL_2 (WSA883X_ANA_PON_LDOL_BASE+0x0002) +#define WSA883X_PON_CTL_3 (WSA883X_ANA_PON_LDOL_BASE+0x0003) +#define WSA883X_PON_CTL_4 (WSA883X_ANA_PON_LDOL_BASE+0x0004) +#define WSA883X_CKWD_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0005) +#define WSA883X_CKWD_CTL_1 (WSA883X_ANA_PON_LDOL_BASE+0x0006) +#define WSA883X_CKWD_CTL_2 (WSA883X_ANA_PON_LDOL_BASE+0x0007) +#define WSA883X_CKSK_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0008) +#define WSA883X_TEST_0 (WSA883X_ANA_PON_LDOL_BASE+0x0009) +#define WSA883X_TEST_1 (WSA883X_ANA_PON_LDOL_BASE+0x000A) +#define WSA883X_STATUS_0 (WSA883X_ANA_PON_LDOL_BASE+0x000B) +#define WSA883X_STATUS_1 (WSA883X_ANA_PON_LDOL_BASE+0x000C) + +#define WSA883X_DIG_CTRL_BASE (WSA883X_BASE+0x00000400) +#define WSA883X_PAGE_REGISTER (WSA883X_DIG_CTRL_BASE+0x0000) +#define WSA883X_CHIP_ID0 (WSA883X_DIG_CTRL_BASE+0x0001) +#define WSA883X_CHIP_ID1 (WSA883X_DIG_CTRL_BASE+0x0002) +#define WSA883X_CHIP_ID2 (WSA883X_DIG_CTRL_BASE+0x0003) +#define WSA883X_CHIP_ID3 (WSA883X_DIG_CTRL_BASE+0x0004) +#define WSA883X_BUS_ID (WSA883X_DIG_CTRL_BASE+0x0005) +#define WSA883X_CDC_RST_CTL (WSA883X_DIG_CTRL_BASE+0x0006) +#define WSA883X_TOP_CLK_CFG (WSA883X_DIG_CTRL_BASE+0x0007) +#define WSA883X_CDC_PATH_MODE (WSA883X_DIG_CTRL_BASE+0x0008) +#define WSA883X_CDC_CLK_CTL (WSA883X_DIG_CTRL_BASE+0x0009) +#define WSA883X_SWR_RESET_EN (WSA883X_DIG_CTRL_BASE+0x000A) +#define WSA883X_PA_FSM_CTL (WSA883X_DIG_CTRL_BASE+0x0010) +#define WSA883X_PA_FSM_TIMER0 (WSA883X_DIG_CTRL_BASE+0x0011) +#define WSA883X_PA_FSM_TIMER1 (WSA883X_DIG_CTRL_BASE+0x0012) +#define WSA883X_PA_FSM_STA (WSA883X_DIG_CTRL_BASE+0x0013) +#define WSA883X_PA_FSM_ERR_COND (WSA883X_DIG_CTRL_BASE+0x0014) +#define WSA883X_PA_FSM_MSK (WSA883X_DIG_CTRL_BASE+0x0015) +#define WSA883X_PA_FSM_BYP (WSA883X_DIG_CTRL_BASE+0x0016) +#define WSA883X_TADC_VALUE_CTL (WSA883X_DIG_CTRL_BASE+0x0020) +#define WSA883X_TEMP_DETECT_CTL (WSA883X_DIG_CTRL_BASE+0x0021) +#define WSA883X_TEMP_MSB (WSA883X_DIG_CTRL_BASE+0x0022) +#define WSA883X_TEMP_LSB (WSA883X_DIG_CTRL_BASE+0x0023) +#define WSA883X_TEMP_CONFIG0 (WSA883X_DIG_CTRL_BASE+0x0024) +#define WSA883X_TEMP_CONFIG1 (WSA883X_DIG_CTRL_BASE+0x0025) +#define WSA883X_VBAT_ADC_FLT_CTL (WSA883X_DIG_CTRL_BASE+0x0026) +#define WSA883X_VBAT_DIN_MSB (WSA883X_DIG_CTRL_BASE+0x0027) +#define WSA883X_VBAT_DIN_LSB (WSA883X_DIG_CTRL_BASE+0x0028) +#define WSA883X_VBAT_DOUT (WSA883X_DIG_CTRL_BASE+0x0029) +#define WSA883X_SDM_PDM9_LSB (WSA883X_DIG_CTRL_BASE+0x002A) +#define WSA883X_SDM_PDM9_MSB (WSA883X_DIG_CTRL_BASE+0x002B) +#define WSA883X_CDC_RX_CTL (WSA883X_DIG_CTRL_BASE+0x0030) +#define WSA883X_CDC_SPK_DSM_A1_0 (WSA883X_DIG_CTRL_BASE+0x0031) +#define WSA883X_CDC_SPK_DSM_A1_1 (WSA883X_DIG_CTRL_BASE+0x0032) +#define WSA883X_CDC_SPK_DSM_A2_0 (WSA883X_DIG_CTRL_BASE+0x0033) +#define WSA883X_CDC_SPK_DSM_A2_1 (WSA883X_DIG_CTRL_BASE+0x0034) +#define WSA883X_CDC_SPK_DSM_A3_0 (WSA883X_DIG_CTRL_BASE+0x0035) +#define WSA883X_CDC_SPK_DSM_A3_1 (WSA883X_DIG_CTRL_BASE+0x0036) +#define WSA883X_CDC_SPK_DSM_A4_0 (WSA883X_DIG_CTRL_BASE+0x0037) +#define WSA883X_CDC_SPK_DSM_A4_1 (WSA883X_DIG_CTRL_BASE+0x0038) +#define WSA883X_CDC_SPK_DSM_A5_0 (WSA883X_DIG_CTRL_BASE+0x0039) +#define WSA883X_CDC_SPK_DSM_A5_1 (WSA883X_DIG_CTRL_BASE+0x003A) +#define WSA883X_CDC_SPK_DSM_A6_0 (WSA883X_DIG_CTRL_BASE+0x003B) +#define WSA883X_CDC_SPK_DSM_A7_0 (WSA883X_DIG_CTRL_BASE+0x003C) +#define WSA883X_CDC_SPK_DSM_C_0 (WSA883X_DIG_CTRL_BASE+0x003D) +#define WSA883X_CDC_SPK_DSM_C_1 (WSA883X_DIG_CTRL_BASE+0x003E) +#define WSA883X_CDC_SPK_DSM_C_2 (WSA883X_DIG_CTRL_BASE+0x003F) +#define WSA883X_CDC_SPK_DSM_C_3 (WSA883X_DIG_CTRL_BASE+0x0040) +#define WSA883X_CDC_SPK_DSM_R1 (WSA883X_DIG_CTRL_BASE+0x0041) +#define WSA883X_CDC_SPK_DSM_R2 (WSA883X_DIG_CTRL_BASE+0x0042) +#define WSA883X_CDC_SPK_DSM_R3 (WSA883X_DIG_CTRL_BASE+0x0043) +#define WSA883X_CDC_SPK_DSM_R4 (WSA883X_DIG_CTRL_BASE+0x0044) +#define WSA883X_CDC_SPK_DSM_R5 (WSA883X_DIG_CTRL_BASE+0x0045) +#define WSA883X_CDC_SPK_DSM_R6 (WSA883X_DIG_CTRL_BASE+0x0046) +#define WSA883X_CDC_SPK_DSM_R7 (WSA883X_DIG_CTRL_BASE+0x0047) +#define WSA883X_CDC_SPK_GAIN_PDM_0 (WSA883X_DIG_CTRL_BASE+0x0048) +#define WSA883X_CDC_SPK_GAIN_PDM_1 (WSA883X_DIG_CTRL_BASE+0x0049) +#define WSA883X_CDC_SPK_GAIN_PDM_2 (WSA883X_DIG_CTRL_BASE+0x004A) +#define WSA883X_PDM_WD_CTL (WSA883X_DIG_CTRL_BASE+0x004B) +#define WSA883X_DEM_BYPASS_DATA0 (WSA883X_DIG_CTRL_BASE+0x004C) +#define WSA883X_DEM_BYPASS_DATA1 (WSA883X_DIG_CTRL_BASE+0x004D) +#define WSA883X_DEM_BYPASS_DATA2 (WSA883X_DIG_CTRL_BASE+0x004E) +#define WSA883X_DEM_BYPASS_DATA3 (WSA883X_DIG_CTRL_BASE+0x004F) +#define WSA883X_WAVG_CTL (WSA883X_DIG_CTRL_BASE+0x0050) +#define WSA883X_WAVG_LRA_PER_0 (WSA883X_DIG_CTRL_BASE+0x0051) +#define WSA883X_WAVG_LRA_PER_1 (WSA883X_DIG_CTRL_BASE+0x0052) +#define WSA883X_WAVG_DELTA_THETA_0 (WSA883X_DIG_CTRL_BASE+0x0053) +#define WSA883X_WAVG_DELTA_THETA_1 (WSA883X_DIG_CTRL_BASE+0x0054) +#define WSA883X_WAVG_DIRECT_AMP_0 (WSA883X_DIG_CTRL_BASE+0x0055) +#define WSA883X_WAVG_DIRECT_AMP_1 (WSA883X_DIG_CTRL_BASE+0x0056) +#define WSA883X_WAVG_PTRN_AMP0_0 (WSA883X_DIG_CTRL_BASE+0x0057) +#define WSA883X_WAVG_PTRN_AMP0_1 (WSA883X_DIG_CTRL_BASE+0x0058) +#define WSA883X_WAVG_PTRN_AMP1_0 (WSA883X_DIG_CTRL_BASE+0x0059) +#define WSA883X_WAVG_PTRN_AMP1_1 (WSA883X_DIG_CTRL_BASE+0x005A) +#define WSA883X_WAVG_PTRN_AMP2_0 (WSA883X_DIG_CTRL_BASE+0x005B) +#define WSA883X_WAVG_PTRN_AMP2_1 (WSA883X_DIG_CTRL_BASE+0x005C) +#define WSA883X_WAVG_PTRN_AMP3_0 (WSA883X_DIG_CTRL_BASE+0x005D) +#define WSA883X_WAVG_PTRN_AMP3_1 (WSA883X_DIG_CTRL_BASE+0x005E) +#define WSA883X_WAVG_PTRN_AMP4_0 (WSA883X_DIG_CTRL_BASE+0x005F) +#define WSA883X_WAVG_PTRN_AMP4_1 (WSA883X_DIG_CTRL_BASE+0x0060) +#define WSA883X_WAVG_PTRN_AMP5_0 (WSA883X_DIG_CTRL_BASE+0x0061) +#define WSA883X_WAVG_PTRN_AMP5_1 (WSA883X_DIG_CTRL_BASE+0x0062) +#define WSA883X_WAVG_PTRN_AMP6_0 (WSA883X_DIG_CTRL_BASE+0x0063) +#define WSA883X_WAVG_PTRN_AMP6_1 (WSA883X_DIG_CTRL_BASE+0x0064) +#define WSA883X_WAVG_PTRN_AMP7_0 (WSA883X_DIG_CTRL_BASE+0x0065) +#define WSA883X_WAVG_PTRN_AMP7_1 (WSA883X_DIG_CTRL_BASE+0x0066) +#define WSA883X_WAVG_PER_0_1 (WSA883X_DIG_CTRL_BASE+0x0067) +#define WSA883X_WAVG_PER_2_3 (WSA883X_DIG_CTRL_BASE+0x0068) +#define WSA883X_WAVG_PER_4_5 (WSA883X_DIG_CTRL_BASE+0x0069) +#define WSA883X_WAVG_PER_6_7 (WSA883X_DIG_CTRL_BASE+0x006A) +#define WSA883X_DRE_CTL_0 (WSA883X_DIG_CTRL_BASE+0x006C) +#define WSA883X_DRE_CTL_1 (WSA883X_DIG_CTRL_BASE+0x006D) +#define WSA883X_CLSH_CTL_0 (WSA883X_DIG_CTRL_BASE+0x0070) +#define WSA883X_CLSH_CTL_1 (WSA883X_DIG_CTRL_BASE+0x0071) +#define WSA883X_CLSH_V_HD_PA (WSA883X_DIG_CTRL_BASE+0x0072) +#define WSA883X_CLSH_V_PA_MIN (WSA883X_DIG_CTRL_BASE+0x0073) +#define WSA883X_CLSH_OVRD_VAL (WSA883X_DIG_CTRL_BASE+0x0074) +#define WSA883X_CLSH_HARD_MAX (WSA883X_DIG_CTRL_BASE+0x0075) +#define WSA883X_CLSH_SOFT_MAX (WSA883X_DIG_CTRL_BASE+0x0076) +#define WSA883X_CLSH_SIG_DP (WSA883X_DIG_CTRL_BASE+0x0077) +#define WSA883X_TAGC_CTL (WSA883X_DIG_CTRL_BASE+0x0078) +#define WSA883X_TAGC_TIME (WSA883X_DIG_CTRL_BASE+0x0079) +#define WSA883X_TAGC_E2E_GAIN (WSA883X_DIG_CTRL_BASE+0x007A) +#define WSA883X_TAGC_FORCE_VAL (WSA883X_DIG_CTRL_BASE+0x007B) +#define WSA883X_VAGC_CTL (WSA883X_DIG_CTRL_BASE+0x007C) +#define WSA883X_VAGC_TIME (WSA883X_DIG_CTRL_BASE+0x007D) +#define WSA883X_VAGC_ATTN_LVL_1_2 (WSA883X_DIG_CTRL_BASE+0x007E) +#define WSA883X_VAGC_ATTN_LVL_3 (WSA883X_DIG_CTRL_BASE+0x007F) +#define WSA883X_INTR_MODE (WSA883X_DIG_CTRL_BASE+0x0080) +#define WSA883X_INTR_MASK0 (WSA883X_DIG_CTRL_BASE+0x0081) +#define WSA883X_INTR_MASK1 (WSA883X_DIG_CTRL_BASE+0x0082) +#define WSA883X_INTR_STATUS0 (WSA883X_DIG_CTRL_BASE+0x0083) +#define WSA883X_INTR_STATUS1 (WSA883X_DIG_CTRL_BASE+0x0084) +#define WSA883X_INTR_CLEAR0 (WSA883X_DIG_CTRL_BASE+0x0085) +#define WSA883X_INTR_CLEAR1 (WSA883X_DIG_CTRL_BASE+0x0086) +#define WSA883X_INTR_LEVEL0 (WSA883X_DIG_CTRL_BASE+0x0087) +#define WSA883X_INTR_LEVEL1 (WSA883X_DIG_CTRL_BASE+0x0088) +#define WSA883X_INTR_SET0 (WSA883X_DIG_CTRL_BASE+0x0089) +#define WSA883X_INTR_SET1 (WSA883X_DIG_CTRL_BASE+0x008A) +#define WSA883X_INTR_TEST0 (WSA883X_DIG_CTRL_BASE+0x008B) +#define WSA883X_INTR_TEST1 (WSA883X_DIG_CTRL_BASE+0x008C) +#define WSA883X_OTP_CTRL0 (WSA883X_DIG_CTRL_BASE+0x0090) +#define WSA883X_OTP_CTRL1 (WSA883X_DIG_CTRL_BASE+0x0091) +#define WSA883X_HDRIVE_CTL_GROUP1 (WSA883X_DIG_CTRL_BASE+0x0092) +#define WSA883X_PIN_CTL (WSA883X_DIG_CTRL_BASE+0x0093) +#define WSA883X_PIN_CTL_OE (WSA883X_DIG_CTRL_BASE+0x0094) +#define WSA883X_PIN_WDATA_IOPAD (WSA883X_DIG_CTRL_BASE+0x0095) +#define WSA883X_PIN_STATUS (WSA883X_DIG_CTRL_BASE+0x0096) +#define WSA883X_I2C_SLAVE_CTL (WSA883X_DIG_CTRL_BASE+0x0097) +#define WSA883X_PDM_TEST_MODE (WSA883X_DIG_CTRL_BASE+0x00A0) +#define WSA883X_ATE_TEST_MODE (WSA883X_DIG_CTRL_BASE+0x00A1) +#define WSA883X_DRE_TEST (WSA883X_DIG_CTRL_BASE+0x00A2) +#define WSA883X_DIG_DEBUG_MODE (WSA883X_DIG_CTRL_BASE+0x00A3) +#define WSA883X_DIG_DEBUG_SEL (WSA883X_DIG_CTRL_BASE+0x00A4) +#define WSA883X_DIG_DEBUG_EN (WSA883X_DIG_CTRL_BASE+0x00A5) +#define WSA883X_SWR_HM_TEST0 (WSA883X_DIG_CTRL_BASE+0x00A6) +#define WSA883X_SWR_HM_TEST1 (WSA883X_DIG_CTRL_BASE+0x00A7) +#define WSA883X_SWR_PAD_CTL (WSA883X_DIG_CTRL_BASE+0x00A8) +#define WSA883X_TEMP_DETECT_DBG_CTL (WSA883X_DIG_CTRL_BASE+0x00A9) +#define WSA883X_TEMP_DEBUG_MSB (WSA883X_DIG_CTRL_BASE+0x00AA) +#define WSA883X_TEMP_DEBUG_LSB (WSA883X_DIG_CTRL_BASE+0x00AB) +#define WSA883X_SAMPLE_EDGE_SEL (WSA883X_DIG_CTRL_BASE+0x00AC) +#define WSA883X_TEST_MODE_CTL (WSA883X_DIG_CTRL_BASE+0x00AD) +#define WSA883X_IOPAD_CTL (WSA883X_DIG_CTRL_BASE+0x00AE) +#define WSA883X_SPARE_0 (WSA883X_DIG_CTRL_BASE+0x00B0) +#define WSA883X_SPARE_1 (WSA883X_DIG_CTRL_BASE+0x00B1) +#define WSA883X_SPARE_2 (WSA883X_DIG_CTRL_BASE+0x00B2) +#define WSA883X_SCODE (WSA883X_DIG_CTRL_BASE+0x00C0) + +#define WSA883X_DIG_TRIM_BASE (WSA883X_BASE+0x00000500) +#define WSA883X_PAGE_REGISTER (WSA883X_DIG_TRIM_BASE+0x0000) +#define WSA883X_OTP_REG_0 (WSA883X_DIG_TRIM_BASE+0x0080) +#define WSA883X_OTP_REG_1 (WSA883X_DIG_TRIM_BASE+0x0081) +#define WSA883X_OTP_REG_2 (WSA883X_DIG_TRIM_BASE+0x0082) +#define WSA883X_OTP_REG_3 (WSA883X_DIG_TRIM_BASE+0x0083) +#define WSA883X_OTP_REG_4 (WSA883X_DIG_TRIM_BASE+0x0084) +#define WSA883X_OTP_REG_5 (WSA883X_DIG_TRIM_BASE+0x0085) +#define WSA883X_OTP_REG_6 (WSA883X_DIG_TRIM_BASE+0x0086) +#define WSA883X_OTP_REG_7 (WSA883X_DIG_TRIM_BASE+0x0087) +#define WSA883X_OTP_REG_8 (WSA883X_DIG_TRIM_BASE+0x0088) +#define WSA883X_OTP_REG_9 (WSA883X_DIG_TRIM_BASE+0x0089) +#define WSA883X_OTP_REG_10 (WSA883X_DIG_TRIM_BASE+0x008A) +#define WSA883X_OTP_REG_11 (WSA883X_DIG_TRIM_BASE+0x008B) +#define WSA883X_OTP_REG_12 (WSA883X_DIG_TRIM_BASE+0x008C) +#define WSA883X_OTP_REG_13 (WSA883X_DIG_TRIM_BASE+0x008D) +#define WSA883X_OTP_REG_14 (WSA883X_DIG_TRIM_BASE+0x008E) +#define WSA883X_OTP_REG_15 (WSA883X_DIG_TRIM_BASE+0x008F) +#define WSA883X_OTP_REG_16 (WSA883X_DIG_TRIM_BASE+0x0090) +#define WSA883X_OTP_REG_17 (WSA883X_DIG_TRIM_BASE+0x0091) +#define WSA883X_OTP_REG_18 (WSA883X_DIG_TRIM_BASE+0x0092) +#define WSA883X_OTP_REG_19 (WSA883X_DIG_TRIM_BASE+0x0093) +#define WSA883X_OTP_REG_20 (WSA883X_DIG_TRIM_BASE+0x0094) +#define WSA883X_OTP_REG_21 (WSA883X_DIG_TRIM_BASE+0x0095) +#define WSA883X_OTP_REG_22 (WSA883X_DIG_TRIM_BASE+0x0096) +#define WSA883X_OTP_REG_23 (WSA883X_DIG_TRIM_BASE+0x0097) +#define WSA883X_OTP_REG_24 (WSA883X_DIG_TRIM_BASE+0x0098) +#define WSA883X_OTP_REG_25 (WSA883X_DIG_TRIM_BASE+0x0099) +#define WSA883X_OTP_REG_26 (WSA883X_DIG_TRIM_BASE+0x009A) +#define WSA883X_OTP_REG_27 (WSA883X_DIG_TRIM_BASE+0x009B) +#define WSA883X_OTP_REG_28 (WSA883X_DIG_TRIM_BASE+0x009C) +#define WSA883X_OTP_REG_29 (WSA883X_DIG_TRIM_BASE+0x009D) +#define WSA883X_OTP_REG_30 (WSA883X_DIG_TRIM_BASE+0x009E) +#define WSA883X_OTP_REG_31 (WSA883X_DIG_TRIM_BASE+0x009F) +#define WSA883X_OTP_REG_SCODE (WSA883X_DIG_TRIM_BASE+0x00A0) +#define WSA883X_OTP_REG_63 (WSA883X_DIG_TRIM_BASE+0x00BF) + +#define WSA883X_DIG_EMEM_BASE (WSA883X_BASE+0x000005C0) +#define WSA883X_EMEM_0 (WSA883X_DIG_EMEM_BASE+0x0000) +#define WSA883X_EMEM_1 (WSA883X_DIG_EMEM_BASE+0x0001) +#define WSA883X_EMEM_2 (WSA883X_DIG_EMEM_BASE+0x0002) +#define WSA883X_EMEM_3 (WSA883X_DIG_EMEM_BASE+0x0003) +#define WSA883X_EMEM_4 (WSA883X_DIG_EMEM_BASE+0x0004) +#define WSA883X_EMEM_5 (WSA883X_DIG_EMEM_BASE+0x0005) +#define WSA883X_EMEM_6 (WSA883X_DIG_EMEM_BASE+0x0006) +#define WSA883X_EMEM_7 (WSA883X_DIG_EMEM_BASE+0x0007) +#define WSA883X_EMEM_8 (WSA883X_DIG_EMEM_BASE+0x0008) +#define WSA883X_EMEM_9 (WSA883X_DIG_EMEM_BASE+0x0009) +#define WSA883X_EMEM_10 (WSA883X_DIG_EMEM_BASE+0x000A) +#define WSA883X_EMEM_11 (WSA883X_DIG_EMEM_BASE+0x000B) +#define WSA883X_EMEM_12 (WSA883X_DIG_EMEM_BASE+0x000C) +#define WSA883X_EMEM_13 (WSA883X_DIG_EMEM_BASE+0x000D) +#define WSA883X_EMEM_14 (WSA883X_DIG_EMEM_BASE+0x000E) +#define WSA883X_EMEM_15 (WSA883X_DIG_EMEM_BASE+0x000F) +#define WSA883X_EMEM_16 (WSA883X_DIG_EMEM_BASE+0x0010) +#define WSA883X_EMEM_17 (WSA883X_DIG_EMEM_BASE+0x0011) +#define WSA883X_EMEM_18 (WSA883X_DIG_EMEM_BASE+0x0012) +#define WSA883X_EMEM_19 (WSA883X_DIG_EMEM_BASE+0x0013) +#define WSA883X_EMEM_20 (WSA883X_DIG_EMEM_BASE+0x0014) +#define WSA883X_EMEM_21 (WSA883X_DIG_EMEM_BASE+0x0015) +#define WSA883X_EMEM_22 (WSA883X_DIG_EMEM_BASE+0x0016) +#define WSA883X_EMEM_23 (WSA883X_DIG_EMEM_BASE+0x0017) +#define WSA883X_EMEM_24 (WSA883X_DIG_EMEM_BASE+0x0018) +#define WSA883X_EMEM_25 (WSA883X_DIG_EMEM_BASE+0x0019) +#define WSA883X_EMEM_26 (WSA883X_DIG_EMEM_BASE+0x001A) +#define WSA883X_EMEM_27 (WSA883X_DIG_EMEM_BASE+0x001B) +#define WSA883X_EMEM_28 (WSA883X_DIG_EMEM_BASE+0x001C) +#define WSA883X_EMEM_29 (WSA883X_DIG_EMEM_BASE+0x001D) +#define WSA883X_EMEM_30 (WSA883X_DIG_EMEM_BASE+0x001E) +#define WSA883X_EMEM_31 (WSA883X_DIG_EMEM_BASE+0x001F) +#define WSA883X_EMEM_32 (WSA883X_DIG_EMEM_BASE+0x0020) +#define WSA883X_EMEM_33 (WSA883X_DIG_EMEM_BASE+0x0021) +#define WSA883X_EMEM_34 (WSA883X_DIG_EMEM_BASE+0x0022) +#define WSA883X_EMEM_35 (WSA883X_DIG_EMEM_BASE+0x0023) +#define WSA883X_EMEM_36 (WSA883X_DIG_EMEM_BASE+0x0024) +#define WSA883X_EMEM_37 (WSA883X_DIG_EMEM_BASE+0x0025) +#define WSA883X_EMEM_38 (WSA883X_DIG_EMEM_BASE+0x0026) +#define WSA883X_EMEM_39 (WSA883X_DIG_EMEM_BASE+0x0027) +#define WSA883X_EMEM_40 (WSA883X_DIG_EMEM_BASE+0x0028) +#define WSA883X_EMEM_41 (WSA883X_DIG_EMEM_BASE+0x0029) +#define WSA883X_EMEM_42 (WSA883X_DIG_EMEM_BASE+0x002A) +#define WSA883X_EMEM_43 (WSA883X_DIG_EMEM_BASE+0x002B) +#define WSA883X_EMEM_44 (WSA883X_DIG_EMEM_BASE+0x002C) +#define WSA883X_EMEM_45 (WSA883X_DIG_EMEM_BASE+0x002D) +#define WSA883X_EMEM_46 (WSA883X_DIG_EMEM_BASE+0x002E) +#define WSA883X_EMEM_47 (WSA883X_DIG_EMEM_BASE+0x002F) +#define WSA883X_EMEM_48 (WSA883X_DIG_EMEM_BASE+0x0030) +#define WSA883X_EMEM_49 (WSA883X_DIG_EMEM_BASE+0x0031) +#define WSA883X_EMEM_50 (WSA883X_DIG_EMEM_BASE+0x0032) +#define WSA883X_EMEM_51 (WSA883X_DIG_EMEM_BASE+0x0033) +#define WSA883X_EMEM_52 (WSA883X_DIG_EMEM_BASE+0x0034) +#define WSA883X_EMEM_53 (WSA883X_DIG_EMEM_BASE+0x0035) +#define WSA883X_EMEM_54 (WSA883X_DIG_EMEM_BASE+0x0036) +#define WSA883X_EMEM_55 (WSA883X_DIG_EMEM_BASE+0x0037) +#define WSA883X_EMEM_56 (WSA883X_DIG_EMEM_BASE+0x0038) +#define WSA883X_EMEM_57 (WSA883X_DIG_EMEM_BASE+0x0039) +#define WSA883X_EMEM_58 (WSA883X_DIG_EMEM_BASE+0x003A) +#define WSA883X_EMEM_59 (WSA883X_DIG_EMEM_BASE+0x003B) +#define WSA883X_EMEM_60 (WSA883X_DIG_EMEM_BASE+0x003C) +#define WSA883X_EMEM_61 (WSA883X_DIG_EMEM_BASE+0x003D) +#define WSA883X_EMEM_62 (WSA883X_DIG_EMEM_BASE+0x003E) +#define WSA883X_EMEM_63 (WSA883X_DIG_EMEM_BASE+0x003F) + +#define WSA883X_NUM_REGISTERS (WSA883X_EMEM_63+1) +#define WSA883X_MAX_REGISTER (WSA883X_NUM_REGISTERS-1) + +#endif /* WSA883X_REGISTERS_H */ diff --git a/asoc/codecs/wsa883x/wsa883x-regmap.c b/asoc/codecs/wsa883x/wsa883x-regmap.c new file mode 100644 index 0000000000..8394e9c73e --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x-regmap.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "wsa883x-registers.h" +#include "wsa883x.h" + +extern const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS]; + +static struct reg_default wsa883x_defaults[] = { + {WSA883X_REF_CTRL, 0x6C}, + {WSA883X_TEST_CTL_0, 0x06}, + {WSA883X_BIAS_0, 0xD2}, + {WSA883X_OP_CTL, 0xE0}, + {WSA883X_IREF_CTL, 0x58}, + {WSA883X_ISENS_CTL, 0x47}, + {WSA883X_CLK_CTL, 0x87}, + {WSA883X_TEST_CTL_1, 0x00}, + {WSA883X_BIAS_1, 0x51}, + {WSA883X_ADC_CTL, 0x03}, + {WSA883X_DOUT_MSB, 0x00}, + {WSA883X_DOUT_LSB, 0x00}, + {WSA883X_VBAT_SNS, 0x00}, + {WSA883X_ITRIM_CODE, 0x1F}, + {WSA883X_EN, 0x00}, + {WSA883X_OVERRIDE1, 0x00}, + {WSA883X_OVERRIDE2, 0x08}, + {WSA883X_VSENSE1, 0xD3}, + {WSA883X_ISENSE1, 0xD4}, + {WSA883X_ISENSE2, 0x20}, + {WSA883X_ISENSE_CAL, 0x00}, + {WSA883X_MISC, 0x00}, + {WSA883X_ADC_0, 0x00}, + {WSA883X_ADC_1, 0x00}, + {WSA883X_ADC_2, 0x00}, + {WSA883X_ADC_3, 0x00}, + {WSA883X_ADC_4, 0x45}, + {WSA883X_ADC_5, 0x20}, + {WSA883X_ADC_6, 0x10}, + {WSA883X_ADC_7, 0x00}, + {WSA883X_STATUS, 0x00}, + {WSA883X_DAC_CTRL_REG, 0x41}, + {WSA883X_DAC_EN_DEBUG_REG, 0x00}, + {WSA883X_DAC_OPAMP_BIAS1_REG, 0x48}, + {WSA883X_DAC_OPAMP_BIAS2_REG, 0x48}, + {WSA883X_DAC_VCM_CTRL_REG, 0x0B}, + {WSA883X_DAC_VOLTAGE_CTRL_REG, 0x05}, + {WSA883X_ATEST1_REG, 0x00}, + {WSA883X_ATEST2_REG, 0x00}, + {WSA883X_SPKR_TOP_BIAS_REG1, 0x4A}, + {WSA883X_SPKR_TOP_BIAS_REG2, 0x65}, + {WSA883X_SPKR_TOP_BIAS_REG3, 0x55}, + {WSA883X_SPKR_TOP_BIAS_REG4, 0xA9}, + {WSA883X_SPKR_CLIP_DET_REG, 0x00}, + {WSA883X_SPKR_DRV_LF_BLK_EN, 0x0F}, + {WSA883X_SPKR_DRV_LF_EN, 0x0A}, + {WSA883X_SPKR_DRV_LF_MASK_DCC_CTL, 0x00}, + {WSA883X_SPKR_DRV_LF_MISC_CTL, 0x32}, + {WSA883X_SPKR_DRV_LF_REG_GAIN, 0x00}, + {WSA883X_SPKR_DRV_LF_OS_CAL_CTL1, 0x90}, + {WSA883X_SPKR_DRV_LF_OS_CAL_CTL, 0x00}, + {WSA883X_SPKR_PWM_CLK_CTL, 0x00}, + {WSA883X_SPKR_PDRV_HS_CTL, 0x50}, + {WSA883X_SPKR_PDRV_LS_CTL, 0x48}, + {WSA883X_SPKR_PWRSTG_DBG, 0x00}, + {WSA883X_SPKR_OCP_CTL, 0x00}, + {WSA883X_SPKR_BBM_CTL, 0x90}, + {WSA883X_PA_STATUS0, 0x00}, + {WSA883X_PA_STATUS1, 0x00}, + {WSA883X_PA_STATUS2, 0x00}, + {WSA883X_EN_CTRL, 0x54}, + {WSA883X_CURRENT_LIMIT, 0x90}, + {WSA883X_IBIAS1, 0x00}, + {WSA883X_IBIAS2, 0x00}, + {WSA883X_IBIAS3, 0x00}, + {WSA883X_LDO_PROG, 0x2A}, + {WSA883X_STABILITY_CTRL1, 0x8E}, + {WSA883X_STABILITY_CTRL2, 0x00}, + {WSA883X_PWRSTAGE_CTRL1, 0x00}, + {WSA883X_PWRSTAGE_CTRL2, 0x40}, + {WSA883X_UVLO, 0xE9}, + {WSA883X_SEQUENCE_CTRL, 0x11}, + {WSA883X_ZX_CTRL_1, 0xF0}, + {WSA883X_ZX_CTRL_2, 0x06}, + {WSA883X_MISC1, 0x02}, + {WSA883X_MISC2, 0x81}, + {WSA883X_GMAMP_SUP1, 0x84}, + {WSA883X_PWRSTAGE_CTRL3, 0x14}, + {WSA883X_PRSTAGE_CTRL4, 0x5F}, + {WSA883X_SPARE1, 0x00}, + {WSA883X_PON_CTL_0, 0xE3}, + {WSA883X_PON_CLT_1, 0x70}, + {WSA883X_PON_CTL_2, 0x00}, + {WSA883X_PON_CTL_3, 0x00}, + {WSA883X_PON_CTL_4, 0x00}, + {WSA883X_CKWD_CTL_0, 0x34}, + {WSA883X_CKWD_CTL_1, 0x80}, + {WSA883X_CKWD_CTL_2, 0x00}, + {WSA883X_CKSK_CTL_0, 0x0A}, + {WSA883X_TEST_0, 0x00}, + {WSA883X_TEST_1, 0x00}, + {WSA883X_STATUS_0, 0x00}, + {WSA883X_STATUS_1, 0x00}, + {WSA883X_PAGE_REGISTER, 0x00}, + {WSA883X_CHIP_ID0, 0x00}, + {WSA883X_CHIP_ID1, 0x00}, + {WSA883X_CHIP_ID2, 0x02}, + {WSA883X_CHIP_ID3, 0x02}, + {WSA883X_BUS_ID, 0x00}, + {WSA883X_CDC_RST_CTL, 0x01}, + {WSA883X_TOP_CLK_CFG, 0x00}, + {WSA883X_CDC_PATH_MODE, 0x00}, + {WSA883X_CDC_CLK_CTL, 0xFF}, + {WSA883X_SWR_RESET_EN, 0x00}, + {WSA883X_PA_FSM_CTL, 0x00}, + {WSA883X_PA_FSM_TIMER0, 0x80}, + {WSA883X_PA_FSM_TIMER1, 0x80}, + {WSA883X_PA_FSM_STA, 0x00}, + {WSA883X_PA_FSM_ERR_COND, 0x00}, + {WSA883X_PA_FSM_MSK, 0x00}, + {WSA883X_PA_FSM_BYP, 0x00}, + {WSA883X_TADC_VALUE_CTL, 0x03}, + {WSA883X_TEMP_DETECT_CTL, 0x01}, + {WSA883X_TEMP_MSB, 0x00}, + {WSA883X_TEMP_LSB, 0x00}, + {WSA883X_TEMP_CONFIG0, 0x00}, + {WSA883X_TEMP_CONFIG1, 0x00}, + {WSA883X_VBAT_ADC_FLT_CTL, 0x00}, + {WSA883X_VBAT_DIN_MSB, 0x00}, + {WSA883X_VBAT_DIN_LSB, 0x00}, + {WSA883X_VBAT_DOUT, 0x00}, + {WSA883X_SDM_PDM9_LSB, 0x00}, + {WSA883X_SDM_PDM9_MSB, 0x00}, + {WSA883X_CDC_RX_CTL, 0xFE}, + {WSA883X_CDC_SPK_DSM_A1_0, 0x00}, + {WSA883X_CDC_SPK_DSM_A1_1, 0x01}, + {WSA883X_CDC_SPK_DSM_A2_0, 0x96}, + {WSA883X_CDC_SPK_DSM_A2_1, 0x09}, + {WSA883X_CDC_SPK_DSM_A3_0, 0xAB}, + {WSA883X_CDC_SPK_DSM_A3_1, 0x05}, + {WSA883X_CDC_SPK_DSM_A4_0, 0x1C}, + {WSA883X_CDC_SPK_DSM_A4_1, 0x02}, + {WSA883X_CDC_SPK_DSM_A5_0, 0x17}, + {WSA883X_CDC_SPK_DSM_A5_1, 0x02}, + {WSA883X_CDC_SPK_DSM_A6_0, 0xAA}, + {WSA883X_CDC_SPK_DSM_A7_0, 0xE3}, + {WSA883X_CDC_SPK_DSM_C_0, 0x69}, + {WSA883X_CDC_SPK_DSM_C_1, 0x54}, + {WSA883X_CDC_SPK_DSM_C_2, 0x02}, + {WSA883X_CDC_SPK_DSM_C_3, 0x15}, + {WSA883X_CDC_SPK_DSM_R1, 0xA4}, + {WSA883X_CDC_SPK_DSM_R2, 0xB5}, + {WSA883X_CDC_SPK_DSM_R3, 0x86}, + {WSA883X_CDC_SPK_DSM_R4, 0x85}, + {WSA883X_CDC_SPK_DSM_R5, 0xAA}, + {WSA883X_CDC_SPK_DSM_R6, 0xE2}, + {WSA883X_CDC_SPK_DSM_R7, 0x62}, + {WSA883X_CDC_SPK_GAIN_PDM_0, 0x00}, + {WSA883X_CDC_SPK_GAIN_PDM_1, 0xFC}, + {WSA883X_CDC_SPK_GAIN_PDM_2, 0x05}, + {WSA883X_PDM_WD_CTL, 0x00}, + {WSA883X_DEM_BYPASS_DATA0, 0x00}, + {WSA883X_DEM_BYPASS_DATA1, 0x00}, + {WSA883X_DEM_BYPASS_DATA2, 0x00}, + {WSA883X_DEM_BYPASS_DATA3, 0x00}, + {WSA883X_WAVG_CTL, 0x06}, + {WSA883X_WAVG_LRA_PER_0, 0xD1}, + {WSA883X_WAVG_LRA_PER_1, 0x00}, + {WSA883X_WAVG_DELTA_THETA_0, 0xE6}, + {WSA883X_WAVG_DELTA_THETA_1, 0x04}, + {WSA883X_WAVG_DIRECT_AMP_0, 0x50}, + {WSA883X_WAVG_DIRECT_AMP_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP0_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP0_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP1_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP1_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP2_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP2_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP3_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP3_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP4_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP4_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP5_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP5_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP6_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP6_1, 0x00}, + {WSA883X_WAVG_PTRN_AMP7_0, 0x50}, + {WSA883X_WAVG_PTRN_AMP7_1, 0x00}, + {WSA883X_WAVG_PER_0_1, 0x88}, + {WSA883X_WAVG_PER_2_3, 0x88}, + {WSA883X_WAVG_PER_4_5, 0x88}, + {WSA883X_WAVG_PER_6_7, 0x88}, + {WSA883X_DRE_CTL_0, 0x30}, + {WSA883X_DRE_CTL_1, 0x20}, + {WSA883X_CLSH_CTL_0, 0x37}, + {WSA883X_CLSH_CTL_1, 0x81}, + {WSA883X_CLSH_V_HD_PA, 0x0F}, + {WSA883X_CLSH_V_PA_MIN, 0x00}, + {WSA883X_CLSH_OVRD_VAL, 0x00}, + {WSA883X_CLSH_HARD_MAX, 0xFF}, + {WSA883X_CLSH_SOFT_MAX, 0xFF}, + {WSA883X_CLSH_SIG_DP, 0x00}, + {WSA883X_TAGC_CTL, 0x10}, + {WSA883X_TAGC_TIME, 0x20}, + {WSA883X_TAGC_E2E_GAIN, 0x02}, + {WSA883X_TAGC_FORCE_VAL, 0x00}, + {WSA883X_VAGC_CTL, 0x00}, + {WSA883X_VAGC_TIME, 0x08}, + {WSA883X_VAGC_ATTN_LVL_1_2, 0x21}, + {WSA883X_VAGC_ATTN_LVL_3, 0x03}, + {WSA883X_INTR_MODE, 0x00}, + {WSA883X_INTR_MASK0, 0x1B}, + {WSA883X_INTR_MASK1, 0x03}, + {WSA883X_INTR_STATUS0, 0x00}, + {WSA883X_INTR_STATUS1, 0x00}, + {WSA883X_INTR_CLEAR0, 0x00}, + {WSA883X_INTR_CLEAR1, 0x03}, + {WSA883X_INTR_LEVEL0, 0x00}, + {WSA883X_INTR_LEVEL1, 0x03}, + {WSA883X_INTR_SET0, 0x00}, + {WSA883X_INTR_SET1, 0x03}, + {WSA883X_INTR_TEST0, 0x00}, + {WSA883X_INTR_TEST1, 0x03}, + {WSA883X_OTP_CTRL0, 0x00}, + {WSA883X_OTP_CTRL1, 0x00}, + {WSA883X_HDRIVE_CTL_GROUP1, 0x00}, + {WSA883X_PIN_CTL, 0x04}, + {WSA883X_PIN_CTL_OE, 0x00}, + {WSA883X_PIN_WDATA_IOPAD, 0x00}, + {WSA883X_PIN_STATUS, 0x00}, + {WSA883X_I2C_SLAVE_CTL, 0x00}, + {WSA883X_PDM_TEST_MODE, 0x00}, + {WSA883X_ATE_TEST_MODE, 0x00}, + {WSA883X_DRE_TEST, 0x00}, + {WSA883X_DIG_DEBUG_MODE, 0x00}, + {WSA883X_DIG_DEBUG_SEL, 0x00}, + {WSA883X_DIG_DEBUG_EN, 0x00}, + {WSA883X_SWR_HM_TEST0, 0x08}, + {WSA883X_SWR_HM_TEST1, 0x00}, + {WSA883X_SWR_PAD_CTL, 0x45}, + {WSA883X_TEMP_DETECT_DBG_CTL, 0x00}, + {WSA883X_TEMP_DEBUG_MSB, 0x00}, + {WSA883X_TEMP_DEBUG_LSB, 0x00}, + {WSA883X_SAMPLE_EDGE_SEL, 0x7F}, + {WSA883X_TEST_MODE_CTL, 0x00}, + {WSA883X_IOPAD_CTL, 0x00}, + {WSA883X_SPARE_0, 0x00}, + {WSA883X_SPARE_1, 0x00}, + {WSA883X_SPARE_2, 0x00}, + {WSA883X_SCODE, 0x00}, + {WSA883X_PAGE_REGISTER, 0x00}, + {WSA883X_OTP_REG_0, 0x01}, + {WSA883X_OTP_REG_1, 0xFF}, + {WSA883X_OTP_REG_2, 0xC0}, + {WSA883X_OTP_REG_3, 0xFF}, + {WSA883X_OTP_REG_4, 0xC0}, + {WSA883X_OTP_REG_5, 0xFF}, + {WSA883X_OTP_REG_6, 0xFF}, + {WSA883X_OTP_REG_7, 0xFF}, + {WSA883X_OTP_REG_8, 0xFF}, + {WSA883X_OTP_REG_9, 0xFF}, + {WSA883X_OTP_REG_10, 0xFF}, + {WSA883X_OTP_REG_11, 0xFF}, + {WSA883X_OTP_REG_12, 0xFF}, + {WSA883X_OTP_REG_13, 0xFF}, + {WSA883X_OTP_REG_14, 0xFF}, + {WSA883X_OTP_REG_15, 0xFF}, + {WSA883X_OTP_REG_16, 0xFF}, + {WSA883X_OTP_REG_17, 0xFF}, + {WSA883X_OTP_REG_18, 0xFF}, + {WSA883X_OTP_REG_19, 0xFF}, + {WSA883X_OTP_REG_20, 0xFF}, + {WSA883X_OTP_REG_21, 0xFF}, + {WSA883X_OTP_REG_22, 0xFF}, + {WSA883X_OTP_REG_23, 0xFF}, + {WSA883X_OTP_REG_24, 0x03}, + {WSA883X_OTP_REG_25, 0x01}, + {WSA883X_OTP_REG_26, 0x03}, + {WSA883X_OTP_REG_27, 0x11}, + {WSA883X_OTP_REG_28, 0x3F}, + {WSA883X_OTP_REG_29, 0x3F}, + {WSA883X_OTP_REG_30, 0x01}, + {WSA883X_OTP_REG_31, 0x01}, + {WSA883X_OTP_REG_SCODE, 0x00}, + {WSA883X_OTP_REG_63, 0x40}, + {WSA883X_EMEM_0, 0x00}, + {WSA883X_EMEM_1, 0x00}, + {WSA883X_EMEM_2, 0x00}, + {WSA883X_EMEM_3, 0x00}, + {WSA883X_EMEM_4, 0x00}, + {WSA883X_EMEM_5, 0x00}, + {WSA883X_EMEM_6, 0x00}, + {WSA883X_EMEM_7, 0x00}, + {WSA883X_EMEM_8, 0x00}, + {WSA883X_EMEM_9, 0x00}, + {WSA883X_EMEM_10, 0x00}, + {WSA883X_EMEM_11, 0x00}, + {WSA883X_EMEM_12, 0x00}, + {WSA883X_EMEM_13, 0x00}, + {WSA883X_EMEM_14, 0x00}, + {WSA883X_EMEM_15, 0x00}, + {WSA883X_EMEM_16, 0x00}, + {WSA883X_EMEM_17, 0x00}, + {WSA883X_EMEM_18, 0x00}, + {WSA883X_EMEM_19, 0x00}, + {WSA883X_EMEM_20, 0x00}, + {WSA883X_EMEM_21, 0x00}, + {WSA883X_EMEM_22, 0x00}, + {WSA883X_EMEM_23, 0x00}, + {WSA883X_EMEM_24, 0x00}, + {WSA883X_EMEM_25, 0x00}, + {WSA883X_EMEM_26, 0x00}, + {WSA883X_EMEM_27, 0x00}, + {WSA883X_EMEM_28, 0x00}, + {WSA883X_EMEM_29, 0x00}, + {WSA883X_EMEM_30, 0x00}, + {WSA883X_EMEM_31, 0x00}, + {WSA883X_EMEM_32, 0x00}, + {WSA883X_EMEM_33, 0x00}, + {WSA883X_EMEM_34, 0x00}, + {WSA883X_EMEM_35, 0x00}, + {WSA883X_EMEM_36, 0x00}, + {WSA883X_EMEM_37, 0x00}, + {WSA883X_EMEM_38, 0x00}, + {WSA883X_EMEM_39, 0x00}, + {WSA883X_EMEM_40, 0x00}, + {WSA883X_EMEM_41, 0x00}, + {WSA883X_EMEM_42, 0x00}, + {WSA883X_EMEM_43, 0x00}, + {WSA883X_EMEM_44, 0x00}, + {WSA883X_EMEM_45, 0x00}, + {WSA883X_EMEM_46, 0x00}, + {WSA883X_EMEM_47, 0x00}, + {WSA883X_EMEM_48, 0x00}, + {WSA883X_EMEM_49, 0x00}, + {WSA883X_EMEM_50, 0x00}, + {WSA883X_EMEM_51, 0x00}, + {WSA883X_EMEM_52, 0x00}, + {WSA883X_EMEM_53, 0x00}, + {WSA883X_EMEM_54, 0x00}, + {WSA883X_EMEM_55, 0x00}, + {WSA883X_EMEM_56, 0x00}, + {WSA883X_EMEM_57, 0x00}, + {WSA883X_EMEM_58, 0x00}, + {WSA883X_EMEM_59, 0x00}, + {WSA883X_EMEM_60, 0x00}, + {WSA883X_EMEM_61, 0x00}, + {WSA883X_EMEM_62, 0x00}, + {WSA883X_EMEM_63, 0x00}, +}; + +static bool wsa883x_readable_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA883X_BASE) + return 0; + + return wsa883x_reg_access[WSA883X_REG(reg)] & RD_REG; +} + +static bool wsa883x_writeable_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA883X_BASE) + return 0; + + return wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG; +} + +static bool wsa883x_volatile_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA883X_BASE) + return 0; + + return ((wsa883x_reg_access[WSA883X_REG(reg)] & RD_REG) && + !(wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG)); +} + +struct regmap_config wsa881x_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wsa883x_defaults, + .num_reg_defaults = ARRAY_SIZE(wsa883x_defaults), + .max_register = WSA883X_MAX_REGISTER, + .volatile_reg = wsa883x_volatile_register, + .readable_reg = wsa883x_readable_register, + .writeable_reg = wsa883x_writeable_register, + .reg_format_endian = REGMAP_ENDIAN_NATIVE, + .val_format_endian = REGMAP_ENDIAN_NATIVE, + .can_multi_write = true, +}; diff --git a/asoc/codecs/wsa883x/wsa883x-tables.c b/asoc/codecs/wsa883x/wsa883x-tables.c new file mode 100644 index 0000000000..16b0a880a7 --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x-tables.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "wsa883x-registers.h" + +const u8 wsa883x_reg_readable[WSA883X_NUM_REGISTERS] = { + [WSA883X_REG(WSA883X_REF_CTRL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEST_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_BIAS_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OP_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_IREF_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ISENS_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLK_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEST_CTL_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_BIAS_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DOUT_MSB)] = RD_REG, + [WSA883X_REG(WSA883X_DOUT_LSB)] = RD_REG, + [WSA883X_REG(WSA883X_VBAT_SNS)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ITRIM_CODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OVERRIDE1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OVERRIDE2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VSENSE1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ISENSE1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ISENSE2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ISENSE_CAL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_MISC)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_5)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_6)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ADC_7)] = RD_WR_REG, + [WSA883X_REG(WSA883X_STATUS)] = RD_REG, + [WSA883X_REG(WSA883X_DAC_CTRL_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DAC_EN_DEBUG_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DAC_OPAMP_BIAS1_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DAC_OPAMP_BIAS2_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DAC_VCM_CTRL_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DAC_VOLTAGE_CTRL_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ATEST1_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ATEST2_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_CLIP_DET_REG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_BLK_EN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_EN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_MASK_DCC_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_MISC_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_REG_GAIN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_PWM_CLK_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_PDRV_HS_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_PDRV_LS_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_PWRSTG_DBG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_OCP_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPKR_BBM_CTL)] = RD_REG, + [WSA883X_REG(WSA883X_PA_STATUS0)] = RD_REG, + [WSA883X_REG(WSA883X_PA_STATUS1)] = RD_REG, + [WSA883X_REG(WSA883X_PA_STATUS2)] = RD_REG, + [WSA883X_REG(WSA883X_EN_CTRL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CURRENT_LIMIT)] = RD_WR_REG, + [WSA883X_REG(WSA883X_IBIAS1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_IBIAS2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_IBIAS3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_LDO_PROG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_STABILITY_CTRL1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_STABILITY_CTRL2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PWRSTAGE_CTRL1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PWRSTAGE_CTRL2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_UVLO)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SEQUENCE_CTRL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ZX_CTRL_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ZX_CTRL_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_MISC1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_MISC2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_GMAMP_SUP1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PWRSTAGE_CTRL3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PRSTAGE_CTRL4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPARE1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PON_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PON_CLT_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PON_CTL_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PON_CTL_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PON_CTL_4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CKWD_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CKWD_CTL_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CKWD_CTL_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CKSK_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEST_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEST_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_STATUS_0)] = RD_REG, + [WSA883X_REG(WSA883X_STATUS_1)] = RD_REG, + [WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CHIP_ID0)] = RD_REG, + [WSA883X_REG(WSA883X_CHIP_ID1)] = RD_REG, + [WSA883X_REG(WSA883X_CHIP_ID2)] = RD_REG, + [WSA883X_REG(WSA883X_CHIP_ID3)] = RD_REG, + [WSA883X_REG(WSA883X_BUS_ID)] = RD_REG, + [WSA883X_REG(WSA883X_CDC_RST_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TOP_CLK_CFG)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_PATH_MODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_CLK_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SWR_RESET_EN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PA_FSM_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PA_FSM_TIMER0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PA_FSM_TIMER1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PA_FSM_STA)] = RD_REG, + [WSA883X_REG(WSA883X_PA_FSM_ERR_COND)] = RD_REG, + [WSA883X_REG(WSA883X_PA_FSM_MSK)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PA_FSM_BYP)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TADC_VALUE_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_DETECT_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_MSB)] = RD_REG, + [WSA883X_REG(WSA883X_TEMP_LSB)] = RD_REG, + [WSA883X_REG(WSA883X_TEMP_CONFIG0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_CONFIG1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VBAT_ADC_FLT_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VBAT_DIN_MSB)] = RD_REG, + [WSA883X_REG(WSA883X_VBAT_DIN_LSB)] = RD_REG, + [WSA883X_REG(WSA883X_VBAT_DOUT)] = RD_REG, + [WSA883X_REG(WSA883X_SDM_PDM9_LSB)] = RD_REG, + [WSA883X_REG(WSA883X_SDM_PDM9_MSB)] = RD_REG, + [WSA883X_REG(WSA883X_CDC_RX_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A1_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A1_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A2_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A2_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A3_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A3_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A4_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A4_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A5_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A5_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A6_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_A7_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_C_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_C_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_C_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_C_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R5)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R6)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_DSM_R7)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PDM_WD_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DEM_BYPASS_DATA0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DEM_BYPASS_DATA1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DEM_BYPASS_DATA2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DEM_BYPASS_DATA3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_LRA_PER_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_LRA_PER_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_DELTA_THETA_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_DELTA_THETA_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_DIRECT_AMP_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_DIRECT_AMP_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP0_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP0_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP1_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP1_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP2_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP2_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP3_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP3_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP4_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP4_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP5_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP5_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP6_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP6_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP7_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PTRN_AMP7_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PER_0_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PER_2_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PER_4_5)] = RD_WR_REG, + [WSA883X_REG(WSA883X_WAVG_PER_6_7)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DRE_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DRE_CTL_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_CTL_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_CTL_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_V_HD_PA)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_V_PA_MIN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_OVRD_VAL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_HARD_MAX)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_SOFT_MAX)] = RD_WR_REG, + [WSA883X_REG(WSA883X_CLSH_SIG_DP)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TAGC_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TAGC_TIME)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TAGC_E2E_GAIN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TAGC_FORCE_VAL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VAGC_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VAGC_TIME)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VAGC_ATTN_LVL_1_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_VAGC_ATTN_LVL_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_MODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_MASK0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_MASK1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_STATUS0)] = RD_REG, + [WSA883X_REG(WSA883X_INTR_STATUS1)] = RD_REG, + [WSA883X_REG(WSA883X_INTR_CLEAR0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_CLEAR1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_LEVEL0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_LEVEL1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_SET0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_SET1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_TEST0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_INTR_TEST1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_CTRL0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_CTRL1)] = RD_REG, + [WSA883X_REG(WSA883X_HDRIVE_CTL_GROUP1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PIN_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PIN_CTL_OE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PIN_WDATA_IOPAD)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PIN_STATUS)] = RD_REG, + [WSA883X_REG(WSA883X_I2C_SLAVE_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PDM_TEST_MODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_ATE_TEST_MODE)] = RD_REG, + [WSA883X_REG(WSA883X_DRE_TEST)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DIG_DEBUG_MODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DIG_DEBUG_SEL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_DIG_DEBUG_EN)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SWR_HM_TEST0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SWR_HM_TEST1)] = RD_REG, + [WSA883X_REG(WSA883X_SWR_PAD_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_DETECT_DBG_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_DEBUG_MSB)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEMP_DEBUG_LSB)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SAMPLE_EDGE_SEL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_TEST_MODE_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_IOPAD_CTL)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPARE_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPARE_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SPARE_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_SCODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_5)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_6)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_7)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_8)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_9)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_10)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_11)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_12)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_13)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_14)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_15)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_16)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_17)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_18)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_19)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_20)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_21)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_22)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_23)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_24)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_25)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_26)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_27)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_28)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_29)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_30)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_31)] = RD_REG, + [WSA883X_REG(WSA883X_OTP_REG_SCODE)] = RD_WR_REG, + [WSA883X_REG(WSA883X_OTP_REG_63)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_0)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_1)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_2)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_3)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_4)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_5)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_6)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_7)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_8)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_9)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_10)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_11)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_12)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_13)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_14)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_15)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_16)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_17)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_18)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_19)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_20)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_21)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_22)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_23)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_24)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_25)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_26)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_27)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_28)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_29)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_30)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_31)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_32)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_33)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_34)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_35)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_36)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_37)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_38)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_39)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_40)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_41)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_42)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_43)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_44)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_45)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_46)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_47)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_48)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_49)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_50)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_51)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_52)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_53)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_54)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_55)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_56)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_57)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_58)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_59)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_60)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_61)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_62)] = RD_WR_REG, + [WSA883X_REG(WSA883X_EMEM_63)] = RD_WR_REG, +}; diff --git a/asoc/codecs/wsa883x/wsa883x-temp-sensor.c b/asoc/codecs/wsa883x/wsa883x-temp-sensor.c new file mode 100644 index 0000000000..a328c75821 --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x-temp-sensor.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2015, 2017-2019 The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "wsa883x-temp-sensor.h" + +#define T1_TEMP -10 +#define T2_TEMP 150 +#define LOW_TEMP_THRESHOLD 5 +#define HIGH_TEMP_THRESHOLD 45 +#define TEMP_INVALID 0xFFFF +#define WSA883X_TEMP_RETRY 3 +/* + * wsa883x_get_temp - get wsa temperature + * @thermal: thermal zone device + * @temp: temperature value + * + * Get the temperature of wsa883x. + * + * Return: 0 on success or negative error code on failure. + */ +int wsa883x_get_temp(struct thermal_zone_device *thermal, + int *temp) +{ + struct wsa883x_tz_priv *pdata; + struct snd_soc_component *component; + struct wsa_temp_register reg; + int dmeas, d1, d2; + int ret = 0; + int temp_val; + int t1 = T1_TEMP; + int t2 = T2_TEMP; + u8 retry = WSA883X_TEMP_RETRY; + + if (!thermal) + return -EINVAL; + + if (thermal->devdata) { + pdata = thermal->devdata; + if (pdata->component) { + component = pdata->component; + } else { + pr_err("%s: codec is NULL\n", __func__); + return -EINVAL; + } + } else { + pr_err("%s: pdata is NULL\n", __func__); + return -EINVAL; + } + if (atomic_cmpxchg(&pdata->is_suspend_spk, 1, 0)) { + /* + * get_temp query happens as part of POST_PM_SUSPEND + * from thermal core. To avoid calls to slimbus + * as part of this thermal query, return default temp + * and reset the suspend flag. + */ + if (!pdata->t0_init) { + if (temp) + *temp = pdata->curr_temp; + return 0; + } + } + +temp_retry: + if (pdata->wsa_temp_reg_read) { + ret = pdata->wsa_temp_reg_read(component, ®); + if (ret) { + pr_err("%s: temp read failed: %d, current temp: %d\n", + __func__, ret, pdata->curr_temp); + if (temp) + *temp = pdata->curr_temp; + return 0; + } + } else { + pr_err("%s: wsa_temp_reg_read is NULL\n", __func__); + return -EINVAL; + } + /* + * Temperature register values are expected to be in the + * following range. + * d1_msb = 68 - 92 and d1_lsb = 0, 64, 128, 192 + * d2_msb = 185 -218 and d2_lsb = 0, 64, 128, 192 + */ + if ((reg.d1_msb < 68 || reg.d1_msb > 92) || + (!(reg.d1_lsb == 0 || reg.d1_lsb == 64 || reg.d1_lsb == 128 || + reg.d1_lsb == 192)) || + (reg.d2_msb < 185 || reg.d2_msb > 218) || + (!(reg.d2_lsb == 0 || reg.d2_lsb == 64 || reg.d2_lsb == 128 || + reg.d2_lsb == 192))) { + printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n", + __func__, reg.d1_msb, reg.d1_lsb, reg.d2_msb, + reg.d2_lsb); + } + dmeas = ((reg.dmeas_msb << 0x8) | reg.dmeas_lsb) >> 0x6; + d1 = ((reg.d1_msb << 0x8) | reg.d1_lsb) >> 0x6; + d2 = ((reg.d2_msb << 0x8) | reg.d2_lsb) >> 0x6; + + if (d1 == d2) + temp_val = TEMP_INVALID; + else + temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1)); + + if (temp_val <= LOW_TEMP_THRESHOLD || + temp_val >= HIGH_TEMP_THRESHOLD) { + pr_debug("%s: T0: %d is out of range[%d, %d]\n", __func__, + temp_val, LOW_TEMP_THRESHOLD, HIGH_TEMP_THRESHOLD); + if (retry--) { + msleep(20); + goto temp_retry; + } + } + pdata->curr_temp = temp_val; + + if (temp) + *temp = temp_val; + pr_debug("%s: t0 measured: %d dmeas = %d, d1 = %d, d2 = %d\n", + __func__, temp_val, dmeas, d1, d2); + return ret; +} +EXPORT_SYMBOL(wsa883x_get_temp); + +static struct thermal_zone_device_ops wsa883x_thermal_ops = { + .get_temp = wsa883x_get_temp, +}; + + +static int wsa883x_pm_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) +{ + struct wsa883x_tz_priv *pdata = + container_of(nb, struct wsa883x_tz_priv, pm_nb); + + switch (mode) { + case PM_SUSPEND_PREPARE: + atomic_set(&pdata->is_suspend_spk, 1); + break; + default: + break; + } + return 0; +} + +int wsa883x_init_thermal(struct wsa883x_tz_priv *tz_pdata) +{ + struct thermal_zone_device *tz_dev; + + if (tz_pdata == NULL) { + pr_err("%s: thermal pdata is NULL\n", __func__); + return -EINVAL; + } + /* Register with the thermal zone */ + tz_dev = thermal_zone_device_register(tz_pdata->name, + 0, 0, tz_pdata, + &wsa883x_thermal_ops, NULL, 0, 0); + if (IS_ERR(tz_dev)) { + pr_err("%s: thermal device register failed.\n", __func__); + return -EINVAL; + } + tz_pdata->tz_dev = tz_dev; + tz_pdata->pm_nb.notifier_call = wsa883x_pm_notify; + register_pm_notifier(&tz_pdata->pm_nb); + atomic_set(&tz_pdata->is_suspend_spk, 0); + + return 0; +} +EXPORT_SYMBOL(wsa883x_init_thermal); + +void wsa883x_deinit_thermal(struct thermal_zone_device *tz_dev) +{ + struct wsa883x_tz_priv *pdata; + + if (tz_dev && tz_dev->devdata) { + pdata = tz_dev->devdata; + if (pdata) + unregister_pm_notifier(&pdata->pm_nb); + } + if (tz_dev) + thermal_zone_device_unregister(tz_dev); +} +EXPORT_SYMBOL(wsa883x_deinit_thermal); diff --git a/asoc/codecs/wsa883x/wsa883x-temp-sensor.h b/asoc/codecs/wsa883x/wsa883x-temp-sensor.h new file mode 100644 index 0000000000..5a8c38747b --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x-temp-sensor.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved. + */ +#ifndef WSA883X_TEMP_SENSOR_H +#define WSA883X_TEMP_SENSOR_H + +#include +#include + +struct wsa_temp_register { + u8 d1_msb; + u8 d1_lsb; + u8 d2_msb; + u8 d2_lsb; + u8 dmeas_msb; + u8 dmeas_lsb; +}; +typedef int32_t (*wsa_temp_register_read)(struct snd_soc_component *component, + struct wsa_temp_register *wsa_temp_reg); +struct wsa883x_tz_priv { + struct thermal_zone_device *tz_dev; + struct snd_soc_component *component; + struct wsa_temp_register *wsa_temp_reg; + char name[80]; + wsa_temp_register_read wsa_temp_reg_read; + struct notifier_block pm_nb; + atomic_t is_suspend_spk; + int t0_init; + int curr_temp; +}; + +int wsa883x_get_temp(struct thermal_zone_device *tz_dev, int *temp); +int wsa883x_init_thermal(struct wsa883x_tz_priv *tz_pdata); +void wsa883x_deinit_thermal(struct thermal_zone_device *tz_dev); +#endif diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c new file mode 100644 index 0000000000..988196e237 --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -0,0 +1,1176 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wsa883x.h" +#include "wsa883x-temp-sensor.h" +#include "internal.h" + +#ifdef CONFIG_DEBUG_FS +static int codec_debug_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static int get_parameters(char *buf, u32 *param1, int num_of_par) +{ + char *token; + int base, cnt; + + token = strsep(&buf, " "); + for (cnt = 0; cnt < num_of_par; cnt++) { + if (token) { + if ((token[1] == 'x') || (token[1] == 'X')) + base = 16; + else + base = 10; + + if (kstrtou32(token, base, ¶m1[cnt]) != 0) + return -EINVAL; + + token = strsep(&buf, " "); + } else { + return -EINVAL; + } + } + return 0; +} + +static bool is_swr_slave_reg_readable(int reg) +{ + int ret = true; + + if (((reg > 0x46) && (reg < 0x4A)) || + ((reg > 0x4A) && (reg < 0x50)) || + ((reg > 0x55) && (reg < 0xD0)) || + ((reg > 0xD0) && (reg < 0xE0)) || + ((reg > 0xE0) && (reg < 0xF0)) || + ((reg > 0xF0) && (reg < 0x100)) || + ((reg > 0x105) && (reg < 0x120)) || + ((reg > 0x205) && (reg < 0x220)) || + ((reg > 0x305) && (reg < 0x320)) || + ((reg > 0x405) && (reg < 0x420)) || + ((reg > 0x128) && (reg < 0x130)) || + ((reg > 0x228) && (reg < 0x230)) || + ((reg > 0x328) && (reg < 0x330)) || + ((reg > 0x428) && (reg < 0x430)) || + ((reg > 0x138) && (reg < 0x205)) || + ((reg > 0x238) && (reg < 0x305)) || + ((reg > 0x338) && (reg < 0x405)) || + ((reg > 0x405) && (reg < 0xF00)) || + ((reg > 0xF05) && (reg < 0xF20)) || + ((reg > 0xF25) && (reg < 0xF30)) || + ((reg > 0xF35) && (reg < 0x2000))) + ret = false; + + return ret; +} + +static ssize_t swr_slave_reg_show(struct swr_device *pdev, char __user *ubuf, + size_t count, loff_t *ppos) +{ + int i, reg_val, len; + ssize_t total = 0; + char tmp_buf[SWR_SLV_MAX_BUF_LEN]; + + if (!ubuf || !ppos) + return 0; + + for (i = (((int) *ppos/BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR); + i <= SWR_SLV_MAX_REG_ADDR; i++) { + if (!is_swr_slave_reg_readable(i)) + continue; + swr_read(pdev, pdev->dev_num, i, ®_val, 1); + len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i, + (reg_val & 0xFF)); + if ((total + len) >= count - 1) + break; + if (copy_to_user((ubuf + total), tmp_buf, len)) { + pr_err("%s: fail to copy reg dump\n", __func__); + total = -EFAULT; + goto copy_err; + } + total += len; + *ppos += len; + } + +copy_err: + *ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE; + return total; +} + +static ssize_t codec_debug_dump(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct swr_device *pdev; + + if (!count || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + return swr_slave_reg_show(pdev, ubuf, count, ppos); +} + +static ssize_t codec_debug_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + char lbuf[SWR_SLV_RD_BUF_LEN]; + struct swr_device *pdev = NULL; + struct wsa883x_priv *wsa883x = NULL; + + if (!count || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + wsa883x = swr_get_dev_data(pdev); + if (!wsa883x) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + snprintf(lbuf, sizeof(lbuf), "0x%x\n", + (wsa883x->read_data & 0xFF)); + + return simple_read_from_buffer(ubuf, count, ppos, lbuf, + strnlen(lbuf, 7)); +} + +static ssize_t codec_debug_peek_write(struct file *file, + const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char lbuf[SWR_SLV_WR_BUF_LEN]; + int rc = 0; + u32 param[5]; + struct swr_device *pdev = NULL; + struct wsa883x_priv *wsa883x = NULL; + + if (!cnt || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + wsa883x = swr_get_dev_data(pdev); + if (!wsa883x) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + if (cnt > sizeof(lbuf) - 1) + return -EINVAL; + + rc = copy_from_user(lbuf, ubuf, cnt); + if (rc) + return -EFAULT; + + lbuf[cnt] = '\0'; + rc = get_parameters(lbuf, param, 1); + if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0))) + return -EINVAL; + swr_read(pdev, pdev->dev_num, param[0], &wsa883x->read_data, 1); + if (rc == 0) + rc = cnt; + else + pr_err("%s: rc = %d\n", __func__, rc); + + return rc; +} + +static ssize_t codec_debug_write(struct file *file, + const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char lbuf[SWR_SLV_WR_BUF_LEN]; + int rc = 0; + u32 param[5]; + struct swr_device *pdev; + + if (!file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + if (cnt > sizeof(lbuf) - 1) + return -EINVAL; + + rc = copy_from_user(lbuf, ubuf, cnt); + if (rc) + return -EFAULT; + + lbuf[cnt] = '\0'; + rc = get_parameters(lbuf, param, 2); + if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && + (param[1] <= 0xFF) && (rc == 0))) + return -EINVAL; + swr_write(pdev, pdev->dev_num, param[0], ¶m[1]); + if (rc == 0) + rc = cnt; + else + pr_err("%s: rc = %d\n", __func__, rc); + + return rc; +} + +static const struct file_operations codec_debug_write_ops = { + .open = codec_debug_open, + .write = codec_debug_write, +}; + +static const struct file_operations codec_debug_read_ops = { + .open = codec_debug_open, + .read = codec_debug_read, + .write = codec_debug_peek_write, +}; + +static const struct file_operations codec_debug_dump_ops = { + .open = codec_debug_open, + .read = codec_debug_dump, +}; +#endif + +static const char * const wsa_pa_gain_text[] = { + "G_18_DB", "G_16P5_DB", "G_15_DB", "G_13P5_DB", "G_12_DB", "G_10P5_DB", + "G_9_DB", "G_7P5_DB", "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", + "G_0_DB" +}; + +static const struct soc_enum wsa_pa_gain_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_pa_gain_text), wsa_pa_gain_text); + +static int wsa_pa_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa883x->pa_gain; + + dev_dbg(component->dev, "%s: PA gain = 0x%x\n", __func__, + wsa883x->pa_gain); + + return 0; +} + +static int wsa_pa_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + wsa883x->pa_gain = ucontrol->value.integer.value[0]; + + return 0; +} + +static int wsa883x_get_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa883x->pa_mute; + + return 0; +} + +static int wsa883x_set_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + int value = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: mute current %d, new %d\n", + __func__, wsa883x->pa_mute, value); + + wsa883x->pa_mute = value; + + return 0; +} + +static int wsa883x_get_t0_init(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + struct wsa883x_tz_priv *pdata = &wsa883x->tz_pdata; + + ucontrol->value.integer.value[0] = pdata->t0_init; + dev_dbg(component->dev, "%s: t0 init %d\n", __func__, pdata->t0_init); + + return 0; +} + +static int wsa883x_set_t0_init(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + struct wsa883x_tz_priv *pdata = &wsa883x->tz_pdata; + + pdata->t0_init = ucontrol->value.integer.value[0]; + dev_dbg(component->dev, "%s: t0 init %d\n", __func__, pdata->t0_init); + + return 0; +} + +static const struct snd_kcontrol_new wsa_snd_controls[] = { + SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum, + wsa_pa_gain_get, wsa_pa_gain_put), + SOC_SINGLE_EXT("WSA PA Mute", SND_SOC_NOPM, 0, 1, 0, + wsa883x_get_mute, wsa883x_set_mute), + SOC_SINGLE_EXT("WSA T0 Init", SND_SOC_NOPM, 0, 1, 0, + wsa883x_get_t0_init, wsa883x_set_t0_init), +}; + +static ssize_t wsa883x_codec_version_read(struct snd_info_entry *entry, + void *file_private_data, struct file *file, + char __user *buf, size_t count, loff_t pos) +{ + struct wsa883x_priv *wsa883x; + char buffer[WSA883X_VERSION_ENTRY_SIZE]; + int len = 0; + + wsa883x = (struct wsa883x_priv *) entry->private_data; + if (!wsa883x) { + pr_err("%s: wsa883x priv is null\n", __func__); + return -EINVAL; + } + + len = snprintf(buffer, sizeof(buffer), "WSA883X-SOUNDWIRE_1_0\n"); + + return simple_read_from_buffer(buf, count, &pos, buffer, len); +} + +static struct snd_info_entry_ops wsa883x_codec_info_ops = { + .read = wsa883x_codec_version_read, +}; + +/* + * wsa883x_codec_info_create_codec_entry - creates wsa883x module + * @codec_root: The parent directory + * @component: Codec instance + * + * Creates wsa883x module and version entry under the given + * parent directory. + * + * Return: 0 on success or negative error code on failure. + */ +int wsa883x_codec_info_create_codec_entry(struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + struct snd_info_entry *version_entry; + struct wsa883x_priv *wsa883x; + struct snd_soc_card *card; + char name[80]; + + if (!codec_root || !component) + return -EINVAL; + + wsa883x = snd_soc_component_get_drvdata(component); + card = component->card; + snprintf(name, sizeof(name), "%s.%x", "wsa883x", + (u32)wsa883x->swr_slave->addr); + + wsa883x->entry = snd_info_create_subdir(codec_root->module, + (const char *)name, + codec_root); + if (!wsa883x->entry) { + dev_dbg(component->dev, "%s: failed to create wsa883x entry\n", + __func__); + return -ENOMEM; + } + + version_entry = snd_info_create_card_entry(card->snd_card, + "version", + wsa883x->entry); + if (!version_entry) { + dev_dbg(component->dev, "%s: failed to create wsa883x version entry\n", + __func__); + return -ENOMEM; + } + + version_entry->private_data = wsa883x; + version_entry->size = WSA883X_VERSION_ENTRY_SIZE; + version_entry->content = SNDRV_INFO_CONTENT_DATA; + version_entry->c.ops = &wsa883x_codec_info_ops; + + if (snd_info_register(version_entry) < 0) { + snd_info_free_entry(version_entry); + return -ENOMEM; + } + wsa883x->version_entry = version_entry; + + return 0; +} +EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry); + +static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x) +{ + mutex_lock(&wsa883x->res_lock); + if (wsa883x->state != WSA883X_DEV_READY) { + regcache_mark_dirty(wsa883x->regmap); + regcache_sync(wsa883x->regmap); + wsa883x->state = WSA883X_DEV_READY; + } + mutex_unlock(&wsa883x->res_lock); +} + +static int wsa883x_visense_txfe_ctrl(struct snd_soc_component *component, + bool enable, u8 isense1_gain, + u8 isense2_gain, u8 vsense_gain) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, + "%s: enable:%d, isense1 gain: %d, isense2 gain: %d, vsense_gain %d\n", + __func__, enable, isense1_gain, isense2_gain, vsense_gain); + + return 0; +} + +static int wsa883x_visense_adc_ctrl(struct snd_soc_component *component, + bool enable) +{ + + dev_dbg(component->dev, "%s: enable:%d\n", __func__, enable); + + return 0; +} + +static void wsa883x_bandgap_ctrl(struct snd_soc_component *component, + bool enable) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: enable:%d, bg_count:%d\n", __func__, + enable, wsa883x->bg_cnt); + mutex_lock(&wsa883x->bg_lock); + if (enable) { + ++wsa883x->bg_cnt; + if (wsa883x->bg_cnt == 1) { + snd_soc_component_update_bits(component, + WSA883X_OP_CTL, + 0x08, 0x08); + } + } else { + --wsa883x->bg_cnt; + if (wsa883x->bg_cnt <= 0) { + WARN_ON(wsa883x->bg_cnt < 0); + wsa883x->bg_cnt = 0; + snd_soc_component_update_bits(component, + WSA883X_OP_CTL, 0x08, 0x00); + } + } + mutex_unlock(&wsa883x->bg_lock); +} + +static void wsa883x_clk_ctrl(struct snd_soc_component *component, bool enable) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: enable:%d, clk_count:%d\n", __func__, + enable, wsa883x->clk_cnt); + mutex_lock(&wsa883x->res_lock); + if (enable) { + ++wsa883x->clk_cnt; + if (wsa883x->clk_cnt == 1) { + snd_soc_component_write(component, + WSA883X_CDC_CLK_CTL, 0x01); + snd_soc_component_write(component, + WSA883X_CLK_CTL, 0x01); + } + } else { + --wsa883x->clk_cnt; + if (wsa883x->clk_cnt <= 0) { + WARN_ON(wsa883x->clk_cnt < 0); + wsa883x->clk_cnt = 0; + snd_soc_component_write(component, + WSA883X_CDC_CLK_CTL, 0x00); + snd_soc_component_write(component, + WSA883X_CLK_CTL, 0x00); + } + } + mutex_unlock(&wsa883x->res_lock); +} + +static int wsa883x_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa883x->comp_enable; + return 0; +} + +static int wsa883x_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + int value = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: Compander enable current %d, new %d\n", + __func__, wsa883x->comp_enable, value); + wsa883x->comp_enable = value; + return 0; +} + +static int wsa883x_get_visense(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa883x->visense_enable; + return 0; +} + +static int wsa883x_set_visense(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + int value = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: VIsense enable current %d, new %d\n", + __func__, wsa883x->visense_enable, value); + wsa883x->visense_enable = value; + return 0; +} + +static const struct snd_kcontrol_new wsa883x_snd_controls[] = { + SOC_SINGLE_EXT("COMP Switch", SND_SOC_NOPM, 0, 1, 0, + wsa883x_get_compander, wsa883x_set_compander), + + SOC_SINGLE_EXT("VISENSE Switch", SND_SOC_NOPM, 0, 1, 0, + wsa883x_get_visense, wsa883x_set_visense), +}; + +static const struct snd_kcontrol_new swr_dac_port[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static int wsa883x_set_port(struct snd_soc_component *component, int port_idx, + u8 *port_id, u8 *num_ch, u8 *ch_mask, u32 *ch_rate, + u8 *port_type) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + *port_id = wsa883x->port[port_idx].port_id; + *num_ch = wsa883x->port[port_idx].num_ch; + *ch_mask = wsa883x->port[port_idx].ch_mask; + *ch_rate = wsa883x->port[port_idx].ch_rate; + *port_type = wsa883x->port[port_idx].port_type; + return 0; +} + +static int wsa883x_enable_swr_dac_port(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 wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + u8 port_id[WSA883X_MAX_SWR_PORTS]; + u8 num_ch[WSA883X_MAX_SWR_PORTS]; + u8 ch_mask[WSA883X_MAX_SWR_PORTS]; + u32 ch_rate[WSA883X_MAX_SWR_PORTS]; + u8 port_type[WSA883X_MAX_SWR_PORTS]; + u8 num_port = 0; + + dev_dbg(component->dev, "%s: event %d name %s\n", __func__, + event, w->name); + if (wsa883x == NULL) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wsa883x_set_port(component, SWR_DAC_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + + if (wsa883x->comp_enable) { + wsa883x_set_port(component, SWR_COMP_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + } + if (wsa883x->visense_enable) { + wsa883x_set_port(component, SWR_VISENSE_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + } + swr_connect_port(wsa883x->swr_slave, &port_id[0], num_port, + &ch_mask[0], &ch_rate[0], &num_ch[0], + &port_type[0]); + break; + case SND_SOC_DAPM_POST_PMU: + break; + case SND_SOC_DAPM_PRE_PMD: + break; + case SND_SOC_DAPM_POST_PMD: + wsa883x_set_port(component, SWR_DAC_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + + if (wsa883x->comp_enable) { + wsa883x_set_port(component, SWR_COMP_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + } + if (wsa883x->visense_enable) { + wsa883x_set_port(component, SWR_VISENSE_PORT, + &port_id[num_port], &num_ch[num_port], + &ch_mask[num_port], &ch_rate[num_port], + &port_type[num_port]); + ++num_port; + } + swr_disconnect_port(wsa883x->swr_slave, &port_id[0], num_port, + &ch_mask[0], &port_type[0]); + break; + default: + break; + } + return 0; +} + +static int wsa883x_rdac_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 wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: %s event: %d visense %d\n", __func__, + w->name, event, wsa883x->visense_enable); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mutex_lock(&wsa883x->temp_lock); + wsa883x_resource_acquire(component, ENABLE); + mutex_unlock(&wsa883x->temp_lock); + break; + case SND_SOC_DAPM_POST_PMD: + swr_slvdev_datapath_control(wsa883x->swr_slave, + wsa883x->swr_slave->dev_num, + false); + mutex_lock(&wsa883x->temp_lock); + wsa883x_resource_acquire(component, DISABLE); + mutex_unlock(&wsa883x->temp_lock); + break; + } + return 0; +} + +static int wsa883x_ramp_pa_gain(struct snd_soc_component *component, + int min_gain, int max_gain, int udelay) +{ + int val; + + for (val = min_gain; max_gain <= val; val--) { + snd_soc_component_update_bits(component, WSA883X_SPKR_DRV_GAIN, + 0xF0, val << 4); + /* + * 1ms delay is needed for every step change in gain as per + * HW requirement. + */ + usleep_range(udelay, udelay + 10); + } + return 0; +} + +static int wsa883x_spkr_pa_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 wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + int min_gain, max_gain; + + dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + swr_slvdev_datapath_control(wsa883x->swr_slave, + wsa883x->swr_slave->dev_num, + true); + /* Set register mode if compander is not enabled */ + if (!wsa883x->comp_enable) + snd_soc_component_update_bits(component, + WSA883X_SPKR_DRV_GAIN, + 0x08, 0x08); + else + snd_soc_component_update_bits(component, + WSA883X_SPKR_DRV_GAIN, + 0x08, 0x00); + + break; + case SND_SOC_DAPM_POST_PMU: + if (!wsa883x->comp_enable) { + max_gain = wsa883x->pa_gain; + /* + * Gain has to set incrementally in 4 steps + * as per HW sequence + */ + if (max_gain > G_4P5DB) + min_gain = G_0DB; + else + min_gain = max_gain + 3; + /* + * 1ms delay is needed before change in gain + * as per HW requirement. + */ + usleep_range(1000, 1010); + wsa883x_ramp_pa_gain(component, min_gain, max_gain, + 1000); + } + if (wsa883x->visense_enable) { + wsa883x_visense_txfe_ctrl(component, ENABLE, + 0x00, 0x03, 0x01); + wsa883x_visense_adc_ctrl(component, ENABLE); + } + /* Force remove group */ + swr_remove_from_group(wsa883x->swr_slave, + wsa883x->swr_slave->dev_num); + break; + case SND_SOC_DAPM_POST_PMD: + if (wsa883x->visense_enable) { + wsa883x_visense_adc_ctrl(component, DISABLE); + wsa883x_visense_txfe_ctrl(component, DISABLE, + 0x00, 0x01, 0x01); + } + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget wsa883x_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN"), + + SND_SOC_DAPM_MIXER_E("SWR DAC_Port", SND_SOC_NOPM, 0, 0, swr_dac_port, + ARRAY_SIZE(swr_dac_port), wsa883x_enable_swr_dac_port, + 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("RDAC", NULL, WSA883X_SPKR_DAC_CTL, 7, 0, + wsa883x_rdac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_PGA_E("SPKR PGA", WSA883X_SPKR_DRV_EN, 7, 0, NULL, 0, + wsa883x_spkr_pa_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_OUTPUT("SPKR"), +}; + +static const struct snd_soc_dapm_route wsa883x_audio_map[] = { + {"SWR DAC_Port", "Switch", "IN"}, + {"RDAC", NULL, "SWR DAC_Port"}, + {"SPKR PGA", NULL, "RDAC"}, + {"SPKR", NULL, "SPKR PGA"}, +}; + +int wsa883x_set_channel_map(struct snd_soc_component *component, u8 *port, + u8 num_port, unsigned int *ch_mask, + unsigned int *ch_rate, u8 *port_type) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + int i; + + if (!port || !ch_mask || !ch_rate || + (num_port > WSA883X_MAX_SWR_PORTS)) { + dev_err(component->dev, + "%s: Invalid port=%pK, ch_mask=%pK, ch_rate=%pK\n", + __func__, port, ch_mask, ch_rate); + return -EINVAL; + } + for (i = 0; i < num_port; i++) { + wsa883x->port[i].port_id = port[i]; + wsa883x->port[i].ch_mask = ch_mask[i]; + wsa883x->port[i].ch_rate = ch_rate[i]; + wsa883x->port[i].num_ch = __sw_hweight8(ch_mask[i]); + if (port_type) + wsa883x->port[i].port_type = port_type[i]; + } + + return 0; +} +EXPORT_SYMBOL(wsa883x_set_channel_map); + +static void wsa883x_init(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + if (!wsa883x) + return; + +} + +static int32_t wsa883x_resource_acquire(struct snd_soc_component *component, + bool enable) +{ + wsa883x_clk_ctrl(component, enable); + wsa883x_bandgap_ctrl(component, enable); + return 0; +} + +static int32_t wsa883x_temp_reg_read(struct snd_soc_component *component, + struct wsa_temp_register *wsa_temp_reg) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + struct swr_device *dev; + u8 retry = WSA883X_NUM_RETRY; + u8 devnum = 0; + + if (!wsa883x) { + dev_err(component->dev, "%s: wsa883x is NULL\n", __func__); + return -EINVAL; + } + dev = wsa883x->swr_slave; + if (dev && (wsa883x->state == WSA883X_DEV_DOWN)) { + while (swr_get_logical_dev_num(dev, dev->addr, &devnum) && + retry--) { + /* Retry after 1 msec delay */ + usleep_range(1000, 1100); + } + if (retry == 0) { + dev_err(component->dev, + "%s get devnum %d for dev addr %lx failed\n", + __func__, devnum, dev->addr); + return -EINVAL; + } + } + wsa883x_regcache_sync(wsa883x); + mutex_lock(&wsa883x->temp_lock); + wsa883x_resource_acquire(component, ENABLE); + + snd_soc_component_update_bits(component, WSA883X_TADC_VALUE_CTL, + 0x01, 0x00); + wsa_temp_reg->dmeas_msb = snd_soc_component_read32( + component, WSA883X_TEMP_MSB); + wsa_temp_reg->dmeas_lsb = snd_soc_component_read32( + component, WSA883X_TEMP_LSB); + snd_soc_component_update_bits(component, WSA883X_TADC_VALUE_CTL, + 0x01, 0x01); + wsa_temp_reg->d1_msb = snd_soc_component_read32( + component, WSA883X_OTP_REG_1); + wsa_temp_reg->d1_lsb = snd_soc_component_read32( + component, WSA883X_OTP_REG_2); + wsa_temp_reg->d2_msb = snd_soc_component_read32( + component, WSA883X_OTP_REG_3); + wsa_temp_reg->d2_lsb = snd_soc_component_read32( + component, WSA883X_OTP_REG_4); + + wsa883x_resource_acquire(component, DISABLE); + mutex_unlock(&wsa883x->temp_lock); + + return 0; +} + +static int wsa883x_codec_probe(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + struct swr_device *dev; + + if (!wsa883x) + return -EINVAL; + snd_soc_component_init_regmap(component, wsa883x->regmap); + + dev = wsa883x->swr_slave; + wsa883x->component = component; + mutex_init(&wsa883x->bg_lock); + wsa883x_init(component); + snprintf(wsa883x->tz_pdata.name, sizeof(wsa883x->tz_pdata.name), + "%s.%x", "wsatz", (u8)dev->addr); + wsa883x->bg_cnt = 0; + wsa883x->clk_cnt = 0; + wsa883x->tz_pdata.component = component; + wsa883x->tz_pdata.wsa_temp_reg_read = wsa883x_temp_reg_read; + wsa883x_init_thermal(&wsa883x->tz_pdata); + snd_soc_add_component_controls(component, wsa_snd_controls, + ARRAY_SIZE(wsa_snd_controls)); + return 0; +} + +static void wsa883x_codec_remove(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + if (wsa883x->tz_pdata.tz_dev) + wsa883x_deinit_thermal(wsa883x->tz_pdata.tz_dev); + mutex_destroy(&wsa883x->bg_lock); + + return; +} + +static const struct snd_soc_component_driver soc_codec_dev_wsa883x = { + .name = DRV_NAME, + .probe = wsa883x_codec_probe, + .remove = wsa883x_codec_remove, + .controls = wsa883x_snd_controls, + .num_controls = ARRAY_SIZE(wsa883x_snd_controls), + .dapm_widgets = wsa883x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets), + .dapm_routes = wsa883x_audio_map, + .num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map), +}; + +static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable) +{ + int ret = 0; + + if (enable) + ret = msm_cdc_pinctrl_select_active_state( + wsa883x->wsa_rst_np); + else + ret = msm_cdc_pinctrl_select_sleep_state( + wsa883x->wsa_rst_np); + if (ret != 0) + dev_err(wsa883x->dev, + "%s: Failed to turn state %d; ret=%d\n", + __func__, enable, ret); + + return ret; +} + +static int wsa883x_swr_probe(struct swr_device *pdev) +{ + int ret = 0; + struct wsa883x_priv *wsa883x; + u8 devnum = 0; + bool pin_state_current = false; + + wsa883x = devm_kzalloc(&pdev->dev, sizeof(struct wsa883x_priv), + GFP_KERNEL); + if (!wsa883x) + return -ENOMEM; + + wsa883x->wsa_rst_np = of_parse_phandle(pdev->dev.of_node, + "qcom,spkr-sd-n-node", 0); + if (!wsa883x->wsa_rst_np) { + dev_dbg(&pdev->dev, "%s: pinctrl not defined\n", __func__); + goto err; + } + swr_set_dev_data(pdev, wsa883x); + wsa883x->swr_slave = pdev; + pin_state_current = msm_cdc_pinctrl_get_state(wsa883x->wsa_rst_np); + wsa883x_gpio_ctrl(wsa883x, true); + /* + * Add 5msec delay to provide sufficient time for + * soundwire auto enumeration of slave devices as + * as per HW requirement. + */ + usleep_range(5000, 5010); + 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); + goto dev_err; + } + pdev->dev_num = devnum; + + wsa883x->regmap = devm_regmap_init_swr(pdev, + &wsa883x_regmap_config); + if (IS_ERR(wsa883x->regmap)) { + ret = PTR_ERR(wsa883x->regmap); + dev_err(&pdev->dev, "%s: regmap_init failed %d\n", + __func__, ret); + goto dev_err; + } + + ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa883x, + NULL, 0); + if (ret) { + dev_err(&pdev->dev, "%s: Codec registration failed\n", + __func__); + goto dev_err; + } + mutex_init(&wsa883x->res_lock); + mutex_init(&wsa883x->temp_lock); + wsa883x->state = WSA883X_DEV_UP; + +#ifdef CONFIG_DEBUG_FS + if (!wcd938x->debugfs_dent) { + wcd938x->debugfs_dent = debugfs_create_dir( + dev_name(&pdev->dev), 0); + if (!IS_ERR(wcd938x->debugfs_dent)) { + wcd938x->debugfs_peek = + debugfs_create_file("swrslave_peek", + S_IFREG | 0444, + wcd938x->debugfs_dent, + (void *) pdev, + &codec_debug_read_ops); + + wcd938x->debugfs_poke = + debugfs_create_file("swrslave_poke", + S_IFREG | 0444, + wcd938x->debugfs_dent, + (void *) pdev, + &codec_debug_write_ops); + + wcd938x->debugfs_reg_dump = + debugfs_create_file( + "swrslave_reg_dump", + S_IFREG | 0444, + wcd938x->debugfs_dent, + (void *) pdev, + &codec_debug_dump_ops); + } +} +#endif + + return 0; + +dev_err: + if (pin_state_current == false) + wsa883x_gpio_ctrl(wsa883x, false); + swr_remove_device(pdev); +err: + return ret; +} + +static int wsa883x_swr_remove(struct swr_device *pdev) +{ + struct wsa883x_priv *wsa883x; + + wsa883x = swr_get_dev_data(pdev); + if (!wsa883x) { + dev_err(&pdev->dev, "%s: wsa883x is NULL\n", __func__); + return -EINVAL; + } +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(wsa883x->debugfs_dent); + wsa883x->debugfs_dent = NULL; +#endif + mutex_destroy(&wsa883x->res_lock); + mutex_destroy(&wsa883x->temp_lock); + snd_soc_unregister_component(&pdev->dev); + if (wsa883x->pd_gpio) + gpio_free(wsa883x->pd_gpio); + swr_set_dev_data(pdev, NULL); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int wsa883x_swr_suspend(struct device *dev) +{ + dev_dbg(dev, "%s: system suspend\n", __func__); + return 0; +} + +static int wsa883x_swr_resume(struct device *dev) +{ + struct wsa883x_priv *wsa883x = swr_get_dev_data(to_swr_device(dev)); + + if (!wsa883x) { + dev_err(dev, "%s: wsa883x private data is NULL\n", __func__); + return -EINVAL; + } + dev_dbg(dev, "%s: system resume\n", __func__); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops wsa883x_swr_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(wsa883x_swr_suspend, wsa883x_swr_resume) +}; + +static const struct swr_device_id wsa883x_swr_id[] = { + {"wsa883x", 0}, + {} +}; + +static const struct of_device_id wsa883x_swr_dt_match[] = { + { + .compatible = "qcom,wsa883x", + }, + {} +}; + +static struct swr_driver wsa883x_swr_driver = { + .driver = { + .name = "wsa883x", + .owner = THIS_MODULE, + .pm = &wsa883x_swr_pm_ops, + .of_match_table = wsa883x_swr_dt_match, + }, + .probe = wsa883x_swr_probe, + .remove = wsa883x_swr_remove, + .id_table = wsa883x_swr_id, +}; + +static int __init wsa883x_swr_init(void) +{ + return swr_driver_register(&wsa883x_swr_driver); +} + +static void __exit wsa883x_swr_exit(void) +{ + swr_driver_unregister(&wsa883x_swr_driver); +} + +module_init(wsa883x_swr_init); +module_exit(wsa883x_swr_exit); + +MODULE_DESCRIPTION("WSA883x codec driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/wsa883x/wsa883x.h b/asoc/codecs/wsa883x/wsa883x.h new file mode 100644 index 0000000000..e080134eb0 --- /dev/null +++ b/asoc/codecs/wsa883x/wsa883x.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _WSA883X_H +#define _WSA883X_H + +#include +#include +#include +#include "wsa883x-registers.h" + +#define WSA883X_MAX_SWR_PORTS 4 + +#if IS_ENABLED(CONFIG_SND_SOC_WSA883X) +int wsa883x_set_channel_map(struct snd_soc_component *component, + u8 *port, u8 num_port, unsigned int *ch_mask, + unsigned int *ch_rate, u8 *port_type); + + +int wsa883x_codec_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component); +#else +static int wsa883x_set_channel_map(struct snd_soc_component *component, + u8 *port, u8 num_port, unsigned int *ch_mask, + unsigned int *ch_rate, u8 *port_type) +{ + return 0; +} + +static int wsa883x_codec_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + return 0; +} + +#endif + +#endif /* _WSA883X_H */