From 179ce4f13f93a4026a9b78fc861ce867f77ed802 Mon Sep 17 00:00:00 2001 From: Junkai Cai Date: Tue, 27 Jul 2021 11:31:42 -0700 Subject: [PATCH] asoc: codecs: Implement codec driver for WSA884X Driver implementation for WSA884X. Use new script to generate register files. Modify register naming convention. Add wsa884x-reg-masks.h and wsa884x-reg-shifts.h Reverting copyrights to 2019 for wsa884x.h file Change-Id: Ic3652d6138a2f62ba59a36d4307c732ab6e8db89 Signed-off-by: Shazmaan Ali --- asoc/codecs/Kbuild | 1 + asoc/codecs/wsa884x/Kbuild | 103 ++ asoc/codecs/wsa884x/Makefile | 6 + asoc/codecs/wsa884x/internal.h | 135 ++ asoc/codecs/wsa884x/wsa884x-reg-masks.h | 87 + asoc/codecs/wsa884x/wsa884x-reg-shifts.h | 87 + asoc/codecs/wsa884x/wsa884x-registers.h | 529 ++++++ asoc/codecs/wsa884x/wsa884x-regmap.c | 544 ++++++ asoc/codecs/wsa884x/wsa884x-tables.c | 500 ++++++ asoc/codecs/wsa884x/wsa884x.c | 2032 ++++++++++++++++++++++ asoc/codecs/wsa884x/wsa884x.h | 49 + 11 files changed, 4073 insertions(+) create mode 100644 asoc/codecs/wsa884x/Kbuild create mode 100644 asoc/codecs/wsa884x/Makefile create mode 100644 asoc/codecs/wsa884x/internal.h create mode 100644 asoc/codecs/wsa884x/wsa884x-reg-masks.h create mode 100644 asoc/codecs/wsa884x/wsa884x-reg-shifts.h create mode 100644 asoc/codecs/wsa884x/wsa884x-registers.h create mode 100644 asoc/codecs/wsa884x/wsa884x-regmap.c create mode 100644 asoc/codecs/wsa884x/wsa884x-tables.c create mode 100644 asoc/codecs/wsa884x/wsa884x.c create mode 100644 asoc/codecs/wsa884x/wsa884x.h diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index 71151ee586..23a8a5298e 100644 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -258,6 +258,7 @@ ifeq ($(KERNEL_BUILD), 1) obj-y += bolero/ obj-y += lpass-cdc/ obj-y += wsa883x/ + obj-y += wsa884x/ obj-y += rouleur/ endif # Module information used by KBuild framework diff --git a/asoc/codecs/wsa884x/Kbuild b/asoc/codecs/wsa884x/Kbuild new file mode 100644 index 0000000000..5efcd27a77 --- /dev/null +++ b/asoc/codecs/wsa884x/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-5.4 + 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 + ifeq ($(CONFIG_ARCH_WAIPIO), y) + include $(AUDIO_ROOT)/config/waipioauto.conf + INCS += -include $(AUDIO_ROOT)/config/waipioautoconf.h + endif + ifeq ($(CONFIG_ARCH_LITO), y) + include $(AUDIO_ROOT)/config/litoauto.conf + INCS += -include $(AUDIO_ROOT)/config/litoautoconf.h + endif +endif + +# As per target team, build is done as follows: +# Defconfig : build with default flags +# Slub : defconfig + CONFIG_SLUB_DEBUG := y + +# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y +# Perf : Using appropriate msmXXXX-perf_defconfig +# +# Shipment builds (user variants) should not have any debug feature +# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds +# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since +# there is no other way to identify defconfig builds, QTI internal +# representation of perf builds (identified using the string 'perf'), +# is used to identify if the build is a slub or defconfig one. This +# way no critical debug feature will be enabled for perf and shipment +# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT +# config. + +############ UAPI ############ +UAPI_DIR := uapi/audio +UAPI_INC := -I$(AUDIO_ROOT)/include/$(UAPI_DIR) + +############ COMMON ############ +COMMON_DIR := include +COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR) + +############ WSA884X ############ + +# for WSA884X Codec +ifdef CONFIG_SND_SOC_WSA884X + WSA884X_OBJS += wsa884x.o + WSA884X_OBJS += wsa884x-regmap.o + WSA884X_OBJS += wsa884x-tables.o +endif + +LINUX_INC += -Iinclude/linux + +INCS += $(COMMON_INC) \ + $(UAPI_INC) + +EXTRA_CFLAGS += $(INCS) + + +CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \ + -DANI_LITTLE_BIT_ENDIAN \ + -DDOT11F_LITTLE_ENDIAN_HOST \ + -DANI_COMPILER_TYPE_GCC \ + -DANI_OS_TYPE_ANDROID=6 \ + -DPTT_SOCK_SVC_ENABLE \ + -Wall\ + -Werror\ + -D__linux__ + +KBUILD_CPPFLAGS += $(CDEFINES) + +# Currently, for versions of gcc which support it, the kernel Makefile +# is disabling the maybe-uninitialized warning. Re-enable it for the +# AUDIO driver. Note that we must use EXTRA_CFLAGS here so that it +# will override the kernel settings. +ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y) +EXTRA_CFLAGS += -Wmaybe-uninitialized +endif +#EXTRA_CFLAGS += -Wmissing-prototypes + +ifeq ($(call cc-option-yn, -Wheader-guard),y) +EXTRA_CFLAGS += -Wheader-guard +endif + + +# Module information used by KBuild framework +obj-$(CONFIG_SND_SOC_WSA884X) += wsa884x_dlkm.o +wsa884x_dlkm-y := $(WSA884X_OBJS) + +# inject some build related information +DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/asoc/codecs/wsa884x/Makefile b/asoc/codecs/wsa884x/Makefile new file mode 100644 index 0000000000..8c87649225 --- /dev/null +++ b/asoc/codecs/wsa884x/Makefile @@ -0,0 +1,6 @@ +modules: + $(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) VERBOSE=1 +modules_install: + $(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(M) clean diff --git a/asoc/codecs/wsa884x/internal.h b/asoc/codecs/wsa884x/internal.h new file mode 100644 index 0000000000..0f79d0d956 --- /dev/null +++ b/asoc/codecs/wsa884x/internal.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + */ + +#ifndef WSA884X_INTERNAL_H +#define WSA884X_INTERNAL_H + +#include +#include "wsa884x.h" +#include "wsa884x-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 WSA884X_DRV_NAME "wsa884x-codec" +#define WSA884X_NUM_RETRY 5 + +#define WSA884X_VERSION_ENTRY_SIZE 32 +#define WSA884X_VARIANT_ENTRY_SIZE 32 + +#define WSA884X_VERSION_1_0 0 +#define WSA884X_VERSION_1_1 1 + +enum { + G_21DB = 0, + G_19P5DB, + G_18DB, + 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, + SWR_CPS_PORT, + SWR_PBRPORT +}; + +struct wsa_ctrl_platform_data { + void *handle; + int (*update_wsa_event)(void *handle, u16 event, u32 data); + int (*register_notifier)(void *handle, struct notifier_block *nblock, + bool enable); +}; + +struct swr_port { + u8 port_id; + u8 ch_mask; + u32 ch_rate; + u8 num_ch; + u8 port_type; +}; + +extern struct regmap_config wsa884x_regmap_config; + +/* + * Private data Structure for wsa884x. All parameters related to + * WSA884X codec needs to be defined here. + */ +struct wsa884x_priv { + struct regmap *regmap; + struct device *dev; + struct swr_device *swr_slave; + struct snd_soc_component *component; + bool comp_enable; + bool visense_enable; + bool ext_vdd_spk; + bool dapm_bias_off; + struct swr_port port[WSA884X_MAX_SWR_PORTS]; + int global_pa_cnt; + int dev_mode; + int comp_offset; + struct mutex res_lock; + struct snd_info_entry *entry; + struct snd_info_entry *version_entry; + struct snd_info_entry *variant_entry; + struct device_node *wsa_rst_np; + int pa_mute; + int curr_temp; + int variant; + int version; + u8 pa_gain; + struct irq_domain *virq; + struct wcd_irq_info irq_info; +#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 + struct device_node *parent_np; + struct platform_device *parent_dev; + struct notifier_block parent_nblock; + void *handle; + int (*register_notifier)(void *handle, + struct notifier_block *nblock, bool enable); + struct cdc_regulator *regulator; + int num_supplies; + struct regulator_bulk_data *supplies; + unsigned long status_mask; + char *wsa884x_name_prefix; + struct snd_soc_dai_driver *dai_driver; + struct snd_soc_component_driver *driver; +}; + +#endif /* WSA884X_INTERNAL_H */ diff --git a/asoc/codecs/wsa884x/wsa884x-reg-masks.h b/asoc/codecs/wsa884x/wsa884x-reg-masks.h new file mode 100644 index 0000000000..99c22ce816 --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x-reg-masks.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef WSA884X_REG_MASKS_H +#define WSA884X_REG_MASKS_H +#include +#include +#include "wsa884x-registers.h" + +#define FIELD_MASK(register_name, field_name) \ + WSA884X_##register_name##_##field_name##_MASK + +#define WSA884X_VBAT_SNS_BOP_FREQ_MASK 0x60 +#define WSA884X_ISENSE2_ISENSE_GAIN_CTL_MASK 0xe0 +#define WSA884X_ADC_2_ISNS_LOAD_STORED_MASK 0x40 +#define WSA884X_ADC_6_INTRLV_RST_OVRD_MASK 0x02 +#define WSA884X_ADC_7_EN_AZ_REG_MASK 0x04 +#define WSA884X_ADC_7_EN_SAR_REG_MASK 0x02 +#define WSA884X_CURRENT_LIMIT_CURRENT_LIMIT_OVRD_EN_MASK 0x80 +#define WSA884X_CURRENT_LIMIT_CURRENT_LIMIT_MASK 0x7c +#define WSA884X_BOOST_MISC_SPKR_RDY_CTL_MASK 0x60 +#define WSA884X_CKWD_CTL_0_CKWD_FDIV_SEL_MASK 0x60 +#define WSA884X_CKWD_CTL_1_CKWD_VCOMP_VREF_SEL_MASK 0x1f +#define WSA884X_CHIP_ID0_BYTE_0_MASK 0xff +#define WSA884X_PA_FSM_EN_GLOBAL_PA_EN_MASK 0x01 +#define WSA884X_PA_FSM_BYP_CTL_PA_FSM_BYP_MASK 0x01 +#define WSA884X_PA_FSM_BYP0_TSADC_EN_MASK 0x80 +#define WSA884X_PA_FSM_BYP0_SPKR_PROT_EN_MASK 0x40 +#define WSA884X_PA_FSM_BYP0_D_UNMUTE_MASK 0x20 +#define WSA884X_PA_FSM_BYP0_BG_EN_MASK 0x04 +#define WSA884X_PA_FSM_BYP0_CLK_WD_EN_MASK 0x02 +#define WSA884X_PA_FSM_BYP0_DC_CAL_EN_MASK 0x01 +#define WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK 0x01 +#define WSA884X_TEMP_CONFIG0_CTL_THRD_SAF2WAR_MASK 0x07 +#define WSA884X_TEMP_CONFIG1_CTL_THRD_WAR2SAF_MASK 0x07 +#define WSA884X_VBAT_THRM_FLT_CTL_VBAT_COEF_SEL_MASK 0x0e +#define WSA884X_VBAT_THRM_FLT_CTL_VBAT_FLT_EN_MASK 0x01 +#define WSA884X_CDC_SPK_DSM_A2_0_COEF_A2_MASK 0xff +#define WSA884X_CDC_SPK_DSM_A2_1_COEF_A2_MASK 0x0f +#define WSA884X_CDC_SPK_DSM_A3_0_COEF_A3_MASK 0xff +#define WSA884X_CDC_SPK_DSM_A3_1_COEF_A3_MASK 0x07 +#define WSA884X_CDC_SPK_DSM_A4_0_COEF_A4_MASK 0xff +#define WSA884X_CDC_SPK_DSM_A4_1_COEF_A4_MASK 0x03 +#define WSA884X_CDC_SPK_DSM_A5_0_COEF_A5_MASK 0xff +#define WSA884X_CDC_SPK_DSM_A5_1_COEF_A5_MASK 0x03 +#define WSA884X_CDC_SPK_DSM_A6_0_COEF_A6_MASK 0xff +#define WSA884X_CDC_SPK_DSM_A7_0_COEF_A7_MASK 0xff +#define WSA884X_CDC_SPK_DSM_C_0_COEF_C3_MASK 0xf0 +#define WSA884X_CDC_SPK_DSM_C_0_COEF_C2_MASK 0x0f +#define WSA884X_CDC_SPK_DSM_C_1_COEF_C5_MASK 0xf0 +#define WSA884X_CDC_SPK_DSM_C_1_COEF_C4_MASK 0x0f +#define WSA884X_CDC_SPK_DSM_C_2_COEF_C7_MASK 0xf0 +#define WSA884X_CDC_SPK_DSM_C_2_COEF_C6_MASK 0x0f +#define WSA884X_CDC_SPK_DSM_C_3_COEF_C7_MASK 0x3f +#define WSA884X_CDC_SPK_DSM_R1_SAT_LIMIT_R1_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R2_SAT_LIMIT_R2_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R3_SAT_LIMIT_R3_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R4_SAT_LIMIT_R4_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R5_SAT_LIMIT_R5_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R6_SAT_LIMIT_R6_MASK 0xff +#define WSA884X_CDC_SPK_DSM_R7_SAT_LIMIT_R7_MASK 0xff +#define WSA884X_PDM_WD_CTL_PDM_WD_EN_MASK 0x01 +#define WSA884X_DRE_CTL_0_PROG_DELAY_MASK 0xf0 +#define WSA884X_DRE_CTL_0_OFFSET_MASK 0x07 +#define WSA884X_DRE_CTL_1_CSR_GAIN_MASK 0x3e +#define WSA884X_DRE_CTL_1_CSR_GAIN_EN_MASK 0x01 +#define WSA884X_TAGC_CTL_THERMAL_THRESH_MASK 0x0e +#define WSA884X_TAGC_CTL_THERMAL_AGC_EN_MASK 0x01 +#define WSA884X_TAGC_TIME_REL_TIME_MASK 0x30 +#define WSA884X_VAGC_CTL_VBAT_AGC_EN_MASK 0x01 +#define WSA884X_VAGC_TIME_REL_TIME_MASK 0x0c +#define WSA884X_VAGC_TIME_HLD_TIME_MASK 0x03 +#define WSA884X_VAGC_ATTN_LVL_2_VBAT_ATTN_LVL_MASK 0x1f +#define WSA884X_VAGC_ATTN_LVL_3_VBAT_ATTN_LVL_MASK 0x1f +#define WSA884X_OTP_REG_0_WSA884X_ID_MASK 0x0f +#define WSA884X_OTP_REG_1_LOW_TEMP_MSB_MASK 0xff +#define WSA884X_OTP_REG_2_LOW_TEMP_LSB_MASK 0xc0 +#define WSA884X_OTP_REG_3_HIGH_TEMP_MSB_MASK 0xff +#define WSA884X_OTP_REG_4_HIGH_TEMP_LSB_MASK 0xc0 +#define WSA884X_DRE_IDLE_DET_CTL_PA_OFF_FORCE_EN_MASK 0x40 +#define WSA884X_DRE_IDLE_DET_CTL_PDM_WD_FORCE_EN_MASK 0x20 +#define WSA884X_DRE_IDLE_DET_CTL_DRE_IDLE_FORCE_EN_MASK 0x10 +#define WSA884X_DRE_IDLE_DET_CTL_DRE_FORCE_VALUE_MASK 0x0f + +#endif /* WSA884X_REG_MASKS_H */ diff --git a/asoc/codecs/wsa884x/wsa884x-reg-shifts.h b/asoc/codecs/wsa884x/wsa884x-reg-shifts.h new file mode 100644 index 0000000000..f60abeaa01 --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x-reg-shifts.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef WSA884X_REG_SHIFTS_H +#define WSA884X_REG_SHIFTS_H +#include +#include +#include "wsa884x-registers.h" + +#define FIELD_SHIFT(register_name, field_name) \ + WSA884X_##register_name##_##field_name##_SHIFT + +#define WSA884X_VBAT_SNS_BOP_FREQ_SHIFT 0x05 +#define WSA884X_ISENSE2_ISENSE_GAIN_CTL_SHIFT 0x05 +#define WSA884X_ADC_2_ISNS_LOAD_STORED_SHIFT 0x06 +#define WSA884X_ADC_6_INTRLV_RST_OVRD_SHIFT 0x01 +#define WSA884X_ADC_7_EN_AZ_REG_SHIFT 0x02 +#define WSA884X_ADC_7_EN_SAR_REG_SHIFT 0x01 +#define WSA884X_CURRENT_LIMIT_CURRENT_LIMIT_OVRD_EN_SHIFT 0x07 +#define WSA884X_CURRENT_LIMIT_CURRENT_LIMIT_SHIFT 0x02 +#define WSA884X_BOOST_MISC_SPKR_RDY_CTL_SHIFT 0x05 +#define WSA884X_CKWD_CTL_0_CKWD_FDIV_SEL_SHIFT 0x05 +#define WSA884X_CKWD_CTL_1_CKWD_VCOMP_VREF_SEL_SHIFT 0x00 +#define WSA884X_CHIP_ID0_BYTE_0_SHIFT 0x00 +#define WSA884X_PA_FSM_EN_GLOBAL_PA_EN_SHIFT 0x00 +#define WSA884X_PA_FSM_BYP_CTL_PA_FSM_BYP_SHIFT 0x00 +#define WSA884X_PA_FSM_BYP0_TSADC_EN_SHIFT 0x07 +#define WSA884X_PA_FSM_BYP0_SPKR_PROT_EN_SHIFT 0x06 +#define WSA884X_PA_FSM_BYP0_D_UNMUTE_SHIFT 0x05 +#define WSA884X_PA_FSM_BYP0_BG_EN_SHIFT 0x02 +#define WSA884X_PA_FSM_BYP0_CLK_WD_EN_SHIFT 0x01 +#define WSA884X_PA_FSM_BYP0_DC_CAL_EN_SHIFT 0x00 +#define WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_SHIFT 0x00 +#define WSA884X_TEMP_CONFIG0_CTL_THRD_SAF2WAR_SHIFT 0x00 +#define WSA884X_TEMP_CONFIG1_CTL_THRD_WAR2SAF_SHIFT 0x00 +#define WSA884X_VBAT_THRM_FLT_CTL_VBAT_COEF_SEL_SHIFT 0x01 +#define WSA884X_VBAT_THRM_FLT_CTL_VBAT_FLT_EN_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A2_0_COEF_A2_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A2_1_COEF_A2_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A3_0_COEF_A3_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A3_1_COEF_A3_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A4_0_COEF_A4_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A4_1_COEF_A4_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A5_0_COEF_A5_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A5_1_COEF_A5_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A6_0_COEF_A6_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_A7_0_COEF_A7_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_C_0_COEF_C3_SHIFT 0x04 +#define WSA884X_CDC_SPK_DSM_C_0_COEF_C2_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_C_1_COEF_C5_SHIFT 0x04 +#define WSA884X_CDC_SPK_DSM_C_1_COEF_C4_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_C_2_COEF_C7_SHIFT 0x04 +#define WSA884X_CDC_SPK_DSM_C_2_COEF_C6_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_C_3_COEF_C7_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R1_SAT_LIMIT_R1_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R2_SAT_LIMIT_R2_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R3_SAT_LIMIT_R3_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R4_SAT_LIMIT_R4_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R5_SAT_LIMIT_R5_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R6_SAT_LIMIT_R6_SHIFT 0x00 +#define WSA884X_CDC_SPK_DSM_R7_SAT_LIMIT_R7_SHIFT 0x00 +#define WSA884X_PDM_WD_CTL_PDM_WD_EN_SHIFT 0x00 +#define WSA884X_DRE_CTL_0_PROG_DELAY_SHIFT 0x04 +#define WSA884X_DRE_CTL_0_OFFSET_SHIFT 0x00 +#define WSA884X_DRE_CTL_1_CSR_GAIN_SHIFT 0x01 +#define WSA884X_DRE_CTL_1_CSR_GAIN_EN_SHIFT 0x00 +#define WSA884X_TAGC_CTL_THERMAL_THRESH_SHIFT 0x01 +#define WSA884X_TAGC_CTL_THERMAL_AGC_EN_SHIFT 0x00 +#define WSA884X_TAGC_TIME_REL_TIME_SHIFT 0x04 +#define WSA884X_VAGC_CTL_VBAT_AGC_EN_SHIFT 0x00 +#define WSA884X_VAGC_TIME_REL_TIME_SHIFT 0x02 +#define WSA884X_VAGC_TIME_HLD_TIME_SHIFT 0x00 +#define WSA884X_VAGC_ATTN_LVL_2_VBAT_ATTN_LVL_SHIFT 0x00 +#define WSA884X_VAGC_ATTN_LVL_3_VBAT_ATTN_LVL_SHIFT 0x00 +#define WSA884X_OTP_REG_0_WSA884X_ID_SHIFT 0x00 +#define WSA884X_OTP_REG_1_LOW_TEMP_MSB_SHIFT 0x00 +#define WSA884X_OTP_REG_2_LOW_TEMP_LSB_SHIFT 0x06 +#define WSA884X_OTP_REG_3_HIGH_TEMP_MSB_SHIFT 0x00 +#define WSA884X_OTP_REG_4_HIGH_TEMP_LSB_SHIFT 0x06 +#define WSA884X_DRE_IDLE_DET_CTL_PA_OFF_FORCE_EN_SHIFT 0x06 +#define WSA884X_DRE_IDLE_DET_CTL_PDM_WD_FORCE_EN_SHIFT 0x05 +#define WSA884X_DRE_IDLE_DET_CTL_DRE_IDLE_FORCE_EN_SHIFT 0x04 +#define WSA884X_DRE_IDLE_DET_CTL_DRE_FORCE_VALUE_SHIFT 0x00 + +#endif /* WSA884X_REG_SHIFTS_H */ diff --git a/asoc/codecs/wsa884x/wsa884x-registers.h b/asoc/codecs/wsa884x/wsa884x-registers.h new file mode 100644 index 0000000000..57341c1c83 --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x-registers.h @@ -0,0 +1,529 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015, 2019-2021, The Linux Foundation. All rights reserved. + */ + + +#ifndef WSA884X_REGISTERS_H +#define WSA884X_REGISTERS_H + +enum { + REG_NO_ACCESS, + RD_REG, + WR_REG, + RD_WR_REG, +}; + +#define WSA884X_BASE 0x0 +#define WSA884X_REG(reg) (reg - WSA884X_BASE) + +#define WSA884X_BG_TSADC_BASE (WSA884X_BASE+0x01) +#define WSA884X_BG_CTRL (WSA884X_BG_TSADC_BASE+0x00) +#define WSA884X_ADC_CTRL (WSA884X_BG_TSADC_BASE+0x01) +#define WSA884X_BOP1_PROG (WSA884X_BG_TSADC_BASE+0x02) +#define WSA884X_BOP2_PROG (WSA884X_BG_TSADC_BASE+0x03) +#define WSA884X_UVLO_PROG (WSA884X_BG_TSADC_BASE+0x04) +#define WSA884X_UVLO_PROG1 (WSA884X_BG_TSADC_BASE+0x05) +#define WSA884X_SPARE_CTRL_0 (WSA884X_BG_TSADC_BASE+0x06) +#define WSA884X_SPARE_CTRL_1 (WSA884X_BG_TSADC_BASE+0x07) +#define WSA884X_SPARE_CTRL_2 (WSA884X_BG_TSADC_BASE+0x08) +#define WSA884X_SPARE_CTRL_3 (WSA884X_BG_TSADC_BASE+0x09) +#define WSA884X_REF_CTRL (WSA884X_BG_TSADC_BASE+0x0a) +#define WSA884X_BG_TEST_CTL (WSA884X_BG_TSADC_BASE+0x0b) +#define WSA884X_BG_BIAS (WSA884X_BG_TSADC_BASE+0x0c) +#define WSA884X_ADC_PROG (WSA884X_BG_TSADC_BASE+0x0d) +#define WSA884X_ADC_IREF_CTL (WSA884X_BG_TSADC_BASE+0x0e) +#define WSA884X_ADC_ISENS_CTL (WSA884X_BG_TSADC_BASE+0x0f) +#define WSA884X_ADC_CLK_CTL (WSA884X_BG_TSADC_BASE+0x10) +#define WSA884X_ADC_TEST_CTL (WSA884X_BG_TSADC_BASE+0x11) +#define WSA884X_ADC_BIAS (WSA884X_BG_TSADC_BASE+0x12) +#define WSA884X_VBAT_SNS (WSA884X_BG_TSADC_BASE+0x13) +#define WSA884X_DOUT_MSB (WSA884X_BG_TSADC_BASE+0x14) +#define WSA884X_DOUT_LSB (WSA884X_BG_TSADC_BASE+0x15) +#define WSA884X_BOP_ATEST_SEL (WSA884X_BG_TSADC_BASE+0x16) +#define WSA884X_MISC0 (WSA884X_BG_TSADC_BASE+0x17) +#define WSA884X_MISC1 (WSA884X_BG_TSADC_BASE+0x18) +#define WSA884X_MISC2 (WSA884X_BG_TSADC_BASE+0x19) +#define WSA884X_MISC3 (WSA884X_BG_TSADC_BASE+0x1a) +#define WSA884X_SPARE_TSBG_0 (WSA884X_BG_TSADC_BASE+0x1b) +#define WSA884X_SPARE_TUNE_0 (WSA884X_BG_TSADC_BASE+0x1c) +#define WSA884X_SPARE_TUNE_1 (WSA884X_BG_TSADC_BASE+0x1d) + +#define WSA884X_IVSENSE_BASE (WSA884X_BASE+0x20) +#define WSA884X_VSENSE1 (WSA884X_IVSENSE_BASE+0x00) +#define WSA884X_ISENSE2 (WSA884X_IVSENSE_BASE+0x01) +#define WSA884X_SPARE_CTL_1 (WSA884X_IVSENSE_BASE+0x02) +#define WSA884X_SPARE_CTL_2 (WSA884X_IVSENSE_BASE+0x03) +#define WSA884X_SPARE_CTL_3 (WSA884X_IVSENSE_BASE+0x04) +#define WSA884X_SPARE_CTL_4 (WSA884X_IVSENSE_BASE+0x05) +#define WSA884X_EN (WSA884X_IVSENSE_BASE+0x06) +#define WSA884X_OVERRIDE1 (WSA884X_IVSENSE_BASE+0x07) +#define WSA884X_OVERRIDE2 (WSA884X_IVSENSE_BASE+0x08) +#define WSA884X_ISENSE1 (WSA884X_IVSENSE_BASE+0x09) +#define WSA884X_ISENSE_CAL (WSA884X_IVSENSE_BASE+0x0a) +#define WSA884X_MISC (WSA884X_IVSENSE_BASE+0x0b) +#define WSA884X_ADC_0 (WSA884X_IVSENSE_BASE+0x0c) +#define WSA884X_ADC_1 (WSA884X_IVSENSE_BASE+0x0d) +#define WSA884X_ADC_2 (WSA884X_IVSENSE_BASE+0x0e) +#define WSA884X_ADC_3 (WSA884X_IVSENSE_BASE+0x0f) +#define WSA884X_ADC_4 (WSA884X_IVSENSE_BASE+0x10) +#define WSA884X_ADC_5 (WSA884X_IVSENSE_BASE+0x11) +#define WSA884X_ADC_6 (WSA884X_IVSENSE_BASE+0x12) +#define WSA884X_ADC_7 (WSA884X_IVSENSE_BASE+0x13) +#define WSA884X_STATUS (WSA884X_IVSENSE_BASE+0x14) +#define WSA884X_IVSENSE_SPARE_TUNE_1 (WSA884X_IVSENSE_BASE+0x15) +#define WSA884X_SPARE_TUNE_2 (WSA884X_IVSENSE_BASE+0x16) +#define WSA884X_SPARE_TUNE_3 (WSA884X_IVSENSE_BASE+0x17) +#define WSA884X_SPARE_TUNE_4 (WSA884X_IVSENSE_BASE+0x18) + +#define WSA884X_SPK_TOP_BASE (WSA884X_BASE+0x40) +#define WSA884X_TOP_CTRL1 (WSA884X_SPK_TOP_BASE+0x00) +#define WSA884X_CLIP_DET_CTRL1 (WSA884X_SPK_TOP_BASE+0x01) +#define WSA884X_CLIP_DET_CTRL2 (WSA884X_SPK_TOP_BASE+0x02) +#define WSA884X_DAC_CTRL1 (WSA884X_SPK_TOP_BASE+0x03) +#define WSA884X_DAC_VCM_CTRL_REG1 (WSA884X_SPK_TOP_BASE+0x04) +#define WSA884X_DAC_VCM_CTRL_REG2 (WSA884X_SPK_TOP_BASE+0x05) +#define WSA884X_DAC_VCM_CTRL_REG3 (WSA884X_SPK_TOP_BASE+0x06) +#define WSA884X_DAC_VCM_CTRL_REG4 (WSA884X_SPK_TOP_BASE+0x07) +#define WSA884X_DAC_VCM_CTRL_REG5 (WSA884X_SPK_TOP_BASE+0x08) +#define WSA884X_DAC_VCM_CTRL_REG6 (WSA884X_SPK_TOP_BASE+0x09) +#define WSA884X_PWM_CLK_CTL (WSA884X_SPK_TOP_BASE+0x0a) +#define WSA884X_DRV_LF_LDO_SEL (WSA884X_SPK_TOP_BASE+0x0b) +#define WSA884X_OCP_CTL (WSA884X_SPK_TOP_BASE+0x0c) +#define WSA884X_PDRV_HS_CTL (WSA884X_SPK_TOP_BASE+0x0d) +#define WSA884X_PDRV_LS_CTL (WSA884X_SPK_TOP_BASE+0x0e) +#define WSA884X_SPK_TOP_SPARE_CTL_1 (WSA884X_SPK_TOP_BASE+0x0f) +#define WSA884X_SPK_TOP_SPARE_CTL_2 (WSA884X_SPK_TOP_BASE+0x10) +#define WSA884X_SPK_TOP_SPARE_CTL_3 (WSA884X_SPK_TOP_BASE+0x11) +#define WSA884X_SPK_TOP_SPARE_CTL_4 (WSA884X_SPK_TOP_BASE+0x12) +#define WSA884X_SPARE_CTL_5 (WSA884X_SPK_TOP_BASE+0x13) +#define WSA884X_DAC_EN_DEBUG_REG (WSA884X_SPK_TOP_BASE+0x14) +#define WSA884X_DAC_OPAMP_BIAS1_REG (WSA884X_SPK_TOP_BASE+0x15) +#define WSA884X_DAC_OPAMP_BIAS2_REG (WSA884X_SPK_TOP_BASE+0x16) +#define WSA884X_DAC_TUNE1 (WSA884X_SPK_TOP_BASE+0x17) +#define WSA884X_DAC_VOLTAGE_CTRL_REG (WSA884X_SPK_TOP_BASE+0x18) +#define WSA884X_ATEST1_REG (WSA884X_SPK_TOP_BASE+0x19) +#define WSA884X_ATEST2_REG (WSA884X_SPK_TOP_BASE+0x1a) +#define WSA884X_TOP_BIAS_REG1 (WSA884X_SPK_TOP_BASE+0x1b) +#define WSA884X_TOP_BIAS_REG2 (WSA884X_SPK_TOP_BASE+0x1c) +#define WSA884X_TOP_BIAS_REG3 (WSA884X_SPK_TOP_BASE+0x1d) +#define WSA884X_TOP_BIAS_REG4 (WSA884X_SPK_TOP_BASE+0x1e) +#define WSA884X_PWRSTG_DBG2 (WSA884X_SPK_TOP_BASE+0x1f) +#define WSA884X_DRV_LF_BLK_EN (WSA884X_SPK_TOP_BASE+0x20) +#define WSA884X_DRV_LF_EN (WSA884X_SPK_TOP_BASE+0x21) +#define WSA884X_DRV_LF_MASK_DCC_CTL (WSA884X_SPK_TOP_BASE+0x22) +#define WSA884X_DRV_LF_MISC_CTL1 (WSA884X_SPK_TOP_BASE+0x23) +#define WSA884X_DRV_LF_REG_GAIN (WSA884X_SPK_TOP_BASE+0x24) +#define WSA884X_DRV_OS_CAL_CTL (WSA884X_SPK_TOP_BASE+0x25) +#define WSA884X_DRV_OS_CAL_CTL1 (WSA884X_SPK_TOP_BASE+0x26) +#define WSA884X_PWRSTG_DBG (WSA884X_SPK_TOP_BASE+0x27) +#define WSA884X_BBM_CTL (WSA884X_SPK_TOP_BASE+0x28) +#define WSA884X_TOP_MISC1 (WSA884X_SPK_TOP_BASE+0x29) +#define WSA884X_DAC_VCM_CTRL_REG7 (WSA884X_SPK_TOP_BASE+0x2a) +#define WSA884X_TOP_BIAS_REG5 (WSA884X_SPK_TOP_BASE+0x2b) +#define WSA884X_DRV_LF_MISC_CTL2 (WSA884X_SPK_TOP_BASE+0x2c) +#define WSA884X_SPK_TOP_SPARE_TUNE_2 (WSA884X_SPK_TOP_BASE+0x2d) +#define WSA884X_SPK_TOP_SPARE_TUNE_3 (WSA884X_SPK_TOP_BASE+0x2e) +#define WSA884X_SPK_TOP_SPARE_TUNE_4 (WSA884X_SPK_TOP_BASE+0x2f) +#define WSA884X_SPARE_TUNE_5 (WSA884X_SPK_TOP_BASE+0x30) +#define WSA884X_SPARE_TUNE_6 (WSA884X_SPK_TOP_BASE+0x31) +#define WSA884X_SPARE_TUNE_7 (WSA884X_SPK_TOP_BASE+0x32) +#define WSA884X_SPARE_TUNE_8 (WSA884X_SPK_TOP_BASE+0x33) +#define WSA884X_SPARE_TUNE_9 (WSA884X_SPK_TOP_BASE+0x34) +#define WSA884X_SPARE_TUNE_10 (WSA884X_SPK_TOP_BASE+0x35) +#define WSA884X_PA_STATUS0 (WSA884X_SPK_TOP_BASE+0x36) +#define WSA884X_PA_STATUS1 (WSA884X_SPK_TOP_BASE+0x37) +#define WSA884X_PA_STATUS2 (WSA884X_SPK_TOP_BASE+0x38) +#define WSA884X_PA_STATUS3 (WSA884X_SPK_TOP_BASE+0x39) +#define WSA884X_PA_STATUS4 (WSA884X_SPK_TOP_BASE+0x3a) +#define WSA884X_PA_STATUS5 (WSA884X_SPK_TOP_BASE+0x3b) +#define WSA884X_SPARE_RO_1 (WSA884X_SPK_TOP_BASE+0x3c) +#define WSA884X_SPARE_RO_2 (WSA884X_SPK_TOP_BASE+0x3d) +#define WSA884X_SPARE_RO_3 (WSA884X_SPK_TOP_BASE+0x3e) + +#define WSA884X_BOOST_BASE (WSA884X_BASE+0x90) +#define WSA884X_STB_CTRL1 (WSA884X_BOOST_BASE+0x00) +#define WSA884X_CURRENT_LIMIT (WSA884X_BOOST_BASE+0x01) +#define WSA884X_BYP_CTRL1 (WSA884X_BOOST_BASE+0x02) +#define WSA884X_SPARE_CTL_0 (WSA884X_BOOST_BASE+0x03) +#define WSA884X_BOOST_SPARE_CTL_1 (WSA884X_BOOST_BASE+0x04) +#define WSA884X_SPARE_RO_0 (WSA884X_BOOST_BASE+0x05) +#define WSA884X_BOOST_SPARE_RO_1 (WSA884X_BOOST_BASE+0x06) +#define WSA884X_IBIAS1 (WSA884X_BOOST_BASE+0x07) +#define WSA884X_IBIAS2 (WSA884X_BOOST_BASE+0x08) +#define WSA884X_IBIAS3 (WSA884X_BOOST_BASE+0x09) +#define WSA884X_EN_CTRL (WSA884X_BOOST_BASE+0x0a) +#define WSA884X_STB_CTRL2 (WSA884X_BOOST_BASE+0x0b) +#define WSA884X_STB_CTRL3 (WSA884X_BOOST_BASE+0x0c) +#define WSA884X_STB_CTRL4 (WSA884X_BOOST_BASE+0x0d) +#define WSA884X_BYP_CTRL2 (WSA884X_BOOST_BASE+0x0e) +#define WSA884X_BYP_CTRL3 (WSA884X_BOOST_BASE+0x0f) +#define WSA884X_ZX_CTRL1 (WSA884X_BOOST_BASE+0x10) +#define WSA884X_ZX_CTRL2 (WSA884X_BOOST_BASE+0x11) +#define WSA884X_BLEEDER_CTRL (WSA884X_BOOST_BASE+0x12) +#define WSA884X_BOOST_MISC (WSA884X_BOOST_BASE+0x13) +#define WSA884X_PWRSTAGE_CTRL1 (WSA884X_BOOST_BASE+0x14) +#define WSA884X_PWRSTAGE_CTRL2 (WSA884X_BOOST_BASE+0x15) +#define WSA884X_PWRSTAGE_CTRL3 (WSA884X_BOOST_BASE+0x16) +#define WSA884X_PWRSTAGE_CTRL4 (WSA884X_BOOST_BASE+0x17) +#define WSA884X_MAXD_REG1 (WSA884X_BOOST_BASE+0x18) +#define WSA884X_MAXD_REG2 (WSA884X_BOOST_BASE+0x19) +#define WSA884X_ILIM_CTRL1 (WSA884X_BOOST_BASE+0x1a) +#define WSA884X_ILIM_CTRL2 (WSA884X_BOOST_BASE+0x1b) +#define WSA884X_TEST_CTRL1 (WSA884X_BOOST_BASE+0x1c) +#define WSA884X_TEST_CTRL2 (WSA884X_BOOST_BASE+0x1d) +#define WSA884X_SPARE1 (WSA884X_BOOST_BASE+0x1e) +#define WSA884X_BOOT_CAP_CHECK (WSA884X_BOOST_BASE+0x1f) + +#define WSA884X_PON_LDOL_BASE (WSA884X_BASE+0xb0) +#define WSA884X_PON_CTL_0 (WSA884X_PON_LDOL_BASE+0x00) +#define WSA884X_PWRSAV_CTL (WSA884X_PON_LDOL_BASE+0x01) +#define WSA884X_PON_LDOL_SPARE_CTL_0 (WSA884X_PON_LDOL_BASE+0x02) +#define WSA884X_PON_LDOL_SPARE_CTL_1 (WSA884X_PON_LDOL_BASE+0x03) +#define WSA884X_PON_LDOL_SPARE_CTL_2 (WSA884X_PON_LDOL_BASE+0x04) +#define WSA884X_PON_LDOL_SPARE_CTL_3 (WSA884X_PON_LDOL_BASE+0x05) +#define WSA884X_PON_CLT_1 (WSA884X_PON_LDOL_BASE+0x06) +#define WSA884X_PON_CTL_2 (WSA884X_PON_LDOL_BASE+0x07) +#define WSA884X_PON_CTL_3 (WSA884X_PON_LDOL_BASE+0x08) +#define WSA884X_CKWD_CTL_0 (WSA884X_PON_LDOL_BASE+0x09) +#define WSA884X_CKWD_CTL_1 (WSA884X_PON_LDOL_BASE+0x0a) +#define WSA884X_CKWD_CTL_2 (WSA884X_PON_LDOL_BASE+0x0b) +#define WSA884X_CKSK_CTL_0 (WSA884X_PON_LDOL_BASE+0x0c) +#define WSA884X_PADSW_CTL_0 (WSA884X_PON_LDOL_BASE+0x0d) +#define WSA884X_TEST_0 (WSA884X_PON_LDOL_BASE+0x0e) +#define WSA884X_TEST_1 (WSA884X_PON_LDOL_BASE+0x0f) +#define WSA884X_STATUS_0 (WSA884X_PON_LDOL_BASE+0x10) +#define WSA884X_STATUS_1 (WSA884X_PON_LDOL_BASE+0x11) +#define WSA884X_PON_LDOL_SPARE_TUNE_0 (WSA884X_PON_LDOL_BASE+0x12) +#define WSA884X_PON_LDOL_SPARE_TUNE_1 (WSA884X_PON_LDOL_BASE+0x13) +#define WSA884X_PON_LDOL_SPARE_TUNE_2 (WSA884X_PON_LDOL_BASE+0x14) +#define WSA884X_PON_LDOL_SPARE_TUNE_3 (WSA884X_PON_LDOL_BASE+0x15) +#define WSA884X_PON_LDOL_SPARE_TUNE_4 (WSA884X_PON_LDOL_BASE+0x16) + +#define WSA884X_DIG_CTRL0_BASE (WSA884X_BASE+0x400) +#define WSA884X_DIG_CTRL0_PAGE (WSA884X_DIG_CTRL0_BASE+0x00) +#define WSA884X_CHIP_ID0 (WSA884X_DIG_CTRL0_BASE+0x01) +#define WSA884X_CHIP_ID1 (WSA884X_DIG_CTRL0_BASE+0x02) +#define WSA884X_CHIP_ID2 (WSA884X_DIG_CTRL0_BASE+0x03) +#define WSA884X_CHIP_ID3 (WSA884X_DIG_CTRL0_BASE+0x04) +#define WSA884X_BUS_ID (WSA884X_DIG_CTRL0_BASE+0x05) +#define WSA884X_CDC_RST_CTL (WSA884X_DIG_CTRL0_BASE+0x10) +#define WSA884X_SWR_RESET_EN (WSA884X_DIG_CTRL0_BASE+0x14) +#define WSA884X_TOP_CLK_CFG (WSA884X_DIG_CTRL0_BASE+0x18) +#define WSA884X_SWR_CLK_RATE (WSA884X_DIG_CTRL0_BASE+0x19) +#define WSA884X_CDC_PATH_MODE (WSA884X_DIG_CTRL0_BASE+0x1a) +#define WSA884X_CDC_CLK_CTL (WSA884X_DIG_CTRL0_BASE+0x1c) +#define WSA884X_PA_FSM_EN (WSA884X_DIG_CTRL0_BASE+0x30) +#define WSA884X_PA_FSM_CTL0 (WSA884X_DIG_CTRL0_BASE+0x31) +#define WSA884X_PA_FSM_CTL1 (WSA884X_DIG_CTRL0_BASE+0x32) +#define WSA884X_PA_FSM_TIMER0 (WSA884X_DIG_CTRL0_BASE+0x33) +#define WSA884X_PA_FSM_TIMER1 (WSA884X_DIG_CTRL0_BASE+0x34) +#define WSA884X_PA_FSM_STA0 (WSA884X_DIG_CTRL0_BASE+0x35) +#define WSA884X_PA_FSM_STA1 (WSA884X_DIG_CTRL0_BASE+0x36) +#define WSA884X_PA_FSM_ERR_CTL (WSA884X_DIG_CTRL0_BASE+0x37) +#define WSA884X_PA_FSM_ERR_COND0 (WSA884X_DIG_CTRL0_BASE+0x38) +#define WSA884X_PA_FSM_ERR_COND1 (WSA884X_DIG_CTRL0_BASE+0x39) +#define WSA884X_PA_FSM_MSK0 (WSA884X_DIG_CTRL0_BASE+0x3a) +#define WSA884X_PA_FSM_MSK1 (WSA884X_DIG_CTRL0_BASE+0x3b) +#define WSA884X_PA_FSM_BYP_CTL (WSA884X_DIG_CTRL0_BASE+0x3c) +#define WSA884X_PA_FSM_BYP0 (WSA884X_DIG_CTRL0_BASE+0x3d) +#define WSA884X_PA_FSM_BYP1 (WSA884X_DIG_CTRL0_BASE+0x3e) +#define WSA884X_TADC_VALUE_CTL (WSA884X_DIG_CTRL0_BASE+0x50) +#define WSA884X_TEMP_DETECT_CTL (WSA884X_DIG_CTRL0_BASE+0x51) +#define WSA884X_TEMP_DIN_MSB (WSA884X_DIG_CTRL0_BASE+0x52) +#define WSA884X_TEMP_DIN_LSB (WSA884X_DIG_CTRL0_BASE+0x53) +#define WSA884X_TEMP_DOUT_MSB (WSA884X_DIG_CTRL0_BASE+0x54) +#define WSA884X_TEMP_DOUT_LSB (WSA884X_DIG_CTRL0_BASE+0x55) +#define WSA884X_TEMP_CONFIG0 (WSA884X_DIG_CTRL0_BASE+0x56) +#define WSA884X_TEMP_CONFIG1 (WSA884X_DIG_CTRL0_BASE+0x57) +#define WSA884X_VBAT_THRM_FLT_CTL (WSA884X_DIG_CTRL0_BASE+0x58) +#define WSA884X_VBAT_CAL_CTL (WSA884X_DIG_CTRL0_BASE+0x59) +#define WSA884X_VBAT_DIN_MSB (WSA884X_DIG_CTRL0_BASE+0x5a) +#define WSA884X_VBAT_DIN_LSB (WSA884X_DIG_CTRL0_BASE+0x5b) +#define WSA884X_VBAT_DOUT_MSB (WSA884X_DIG_CTRL0_BASE+0x5c) +#define WSA884X_VBAT_DOUT_LSB (WSA884X_DIG_CTRL0_BASE+0x5d) +#define WSA884X_VBAT_CAL_MSB (WSA884X_DIG_CTRL0_BASE+0x5e) +#define WSA884X_VBAT_CAL_LSB (WSA884X_DIG_CTRL0_BASE+0x5f) +#define WSA884X_UVLO_DEGLITCH_CTL (WSA884X_DIG_CTRL0_BASE+0x60) +#define WSA884X_BOP_DEGLITCH_CTL (WSA884X_DIG_CTRL0_BASE+0x61) +#define WSA884X_VBAT_ZONE_DETC_CTL (WSA884X_DIG_CTRL0_BASE+0x64) +#define WSA884X_CPS_CTL (WSA884X_DIG_CTRL0_BASE+0x68) +#define WSA884X_CDC_RX_CTL (WSA884X_DIG_CTRL0_BASE+0x70) +#define WSA884X_CDC_SPK_DSM_A1_0 (WSA884X_DIG_CTRL0_BASE+0x71) +#define WSA884X_CDC_SPK_DSM_A1_1 (WSA884X_DIG_CTRL0_BASE+0x72) +#define WSA884X_CDC_SPK_DSM_A2_0 (WSA884X_DIG_CTRL0_BASE+0x73) +#define WSA884X_CDC_SPK_DSM_A2_1 (WSA884X_DIG_CTRL0_BASE+0x74) +#define WSA884X_CDC_SPK_DSM_A3_0 (WSA884X_DIG_CTRL0_BASE+0x75) +#define WSA884X_CDC_SPK_DSM_A3_1 (WSA884X_DIG_CTRL0_BASE+0x76) +#define WSA884X_CDC_SPK_DSM_A4_0 (WSA884X_DIG_CTRL0_BASE+0x77) +#define WSA884X_CDC_SPK_DSM_A4_1 (WSA884X_DIG_CTRL0_BASE+0x78) +#define WSA884X_CDC_SPK_DSM_A5_0 (WSA884X_DIG_CTRL0_BASE+0x79) +#define WSA884X_CDC_SPK_DSM_A5_1 (WSA884X_DIG_CTRL0_BASE+0x7a) +#define WSA884X_CDC_SPK_DSM_A6_0 (WSA884X_DIG_CTRL0_BASE+0x7b) +#define WSA884X_CDC_SPK_DSM_A7_0 (WSA884X_DIG_CTRL0_BASE+0x7c) +#define WSA884X_CDC_SPK_DSM_C_0 (WSA884X_DIG_CTRL0_BASE+0x7d) +#define WSA884X_CDC_SPK_DSM_C_1 (WSA884X_DIG_CTRL0_BASE+0x7e) +#define WSA884X_CDC_SPK_DSM_C_2 (WSA884X_DIG_CTRL0_BASE+0x7f) +#define WSA884X_CDC_SPK_DSM_C_3 (WSA884X_DIG_CTRL0_BASE+0x80) +#define WSA884X_CDC_SPK_DSM_R1 (WSA884X_DIG_CTRL0_BASE+0x81) +#define WSA884X_CDC_SPK_DSM_R2 (WSA884X_DIG_CTRL0_BASE+0x82) +#define WSA884X_CDC_SPK_DSM_R3 (WSA884X_DIG_CTRL0_BASE+0x83) +#define WSA884X_CDC_SPK_DSM_R4 (WSA884X_DIG_CTRL0_BASE+0x84) +#define WSA884X_CDC_SPK_DSM_R5 (WSA884X_DIG_CTRL0_BASE+0x85) +#define WSA884X_CDC_SPK_DSM_R6 (WSA884X_DIG_CTRL0_BASE+0x86) +#define WSA884X_CDC_SPK_DSM_R7 (WSA884X_DIG_CTRL0_BASE+0x87) +#define WSA884X_CDC_SPK_GAIN_PDM_0 (WSA884X_DIG_CTRL0_BASE+0x88) +#define WSA884X_CDC_SPK_GAIN_PDM_1 (WSA884X_DIG_CTRL0_BASE+0x89) +#define WSA884X_CDC_SPK_GAIN_PDM_2 (WSA884X_DIG_CTRL0_BASE+0x8a) +#define WSA884X_PDM_WD_CTL (WSA884X_DIG_CTRL0_BASE+0x8b) +#define WSA884X_DEM_BYPASS_DATA0 (WSA884X_DIG_CTRL0_BASE+0x90) +#define WSA884X_DEM_BYPASS_DATA1 (WSA884X_DIG_CTRL0_BASE+0x91) +#define WSA884X_DEM_BYPASS_DATA2 (WSA884X_DIG_CTRL0_BASE+0x92) +#define WSA884X_DEM_BYPASS_DATA3 (WSA884X_DIG_CTRL0_BASE+0x93) +#define WSA884X_DRE_CTL_0 (WSA884X_DIG_CTRL0_BASE+0xb0) +#define WSA884X_DRE_CTL_1 (WSA884X_DIG_CTRL0_BASE+0xb1) +#define WSA884X_DRE_IDLE_DET_CTL (WSA884X_DIG_CTRL0_BASE+0xb2) +#define WSA884X_GAIN_RAMPING_CTL (WSA884X_DIG_CTRL0_BASE+0xb8) +#define WSA884X_GAIN_RAMPING_MIN (WSA884X_DIG_CTRL0_BASE+0xb9) +#define WSA884X_TAGC_CTL (WSA884X_DIG_CTRL0_BASE+0xc0) +#define WSA884X_TAGC_TIME (WSA884X_DIG_CTRL0_BASE+0xc1) +#define WSA884X_TAGC_FORCE_VAL (WSA884X_DIG_CTRL0_BASE+0xc2) +#define WSA884X_VAGC_CTL (WSA884X_DIG_CTRL0_BASE+0xc8) +#define WSA884X_VAGC_TIME (WSA884X_DIG_CTRL0_BASE+0xc9) +#define WSA884X_VAGC_ATTN_LVL_1 (WSA884X_DIG_CTRL0_BASE+0xca) +#define WSA884X_VAGC_ATTN_LVL_2 (WSA884X_DIG_CTRL0_BASE+0xcb) +#define WSA884X_VAGC_ATTN_LVL_3 (WSA884X_DIG_CTRL0_BASE+0xcc) +#define WSA884X_CLSH_CTL_0 (WSA884X_DIG_CTRL0_BASE+0xd0) +#define WSA884X_CLSH_CTL_1 (WSA884X_DIG_CTRL0_BASE+0xd1) +#define WSA884X_CLSH_V_HD_PA (WSA884X_DIG_CTRL0_BASE+0xd2) +#define WSA884X_CLSH_V_PA_MIN (WSA884X_DIG_CTRL0_BASE+0xd3) +#define WSA884X_CLSH_OVRD_VAL (WSA884X_DIG_CTRL0_BASE+0xd4) +#define WSA884X_CLSH_HARD_MAX (WSA884X_DIG_CTRL0_BASE+0xd5) +#define WSA884X_CLSH_SOFT_MAX (WSA884X_DIG_CTRL0_BASE+0xd6) +#define WSA884X_CLSH_SIG_DP (WSA884X_DIG_CTRL0_BASE+0xd7) +#define WSA884X_PBR_DELAY_CTL (WSA884X_DIG_CTRL0_BASE+0xd8) +#define WSA884X_CLSH_SRL_MAX_PBR (WSA884X_DIG_CTRL0_BASE+0xe0) +#define WSA884X_CLSH_VTH1 (WSA884X_DIG_CTRL0_BASE+0xe1) +#define WSA884X_CLSH_VTH2 (WSA884X_DIG_CTRL0_BASE+0xe2) +#define WSA884X_CLSH_VTH3 (WSA884X_DIG_CTRL0_BASE+0xe3) +#define WSA884X_CLSH_VTH4 (WSA884X_DIG_CTRL0_BASE+0xe4) +#define WSA884X_CLSH_VTH5 (WSA884X_DIG_CTRL0_BASE+0xe5) +#define WSA884X_CLSH_VTH6 (WSA884X_DIG_CTRL0_BASE+0xe6) +#define WSA884X_CLSH_VTH7 (WSA884X_DIG_CTRL0_BASE+0xe7) +#define WSA884X_CLSH_VTH8 (WSA884X_DIG_CTRL0_BASE+0xe8) +#define WSA884X_CLSH_VTH9 (WSA884X_DIG_CTRL0_BASE+0xe9) +#define WSA884X_CLSH_VTH10 (WSA884X_DIG_CTRL0_BASE+0xea) +#define WSA884X_CLSH_VTH11 (WSA884X_DIG_CTRL0_BASE+0xeb) +#define WSA884X_CLSH_VTH12 (WSA884X_DIG_CTRL0_BASE+0xec) +#define WSA884X_CLSH_VTH13 (WSA884X_DIG_CTRL0_BASE+0xed) +#define WSA884X_CLSH_VTH14 (WSA884X_DIG_CTRL0_BASE+0xee) +#define WSA884X_CLSH_VTH15 (WSA884X_DIG_CTRL0_BASE+0xef) + +#define WSA884X_DIG_CTRL1_BASE (WSA884X_BASE+0x500) +#define WSA884X_DIG_CTRL1_PAGE (WSA884X_DIG_CTRL1_BASE+0x00) +#define WSA884X_BST_CFG (WSA884X_DIG_CTRL1_BASE+0x01) +#define WSA884X_ANA_WO_CTL_0 (WSA884X_DIG_CTRL1_BASE+0x04) +#define WSA884X_ANA_WO_CTL_1 (WSA884X_DIG_CTRL1_BASE+0x05) +#define WSA884X_PIN_CTL (WSA884X_DIG_CTRL1_BASE+0x10) +#define WSA884X_PIN_CTL_OE (WSA884X_DIG_CTRL1_BASE+0x11) +#define WSA884X_PIN_WDATA_IOPAD (WSA884X_DIG_CTRL1_BASE+0x12) +#define WSA884X_PIN_STATUS (WSA884X_DIG_CTRL1_BASE+0x13) +#define WSA884X_I2C_SLAVE_CTL (WSA884X_DIG_CTRL1_BASE+0x14) +#define WSA884X_SPMI_PAD_CTL0 (WSA884X_DIG_CTRL1_BASE+0x15) +#define WSA884X_SPMI_PAD_CTL1 (WSA884X_DIG_CTRL1_BASE+0x16) +#define WSA884X_SPMI_PAD_CTL2 (WSA884X_DIG_CTRL1_BASE+0x17) +#define WSA884X_MEM_CTL (WSA884X_DIG_CTRL1_BASE+0x18) +#define WSA884X_SWR_HM_TEST0 (WSA884X_DIG_CTRL1_BASE+0x19) +#define WSA884X_SWR_HM_TEST1 (WSA884X_DIG_CTRL1_BASE+0x1a) +#define WSA884X_OTP_CTRL0 (WSA884X_DIG_CTRL1_BASE+0x30) +#define WSA884X_OTP_CTRL1 (WSA884X_DIG_CTRL1_BASE+0x31) +#define WSA884X_OTP_CTRL2 (WSA884X_DIG_CTRL1_BASE+0x32) +#define WSA884X_OTP_STAT (WSA884X_DIG_CTRL1_BASE+0x33) +#define WSA884X_OTP_PRG_TCSP0 (WSA884X_DIG_CTRL1_BASE+0x34) +#define WSA884X_OTP_PRG_TCSP1 (WSA884X_DIG_CTRL1_BASE+0x35) +#define WSA884X_OTP_PRG_TPPS (WSA884X_DIG_CTRL1_BASE+0x36) +#define WSA884X_OTP_PRG_TVPS (WSA884X_DIG_CTRL1_BASE+0x37) +#define WSA884X_OTP_PRG_TVPH (WSA884X_DIG_CTRL1_BASE+0x38) +#define WSA884X_OTP_PRG_TPPR0 (WSA884X_DIG_CTRL1_BASE+0x39) +#define WSA884X_OTP_PRG_TPPR1 (WSA884X_DIG_CTRL1_BASE+0x3a) +#define WSA884X_OTP_PRG_TPPH (WSA884X_DIG_CTRL1_BASE+0x3b) +#define WSA884X_OTP_PRG_END (WSA884X_DIG_CTRL1_BASE+0x3c) +#define WSA884X_WAVG_PLAY (WSA884X_DIG_CTRL1_BASE+0x40) +#define WSA884X_WAVG_CTL (WSA884X_DIG_CTRL1_BASE+0x41) +#define WSA884X_WAVG_LRA_PER_0 (WSA884X_DIG_CTRL1_BASE+0x43) +#define WSA884X_WAVG_LRA_PER_1 (WSA884X_DIG_CTRL1_BASE+0x44) +#define WSA884X_WAVG_DELTA_THETA_0 (WSA884X_DIG_CTRL1_BASE+0x45) +#define WSA884X_WAVG_DELTA_THETA_1 (WSA884X_DIG_CTRL1_BASE+0x46) +#define WSA884X_WAVG_DIRECT_AMP_0 (WSA884X_DIG_CTRL1_BASE+0x47) +#define WSA884X_WAVG_DIRECT_AMP_1 (WSA884X_DIG_CTRL1_BASE+0x48) +#define WSA884X_WAVG_PTRN_AMP0_0 (WSA884X_DIG_CTRL1_BASE+0x49) +#define WSA884X_WAVG_PTRN_AMP0_1 (WSA884X_DIG_CTRL1_BASE+0x4a) +#define WSA884X_WAVG_PTRN_AMP1_0 (WSA884X_DIG_CTRL1_BASE+0x4b) +#define WSA884X_WAVG_PTRN_AMP1_1 (WSA884X_DIG_CTRL1_BASE+0x4c) +#define WSA884X_WAVG_PTRN_AMP2_0 (WSA884X_DIG_CTRL1_BASE+0x4d) +#define WSA884X_WAVG_PTRN_AMP2_1 (WSA884X_DIG_CTRL1_BASE+0x4e) +#define WSA884X_WAVG_PTRN_AMP3_0 (WSA884X_DIG_CTRL1_BASE+0x4f) +#define WSA884X_WAVG_PTRN_AMP3_1 (WSA884X_DIG_CTRL1_BASE+0x50) +#define WSA884X_WAVG_PTRN_AMP4_0 (WSA884X_DIG_CTRL1_BASE+0x51) +#define WSA884X_WAVG_PTRN_AMP4_1 (WSA884X_DIG_CTRL1_BASE+0x52) +#define WSA884X_WAVG_PTRN_AMP5_0 (WSA884X_DIG_CTRL1_BASE+0x53) +#define WSA884X_WAVG_PTRN_AMP5_1 (WSA884X_DIG_CTRL1_BASE+0x54) +#define WSA884X_WAVG_PTRN_AMP6_0 (WSA884X_DIG_CTRL1_BASE+0x55) +#define WSA884X_WAVG_PTRN_AMP6_1 (WSA884X_DIG_CTRL1_BASE+0x56) +#define WSA884X_WAVG_PTRN_AMP7_0 (WSA884X_DIG_CTRL1_BASE+0x57) +#define WSA884X_WAVG_PTRN_AMP7_1 (WSA884X_DIG_CTRL1_BASE+0x58) +#define WSA884X_WAVG_PER_0_1 (WSA884X_DIG_CTRL1_BASE+0x59) +#define WSA884X_WAVG_PER_2_3 (WSA884X_DIG_CTRL1_BASE+0x5a) +#define WSA884X_WAVG_PER_4_5 (WSA884X_DIG_CTRL1_BASE+0x5b) +#define WSA884X_WAVG_PER_6_7 (WSA884X_DIG_CTRL1_BASE+0x5c) +#define WSA884X_WAVG_STA (WSA884X_DIG_CTRL1_BASE+0x5d) +#define WSA884X_INTR_MODE (WSA884X_DIG_CTRL1_BASE+0x80) +#define WSA884X_INTR_MASK0 (WSA884X_DIG_CTRL1_BASE+0x81) +#define WSA884X_INTR_MASK1 (WSA884X_DIG_CTRL1_BASE+0x82) +#define WSA884X_INTR_STATUS0 (WSA884X_DIG_CTRL1_BASE+0x83) +#define WSA884X_INTR_STATUS1 (WSA884X_DIG_CTRL1_BASE+0x84) +#define WSA884X_INTR_CLEAR0 (WSA884X_DIG_CTRL1_BASE+0x85) +#define WSA884X_INTR_CLEAR1 (WSA884X_DIG_CTRL1_BASE+0x86) +#define WSA884X_INTR_LEVEL0 (WSA884X_DIG_CTRL1_BASE+0x87) +#define WSA884X_INTR_LEVEL1 (WSA884X_DIG_CTRL1_BASE+0x88) +#define WSA884X_INTR_SET0 (WSA884X_DIG_CTRL1_BASE+0x89) +#define WSA884X_INTR_SET1 (WSA884X_DIG_CTRL1_BASE+0x8a) +#define WSA884X_INTR_TEST0 (WSA884X_DIG_CTRL1_BASE+0x8b) +#define WSA884X_INTR_TEST1 (WSA884X_DIG_CTRL1_BASE+0x8c) +#define WSA884X_PDM_TEST_MODE (WSA884X_DIG_CTRL1_BASE+0xc0) +#define WSA884X_ATE_TEST_MODE (WSA884X_DIG_CTRL1_BASE+0xc1) +#define WSA884X_PA_FSM_DBG (WSA884X_DIG_CTRL1_BASE+0xc2) +#define WSA884X_DIG_DEBUG_MODE (WSA884X_DIG_CTRL1_BASE+0xc3) +#define WSA884X_DIG_DEBUG_SEL (WSA884X_DIG_CTRL1_BASE+0xc4) +#define WSA884X_DIG_DEBUG_EN (WSA884X_DIG_CTRL1_BASE+0xc5) +#define WSA884X_TADC_DETECT_DBG_CTL (WSA884X_DIG_CTRL1_BASE+0xc9) +#define WSA884X_TADC_DEBUG_MSB (WSA884X_DIG_CTRL1_BASE+0xca) +#define WSA884X_TADC_DEBUG_LSB (WSA884X_DIG_CTRL1_BASE+0xcb) +#define WSA884X_SAMPLE_EDGE_SEL (WSA884X_DIG_CTRL1_BASE+0xcc) +#define WSA884X_SWR_EDGE_SEL (WSA884X_DIG_CTRL1_BASE+0xcd) +#define WSA884X_TEST_MODE_CTL (WSA884X_DIG_CTRL1_BASE+0xce) +#define WSA884X_IOPAD_CTL (WSA884X_DIG_CTRL1_BASE+0xcf) +#define WSA884X_ANA_CSR_DBG_ADD (WSA884X_DIG_CTRL1_BASE+0xd0) +#define WSA884X_ANA_CSR_DBG_CTL (WSA884X_DIG_CTRL1_BASE+0xd1) +#define WSA884X_CLK_DBG_CTL (WSA884X_DIG_CTRL1_BASE+0xd2) +#define WSA884X_SPARE_R (WSA884X_DIG_CTRL1_BASE+0xf0) +#define WSA884X_SPARE_0 (WSA884X_DIG_CTRL1_BASE+0xf1) +#define WSA884X_SPARE_1 (WSA884X_DIG_CTRL1_BASE+0xf2) +#define WSA884X_SPARE_2 (WSA884X_DIG_CTRL1_BASE+0xf3) +#define WSA884X_SCODE (WSA884X_DIG_CTRL1_BASE+0xff) + +#define WSA884X_DIG_TRIM_BASE (WSA884X_BASE+0x800) +#define WSA884X_DIG_TRIM_PAGE (WSA884X_DIG_TRIM_BASE+0x00) +#define WSA884X_OTP_REG_0 (WSA884X_DIG_TRIM_BASE+0x80) +#define WSA884X_OTP_REG_1 (WSA884X_DIG_TRIM_BASE+0x81) +#define WSA884X_OTP_REG_2 (WSA884X_DIG_TRIM_BASE+0x82) +#define WSA884X_OTP_REG_3 (WSA884X_DIG_TRIM_BASE+0x83) +#define WSA884X_OTP_REG_4 (WSA884X_DIG_TRIM_BASE+0x84) +#define WSA884X_OTP_REG_5 (WSA884X_DIG_TRIM_BASE+0x85) +#define WSA884X_OTP_REG_6 (WSA884X_DIG_TRIM_BASE+0x86) +#define WSA884X_OTP_REG_7 (WSA884X_DIG_TRIM_BASE+0x87) +#define WSA884X_OTP_REG_8 (WSA884X_DIG_TRIM_BASE+0x88) +#define WSA884X_OTP_REG_9 (WSA884X_DIG_TRIM_BASE+0x89) +#define WSA884X_OTP_REG_10 (WSA884X_DIG_TRIM_BASE+0x8a) +#define WSA884X_OTP_REG_11 (WSA884X_DIG_TRIM_BASE+0x8b) +#define WSA884X_OTP_REG_12 (WSA884X_DIG_TRIM_BASE+0x8c) +#define WSA884X_OTP_REG_13 (WSA884X_DIG_TRIM_BASE+0x8d) +#define WSA884X_OTP_REG_14 (WSA884X_DIG_TRIM_BASE+0x8e) +#define WSA884X_OTP_REG_15 (WSA884X_DIG_TRIM_BASE+0x8f) +#define WSA884X_OTP_REG_16 (WSA884X_DIG_TRIM_BASE+0x90) +#define WSA884X_OTP_REG_17 (WSA884X_DIG_TRIM_BASE+0x91) +#define WSA884X_OTP_REG_18 (WSA884X_DIG_TRIM_BASE+0x92) +#define WSA884X_OTP_REG_19 (WSA884X_DIG_TRIM_BASE+0x93) +#define WSA884X_OTP_REG_20 (WSA884X_DIG_TRIM_BASE+0x94) +#define WSA884X_OTP_REG_21 (WSA884X_DIG_TRIM_BASE+0x95) +#define WSA884X_OTP_REG_22 (WSA884X_DIG_TRIM_BASE+0x96) +#define WSA884X_OTP_REG_23 (WSA884X_DIG_TRIM_BASE+0x97) +#define WSA884X_OTP_REG_24 (WSA884X_DIG_TRIM_BASE+0x98) +#define WSA884X_OTP_REG_25 (WSA884X_DIG_TRIM_BASE+0x99) +#define WSA884X_OTP_REG_26 (WSA884X_DIG_TRIM_BASE+0x9a) +#define WSA884X_OTP_REG_27 (WSA884X_DIG_TRIM_BASE+0x9b) +#define WSA884X_OTP_REG_28 (WSA884X_DIG_TRIM_BASE+0x9c) +#define WSA884X_OTP_REG_29 (WSA884X_DIG_TRIM_BASE+0x9d) +#define WSA884X_OTP_REG_30 (WSA884X_DIG_TRIM_BASE+0x9e) +#define WSA884X_OTP_REG_31 (WSA884X_DIG_TRIM_BASE+0x9f) +#define WSA884X_OTP_REG_32 (WSA884X_DIG_TRIM_BASE+0xa0) +#define WSA884X_OTP_REG_33 (WSA884X_DIG_TRIM_BASE+0xa1) +#define WSA884X_OTP_REG_34 (WSA884X_DIG_TRIM_BASE+0xa2) +#define WSA884X_OTP_REG_35 (WSA884X_DIG_TRIM_BASE+0xa3) +#define WSA884X_OTP_REG_36 (WSA884X_DIG_TRIM_BASE+0xa4) +#define WSA884X_OTP_REG_37 (WSA884X_DIG_TRIM_BASE+0xa5) +#define WSA884X_OTP_REG_38 (WSA884X_DIG_TRIM_BASE+0xa6) +#define WSA884X_OTP_REG_39 (WSA884X_DIG_TRIM_BASE+0xa7) +#define WSA884X_OTP_REG_40 (WSA884X_DIG_TRIM_BASE+0xa8) +#define WSA884X_OTP_REG_41 (WSA884X_DIG_TRIM_BASE+0xa9) +#define WSA884X_OTP_REG_63 (WSA884X_DIG_TRIM_BASE+0xbf) + +#define WSA884X_EMEM_BASE (WSA884X_BASE+0x8c0) +#define WSA884X_EMEM_0 (WSA884X_EMEM_BASE+0x00) +#define WSA884X_EMEM_1 (WSA884X_EMEM_BASE+0x01) +#define WSA884X_EMEM_2 (WSA884X_EMEM_BASE+0x02) +#define WSA884X_EMEM_3 (WSA884X_EMEM_BASE+0x03) +#define WSA884X_EMEM_4 (WSA884X_EMEM_BASE+0x04) +#define WSA884X_EMEM_5 (WSA884X_EMEM_BASE+0x05) +#define WSA884X_EMEM_6 (WSA884X_EMEM_BASE+0x06) +#define WSA884X_EMEM_7 (WSA884X_EMEM_BASE+0x07) +#define WSA884X_EMEM_8 (WSA884X_EMEM_BASE+0x08) +#define WSA884X_EMEM_9 (WSA884X_EMEM_BASE+0x09) +#define WSA884X_EMEM_10 (WSA884X_EMEM_BASE+0x0a) +#define WSA884X_EMEM_11 (WSA884X_EMEM_BASE+0x0b) +#define WSA884X_EMEM_12 (WSA884X_EMEM_BASE+0x0c) +#define WSA884X_EMEM_13 (WSA884X_EMEM_BASE+0x0d) +#define WSA884X_EMEM_14 (WSA884X_EMEM_BASE+0x0e) +#define WSA884X_EMEM_15 (WSA884X_EMEM_BASE+0x0f) +#define WSA884X_EMEM_16 (WSA884X_EMEM_BASE+0x10) +#define WSA884X_EMEM_17 (WSA884X_EMEM_BASE+0x11) +#define WSA884X_EMEM_18 (WSA884X_EMEM_BASE+0x12) +#define WSA884X_EMEM_19 (WSA884X_EMEM_BASE+0x13) +#define WSA884X_EMEM_20 (WSA884X_EMEM_BASE+0x14) +#define WSA884X_EMEM_21 (WSA884X_EMEM_BASE+0x15) +#define WSA884X_EMEM_22 (WSA884X_EMEM_BASE+0x16) +#define WSA884X_EMEM_23 (WSA884X_EMEM_BASE+0x17) +#define WSA884X_EMEM_24 (WSA884X_EMEM_BASE+0x18) +#define WSA884X_EMEM_25 (WSA884X_EMEM_BASE+0x19) +#define WSA884X_EMEM_26 (WSA884X_EMEM_BASE+0x1a) +#define WSA884X_EMEM_27 (WSA884X_EMEM_BASE+0x1b) +#define WSA884X_EMEM_28 (WSA884X_EMEM_BASE+0x1c) +#define WSA884X_EMEM_29 (WSA884X_EMEM_BASE+0x1d) +#define WSA884X_EMEM_30 (WSA884X_EMEM_BASE+0x1e) +#define WSA884X_EMEM_31 (WSA884X_EMEM_BASE+0x1f) +#define WSA884X_EMEM_32 (WSA884X_EMEM_BASE+0x20) +#define WSA884X_EMEM_33 (WSA884X_EMEM_BASE+0x21) +#define WSA884X_EMEM_34 (WSA884X_EMEM_BASE+0x22) +#define WSA884X_EMEM_35 (WSA884X_EMEM_BASE+0x23) +#define WSA884X_EMEM_36 (WSA884X_EMEM_BASE+0x24) +#define WSA884X_EMEM_37 (WSA884X_EMEM_BASE+0x25) +#define WSA884X_EMEM_38 (WSA884X_EMEM_BASE+0x26) +#define WSA884X_EMEM_39 (WSA884X_EMEM_BASE+0x27) +#define WSA884X_EMEM_40 (WSA884X_EMEM_BASE+0x28) +#define WSA884X_EMEM_41 (WSA884X_EMEM_BASE+0x29) +#define WSA884X_EMEM_42 (WSA884X_EMEM_BASE+0x2a) +#define WSA884X_EMEM_43 (WSA884X_EMEM_BASE+0x2b) +#define WSA884X_EMEM_44 (WSA884X_EMEM_BASE+0x2c) +#define WSA884X_EMEM_45 (WSA884X_EMEM_BASE+0x2d) +#define WSA884X_EMEM_46 (WSA884X_EMEM_BASE+0x2e) +#define WSA884X_EMEM_47 (WSA884X_EMEM_BASE+0x2f) +#define WSA884X_EMEM_48 (WSA884X_EMEM_BASE+0x30) +#define WSA884X_EMEM_49 (WSA884X_EMEM_BASE+0x31) +#define WSA884X_EMEM_50 (WSA884X_EMEM_BASE+0x32) +#define WSA884X_EMEM_51 (WSA884X_EMEM_BASE+0x33) +#define WSA884X_EMEM_52 (WSA884X_EMEM_BASE+0x34) +#define WSA884X_EMEM_53 (WSA884X_EMEM_BASE+0x35) +#define WSA884X_EMEM_54 (WSA884X_EMEM_BASE+0x36) +#define WSA884X_EMEM_55 (WSA884X_EMEM_BASE+0x37) +#define WSA884X_EMEM_56 (WSA884X_EMEM_BASE+0x38) +#define WSA884X_EMEM_57 (WSA884X_EMEM_BASE+0x39) +#define WSA884X_EMEM_58 (WSA884X_EMEM_BASE+0x3a) +#define WSA884X_EMEM_59 (WSA884X_EMEM_BASE+0x3b) +#define WSA884X_EMEM_60 (WSA884X_EMEM_BASE+0x3c) +#define WSA884X_EMEM_61 (WSA884X_EMEM_BASE+0x3d) +#define WSA884X_EMEM_62 (WSA884X_EMEM_BASE+0x3e) +#define WSA884X_EMEM_63 (WSA884X_EMEM_BASE+0x3f) + +#define WSA884X_NUM_REGISTERS (WSA884X_EMEM_63+1) +#define WSA884X_MAX_REGISTER (WSA884X_NUM_REGISTERS-1) + +#endif /* WSA884X_REGISTERS_H */ diff --git a/asoc/codecs/wsa884x/wsa884x-regmap.c b/asoc/codecs/wsa884x/wsa884x-regmap.c new file mode 100644 index 0000000000..650d3c940a --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x-regmap.c @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "wsa884x-registers.h" +#include "wsa884x.h" + +extern const u8 wsa884x_reg_access[WSA884X_NUM_REGISTERS]; + +static struct reg_default wsa884x_defaults[] = { + {WSA884X_BG_CTRL, 0xa5}, + {WSA884X_ADC_CTRL, 0x00}, + {WSA884X_BOP1_PROG, 0x22}, + {WSA884X_BOP2_PROG, 0x44}, + {WSA884X_UVLO_PROG, 0x99}, + {WSA884X_UVLO_PROG1, 0x70}, + {WSA884X_SPARE_CTRL_0, 0x00}, + {WSA884X_SPARE_CTRL_1, 0x00}, + {WSA884X_SPARE_CTRL_2, 0x00}, + {WSA884X_SPARE_CTRL_3, 0x00}, + {WSA884X_REF_CTRL, 0xd2}, + {WSA884X_BG_TEST_CTL, 0x06}, + {WSA884X_BG_BIAS, 0xd7}, + {WSA884X_ADC_PROG, 0x08}, + {WSA884X_ADC_IREF_CTL, 0x57}, + {WSA884X_ADC_ISENS_CTL, 0x47}, + {WSA884X_ADC_CLK_CTL, 0x87}, + {WSA884X_ADC_TEST_CTL, 0x00}, + {WSA884X_ADC_BIAS, 0x51}, + {WSA884X_VBAT_SNS, 0xa0}, + {WSA884X_DOUT_MSB, 0x00}, + {WSA884X_DOUT_LSB, 0x00}, + {WSA884X_BOP_ATEST_SEL, 0x00}, + {WSA884X_MISC0, 0x04}, + {WSA884X_MISC1, 0x75}, + {WSA884X_MISC2, 0x00}, + {WSA884X_MISC3, 0x10}, + {WSA884X_SPARE_TSBG_0, 0x00}, + {WSA884X_SPARE_TUNE_0, 0x00}, + {WSA884X_SPARE_TUNE_1, 0x00}, + {WSA884X_VSENSE1, 0xe7}, + {WSA884X_ISENSE2, 0x27}, + {WSA884X_SPARE_CTL_1, 0x00}, + {WSA884X_SPARE_CTL_2, 0x00}, + {WSA884X_SPARE_CTL_3, 0x00}, + {WSA884X_SPARE_CTL_4, 0x00}, + {WSA884X_EN, 0x10}, + {WSA884X_OVERRIDE1, 0x00}, + {WSA884X_OVERRIDE2, 0x08}, + {WSA884X_ISENSE1, 0xd4}, + {WSA884X_ISENSE_CAL, 0x00}, + {WSA884X_MISC, 0x00}, + {WSA884X_ADC_0, 0x00}, + {WSA884X_ADC_1, 0x00}, + {WSA884X_ADC_2, 0x40}, + {WSA884X_ADC_3, 0x80}, + {WSA884X_ADC_4, 0x25}, + {WSA884X_ADC_5, 0x24}, + {WSA884X_ADC_6, 0x0a}, + {WSA884X_ADC_7, 0x81}, + {WSA884X_STATUS, 0x00}, + {WSA884X_IVSENSE_SPARE_TUNE_1, 0x00}, + {WSA884X_SPARE_TUNE_2, 0x00}, + {WSA884X_SPARE_TUNE_3, 0x00}, + {WSA884X_SPARE_TUNE_4, 0x00}, + {WSA884X_TOP_CTRL1, 0xd3}, + {WSA884X_CLIP_DET_CTRL1, 0x7e}, + {WSA884X_CLIP_DET_CTRL2, 0x4c}, + {WSA884X_DAC_CTRL1, 0xa4}, + {WSA884X_DAC_VCM_CTRL_REG1, 0x02}, + {WSA884X_DAC_VCM_CTRL_REG2, 0x00}, + {WSA884X_DAC_VCM_CTRL_REG3, 0x00}, + {WSA884X_DAC_VCM_CTRL_REG4, 0x00}, + {WSA884X_DAC_VCM_CTRL_REG5, 0x00}, + {WSA884X_DAC_VCM_CTRL_REG6, 0x00}, + {WSA884X_PWM_CLK_CTL, 0x20}, + {WSA884X_DRV_LF_LDO_SEL, 0xaa}, + {WSA884X_OCP_CTL, 0xc6}, + {WSA884X_PDRV_HS_CTL, 0x52}, + {WSA884X_PDRV_LS_CTL, 0x4a}, + {WSA884X_SPK_TOP_SPARE_CTL_1, 0x00}, + {WSA884X_SPK_TOP_SPARE_CTL_2, 0x00}, + {WSA884X_SPK_TOP_SPARE_CTL_3, 0x00}, + {WSA884X_SPK_TOP_SPARE_CTL_4, 0x00}, + {WSA884X_SPARE_CTL_5, 0x00}, + {WSA884X_DAC_EN_DEBUG_REG, 0x00}, + {WSA884X_DAC_OPAMP_BIAS1_REG, 0x48}, + {WSA884X_DAC_OPAMP_BIAS2_REG, 0x48}, + {WSA884X_DAC_TUNE1, 0x02}, + {WSA884X_DAC_VOLTAGE_CTRL_REG, 0x05}, + {WSA884X_ATEST1_REG, 0x00}, + {WSA884X_ATEST2_REG, 0x00}, + {WSA884X_TOP_BIAS_REG1, 0x6a}, + {WSA884X_TOP_BIAS_REG2, 0x65}, + {WSA884X_TOP_BIAS_REG3, 0x55}, + {WSA884X_TOP_BIAS_REG4, 0xa9}, + {WSA884X_PWRSTG_DBG2, 0x21}, + {WSA884X_DRV_LF_BLK_EN, 0x0f}, + {WSA884X_DRV_LF_EN, 0x0a}, + {WSA884X_DRV_LF_MASK_DCC_CTL, 0x08}, + {WSA884X_DRV_LF_MISC_CTL1, 0x30}, + {WSA884X_DRV_LF_REG_GAIN, 0x00}, + {WSA884X_DRV_OS_CAL_CTL, 0x00}, + {WSA884X_DRV_OS_CAL_CTL1, 0x90}, + {WSA884X_PWRSTG_DBG, 0x08}, + {WSA884X_BBM_CTL, 0x92}, + {WSA884X_TOP_MISC1, 0x00}, + {WSA884X_DAC_VCM_CTRL_REG7, 0x00}, + {WSA884X_TOP_BIAS_REG5, 0x15}, + {WSA884X_DRV_LF_MISC_CTL2, 0x00}, + {WSA884X_SPK_TOP_SPARE_TUNE_2, 0x00}, + {WSA884X_SPK_TOP_SPARE_TUNE_3, 0x00}, + {WSA884X_SPK_TOP_SPARE_TUNE_4, 0x00}, + {WSA884X_SPARE_TUNE_5, 0x00}, + {WSA884X_SPARE_TUNE_6, 0x00}, + {WSA884X_SPARE_TUNE_7, 0x00}, + {WSA884X_SPARE_TUNE_8, 0x00}, + {WSA884X_SPARE_TUNE_9, 0x00}, + {WSA884X_SPARE_TUNE_10, 0x00}, + {WSA884X_PA_STATUS0, 0x00}, + {WSA884X_PA_STATUS1, 0x00}, + {WSA884X_PA_STATUS2, 0x00}, + {WSA884X_PA_STATUS3, 0x00}, + {WSA884X_PA_STATUS4, 0x00}, + {WSA884X_PA_STATUS5, 0x00}, + {WSA884X_SPARE_RO_1, 0x00}, + {WSA884X_SPARE_RO_2, 0x00}, + {WSA884X_SPARE_RO_3, 0x00}, + {WSA884X_STB_CTRL1, 0x42}, + {WSA884X_CURRENT_LIMIT, 0x54}, + {WSA884X_BYP_CTRL1, 0x01}, + {WSA884X_SPARE_CTL_0, 0x00}, + {WSA884X_BOOST_SPARE_CTL_1, 0x00}, + {WSA884X_SPARE_RO_0, 0x00}, + {WSA884X_BOOST_SPARE_RO_1, 0x00}, + {WSA884X_IBIAS1, 0x00}, + {WSA884X_IBIAS2, 0x00}, + {WSA884X_IBIAS3, 0x00}, + {WSA884X_EN_CTRL, 0x42}, + {WSA884X_STB_CTRL2, 0x03}, + {WSA884X_STB_CTRL3, 0x3c}, + {WSA884X_STB_CTRL4, 0x30}, + {WSA884X_BYP_CTRL2, 0x97}, + {WSA884X_BYP_CTRL3, 0x11}, + {WSA884X_ZX_CTRL1, 0xf0}, + {WSA884X_ZX_CTRL2, 0x04}, + {WSA884X_BLEEDER_CTRL, 0x04}, + {WSA884X_BOOST_MISC, 0x62}, + {WSA884X_PWRSTAGE_CTRL1, 0x00}, + {WSA884X_PWRSTAGE_CTRL2, 0x31}, + {WSA884X_PWRSTAGE_CTRL3, 0x81}, + {WSA884X_PWRSTAGE_CTRL4, 0x5f}, + {WSA884X_MAXD_REG1, 0x00}, + {WSA884X_MAXD_REG2, 0x5b}, + {WSA884X_ILIM_CTRL1, 0xe2}, + {WSA884X_ILIM_CTRL2, 0x90}, + {WSA884X_TEST_CTRL1, 0x00}, + {WSA884X_TEST_CTRL2, 0x00}, + {WSA884X_SPARE1, 0x00}, + {WSA884X_BOOT_CAP_CHECK, 0x01}, + {WSA884X_PON_CTL_0, 0x12}, + {WSA884X_PWRSAV_CTL, 0xaa}, + {WSA884X_PON_LDOL_SPARE_CTL_0, 0x00}, + {WSA884X_PON_LDOL_SPARE_CTL_1, 0x00}, + {WSA884X_PON_LDOL_SPARE_CTL_2, 0x00}, + {WSA884X_PON_LDOL_SPARE_CTL_3, 0x00}, + {WSA884X_PON_CLT_1, 0xe1}, + {WSA884X_PON_CTL_2, 0x00}, + {WSA884X_PON_CTL_3, 0x70}, + {WSA884X_CKWD_CTL_0, 0x14}, + {WSA884X_CKWD_CTL_1, 0x3b}, + {WSA884X_CKWD_CTL_2, 0x00}, + {WSA884X_CKSK_CTL_0, 0x00}, + {WSA884X_PADSW_CTL_0, 0x00}, + {WSA884X_TEST_0, 0x00}, + {WSA884X_TEST_1, 0x00}, + {WSA884X_STATUS_0, 0x00}, + {WSA884X_STATUS_1, 0x00}, + {WSA884X_PON_LDOL_SPARE_TUNE_0, 0x00}, + {WSA884X_PON_LDOL_SPARE_TUNE_1, 0x00}, + {WSA884X_PON_LDOL_SPARE_TUNE_2, 0x00}, + {WSA884X_PON_LDOL_SPARE_TUNE_3, 0x00}, + {WSA884X_PON_LDOL_SPARE_TUNE_4, 0x00}, + {WSA884X_DIG_CTRL0_PAGE, 0x00}, + {WSA884X_CHIP_ID0, 0x00}, + {WSA884X_CHIP_ID1, 0x00}, + {WSA884X_CHIP_ID2, 0x04}, + {WSA884X_CHIP_ID3, 0x02}, + {WSA884X_BUS_ID, 0x00}, + {WSA884X_CDC_RST_CTL, 0x01}, + {WSA884X_SWR_RESET_EN, 0x00}, + {WSA884X_TOP_CLK_CFG, 0x00}, + {WSA884X_SWR_CLK_RATE, 0x00}, + {WSA884X_CDC_PATH_MODE, 0x00}, + {WSA884X_CDC_CLK_CTL, 0x1f}, + {WSA884X_PA_FSM_EN, 0x00}, + {WSA884X_PA_FSM_CTL0, 0x00}, + {WSA884X_PA_FSM_CTL1, 0xfe}, + {WSA884X_PA_FSM_TIMER0, 0x80}, + {WSA884X_PA_FSM_TIMER1, 0x80}, + {WSA884X_PA_FSM_STA0, 0x00}, + {WSA884X_PA_FSM_STA1, 0x00}, + {WSA884X_PA_FSM_ERR_CTL, 0x00}, + {WSA884X_PA_FSM_ERR_COND0, 0x00}, + {WSA884X_PA_FSM_ERR_COND1, 0x00}, + {WSA884X_PA_FSM_MSK0, 0x00}, + {WSA884X_PA_FSM_MSK1, 0x00}, + {WSA884X_PA_FSM_BYP_CTL, 0x00}, + {WSA884X_PA_FSM_BYP0, 0x00}, + {WSA884X_PA_FSM_BYP1, 0x00}, + {WSA884X_TADC_VALUE_CTL, 0x03}, + {WSA884X_TEMP_DETECT_CTL, 0x01}, + {WSA884X_TEMP_DIN_MSB, 0x00}, + {WSA884X_TEMP_DIN_LSB, 0x00}, + {WSA884X_TEMP_DOUT_MSB, 0x00}, + {WSA884X_TEMP_DOUT_LSB, 0x00}, + {WSA884X_TEMP_CONFIG0, 0x00}, + {WSA884X_TEMP_CONFIG1, 0x00}, + {WSA884X_VBAT_THRM_FLT_CTL, 0x7f}, + {WSA884X_VBAT_CAL_CTL, 0x01}, + {WSA884X_VBAT_DIN_MSB, 0x00}, + {WSA884X_VBAT_DIN_LSB, 0x00}, + {WSA884X_VBAT_DOUT_MSB, 0x00}, + {WSA884X_VBAT_DOUT_LSB, 0x00}, + {WSA884X_VBAT_CAL_MSB, 0x00}, + {WSA884X_VBAT_CAL_LSB, 0x00}, + {WSA884X_UVLO_DEGLITCH_CTL, 0x05}, + {WSA884X_BOP_DEGLITCH_CTL, 0x05}, + {WSA884X_VBAT_ZONE_DETC_CTL, 0x31}, + {WSA884X_CPS_CTL, 0x00}, + {WSA884X_CDC_RX_CTL, 0xfe}, + {WSA884X_CDC_SPK_DSM_A1_0, 0x00}, + {WSA884X_CDC_SPK_DSM_A1_1, 0x01}, + {WSA884X_CDC_SPK_DSM_A2_0, 0x96}, + {WSA884X_CDC_SPK_DSM_A2_1, 0x09}, + {WSA884X_CDC_SPK_DSM_A3_0, 0xab}, + {WSA884X_CDC_SPK_DSM_A3_1, 0x05}, + {WSA884X_CDC_SPK_DSM_A4_0, 0x1c}, + {WSA884X_CDC_SPK_DSM_A4_1, 0x02}, + {WSA884X_CDC_SPK_DSM_A5_0, 0x17}, + {WSA884X_CDC_SPK_DSM_A5_1, 0x02}, + {WSA884X_CDC_SPK_DSM_A6_0, 0xaa}, + {WSA884X_CDC_SPK_DSM_A7_0, 0xe3}, + {WSA884X_CDC_SPK_DSM_C_0, 0x69}, + {WSA884X_CDC_SPK_DSM_C_1, 0x54}, + {WSA884X_CDC_SPK_DSM_C_2, 0x02}, + {WSA884X_CDC_SPK_DSM_C_3, 0x15}, + {WSA884X_CDC_SPK_DSM_R1, 0xa4}, + {WSA884X_CDC_SPK_DSM_R2, 0xb5}, + {WSA884X_CDC_SPK_DSM_R3, 0x86}, + {WSA884X_CDC_SPK_DSM_R4, 0x85}, + {WSA884X_CDC_SPK_DSM_R5, 0xaa}, + {WSA884X_CDC_SPK_DSM_R6, 0xe2}, + {WSA884X_CDC_SPK_DSM_R7, 0x62}, + {WSA884X_CDC_SPK_GAIN_PDM_0, 0x00}, + {WSA884X_CDC_SPK_GAIN_PDM_1, 0xfc}, + {WSA884X_CDC_SPK_GAIN_PDM_2, 0x05}, + {WSA884X_PDM_WD_CTL, 0x00}, + {WSA884X_DEM_BYPASS_DATA0, 0x00}, + {WSA884X_DEM_BYPASS_DATA1, 0x00}, + {WSA884X_DEM_BYPASS_DATA2, 0x00}, + {WSA884X_DEM_BYPASS_DATA3, 0x00}, + {WSA884X_DRE_CTL_0, 0x70}, + {WSA884X_DRE_CTL_1, 0x04}, + {WSA884X_DRE_IDLE_DET_CTL, 0x2f}, + {WSA884X_GAIN_RAMPING_CTL, 0x50}, + {WSA884X_GAIN_RAMPING_MIN, 0x12}, + {WSA884X_TAGC_CTL, 0x15}, + {WSA884X_TAGC_TIME, 0xbc}, + {WSA884X_TAGC_FORCE_VAL, 0x00}, + {WSA884X_VAGC_CTL, 0x01}, + {WSA884X_VAGC_TIME, 0x0f}, + {WSA884X_VAGC_ATTN_LVL_1, 0x03}, + {WSA884X_VAGC_ATTN_LVL_2, 0x06}, + {WSA884X_VAGC_ATTN_LVL_3, 0x09}, + {WSA884X_CLSH_CTL_0, 0x37}, + {WSA884X_CLSH_CTL_1, 0x81}, + {WSA884X_CLSH_V_HD_PA, 0x0c}, + {WSA884X_CLSH_V_PA_MIN, 0x00}, + {WSA884X_CLSH_OVRD_VAL, 0x00}, + {WSA884X_CLSH_HARD_MAX, 0xff}, + {WSA884X_CLSH_SOFT_MAX, 0xf5}, + {WSA884X_CLSH_SIG_DP, 0x00}, + {WSA884X_PBR_DELAY_CTL, 0x07}, + {WSA884X_CLSH_SRL_MAX_PBR, 0x02}, + {WSA884X_CLSH_VTH1, 0x00}, + {WSA884X_CLSH_VTH2, 0x00}, + {WSA884X_CLSH_VTH3, 0x00}, + {WSA884X_CLSH_VTH4, 0x00}, + {WSA884X_CLSH_VTH5, 0x00}, + {WSA884X_CLSH_VTH6, 0x00}, + {WSA884X_CLSH_VTH7, 0x00}, + {WSA884X_CLSH_VTH8, 0x00}, + {WSA884X_CLSH_VTH9, 0x00}, + {WSA884X_CLSH_VTH10, 0x00}, + {WSA884X_CLSH_VTH11, 0x00}, + {WSA884X_CLSH_VTH12, 0x00}, + {WSA884X_CLSH_VTH13, 0x00}, + {WSA884X_CLSH_VTH14, 0x00}, + {WSA884X_CLSH_VTH15, 0x00}, + {WSA884X_DIG_CTRL1_PAGE, 0x00}, + {WSA884X_BST_CFG, 0x00}, + {WSA884X_ANA_WO_CTL_0, 0xe9}, + {WSA884X_ANA_WO_CTL_1, 0x00}, + {WSA884X_PIN_CTL, 0x04}, + {WSA884X_PIN_CTL_OE, 0x00}, + {WSA884X_PIN_WDATA_IOPAD, 0x00}, + {WSA884X_PIN_STATUS, 0x00}, + {WSA884X_I2C_SLAVE_CTL, 0x00}, + {WSA884X_SPMI_PAD_CTL0, 0x2f}, + {WSA884X_SPMI_PAD_CTL1, 0x2f}, + {WSA884X_SPMI_PAD_CTL2, 0x2f}, + {WSA884X_MEM_CTL, 0x00}, + {WSA884X_SWR_HM_TEST0, 0x08}, + {WSA884X_SWR_HM_TEST1, 0x00}, + {WSA884X_OTP_CTRL0, 0x00}, + {WSA884X_OTP_CTRL1, 0x00}, + {WSA884X_OTP_CTRL2, 0x00}, + {WSA884X_OTP_STAT, 0x00}, + {WSA884X_OTP_PRG_TCSP0, 0x77}, + {WSA884X_OTP_PRG_TCSP1, 0x00}, + {WSA884X_OTP_PRG_TPPS, 0x47}, + {WSA884X_OTP_PRG_TVPS, 0x3b}, + {WSA884X_OTP_PRG_TVPH, 0x47}, + {WSA884X_OTP_PRG_TPPR0, 0x47}, + {WSA884X_OTP_PRG_TPPR1, 0x00}, + {WSA884X_OTP_PRG_TPPH, 0x47}, + {WSA884X_OTP_PRG_END, 0x47}, + {WSA884X_WAVG_PLAY, 0x00}, + {WSA884X_WAVG_CTL, 0x06}, + {WSA884X_WAVG_LRA_PER_0, 0xd1}, + {WSA884X_WAVG_LRA_PER_1, 0x00}, + {WSA884X_WAVG_DELTA_THETA_0, 0xe6}, + {WSA884X_WAVG_DELTA_THETA_1, 0x04}, + {WSA884X_WAVG_DIRECT_AMP_0, 0x50}, + {WSA884X_WAVG_DIRECT_AMP_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP0_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP0_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP1_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP1_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP2_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP2_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP3_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP3_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP4_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP4_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP5_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP5_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP6_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP6_1, 0x00}, + {WSA884X_WAVG_PTRN_AMP7_0, 0x50}, + {WSA884X_WAVG_PTRN_AMP7_1, 0x00}, + {WSA884X_WAVG_PER_0_1, 0x88}, + {WSA884X_WAVG_PER_2_3, 0x88}, + {WSA884X_WAVG_PER_4_5, 0x88}, + {WSA884X_WAVG_PER_6_7, 0x88}, + {WSA884X_WAVG_STA, 0x00}, + {WSA884X_INTR_MODE, 0x00}, + {WSA884X_INTR_MASK0, 0x90}, + {WSA884X_INTR_MASK1, 0x00}, + {WSA884X_INTR_STATUS0, 0x00}, + {WSA884X_INTR_STATUS1, 0x00}, + {WSA884X_INTR_CLEAR0, 0x00}, + {WSA884X_INTR_CLEAR1, 0x00}, + {WSA884X_INTR_LEVEL0, 0x04}, + {WSA884X_INTR_LEVEL1, 0x00}, + {WSA884X_INTR_SET0, 0x00}, + {WSA884X_INTR_SET1, 0x00}, + {WSA884X_INTR_TEST0, 0x00}, + {WSA884X_INTR_TEST1, 0x00}, + {WSA884X_PDM_TEST_MODE, 0x00}, + {WSA884X_ATE_TEST_MODE, 0x00}, + {WSA884X_PA_FSM_DBG, 0x00}, + {WSA884X_DIG_DEBUG_MODE, 0x00}, + {WSA884X_DIG_DEBUG_SEL, 0x00}, + {WSA884X_DIG_DEBUG_EN, 0x00}, + {WSA884X_TADC_DETECT_DBG_CTL, 0x00}, + {WSA884X_TADC_DEBUG_MSB, 0x00}, + {WSA884X_TADC_DEBUG_LSB, 0x00}, + {WSA884X_SAMPLE_EDGE_SEL, 0x7f}, + {WSA884X_SWR_EDGE_SEL, 0x00}, + {WSA884X_TEST_MODE_CTL, 0x05}, + {WSA884X_IOPAD_CTL, 0x00}, + {WSA884X_ANA_CSR_DBG_ADD, 0x00}, + {WSA884X_ANA_CSR_DBG_CTL, 0x12}, + {WSA884X_CLK_DBG_CTL, 0x00}, + {WSA884X_SPARE_R, 0x00}, + {WSA884X_SPARE_0, 0x00}, + {WSA884X_SPARE_1, 0x00}, + {WSA884X_SPARE_2, 0x00}, + {WSA884X_SCODE, 0x00}, + {WSA884X_DIG_TRIM_PAGE, 0x00}, + {WSA884X_OTP_REG_0, 0x05}, + {WSA884X_OTP_REG_1, 0x49}, + {WSA884X_OTP_REG_2, 0x80}, + {WSA884X_OTP_REG_3, 0xc9}, + {WSA884X_OTP_REG_4, 0x40}, + {WSA884X_OTP_REG_5, 0xff}, + {WSA884X_OTP_REG_6, 0xff}, + {WSA884X_OTP_REG_7, 0xff}, + {WSA884X_OTP_REG_8, 0xff}, + {WSA884X_OTP_REG_9, 0xff}, + {WSA884X_OTP_REG_10, 0xff}, + {WSA884X_OTP_REG_11, 0xff}, + {WSA884X_OTP_REG_12, 0xff}, + {WSA884X_OTP_REG_13, 0xff}, + {WSA884X_OTP_REG_14, 0xff}, + {WSA884X_OTP_REG_15, 0xff}, + {WSA884X_OTP_REG_16, 0xff}, + {WSA884X_OTP_REG_17, 0xff}, + {WSA884X_OTP_REG_18, 0xff}, + {WSA884X_OTP_REG_19, 0xff}, + {WSA884X_OTP_REG_20, 0xff}, + {WSA884X_OTP_REG_21, 0xff}, + {WSA884X_OTP_REG_22, 0xff}, + {WSA884X_OTP_REG_23, 0xff}, + {WSA884X_OTP_REG_24, 0x00}, + {WSA884X_OTP_REG_25, 0x22}, + {WSA884X_OTP_REG_26, 0x03}, + {WSA884X_OTP_REG_27, 0x00}, + {WSA884X_OTP_REG_28, 0x00}, + {WSA884X_OTP_REG_29, 0x00}, + {WSA884X_OTP_REG_30, 0x00}, + {WSA884X_OTP_REG_31, 0x8f}, + {WSA884X_OTP_REG_32, 0x00}, + {WSA884X_OTP_REG_33, 0xff}, + {WSA884X_OTP_REG_34, 0x0f}, + {WSA884X_OTP_REG_35, 0x12}, + {WSA884X_OTP_REG_36, 0x08}, + {WSA884X_OTP_REG_37, 0x1f}, + {WSA884X_OTP_REG_38, 0x0b}, + {WSA884X_OTP_REG_39, 0x00}, + {WSA884X_OTP_REG_40, 0x00}, + {WSA884X_OTP_REG_41, 0x00}, + {WSA884X_OTP_REG_63, 0x40}, + {WSA884X_EMEM_0, 0x00}, + {WSA884X_EMEM_1, 0x00}, + {WSA884X_EMEM_2, 0x00}, + {WSA884X_EMEM_3, 0x00}, + {WSA884X_EMEM_4, 0x00}, + {WSA884X_EMEM_5, 0x00}, + {WSA884X_EMEM_6, 0x00}, + {WSA884X_EMEM_7, 0x00}, + {WSA884X_EMEM_8, 0x00}, + {WSA884X_EMEM_9, 0x00}, + {WSA884X_EMEM_10, 0x00}, + {WSA884X_EMEM_11, 0x00}, + {WSA884X_EMEM_12, 0x00}, + {WSA884X_EMEM_13, 0x00}, + {WSA884X_EMEM_14, 0x00}, + {WSA884X_EMEM_15, 0x00}, + {WSA884X_EMEM_16, 0x00}, + {WSA884X_EMEM_17, 0x00}, + {WSA884X_EMEM_18, 0x00}, + {WSA884X_EMEM_19, 0x00}, + {WSA884X_EMEM_20, 0x00}, + {WSA884X_EMEM_21, 0x00}, + {WSA884X_EMEM_22, 0x00}, + {WSA884X_EMEM_23, 0x00}, + {WSA884X_EMEM_24, 0x00}, + {WSA884X_EMEM_25, 0x00}, + {WSA884X_EMEM_26, 0x00}, + {WSA884X_EMEM_27, 0x00}, + {WSA884X_EMEM_28, 0x00}, + {WSA884X_EMEM_29, 0x00}, + {WSA884X_EMEM_30, 0x00}, + {WSA884X_EMEM_31, 0x00}, + {WSA884X_EMEM_32, 0x00}, + {WSA884X_EMEM_33, 0x00}, + {WSA884X_EMEM_34, 0x00}, + {WSA884X_EMEM_35, 0x00}, + {WSA884X_EMEM_36, 0x00}, + {WSA884X_EMEM_37, 0x00}, + {WSA884X_EMEM_38, 0x00}, + {WSA884X_EMEM_39, 0x00}, + {WSA884X_EMEM_40, 0x00}, + {WSA884X_EMEM_41, 0x00}, + {WSA884X_EMEM_42, 0x00}, + {WSA884X_EMEM_43, 0x00}, + {WSA884X_EMEM_44, 0x00}, + {WSA884X_EMEM_45, 0x00}, + {WSA884X_EMEM_46, 0x00}, + {WSA884X_EMEM_47, 0x00}, + {WSA884X_EMEM_48, 0x00}, + {WSA884X_EMEM_49, 0x00}, + {WSA884X_EMEM_50, 0x00}, + {WSA884X_EMEM_51, 0x00}, + {WSA884X_EMEM_52, 0x00}, + {WSA884X_EMEM_53, 0x00}, + {WSA884X_EMEM_54, 0x00}, + {WSA884X_EMEM_55, 0x00}, + {WSA884X_EMEM_56, 0x00}, + {WSA884X_EMEM_57, 0x00}, + {WSA884X_EMEM_58, 0x00}, + {WSA884X_EMEM_59, 0x00}, + {WSA884X_EMEM_60, 0x00}, + {WSA884X_EMEM_61, 0x00}, + {WSA884X_EMEM_62, 0x00}, + {WSA884X_EMEM_63, 0x00}, +}; + +static bool wsa884x_readable_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA884X_BASE) + return 0; + + return wsa884x_reg_access[WSA884X_REG(reg)] & RD_REG; +} + +static bool wsa884x_writeable_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA884X_BASE) + return 0; + + return wsa884x_reg_access[WSA884X_REG(reg)] & WR_REG; +} + +static bool wsa884x_volatile_register(struct device *dev, unsigned int reg) +{ + if (reg <= WSA884X_BASE) + return 0; + + return ((wsa884x_reg_access[WSA884X_REG(reg)] & RD_REG) && + !(wsa884x_reg_access[WSA884X_REG(reg)] & WR_REG)); +} + + +struct regmap_config wsa884x_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wsa884x_defaults, + .num_reg_defaults = ARRAY_SIZE(wsa884x_defaults), + .max_register = WSA884X_MAX_REGISTER, + .volatile_reg = wsa884x_volatile_register, + .readable_reg = wsa884x_readable_register, + .writeable_reg = wsa884x_writeable_register, + .reg_format_endian = REGMAP_ENDIAN_NATIVE, + .val_format_endian = REGMAP_ENDIAN_NATIVE, + .can_multi_write = true, +}; diff --git a/asoc/codecs/wsa884x/wsa884x-tables.c b/asoc/codecs/wsa884x/wsa884x-tables.c new file mode 100644 index 0000000000..be8568115f --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x-tables.c @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "wsa884x-registers.h" + +const u8 wsa884x_reg_access[WSA884X_NUM_REGISTERS] = { + [WSA884X_REG(WSA884X_BG_CTRL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_CTRL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOP1_PROG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOP2_PROG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_UVLO_PROG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_UVLO_PROG1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTRL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTRL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTRL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTRL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_REF_CTRL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BG_TEST_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BG_BIAS)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_PROG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_IREF_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_ISENS_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_CLK_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_TEST_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_BIAS)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VBAT_SNS)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DOUT_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_DOUT_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_BOP_ATEST_SEL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MISC0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MISC1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MISC2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MISC3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TSBG_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VSENSE1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ISENSE2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OVERRIDE1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OVERRIDE2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ISENSE1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ISENSE_CAL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MISC)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ADC_7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_STATUS)] = RD_REG, + [WSA884X_REG(WSA884X_IVSENSE_SPARE_TUNE_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLIP_DET_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLIP_DET_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWM_CLK_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_LDO_SEL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OCP_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PDRV_HS_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PDRV_LS_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_CTL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_CTL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_CTL_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_EN_DEBUG_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_OPAMP_BIAS1_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_OPAMP_BIAS2_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_TUNE1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VOLTAGE_CTRL_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ATEST1_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ATEST2_REG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_BIAS_REG1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_BIAS_REG2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_BIAS_REG3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_BIAS_REG4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTG_DBG2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_BLK_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_MASK_DCC_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_MISC_CTL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_REG_GAIN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_OS_CAL_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_OS_CAL_CTL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTG_DBG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BBM_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_MISC1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DAC_VCM_CTRL_REG7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_BIAS_REG5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRV_LF_MISC_CTL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_TUNE_2)] = RD_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_TUNE_3)] = RD_REG, + [WSA884X_REG(WSA884X_SPK_TOP_SPARE_TUNE_4)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_5)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_6)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_7)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_8)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_9)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_TUNE_10)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS0)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS1)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS2)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS3)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS4)] = RD_REG, + [WSA884X_REG(WSA884X_PA_STATUS5)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_RO_1)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_RO_2)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_RO_3)] = RD_REG, + [WSA884X_REG(WSA884X_STB_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CURRENT_LIMIT)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BYP_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOOST_SPARE_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_RO_0)] = RD_REG, + [WSA884X_REG(WSA884X_BOOST_SPARE_RO_1)] = RD_REG, + [WSA884X_REG(WSA884X_IBIAS1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_IBIAS2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_IBIAS3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EN_CTRL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_STB_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_STB_CTRL3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_STB_CTRL4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BYP_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BYP_CTRL3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ZX_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ZX_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BLEEDER_CTRL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOOST_MISC)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTAGE_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTAGE_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTAGE_CTRL3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSTAGE_CTRL4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MAXD_REG1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MAXD_REG2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ILIM_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ILIM_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEST_CTRL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEST_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOOT_CAP_CHECK)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PWRSAV_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_CTL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_CTL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_CLT_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_CTL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_CTL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CKWD_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CKWD_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CKWD_CTL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CKSK_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PADSW_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEST_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEST_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_STATUS_0)] = RD_REG, + [WSA884X_REG(WSA884X_STATUS_1)] = RD_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_TUNE_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_TUNE_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_TUNE_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_TUNE_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PON_LDOL_SPARE_TUNE_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_CTRL0_PAGE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CHIP_ID0)] = RD_REG, + [WSA884X_REG(WSA884X_CHIP_ID1)] = RD_REG, + [WSA884X_REG(WSA884X_CHIP_ID2)] = RD_REG, + [WSA884X_REG(WSA884X_CHIP_ID3)] = RD_REG, + [WSA884X_REG(WSA884X_BUS_ID)] = RD_REG, + [WSA884X_REG(WSA884X_CDC_RST_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SWR_RESET_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TOP_CLK_CFG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SWR_CLK_RATE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_PATH_MODE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_CLK_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_CTL0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_CTL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_TIMER0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_TIMER1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_STA0)] = RD_REG, + [WSA884X_REG(WSA884X_PA_FSM_STA1)] = RD_REG, + [WSA884X_REG(WSA884X_PA_FSM_ERR_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_ERR_COND0)] = RD_REG, + [WSA884X_REG(WSA884X_PA_FSM_ERR_COND1)] = RD_REG, + [WSA884X_REG(WSA884X_PA_FSM_MSK0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_MSK1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_BYP_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_BYP0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PA_FSM_BYP1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TADC_VALUE_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEMP_DETECT_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEMP_DIN_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_TEMP_DIN_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_TEMP_DOUT_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_TEMP_DOUT_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_TEMP_CONFIG0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEMP_CONFIG1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VBAT_THRM_FLT_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VBAT_CAL_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VBAT_DIN_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_VBAT_DIN_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_VBAT_DOUT_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_VBAT_DOUT_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_VBAT_CAL_MSB)] = RD_REG, + [WSA884X_REG(WSA884X_VBAT_CAL_LSB)] = RD_REG, + [WSA884X_REG(WSA884X_UVLO_DEGLITCH_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BOP_DEGLITCH_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VBAT_ZONE_DETC_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CPS_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_RX_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A1_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A1_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A2_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A2_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A3_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A3_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A4_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A4_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A5_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A5_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A6_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_A7_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_C_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_C_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_C_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_C_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_DSM_R7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_GAIN_PDM_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_GAIN_PDM_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CDC_SPK_GAIN_PDM_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PDM_WD_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DEM_BYPASS_DATA0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DEM_BYPASS_DATA1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DEM_BYPASS_DATA2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DEM_BYPASS_DATA3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRE_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRE_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DRE_IDLE_DET_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_GAIN_RAMPING_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_GAIN_RAMPING_MIN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TAGC_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TAGC_TIME)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TAGC_FORCE_VAL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VAGC_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VAGC_TIME)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VAGC_ATTN_LVL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VAGC_ATTN_LVL_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_VAGC_ATTN_LVL_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_V_HD_PA)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_V_PA_MIN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_OVRD_VAL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_HARD_MAX)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_SOFT_MAX)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_SIG_DP)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PBR_DELAY_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_SRL_MAX_PBR)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH8)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH9)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH10)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH11)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH12)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH13)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH14)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLSH_VTH15)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_CTRL1_PAGE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_BST_CFG)] = RD_REG, + [WSA884X_REG(WSA884X_ANA_WO_CTL_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ANA_WO_CTL_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PIN_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PIN_CTL_OE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PIN_WDATA_IOPAD)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PIN_STATUS)] = RD_REG, + [WSA884X_REG(WSA884X_I2C_SLAVE_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPMI_PAD_CTL0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPMI_PAD_CTL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPMI_PAD_CTL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_MEM_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SWR_HM_TEST0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SWR_HM_TEST1)] = RD_REG, + [WSA884X_REG(WSA884X_OTP_CTRL0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_CTRL1)] = RD_REG, + [WSA884X_REG(WSA884X_OTP_CTRL2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_STAT)] = RD_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TCSP0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TCSP1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TPPS)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TVPS)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TVPH)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TPPR0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TPPR1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_TPPH)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_PRG_END)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PLAY)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_LRA_PER_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_LRA_PER_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_DELTA_THETA_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_DELTA_THETA_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_DIRECT_AMP_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_DIRECT_AMP_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP0_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP0_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP1_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP1_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP2_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP2_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP3_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP3_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP4_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP4_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP5_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP5_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP6_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP6_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP7_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PTRN_AMP7_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PER_0_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PER_2_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PER_4_5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_PER_6_7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_WAVG_STA)] = RD_REG, + [WSA884X_REG(WSA884X_INTR_MODE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_MASK0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_MASK1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_STATUS0)] = RD_REG, + [WSA884X_REG(WSA884X_INTR_STATUS1)] = RD_REG, + [WSA884X_REG(WSA884X_INTR_CLEAR0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_CLEAR1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_LEVEL0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_LEVEL1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_SET0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_SET1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_TEST0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_INTR_TEST1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_PDM_TEST_MODE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ATE_TEST_MODE)] = RD_REG, + [WSA884X_REG(WSA884X_PA_FSM_DBG)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_DEBUG_MODE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_DEBUG_SEL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_DEBUG_EN)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TADC_DETECT_DBG_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TADC_DEBUG_MSB)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TADC_DEBUG_LSB)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SAMPLE_EDGE_SEL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SWR_EDGE_SEL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_TEST_MODE_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_IOPAD_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ANA_CSR_DBG_ADD)] = RD_WR_REG, + [WSA884X_REG(WSA884X_ANA_CSR_DBG_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_CLK_DBG_CTL)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_R)] = RD_REG, + [WSA884X_REG(WSA884X_SPARE_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SPARE_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_SCODE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_DIG_TRIM_PAGE)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_8)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_9)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_10)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_11)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_12)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_13)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_14)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_15)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_16)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_17)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_18)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_19)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_20)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_21)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_22)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_23)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_24)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_25)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_26)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_27)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_28)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_29)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_30)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_31)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_32)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_33)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_34)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_35)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_36)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_37)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_38)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_39)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_40)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_41)] = RD_WR_REG, + [WSA884X_REG(WSA884X_OTP_REG_63)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_0)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_1)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_2)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_3)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_4)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_5)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_6)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_7)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_8)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_9)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_10)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_11)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_12)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_13)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_14)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_15)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_16)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_17)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_18)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_19)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_20)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_21)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_22)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_23)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_24)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_25)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_26)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_27)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_28)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_29)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_30)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_31)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_32)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_33)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_34)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_35)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_36)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_37)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_38)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_39)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_40)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_41)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_42)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_43)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_44)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_45)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_46)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_47)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_48)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_49)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_50)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_51)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_52)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_53)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_54)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_55)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_56)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_57)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_58)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_59)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_60)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_61)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_62)] = RD_WR_REG, + [WSA884X_REG(WSA884X_EMEM_63)] = RD_WR_REG, +}; diff --git a/asoc/codecs/wsa884x/wsa884x.c b/asoc/codecs/wsa884x/wsa884x.c new file mode 100644 index 0000000000..a5bcd362cd --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x.c @@ -0,0 +1,2032 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2021, 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 +#include +#include "wsa884x.h" +#include "internal.h" +#include "asoc/bolero-slave-internal.h" +#include + +#define T1_TEMP -10 +#define T2_TEMP 150 +#define LOW_TEMP_THRESHOLD 5 +#define HIGH_TEMP_THRESHOLD 45 +#define TEMP_INVALID 0xFFFF +#define WSA884X_TEMP_RETRY 3 + +#define MAX_NAME_LEN 40 +#define WSA884X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_384000) +/* Fractional Rates */ +#define WSA884X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define WSA884X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define REG_FIELD_VALUE(register_name, field_name, value) \ +(WSA884X_##register_name, FIELD_MASK(register_name, field_name), \ +value << FIELD_SHIFT(register_name, field_name)) + +enum { + WSA_4OHMS = 4, + WSA_8OHMS = 8, + WSA_16OHMS = 16, + WSA_32OHMS = 32, +}; + +struct wsa_temp_register { + u8 d1_msb; + u8 d1_lsb; + u8 d2_msb; + u8 d2_lsb; + u8 dmeas_msb; + u8 dmeas_lsb; +}; + +enum { + COMP_OFFSET0, + COMP_OFFSET1, + COMP_OFFSET2, + COMP_OFFSET3, + COMP_OFFSET4, +}; + +struct wsa_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +static const struct wsa_reg_mask_val reg_init[] = { + {REG_FIELD_VALUE(PA_FSM_BYP_CTL, PA_FSM_BYP, 0x00)}, + {REG_FIELD_VALUE(ISENSE2, ISENSE_GAIN_CTL, 0x02)}, + {REG_FIELD_VALUE(ADC_6, INTRLV_RST_OVRD, 0x01)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A2_0, COEF_A2, 0x0A)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A2_0, COEF_A2, 0x0A)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A2_1, COEF_A2, 0x08)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A3_0, COEF_A3, 0xF3)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A3_1, COEF_A3, 0x07)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A4_0, COEF_A4, 0x79)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A4_1, COEF_A4, 0x02)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A5_0, COEF_A5, 0x0B)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A5_1, COEF_A5, 0x02)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A6_0, COEF_A6, 0x8A)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_A7_0, COEF_A7, 0x9B)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_0, COEF_C3, 0x06)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_0, COEF_C2, 0x08)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_1, COEF_C5, 0x05)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_1, COEF_C4, 0x04)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_2, COEF_C7, 0x0F)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_C_3, COEF_C7, 0x20)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R1, SAT_LIMIT_R1, 0x83)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R2, SAT_LIMIT_R2, 0x7F)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R3, SAT_LIMIT_R3, 0x9D)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R4, SAT_LIMIT_R4, 0x82)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R5, SAT_LIMIT_R5, 0x8B)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R6, SAT_LIMIT_R6, 0x9B)}, + {REG_FIELD_VALUE(CDC_SPK_DSM_R7, SAT_LIMIT_R7, 0x3F)}, + {REG_FIELD_VALUE(VBAT_SNS, BOP_FREQ, 0x01)}, + {REG_FIELD_VALUE(DRE_CTL_0, PROG_DELAY, 0x09)}, + {REG_FIELD_VALUE(DRE_IDLE_DET_CTL, DRE_IDLE_FORCE_EN, 0x00)}, + {REG_FIELD_VALUE(CURRENT_LIMIT, CURRENT_LIMIT, 0x08)}, + {REG_FIELD_VALUE(DRE_CTL_0, OFFSET, 0x02)}, + {REG_FIELD_VALUE(VAGC_TIME, REL_TIME, 0x03)}, + {REG_FIELD_VALUE(VAGC_TIME, HLD_TIME, 0x03)}, + {REG_FIELD_VALUE(VAGC_ATTN_LVL_2, VBAT_ATTN_LVL, 0x01)}, + {REG_FIELD_VALUE(VAGC_ATTN_LVL_3, VBAT_ATTN_LVL, 0x02)}, + {REG_FIELD_VALUE(VAGC_CTL, VBAT_AGC_EN, 0x01)}, + {REG_FIELD_VALUE(TAGC_CTL, THERMAL_THRESH, 0x05)}, + {REG_FIELD_VALUE(TAGC_TIME, REL_TIME, 0x03)}, + // {WSA884X_TAGC_E2E_GAIN, 0x1F, 0x02},??? + {REG_FIELD_VALUE(TEMP_CONFIG0, CTL_THRD_SAF2WAR, 0x02)}, + {REG_FIELD_VALUE(TEMP_CONFIG1, CTL_THRD_WAR2SAF, 0x02)}, + {REG_FIELD_VALUE(OTP_REG_1, LOW_TEMP_MSB, 0x49)}, + {REG_FIELD_VALUE(OTP_REG_2, LOW_TEMP_LSB, 0x02)}, + {REG_FIELD_VALUE(OTP_REG_3, HIGH_TEMP_MSB, 0xC9)}, + {REG_FIELD_VALUE(OTP_REG_4, HIGH_TEMP_LSB, 0x01)}, + {REG_FIELD_VALUE(TAGC_CTL, THERMAL_AGC_EN, 0x01)}, + {REG_FIELD_VALUE(ADC_2, ISNS_LOAD_STORED, 0x00)}, + {REG_FIELD_VALUE(ADC_7, EN_AZ_REG, 0x01)}, + {REG_FIELD_VALUE(ADC_7, EN_SAR_REG, 0x01)}, + {REG_FIELD_VALUE(CKWD_CTL_0, CKWD_FDIV_SEL, 0x00)}, + {REG_FIELD_VALUE(DRE_CTL_1, CSR_GAIN, 0x10)}, + {REG_FIELD_VALUE(CKWD_CTL_1, CKWD_VCOMP_VREF_SEL, 0x1B)}, + {REG_FIELD_VALUE(BOOST_MISC, SPKR_RDY_CTL, 0x03)}, +}; + +static int wsa884x_handle_post_irq(void *data); +static int wsa884x_get_temperature(struct snd_soc_component *component, + int *temp); +enum { + WSA8840 = 0, + WSA8845, + WSA8842, + WSA8845_V2 = 5, +}; + +enum { + SPKR_STATUS = 0, + WSA_SUPPLIES_LPM_MODE, + SPKR_ADIE_LB, +}; + +enum { + WSA884X_IRQ_INT_SAF2WAR = 0, + WSA884X_IRQ_INT_WAR2SAF, + WSA884X_IRQ_INT_DISABLE, + WSA884X_IRQ_INT_OCP, + WSA884X_IRQ_INT_CLIP, + WSA884X_IRQ_INT_PDM_WD, + WSA884X_IRQ_INT_CLK_WD, + WSA884X_IRQ_INT_INTR_PIN, + WSA884X_IRQ_INT_UVLO, + WSA884X_IRQ_INT_PA_ON_ERR, + WSA884X_NUM_IRQS, +}; + +static const struct regmap_irq wsa884x_irqs[WSA884X_NUM_IRQS] = { + REGMAP_IRQ_REG(WSA884X_IRQ_INT_SAF2WAR, 0, 0x01), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_WAR2SAF, 0, 0x02), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_DISABLE, 0, 0x04), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_OCP, 0, 0x08), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_CLIP, 0, 0x10), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_PDM_WD, 0, 0x20), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_CLK_WD, 0, 0x40), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_INTR_PIN, 0, 0x80), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_UVLO, 1, 0x01), + REGMAP_IRQ_REG(WSA884X_IRQ_INT_PA_ON_ERR, 1, 0x02), +}; + +static struct regmap_irq_chip wsa884x_regmap_irq_chip = { + .name = "wsa884x", + .irqs = wsa884x_irqs, + .num_irqs = ARRAY_SIZE(wsa884x_irqs), + .num_regs = 2, + .status_base = WSA884X_INTR_STATUS0, + .mask_base = WSA884X_INTR_MASK0, + .type_base = WSA884X_INTR_LEVEL0, + .ack_base = WSA884X_INTR_CLEAR0, + .use_ack = 1, + .runtime_pm = false, + .handle_post_irq = wsa884x_handle_post_irq, + .irq_drv_data = NULL, +}; + +static int wsa884x_handle_post_irq(void *data) +{ + struct wsa884x_priv *wsa884x = data; + u32 sts1 = 0, sts2 = 0; + + regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS0, &sts1); + regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS1, &sts2); + + wsa884x->swr_slave->slave_irq_pending = + ((sts1 || sts2) ? true : false); + + return IRQ_HANDLED; +} + +#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, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i, + (reg_val & 0xFF)); + if (len < 0) { + pr_err("%s: fail to fill the buffer\n", __func__); + total = -EFAULT; + goto copy_err; + } + if ((total + len) >= count - 1) + 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 wsa884x_priv *wsa884x = NULL; + + if (!count || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + wsa884x = swr_get_dev_data(pdev); + if (!wsa884x) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + snprintf(lbuf, sizeof(lbuf), "0x%x\n", + (wsa884x->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 wsa884x_priv *wsa884x = NULL; + + if (!cnt || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + wsa884x = swr_get_dev_data(pdev); + if (!wsa884x) + 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], &wsa884x->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 void wsa884x_regcache_sync(struct wsa884x_priv *wsa884x) +{ + mutex_lock(&wsa884x->res_lock); + regcache_mark_dirty(wsa884x->regmap); + regcache_sync(wsa884x->regmap); + mutex_unlock(&wsa884x->res_lock); +} + +static irqreturn_t wsa884x_saf2war_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_war2saf_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_otp_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_ocp_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_clip_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_pdm_wd_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_clk_wd_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_ext_int_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_uvlo_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static irqreturn_t wsa884x_pa_on_err_handle_irq(int irq, void *data) +{ + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", + __func__, irq); + return IRQ_HANDLED; +} + +static const char * const wsa_dev_mode_text[] = { + "speaker", "receiver", "ultrasound" +}; + +static const struct soc_enum wsa_dev_mode_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_dev_mode_text), wsa_dev_mode_text); + +static int wsa_dev_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->dev_mode; + + dev_dbg(component->dev, "%s: mode = 0x%x\n", __func__, + wsa884x->dev_mode); + + return 0; +} + +static int wsa_dev_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + wsa884x->dev_mode = ucontrol->value.integer.value[0]; + + return 0; +} + +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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->pa_gain; + + dev_dbg(component->dev, "%s: PA gain = 0x%x\n", __func__, + wsa884x->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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + wsa884x->pa_gain = ucontrol->value.integer.value[0]; + + return 0; +} + +static int wsa884x_get_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->pa_mute; + + return 0; +} + +static int wsa884x_set_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = 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__, wsa884x->pa_mute, value); + + wsa884x->pa_mute = value; + + return 0; +} + +static int wsa_get_temp(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + int temp = 0; + + if (test_bit(SPKR_STATUS, &wsa884x->status_mask)) + temp = wsa884x->curr_temp; + else + wsa884x_get_temperature(component, &temp); + + ucontrol->value.integer.value[0] = temp; + + return 0; +} + +static ssize_t wsa884x_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 wsa884x_priv *wsa884x; + char buffer[WSA884X_VERSION_ENTRY_SIZE]; + int len = 0; + + wsa884x = (struct wsa884x_priv *) entry->private_data; + if (!wsa884x) { + pr_err("%s: wsa884x priv is null\n", __func__); + return -EINVAL; + } + + switch (wsa884x->version) { + case WSA884X_VERSION_1_0: + len = snprintf(buffer, sizeof(buffer), "WSA884X_1_0\n"); + break; + case WSA884X_VERSION_1_1: + len = snprintf(buffer, sizeof(buffer), "WSA884X_1_1\n"); + break; + default: + len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n"); + break; + } + + return simple_read_from_buffer(buf, count, &pos, buffer, len); +} + +static struct snd_info_entry_ops wsa884x_codec_info_ops = { + .read = wsa884x_codec_version_read, +}; + +static ssize_t wsa884x_variant_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + char __user *buf, size_t count, + loff_t pos) +{ + struct wsa884x_priv *wsa884x; + char buffer[WSA884X_VARIANT_ENTRY_SIZE]; + int len = 0; + + wsa884x = (struct wsa884x_priv *) entry->private_data; + if (!wsa884x) { + pr_err("%s: wsa884x priv is null\n", __func__); + return -EINVAL; + } + + switch (wsa884x->variant) { + case WSA8840: + len = snprintf(buffer, sizeof(buffer), "WSA8840\n"); + break; + case WSA8845: + case WSA8845_V2: + len = snprintf(buffer, sizeof(buffer), "WSA8845\n"); + break; + case WSA8842: + len = snprintf(buffer, sizeof(buffer), "WSA8842\n"); + break; + default: + len = snprintf(buffer, sizeof(buffer), "UNDEFINED\n"); + break; + } + + return simple_read_from_buffer(buf, count, &pos, buffer, len); +} + +static struct snd_info_entry_ops wsa884x_variant_ops = { + .read = wsa884x_variant_read, +}; + +/* + * wsa884x_codec_info_create_codec_entry - creates wsa884x module + * @codec_root: The parent directory + * @component: Codec instance + * + * Creates wsa884x module and version entry under the given + * parent directory. + * + * Return: 0 on success or negative error code on failure. + */ +int wsa884x_codec_info_create_codec_entry(struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + struct snd_info_entry *version_entry; + struct snd_info_entry *variant_entry; + struct wsa884x_priv *wsa884x; + struct snd_soc_card *card; + char name[80]; + + if (!codec_root || !component) + return -EINVAL; + + wsa884x = snd_soc_component_get_drvdata(component); + if (wsa884x->entry) { + dev_dbg(wsa884x->dev, + "%s:wsa884x module already created\n", __func__); + return 0; + } + card = component->card; + + snprintf(name, sizeof(name), "%s.%llx", "wsa884x", + wsa884x->swr_slave->addr); + + wsa884x->entry = snd_info_create_module_entry(codec_root->module, + (const char *)name, + codec_root); + if (!wsa884x->entry) { + dev_dbg(component->dev, "%s: failed to create wsa884x entry\n", + __func__); + return -ENOMEM; + } + wsa884x->entry->mode = S_IFDIR | 0555; + if (snd_info_register(wsa884x->entry) < 0) { + snd_info_free_entry(wsa884x->entry); + return -ENOMEM; + } + + version_entry = snd_info_create_card_entry(card->snd_card, + "version", + wsa884x->entry); + if (!version_entry) { + dev_dbg(component->dev, "%s: failed to create wsa884x version entry\n", + __func__); + snd_info_free_entry(wsa884x->entry); + return -ENOMEM; + } + + version_entry->private_data = wsa884x; + version_entry->size = WSA884X_VERSION_ENTRY_SIZE; + version_entry->content = SNDRV_INFO_CONTENT_DATA; + version_entry->c.ops = &wsa884x_codec_info_ops; + + if (snd_info_register(version_entry) < 0) { + snd_info_free_entry(version_entry); + snd_info_free_entry(wsa884x->entry); + return -ENOMEM; + } + wsa884x->version_entry = version_entry; + + variant_entry = snd_info_create_card_entry(card->snd_card, + "variant", + wsa884x->entry); + if (!variant_entry) { + dev_dbg(component->dev, + "%s: failed to create wsa884x variant entry\n", + __func__); + snd_info_free_entry(version_entry); + snd_info_free_entry(wsa884x->entry); + return -ENOMEM; + } + + variant_entry->private_data = wsa884x; + variant_entry->size = WSA884X_VARIANT_ENTRY_SIZE; + variant_entry->content = SNDRV_INFO_CONTENT_DATA; + variant_entry->c.ops = &wsa884x_variant_ops; + + if (snd_info_register(variant_entry) < 0) { + snd_info_free_entry(variant_entry); + snd_info_free_entry(version_entry); + snd_info_free_entry(wsa884x->entry); + return -ENOMEM; + } + wsa884x->variant_entry = variant_entry; + + return 0; +} +EXPORT_SYMBOL(wsa884x_codec_info_create_codec_entry); + +/* + * wsa884x_codec_get_dev_num - returns swr device number + * @component: Codec instance + * + * Return: swr device number on success or negative error + * code on failure. + */ +int wsa884x_codec_get_dev_num(struct snd_soc_component *component) +{ + struct wsa884x_priv *wsa884x; + + if (!component) + return -EINVAL; + + wsa884x = snd_soc_component_get_drvdata(component); + if (!wsa884x) { + pr_err("%s: wsa884x component is NULL\n", __func__); + return -EINVAL; + } + + return wsa884x->swr_slave->dev_num; +} +EXPORT_SYMBOL(wsa884x_codec_get_dev_num); + +static int wsa884x_get_dev_num(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x; + + if (!component) + return -EINVAL; + + wsa884x = snd_soc_component_get_drvdata(component); + if (!wsa884x) { + pr_err("%s: wsa884x component is NULL\n", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = wsa884x->swr_slave->dev_num; + return 0; +} + +static int wsa884x_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->comp_enable; + return 0; +} + +static int wsa884x_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = 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__, wsa884x->comp_enable, value); + wsa884x->comp_enable = value; + return 0; +} + +static int wsa884x_get_comp_offset(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->comp_offset; + return 0; +} + +static int wsa884x_set_comp_offset(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + int value = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: comp_offset %d\n", + __func__, wsa884x->comp_offset); + wsa884x->comp_offset = value; + return 0; +} + +static int wsa884x_get_visense(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->visense_enable; + return 0; +} + +static int wsa884x_set_visense(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = 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__, wsa884x->visense_enable, value); + wsa884x->visense_enable = value; + return 0; +} + +static int wsa884x_get_ext_vdd_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa884x->ext_vdd_spk; + + return 0; +} + +static int wsa884x_put_ext_vdd_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + int value = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: Ext VDD SPK enable current %d, new %d\n", + __func__, wsa884x->ext_vdd_spk, value); + wsa884x->ext_vdd_spk = value; + + return 0; +} + +static const struct snd_kcontrol_new wsa884x_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, + wsa884x_get_mute, wsa884x_set_mute), + + SOC_SINGLE_EXT("WSA Temp", SND_SOC_NOPM, 0, UINT_MAX, 0, + wsa_get_temp, NULL), + + SOC_SINGLE_EXT("WSA Get DevNum", SND_SOC_NOPM, 0, UINT_MAX, 0, + wsa884x_get_dev_num, NULL), + + SOC_ENUM_EXT("WSA MODE", wsa_dev_mode_enum, + wsa_dev_mode_get, wsa_dev_mode_put), + + SOC_SINGLE_EXT("COMP Offset", SND_SOC_NOPM, 0, 4, 0, + wsa884x_get_comp_offset, wsa884x_set_comp_offset), + + SOC_SINGLE_EXT("COMP Switch", SND_SOC_NOPM, 0, 1, 0, + wsa884x_get_compander, wsa884x_set_compander), + + SOC_SINGLE_EXT("VISENSE Switch", SND_SOC_NOPM, 0, 1, 0, + wsa884x_get_visense, wsa884x_set_visense), + + SOC_SINGLE_EXT("External VDD_SPK", SND_SOC_NOPM, 0, 1, 0, + wsa884x_get_ext_vdd_spk, wsa884x_put_ext_vdd_spk), +}; + +static const struct snd_kcontrol_new swr_dac_port[] = { + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) +}; + +static int wsa884x_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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + *port_id = wsa884x->port[port_idx].port_id; + *num_ch = wsa884x->port[port_idx].num_ch; + *ch_mask = wsa884x->port[port_idx].ch_mask; + *ch_rate = wsa884x->port[port_idx].ch_rate; + *port_type = wsa884x->port[port_idx].port_type; + return 0; +} + +static int wsa884x_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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + u8 port_id[WSA884X_MAX_SWR_PORTS]; + u8 num_ch[WSA884X_MAX_SWR_PORTS]; + u8 ch_mask[WSA884X_MAX_SWR_PORTS]; + u32 ch_rate[WSA884X_MAX_SWR_PORTS]; + u8 port_type[WSA884X_MAX_SWR_PORTS]; + u8 num_port = 0; + + dev_dbg(component->dev, "%s: event %d name %s\n", __func__, + event, w->name); + if (wsa884x == NULL) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wsa884x_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 (wsa884x->comp_enable) { + wsa884x_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 (wsa884x->visense_enable) { + wsa884x_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(wsa884x->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: + set_bit(SPKR_STATUS, &wsa884x->status_mask); + break; + case SND_SOC_DAPM_PRE_PMD: + wsa884x_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 (wsa884x->comp_enable) { + wsa884x_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 (wsa884x->visense_enable) { + wsa884x_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(wsa884x->swr_slave, &port_id[0], num_port, + &ch_mask[0], &port_type[0]); + break; + case SND_SOC_DAPM_POST_PMD: + if (swr_set_device_group(wsa884x->swr_slave, SWR_GROUP_NONE)) + dev_err(component->dev, + "%s: set num ch failed\n", __func__); + + swr_slvdev_datapath_control(wsa884x->swr_slave, + wsa884x->swr_slave->dev_num, + false); + break; + default: + break; + } + return 0; +} + +static int wsa884x_spkr_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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + swr_slvdev_datapath_control(wsa884x->swr_slave, + wsa884x->swr_slave->dev_num, + true); + /* Added delay as per HW sequence */ + usleep_range(250, 300); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(DRE_CTL_1, CSR_GAIN_EN, 0x01)); + /* Added delay as per HW sequence */ + usleep_range(250, 300); + if (wsa884x->comp_enable) + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(DRE_CTL_0, OFFSET, + wsa884x->comp_offset)); + wcd_enable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO); + /* Force remove group */ + swr_remove_from_group(wsa884x->swr_slave, + wsa884x->swr_slave->dev_num); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(VBAT_THRM_FLT_CTL, VBAT_COEF_SEL, 0x03)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(VBAT_THRM_FLT_CTL, VBAT_FLT_EN, 0x01)); + if (test_bit(SPKR_ADIE_LB, &wsa884x->status_mask)) + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x01)); + break; + case SND_SOC_DAPM_PRE_PMD: + if (!test_bit(SPKR_ADIE_LB, &wsa884x->status_mask)) + wcd_disable_irq(&wsa884x->irq_info, + WSA884X_IRQ_INT_PDM_WD); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(VBAT_THRM_FLT_CTL, VBAT_FLT_EN, 0x00)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(VBAT_THRM_FLT_CTL, VBAT_COEF_SEL, 0x00)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x00)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PDM_WD_CTL, PDM_WD_EN, 0x00)); + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO); + clear_bit(SPKR_STATUS, &wsa884x->status_mask); + clear_bit(SPKR_ADIE_LB, &wsa884x->status_mask); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget wsa884x_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), wsa884x_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_SPK("SPKR", wsa884x_spkr_event), +}; + +static const struct snd_soc_dapm_route wsa884x_audio_map[] = { + {"SWR DAC_Port", "Switch", "IN"}, + {"SPKR", NULL, "SWR DAC_Port"}, +}; + +int wsa884x_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 wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + int i; + + if (!port || !ch_mask || !ch_rate || + (num_port > WSA884X_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++) { + wsa884x->port[i].port_id = port[i]; + wsa884x->port[i].ch_mask = ch_mask[i]; + wsa884x->port[i].ch_rate = ch_rate[i]; + wsa884x->port[i].num_ch = __sw_hweight8(ch_mask[i]); + if (port_type) + wsa884x->port[i].port_type = port_type[i]; + } + + return 0; +} +EXPORT_SYMBOL(wsa884x_set_channel_map); + +static void wsa884x_codec_init(struct snd_soc_component *component) +{ + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + int i; + + if (!wsa884x) + return; + + for (i = 0; i < ARRAY_SIZE(reg_init); i++) + snd_soc_component_update_bits(component, reg_init[i].reg, + reg_init[i].mask, reg_init[i].val); + + if (wsa884x->variant == WSA8840 || wsa884x->variant == WSA8842) { + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(DRE_CTL_0, OFFSET, 0x03)); + wsa884x->comp_offset = COMP_OFFSET3; + } +} + +static int32_t wsa884x_temp_reg_read(struct snd_soc_component *component, + struct wsa_temp_register *wsa_temp_reg) +{ + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + if (!wsa884x) { + dev_err(component->dev, "%s: wsa884x is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&wsa884x->res_lock); + + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, DC_CAL_EN, 0x01)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, BG_EN, 0x01)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, CLK_WD_EN, 0x01)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, TSADC_EN, 0x01)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, D_UNMUTE, 0x01)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_BYP0, SPKR_PROT_EN, 0x01)); + + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(TADC_VALUE_CTL, TEMP_VALUE_RD_EN, 0x00)); + wsa_temp_reg->dmeas_msb = snd_soc_component_read(component, + WSA884X_TEMP_DIN_MSB); + wsa_temp_reg->dmeas_lsb = snd_soc_component_read(component, + WSA884X_TEMP_DIN_LSB); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(TADC_VALUE_CTL, TEMP_VALUE_RD_EN, 0x01)); + wsa_temp_reg->d1_msb = snd_soc_component_read(component, + WSA884X_OTP_REG_1); + wsa_temp_reg->d1_lsb = snd_soc_component_read(component, + WSA884X_OTP_REG_2); + wsa_temp_reg->d2_msb = snd_soc_component_read(component, + WSA884X_OTP_REG_3); + wsa_temp_reg->d2_lsb = snd_soc_component_read(component, + WSA884X_OTP_REG_4); + + snd_soc_component_update_bits(component, + WSA884X_PA_FSM_BYP0, 0xE7, 0x00); + mutex_unlock(&wsa884x->res_lock); + + return 0; +} + +static int wsa884x_get_temperature(struct snd_soc_component *component, + int *temp) +{ + struct wsa_temp_register reg; + int dmeas, d1, d2; + int ret = 0; + int temp_val = 0; + int t1 = T1_TEMP; + int t2 = T2_TEMP; + u8 retry = WSA884X_TEMP_RETRY; + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + if (!wsa884x) + return -EINVAL; + + do { + ret = wsa884x_temp_reg_read(component, ®); + if (ret) { + pr_err("%s: temp read failed: %d, current temp: %d\n", + __func__, ret, wsa884x->curr_temp); + if (temp) + *temp = wsa884x->curr_temp; + return 0; + } + /* + * 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(10); + } else { + break; + } + } while (retry); + + wsa884x->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; +} + +static int wsa884x_codec_probe(struct snd_soc_component *component) +{ + char w_name[MAX_NAME_LEN]; + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + struct swr_device *dev; + int variant = 0, version = 0; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + + if (!wsa884x) + return -EINVAL; + + if (!component->name_prefix) + return -EINVAL; + + snd_soc_component_init_regmap(component, wsa884x->regmap); + + dev = wsa884x->swr_slave; + wsa884x->component = component; + + variant = (snd_soc_component_read(component, WSA884X_OTP_REG_0) + & FIELD_MASK(OTP_REG_0, WSA884X_ID)); + wsa884x->variant = variant; + + version = (snd_soc_component_read(component, WSA884X_CHIP_ID0) + & FIELD_MASK(CHIP_ID0, BYTE_0)); + + wsa884x->version = version; + + wsa884x->comp_offset = COMP_OFFSET2; + wsa884x_codec_init(component); + wsa884x->global_pa_cnt = 0; + + memset(w_name, 0, sizeof(w_name)); + strlcpy(w_name, component->name_prefix, sizeof(w_name)); + strlcat(w_name, " ", sizeof(w_name)); + strlcat(w_name, wsa884x->dai_driver->playback.stream_name, + sizeof(w_name)); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, sizeof(w_name)); + strlcpy(w_name, component->name_prefix, sizeof(w_name)); + strlcat(w_name, " IN", sizeof(w_name)); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, sizeof(w_name)); + strlcpy(w_name, component->name_prefix, sizeof(w_name)); + strlcat(w_name, " SWR DAC_Port", sizeof(w_name)); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, sizeof(w_name)); + strlcpy(w_name, component->name_prefix, sizeof(w_name)); + strlcat(w_name, " SPKR", sizeof(w_name)); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static void wsa884x_codec_remove(struct snd_soc_component *component) +{ + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + if (!wsa884x) + return; + + snd_soc_component_exit_regmap(component); + + return; +} + +static int wsa884x_soc_codec_suspend(struct snd_soc_component *component) +{ + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + if (!wsa884x) + return 0; + + wsa884x->dapm_bias_off = true; + return 0; +} + +static int wsa884x_soc_codec_resume(struct snd_soc_component *component) +{ + struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component); + + if (!wsa884x) + return 0; + + wsa884x->dapm_bias_off = false; + return 0; +} + +static const struct snd_soc_component_driver soc_codec_dev_wsa884x_wsa = { + .name = "", + .probe = wsa884x_codec_probe, + .remove = wsa884x_codec_remove, + .controls = wsa884x_snd_controls, + .num_controls = ARRAY_SIZE(wsa884x_snd_controls), + .dapm_widgets = wsa884x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wsa884x_dapm_widgets), + .dapm_routes = wsa884x_audio_map, + .num_dapm_routes = ARRAY_SIZE(wsa884x_audio_map), + .suspend = wsa884x_soc_codec_suspend, + .resume = wsa884x_soc_codec_resume, +}; + +static int wsa884x_gpio_ctrl(struct wsa884x_priv *wsa884x, bool enable) +{ + int ret = 0; + + if (enable) + ret = msm_cdc_pinctrl_select_active_state( + wsa884x->wsa_rst_np); + else + ret = msm_cdc_pinctrl_select_sleep_state( + wsa884x->wsa_rst_np); + if (ret != 0) + dev_err(wsa884x->dev, + "%s: Failed to turn state %d; ret=%d\n", + __func__, enable, ret); + + return ret; +} + +static int wsa884x_swr_up(struct wsa884x_priv *wsa884x) +{ + int ret; + + ret = wsa884x_gpio_ctrl(wsa884x, true); + if (ret) + dev_err(wsa884x->dev, "%s: Failed to enable gpio\n", __func__); + + return ret; +} + +static int wsa884x_swr_down(struct wsa884x_priv *wsa884x) +{ + int ret; + + ret = wsa884x_gpio_ctrl(wsa884x, false); + if (ret) + dev_err(wsa884x->dev, "%s: Failed to disable gpio\n", __func__); + + return ret; +} + +static int wsa884x_swr_reset(struct wsa884x_priv *wsa884x) +{ + u8 retry = WSA884X_NUM_RETRY; + u8 devnum = 0; + struct swr_device *pdev; + + pdev = wsa884x->swr_slave; + while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) { + /* Retry after 1 msec delay */ + usleep_range(1000, 1100); + } + pdev->dev_num = devnum; + wsa884x_regcache_sync(wsa884x); + + return 0; +} + +static int wsa884x_event_notify(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + u16 event = (val & 0xffff); + struct wsa884x_priv *wsa884x = container_of(nb, struct wsa884x_priv, + parent_nblock); + + if (!wsa884x) + return -EINVAL; + + switch (event) { + case BOLERO_SLV_EVT_PA_OFF_PRE_SSR: + if (test_bit(SPKR_STATUS, &wsa884x->status_mask)) + snd_soc_component_update_bits(wsa884x->component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x00)); + wsa884x_swr_down(wsa884x); + break; + + case BOLERO_SLV_EVT_SSR_UP: + wsa884x_swr_up(wsa884x); + /* Add delay to allow enumerate */ + usleep_range(20000, 20010); + wsa884x_swr_reset(wsa884x); + break; + + case BOLERO_SLV_EVT_PA_ON_POST_FSCLK: + if (test_bit(SPKR_STATUS, &wsa884x->status_mask)) { + snd_soc_component_update_bits(wsa884x->component, + REG_FIELD_VALUE(PDM_WD_CTL, PDM_WD_EN, 0x01)); + snd_soc_component_update_bits(wsa884x->component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x01)); + wcd_enable_irq(&wsa884x->irq_info, + WSA884X_IRQ_INT_PDM_WD); + /* Added delay as per HW sequence */ + usleep_range(3000, 3100); + snd_soc_component_update_bits(wsa884x->component, + REG_FIELD_VALUE(DRE_CTL_1, CSR_GAIN_EN, 0x00)); + /* Added delay as per HW sequence */ + usleep_range(5000, 5050); + } + break; + case BOLERO_SLV_EVT_PA_ON_POST_FSCLK_ADIE_LB: + if (test_bit(SPKR_STATUS, &wsa884x->status_mask)) + set_bit(SPKR_ADIE_LB, &wsa884x->status_mask); + break; + default: + dev_dbg(wsa884x->dev, "%s: unknown event %d\n", + __func__, event); + break; + } + + return 0; +} + +static int wsa884x_enable_supplies(struct device *dev, + struct wsa884x_priv *priv) +{ + int ret = 0; + + /* Parse power supplies */ + msm_cdc_get_power_supplies(dev, &priv->regulator, + &priv->num_supplies); + if (!priv->regulator || (priv->num_supplies <= 0)) { + dev_err(dev, "%s: no power supplies defined\n", __func__); + return -EINVAL; + } + + ret = msm_cdc_init_supplies(dev, &priv->supplies, + priv->regulator, priv->num_supplies); + if (!priv->supplies) { + dev_err(dev, "%s: Cannot init wsa supplies\n", + __func__); + return ret; + } + + ret = msm_cdc_enable_static_supplies(dev, priv->supplies, + priv->regulator, + priv->num_supplies); + if (ret) + dev_err(dev, "%s: wsa static supply enable failed!\n", + __func__); + + return ret; +} + +static struct snd_soc_dai_driver wsa_dai[] = { + { + .name = "", + .playback = { + .stream_name = "", + .rates = WSA884X_RATES | WSA884X_FRAC_RATES, + .formats = WSA884X_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + }, +}; + +static int wsa884x_swr_probe(struct swr_device *pdev) +{ + int ret = 0, i = 0; + struct wsa884x_priv *wsa884x; + u8 devnum = 0; + bool pin_state_current = false; + struct wsa_ctrl_platform_data *plat_data = NULL; + struct snd_soc_component *component; + const char *wsa884x_name_prefix_of = NULL; + char buffer[MAX_NAME_LEN]; + int dev_index = 0; + + wsa884x = devm_kzalloc(&pdev->dev, sizeof(struct wsa884x_priv), + GFP_KERNEL); + if (!wsa884x) + return -ENOMEM; + + ret = wsa884x_enable_supplies(&pdev->dev, wsa884x); + if (ret) { + ret = -EPROBE_DEFER; + goto err; + } + + wsa884x->wsa_rst_np = of_parse_phandle(pdev->dev.of_node, + "qcom,spkr-sd-n-node", 0); + if (!wsa884x->wsa_rst_np) { + dev_dbg(&pdev->dev, "%s: pinctrl not defined\n", __func__); + goto err_supply; + } + swr_set_dev_data(pdev, wsa884x); + wsa884x->swr_slave = pdev; + pin_state_current = msm_cdc_pinctrl_get_state(wsa884x->wsa_rst_np); + wsa884x_gpio_ctrl(wsa884x, true); + /* + * Add 5msec delay to provide sufficient time for + * soundwire auto enumeration of slave devices 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); + ret = -EPROBE_DEFER; + goto err_supply; + } + pdev->dev_num = devnum; + + wsa884x->regmap = devm_regmap_init_swr(pdev, + &wsa884x_regmap_config); + if (IS_ERR(wsa884x->regmap)) { + ret = PTR_ERR(wsa884x->regmap); + dev_err(&pdev->dev, "%s: regmap_init failed %d\n", + __func__, ret); + goto dev_err; + } + + devm_regmap_qti_debugfs_register(&pdev->dev, wsa884x->regmap); + + /* Set all interrupts as edge triggered */ + for (i = 0; i < wsa884x_regmap_irq_chip.num_regs; i++) + regmap_write(wsa884x->regmap, (WSA884X_INTR_LEVEL0 + i), 0); + + wsa884x_regmap_irq_chip.irq_drv_data = wsa884x; + wsa884x->irq_info.wcd_regmap_irq_chip = &wsa884x_regmap_irq_chip; + wsa884x->irq_info.codec_name = "WSA884X"; + wsa884x->irq_info.regmap = wsa884x->regmap; + wsa884x->irq_info.dev = &pdev->dev; + ret = wcd_irq_init(&wsa884x->irq_info, &wsa884x->virq); + + if (ret) { + dev_err(wsa884x->dev, "%s: IRQ init failed: %d\n", + __func__, ret); + goto dev_err; + } + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_SAF2WAR, + "WSA SAF2WAR", wsa884x_saf2war_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_SAF2WAR); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_WAR2SAF, + "WSA WAR2SAF", wsa884x_war2saf_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_WAR2SAF); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_DISABLE, + "WSA OTP", wsa884x_otp_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_DISABLE); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_OCP, + "WSA OCP", wsa884x_ocp_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_OCP); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLIP, + "WSA CLIP", wsa884x_clip_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLIP); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PDM_WD, + "WSA PDM WD", wsa884x_pdm_wd_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PDM_WD); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLK_WD, + "WSA CLK WD", wsa884x_clk_wd_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLK_WD); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_INTR_PIN, + "WSA EXT INT", wsa884x_ext_int_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_INTR_PIN); + + /* Under Voltage Lock out (UVLO) interrupt handle */ + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO, + "WSA UVLO", wsa884x_uvlo_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO); + + wcd_request_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PA_ON_ERR, + "WSA PA ERR", wsa884x_pa_on_err_handle_irq, NULL); + + wcd_disable_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PA_ON_ERR); + + ret = of_property_read_string(pdev->dev.of_node, "qcom,wsa-prefix", + &wsa884x_name_prefix_of); + if (ret) { + dev_err(&pdev->dev, + "%s: Looking up %s property in node %s failed\n", + __func__, "qcom,wsa-prefix", + pdev->dev.of_node->full_name); + goto err_irq; + } + + wsa884x->driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_component_driver), GFP_KERNEL); + if (!wsa884x->driver) { + ret = -ENOMEM; + goto err_irq; + } + + memcpy(wsa884x->driver, &soc_codec_dev_wsa884x_wsa, + sizeof(struct snd_soc_component_driver)); + + wsa884x->dai_driver = devm_kzalloc(&pdev->dev, + sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (!wsa884x->dai_driver) { + ret = -ENOMEM; + goto err_mem; + } + + memcpy(wsa884x->dai_driver, wsa_dai, sizeof(struct snd_soc_dai_driver)); + + /* Get last digit from HEX format */ + dev_index = (int)((char)(pdev->addr & 0xF)); + + if (of_device_is_compatible(pdev->dev.of_node, "qcom,wsa884x_2")) + dev_index += 2; + + snprintf(buffer, sizeof(buffer), "wsa-codec.%d", dev_index); + wsa884x->driver->name = kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), "wsa_rx%d", dev_index); + wsa884x->dai_driver->name = + kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + snprintf(buffer, sizeof(buffer), "WSA884X_AIF%d Playback", dev_index); + wsa884x->dai_driver->playback.stream_name = + kstrndup(buffer, strlen(buffer), GFP_KERNEL); + + /* Number of DAI's used is 1 */ + ret = snd_soc_register_component(&pdev->dev, + wsa884x->driver, wsa884x->dai_driver, 1); + + wsa884x->wsa884x_name_prefix = kstrndup(wsa884x_name_prefix_of, + strlen(wsa884x_name_prefix_of), GFP_KERNEL); + component = snd_soc_lookup_component(&pdev->dev, wsa884x->driver->name); + if (!component) { + dev_err(&pdev->dev, "%s: component is NULL\n", __func__); + ret = -EINVAL; + goto err_mem; + } + component->name_prefix = wsa884x->wsa884x_name_prefix; + + wsa884x->parent_np = of_parse_phandle(pdev->dev.of_node, + "qcom,bolero-handle", 0); + if (!wsa884x->parent_np) + wsa884x->parent_np = of_parse_phandle(pdev->dev.of_node, + "qcom,lpass-cdc-handle", 0); + if (wsa884x->parent_np) { + wsa884x->parent_dev = + of_find_device_by_node(wsa884x->parent_np); + if (wsa884x->parent_dev) { + plat_data = dev_get_platdata(&wsa884x->parent_dev->dev); + if (plat_data) { + wsa884x->parent_nblock.notifier_call = + wsa884x_event_notify; + if (plat_data->register_notifier) + plat_data->register_notifier( + plat_data->handle, + &wsa884x->parent_nblock, + true); + wsa884x->register_notifier = + plat_data->register_notifier; + wsa884x->handle = plat_data->handle; + } else { + dev_err(&pdev->dev, "%s: plat data not found\n", + __func__); + } + } else { + dev_err(&pdev->dev, "%s: parent dev not found\n", + __func__); + } + } else { + dev_info(&pdev->dev, "%s: parent node not found\n", __func__); + } + + mutex_init(&wsa884x->res_lock); + +#ifdef CONFIG_DEBUG_FS + if (!wsa884x->debugfs_dent) { + wsa884x->debugfs_dent = debugfs_create_dir( + dev_name(&pdev->dev), 0); + if (!IS_ERR(wsa884x->debugfs_dent)) { + wsa884x->debugfs_peek = + debugfs_create_file("swrslave_peek", + S_IFREG | 0444, + wsa884x->debugfs_dent, + (void *) pdev, + &codec_debug_read_ops); + + wsa884x->debugfs_poke = + debugfs_create_file("swrslave_poke", + S_IFREG | 0444, + wsa884x->debugfs_dent, + (void *) pdev, + &codec_debug_write_ops); + + wsa884x->debugfs_reg_dump = + debugfs_create_file( + "swrslave_reg_dump", + S_IFREG | 0444, + wsa884x->debugfs_dent, + (void *) pdev, + &codec_debug_dump_ops); + } +} +#endif + + return 0; + +err_mem: + kfree(wsa884x->wsa884x_name_prefix); + if (wsa884x->dai_driver) { + kfree(wsa884x->dai_driver->name); + kfree(wsa884x->dai_driver->playback.stream_name); + kfree(wsa884x->dai_driver); + } + if (wsa884x->driver) { + kfree(wsa884x->driver->name); + kfree(wsa884x->driver); + } +err_irq: + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_SAF2WAR, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_WAR2SAF, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_DISABLE, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_OCP, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLIP, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PDM_WD, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLK_WD, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_INTR_PIN, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PA_ON_ERR, NULL); + wcd_irq_exit(&wsa884x->irq_info, wsa884x->virq); +dev_err: + if (pin_state_current == false) + wsa884x_gpio_ctrl(wsa884x, false); + swr_remove_device(pdev); +err_supply: + msm_cdc_release_supplies(&pdev->dev, wsa884x->supplies, + wsa884x->regulator, + wsa884x->num_supplies); +err: + swr_set_dev_data(pdev, NULL); + return ret; +} + +static int wsa884x_swr_remove(struct swr_device *pdev) +{ + struct wsa884x_priv *wsa884x; + + wsa884x = swr_get_dev_data(pdev); + if (!wsa884x) { + dev_err(&pdev->dev, "%s: wsa884x is NULL\n", __func__); + return -EINVAL; + } + + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_SAF2WAR, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_WAR2SAF, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_DISABLE, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_OCP, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLIP, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PDM_WD, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_CLK_WD, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_INTR_PIN, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_UVLO, NULL); + wcd_free_irq(&wsa884x->irq_info, WSA884X_IRQ_INT_PA_ON_ERR, NULL); + + if (wsa884x->register_notifier) + wsa884x->register_notifier(wsa884x->handle, + &wsa884x->parent_nblock, false); +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(wsa884x->debugfs_dent); + wsa884x->debugfs_dent = NULL; +#endif + mutex_destroy(&wsa884x->res_lock); + snd_soc_unregister_component(&pdev->dev); + kfree(wsa884x->wsa884x_name_prefix); + if (wsa884x->dai_driver) { + kfree(wsa884x->dai_driver->name); + kfree(wsa884x->dai_driver->playback.stream_name); + kfree(wsa884x->dai_driver); + } + if (wsa884x->driver) { + kfree(wsa884x->driver->name); + kfree(wsa884x->driver); + } + msm_cdc_release_supplies(&pdev->dev, wsa884x->supplies, + wsa884x->regulator, + wsa884x->num_supplies); + swr_set_dev_data(pdev, NULL); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int wsa884x_swr_suspend(struct device *dev) +{ + struct wsa884x_priv *wsa884x = swr_get_dev_data(to_swr_device(dev)); + + if (!wsa884x) { + dev_err(dev, "%s: wsa884x private data is NULL\n", __func__); + return -EINVAL; + } + dev_dbg(dev, "%s: system suspend\n", __func__); + if (wsa884x->dapm_bias_off) { + msm_cdc_set_supplies_lpm_mode(dev, wsa884x->supplies, + wsa884x->regulator, + wsa884x->num_supplies, + true); + set_bit(WSA_SUPPLIES_LPM_MODE, &wsa884x->status_mask); + } + return 0; +} + +static int wsa884x_swr_resume(struct device *dev) +{ + struct wsa884x_priv *wsa884x = swr_get_dev_data(to_swr_device(dev)); + + if (!wsa884x) { + dev_err(dev, "%s: wsa884x private data is NULL\n", __func__); + return -EINVAL; + } + if (test_bit(WSA_SUPPLIES_LPM_MODE, &wsa884x->status_mask)) { + msm_cdc_set_supplies_lpm_mode(dev, wsa884x->supplies, + wsa884x->regulator, + wsa884x->num_supplies, + false); + clear_bit(WSA_SUPPLIES_LPM_MODE, &wsa884x->status_mask); + } + dev_dbg(dev, "%s: system resume\n", __func__); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops wsa884x_swr_pm_ops = { + .suspend_late = wsa884x_swr_suspend, + .resume_early = wsa884x_swr_resume, +}; + +static const struct swr_device_id wsa884x_swr_id[] = { + {"wsa884x", 0}, + {"wsa884x_2", 0}, + {} +}; + +static const struct of_device_id wsa884x_swr_dt_match[] = { + { + .compatible = "qcom,wsa884x", + }, + { + .compatible = "qcom,wsa884x_2", + }, + {} +}; + +static struct swr_driver wsa884x_swr_driver = { + .driver = { + .name = "wsa884x", + .owner = THIS_MODULE, + .pm = &wsa884x_swr_pm_ops, + .of_match_table = wsa884x_swr_dt_match, + }, + .probe = wsa884x_swr_probe, + .remove = wsa884x_swr_remove, + .id_table = wsa884x_swr_id, +}; + +static int __init wsa884x_swr_init(void) +{ + return swr_driver_register(&wsa884x_swr_driver); +} + +static void __exit wsa884x_swr_exit(void) +{ + swr_driver_unregister(&wsa884x_swr_driver); +} + +module_init(wsa884x_swr_init); +module_exit(wsa884x_swr_exit); + +MODULE_DESCRIPTION("WSA884x codec driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/wsa884x/wsa884x.h b/asoc/codecs/wsa884x/wsa884x.h new file mode 100644 index 0000000000..4793f43a7c --- /dev/null +++ b/asoc/codecs/wsa884x/wsa884x.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _WSA884X_H +#define _WSA884X_H + +#include +#include +#include +#include "wsa884x-registers.h" +#include "wsa884x-reg-masks.h" +#include "wsa884x-reg-shifts.h" + + +#define WSA884X_MAX_SWR_PORTS 4 + +#if IS_ENABLED(CONFIG_SND_SOC_WSA884X) +int wsa884x_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 wsa884x_codec_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component); +int wsa884x_codec_get_dev_num(struct snd_soc_component *component); +#else +static int wsa884x_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 wsa884x_codec_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + return 0; +} + +static int wsa884x_codec_get_dev_num(struct snd_soc_component *component) +{ + return 0; +} +#endif + +#endif /* _WSA884X_H */