diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index 0a81acc0c9..2408d0d6d8 100644 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -256,6 +256,7 @@ ifeq ($(KERNEL_BUILD), 1) obj-y += wcd937x/ obj-y += wcd938x/ obj-y += bolero/ + obj-y += lpass-cdc/ obj-y += wsa883x/ obj-y += rouleur/ endif diff --git a/asoc/codecs/lpass-cdc/Kbuild b/asoc/codecs/lpass-cdc/Kbuild new file mode 100644 index 0000000000..1e0f9b5b9e --- /dev/null +++ b/asoc/codecs/lpass-cdc/Kbuild @@ -0,0 +1,159 @@ +# We can build either as part of a standalone Kernel build or as +# an external module. Determine which mechanism is being used +ifeq ($(MODNAME),) + KERNEL_BUILD := 1 +else + KERNEL_BUILD := 0 +endif + + + +ifeq ($(KERNEL_BUILD), 1) + # These are configurable via Kconfig for kernel-based builds + # Need to explicitly configure for Android-based builds + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio +endif + +ifeq ($(KERNEL_BUILD), 0) + ifeq ($(CONFIG_ARCH_SM6150), y) + include $(AUDIO_ROOT)/config/sm6150auto.conf + export + INCS += -include $(AUDIO_ROOT)/config/sm6150autoconf.h + endif + ifeq ($(CONFIG_ARCH_TRINKET), y) + include $(AUDIO_ROOT)/config/sm6150auto.conf + export + INCS += -include $(AUDIO_ROOT)/config/sm6150autoconf.h + endif + ifeq ($(CONFIG_ARCH_KONA), y) + include $(AUDIO_ROOT)/config/konaauto.conf + INCS += -include $(AUDIO_ROOT)/config/konaautoconf.h + endif + ifeq ($(CONFIG_ARCH_LITO), y) + include $(AUDIO_ROOT)/config/litoauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/litoautoconf.h + endif + ifeq ($(CONFIG_ARCH_BENGAL), y) + include $(AUDIO_ROOT)/config/bengalauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/bengalautoconf.h + endif + ifeq ($(CONFIG_ARCH_QCS405), y) + include $(AUDIO_ROOT)/config/qcs405auto.conf + export + INCS += -include $(AUDIO_ROOT)/config/qcs405autoconf.h + endif +endif + +# As per target team, build is done as follows: +# Defconfig : build with default flags +# Slub : defconfig + CONFIG_SLUB_DEBUG := y + +# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y +# Perf : Using appropriate msmXXXX-perf_defconfig +# +# Shipment builds (user variants) should not have any debug feature +# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds +# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since +# there is no other way to identify defconfig builds, QTI internal +# representation of perf builds (identified using the string 'perf'), +# is used to identify if the build is a slub or defconfig one. This +# way no critical debug feature will be enabled for perf and shipment +# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT +# config. + +############ UAPI ############ +UAPI_DIR := uapi/audio +UAPI_INC := -I$(AUDIO_ROOT)/include/$(UAPI_DIR) + +############ COMMON ############ +COMMON_DIR := include +COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR) + +############ LPASS_CDC ############ + +# for LPASS_CDC Codec +ifdef CONFIG_SND_SOC_LPASS_CDC + LPASS_CDC_OBJS += lpass-cdc.o + LPASS_CDC_OBJS += lpass-cdc-utils.o + LPASS_CDC_OBJS += lpass-cdc-regmap.o + LPASS_CDC_OBJS += lpass-cdc-tables.o + LPASS_CDC_OBJS += lpass-cdc-clk-rsc.o +endif + +ifdef CONFIG_WSA_MACRO + WSA_OBJS += lpass-cdc-wsa-macro.o +endif + +ifdef CONFIG_VA_MACRO + VA_OBJS += lpass-cdc-va-macro.o +endif + +ifdef CONFIG_TX_MACRO + TX_OBJS += lpass-cdc-tx-macro.o +endif + +ifdef CONFIG_RX_MACRO + RX_OBJS += lpass-cdc-rx-macro.o +endif + +LINUX_INC += -Iinclude/linux + +INCS += $(COMMON_INC) \ + $(UAPI_INC) + +EXTRA_CFLAGS += $(INCS) + + +CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \ + -DANI_LITTLE_BIT_ENDIAN \ + -DDOT11F_LITTLE_ENDIAN_HOST \ + -DANI_COMPILER_TYPE_GCC \ + -DANI_OS_TYPE_ANDROID=6 \ + -DPTT_SOCK_SVC_ENABLE \ + -Wall\ + -Werror\ + -D__linux__ + +KBUILD_CPPFLAGS += $(CDEFINES) + +# Currently, for versions of gcc which support it, the kernel Makefile +# is disabling the maybe-uninitialized warning. Re-enable it for the +# AUDIO driver. Note that we must use EXTRA_CFLAGS here so that it +# will override the kernel settings. +ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y) +EXTRA_CFLAGS += -Wmaybe-uninitialized +endif +#EXTRA_CFLAGS += -Wmissing-prototypes + +ifeq ($(call cc-option-yn, -Wheader-guard),y) +EXTRA_CFLAGS += -Wheader-guard +endif + +ifeq ($(KERNEL_BUILD), 0) +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers +KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers +endif + +# Module information used by KBuild framework +obj-$(CONFIG_SND_SOC_LPASS_CDC) += lpass_cdc_dlkm.o +lpass_cdc_dlkm-y := $(LPASS_CDC_OBJS) + +obj-$(CONFIG_WSA_MACRO) += wsa_macro_dlkm.o +wsa_macro_dlkm-y := $(WSA_OBJS) + +obj-$(CONFIG_VA_MACRO) += va_macro_dlkm.o +va_macro_dlkm-y := $(VA_OBJS) + +obj-$(CONFIG_TX_MACRO) += tx_macro_dlkm.o +tx_macro_dlkm-y := $(TX_OBJS) + +obj-$(CONFIG_RX_MACRO) += rx_macro_dlkm.o +rx_macro_dlkm-y := $(RX_OBJS) + +# inject some build related information +DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/asoc/codecs/lpass-cdc/internal.h b/asoc/codecs/lpass-cdc/internal.h new file mode 100644 index 0000000000..7f08ab24a9 --- /dev/null +++ b/asoc/codecs/lpass-cdc/internal.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _LPASS_CDC_INTERNAL_H +#define _LPASS_CDC_INTERNAL_H + +#include "lpass-cdc-registers.h" + +#define LPASS_CDC_CHILD_DEVICES_MAX 6 + +/* from lpass_cdc to WCD events */ +enum { + LPASS_CDC_WCD_EVT_TX_CH_HOLD_CLEAR = 1, + LPASS_CDC_WCD_EVT_PA_OFF_PRE_SSR, + LPASS_CDC_WCD_EVT_SSR_DOWN, + LPASS_CDC_WCD_EVT_SSR_UP, + LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK, + LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB, +}; + +enum { + REG_NO_ACCESS, + RD_REG, + WR_REG, + RD_WR_REG +}; + +/* from WCD to lpass_cdc events */ +enum { + WCD_LPASS_CDC_EVT_RX_MUTE = 1, /* for RX mute/unmute */ + WCD_LPASS_CDC_EVT_IMPED_TRUE, /* for imped true */ + WCD_LPASS_CDC_EVT_IMPED_FALSE, /* for imped false */ + WCD_LPASS_CDC_EVT_RX_COMPANDER_SOFT_RST, + WCD_LPASS_CDC_EVT_BCS_CLK_OFF, + WCD_LPASS_CDC_EVT_RX_PA_GAIN_UPDATE, + WCD_LPASS_CDC_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */ + WCD_LPASS_CDC_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */ +}; + +struct wcd_ctrl_platform_data { + void *handle; + int (*update_wcd_event)(void *handle, u16 event, u32 data); + int (*register_notifier)(void *handle, + struct notifier_block *nblock, + bool enable); +}; + +struct lpass_cdc_priv { + struct device *dev; + struct snd_soc_component *component; + struct regmap *regmap; + struct mutex io_lock; + struct mutex clk_lock; + struct mutex vote_lock; + bool va_without_decimation; + bool macros_supported[MAX_MACRO]; + bool dev_up; + bool initial_boot; + struct macro_ops macro_params[MAX_MACRO]; + struct snd_soc_dai_driver *lpass_cdc_dais; + u16 num_dais; + u16 num_macros_registered; + u16 num_macros; + u16 current_mclk_mux_macro[MAX_MACRO]; + struct work_struct lpass_cdc_add_child_devices_work; + u32 version; + struct clk *lpass_core_hw_vote; + struct clk *lpass_audio_hw_vote; + int core_hw_vote_count; + int core_audio_vote_count; + + /* Entry for version info */ + struct snd_info_entry *entry; + struct snd_info_entry *version_entry; + + int (*read_dev)(struct lpass_cdc_priv *priv, + u16 macro_id, u16 reg, u8 *val); + int (*write_dev)(struct lpass_cdc_priv *priv, + u16 macro_id, u16 reg, u8 val); + struct platform_device *pdev_child_devices + [LPASS_CDC_CHILD_DEVICES_MAX]; + u16 child_count; + struct wcd_ctrl_platform_data plat_data; + struct device *wcd_dev; + struct blocking_notifier_head notifier; + struct device *clk_dev; + rsc_clk_cb_t rsc_clk_cb; + s32 dmic_0_1_clk_cnt; + s32 dmic_2_3_clk_cnt; + s32 dmic_4_5_clk_cnt; + s32 dmic_6_7_clk_cnt; + u8 dmic_0_1_clk_div; + u8 dmic_2_3_clk_div; + u8 dmic_4_5_clk_div; + u8 dmic_6_7_clk_div; +}; + +struct regmap *lpass_cdc_regmap_init(struct device *dev, + const struct regmap_config *config); +int lpass_cdc_get_macro_id(bool va_no_dec_flag, u16 reg); + +extern const struct regmap_config lpass_cdc_regmap_config; +extern u8 *lpass_cdc_reg_access[MAX_MACRO]; +extern u8 lpass_cdc_va_top_reg_access[LPASS_CDC_VA_MACRO_TOP_MAX]; +extern u8 lpass_cdc_va_reg_access_v2[LPASS_CDC_VA_MACRO_MAX]; +extern u8 lpass_cdc_va_reg_access_v3[LPASS_CDC_VA_MACRO_MAX]; +extern u8 lpass_cdc_tx_reg_access_v2[LPASS_CDC_TX_MACRO_MAX]; +extern const u16 macro_id_base_offset[MAX_MACRO]; + +#endif diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.c b/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.c new file mode 100644 index 0000000000..658b2d9209 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.c @@ -0,0 +1,768 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lpass-cdc.h" +#include "lpass-cdc-clk-rsc.h" + +#define DRV_NAME "lpass-cdc-clk-rsc" +#define LPASS_CDC_CLK_NAME_LENGTH 30 +#define NPL_CLK_OFFSET (TX_NPL_CLK - TX_CORE_CLK) + +static char clk_src_name[MAX_CLK][LPASS_CDC_CLK_NAME_LENGTH] = { + "tx_core_clk", + "rx_core_clk", + "wsa_core_clk", + "va_core_clk", + "tx_npl_clk", + "rx_npl_clk", + "wsa_npl_clk", + "va_npl_clk", +}; + +struct lpass_cdc_clk_rsc { + struct device *dev; + struct mutex rsc_clk_lock; + struct mutex fs_gen_lock; + struct clk *clk[MAX_CLK]; + int clk_cnt[MAX_CLK]; + int reg_seq_en_cnt; + int va_tx_clk_cnt; + bool dev_up; + bool dev_up_gfmux; + u32 num_fs_reg; + u32 *fs_gen_seq; + int default_clk_id[MAX_CLK]; + struct regmap *regmap; + char __iomem *rx_clk_muxsel; + char __iomem *wsa_clk_muxsel; + char __iomem *va_clk_muxsel; +}; + +static int lpass_cdc_clk_rsc_cb(struct device *dev, u16 event) +{ + struct lpass_cdc_clk_rsc *priv; + + if (!dev) { + pr_err("%s: Invalid device pointer\n", + __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + if (!priv) { + pr_err("%s: Invalid clk rsc priviate data\n", + __func__); + return -EINVAL; + } + + mutex_lock(&priv->rsc_clk_lock); + if (event == LPASS_CDC_MACRO_EVT_SSR_UP) { + priv->dev_up = true; + } else if (event == LPASS_CDC_MACRO_EVT_SSR_DOWN) { + priv->dev_up = false; + priv->dev_up_gfmux = false; + } else if (event == LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP) { + priv->dev_up_gfmux = true; + } + mutex_unlock(&priv->rsc_clk_lock); + + return 0; +} + +static char __iomem *lpass_cdc_clk_rsc_get_clk_muxsel(struct lpass_cdc_clk_rsc *priv, + int clk_id) +{ + switch (clk_id) { + case RX_CORE_CLK: + return priv->rx_clk_muxsel; + case WSA_CORE_CLK: + return priv->wsa_clk_muxsel; + case VA_CORE_CLK: + return priv->va_clk_muxsel; + case TX_CORE_CLK: + default: + dev_err_ratelimited(priv->dev, "%s: Invalid case\n", __func__); + break; + } + + return NULL; +} + +int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id) +{ + struct device *clk_dev = NULL; + struct lpass_cdc_clk_rsc *priv = NULL; + int count = 0; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return -EINVAL; + } + + if (clk_id < 0 || clk_id >= MAX_CLK - NPL_CLK_OFFSET) { + pr_err("%s: Invalid clk_id: %d\n", + __func__, clk_id); + return -EINVAL; + } + + clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk priviate data\n", __func__); + return -EINVAL; + } + mutex_lock(&priv->rsc_clk_lock); + while (__clk_is_enabled(priv->clk[clk_id])) { + clk_disable_unprepare(priv->clk[clk_id + NPL_CLK_OFFSET]); + clk_disable_unprepare(priv->clk[clk_id]); + count++; + } + dev_dbg(priv->dev, + "%s: clock reset after ssr, count %d\n", __func__, count); + + trace_printk("%s: clock reset after ssr, count %d\n", __func__, count); + while (count--) { + clk_prepare_enable(priv->clk[clk_id]); + clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]); + } + mutex_unlock(&priv->rsc_clk_lock); + return 0; +} +EXPORT_SYMBOL(lpass_cdc_rsc_clk_reset); + +void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev, bool enable) +{ + struct device *clk_dev = NULL; + struct lpass_cdc_clk_rsc *priv = NULL; + int i = 0; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return; + } + + clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return; + } + + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk private data\n", __func__); + return; + } + mutex_lock(&priv->rsc_clk_lock); + for (i = 0; i < MAX_CLK - NPL_CLK_OFFSET; i++) { + if (enable) { + if (priv->clk[i]) + clk_prepare_enable(priv->clk[i]); + if (priv->clk[i + NPL_CLK_OFFSET]) + clk_prepare_enable( + priv->clk[i + NPL_CLK_OFFSET]); + } else { + if (priv->clk[i + NPL_CLK_OFFSET]) + clk_disable_unprepare( + priv->clk[i + NPL_CLK_OFFSET]); + if (priv->clk[i]) + clk_disable_unprepare(priv->clk[i]); + } + } + mutex_unlock(&priv->rsc_clk_lock); + return; +} +EXPORT_SYMBOL(lpass_cdc_clk_rsc_enable_all_clocks); + +static int lpass_cdc_clk_rsc_mux0_clk_request(struct lpass_cdc_clk_rsc *priv, + int clk_id, + bool enable) +{ + int ret = 0; + + if (enable) { + /* Enable Requested Core clk */ + if (priv->clk_cnt[clk_id] == 0) { + ret = clk_prepare_enable(priv->clk[clk_id]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, clk_id); + goto done; + } + if (priv->clk[clk_id + NPL_CLK_OFFSET]) { + ret = clk_prepare_enable( + priv->clk[clk_id + NPL_CLK_OFFSET]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, + clk_id + NPL_CLK_OFFSET); + goto err; + } + } + } + priv->clk_cnt[clk_id]++; + } else { + if (priv->clk_cnt[clk_id] <= 0) { + dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n", + __func__, clk_id); + priv->clk_cnt[clk_id] = 0; + goto done; + } + priv->clk_cnt[clk_id]--; + if (priv->clk_cnt[clk_id] == 0) { + if (priv->clk[clk_id + NPL_CLK_OFFSET]) + clk_disable_unprepare( + priv->clk[clk_id + NPL_CLK_OFFSET]); + clk_disable_unprepare(priv->clk[clk_id]); + } + } + return ret; + +err: + clk_disable_unprepare(priv->clk[clk_id]); +done: + return ret; +} + +static int lpass_cdc_clk_rsc_mux1_clk_request(struct lpass_cdc_clk_rsc *priv, + int clk_id, + bool enable) +{ + char __iomem *clk_muxsel = NULL; + int ret = 0; + int default_clk_id = priv->default_clk_id[clk_id]; + u32 muxsel = 0; + + clk_muxsel = lpass_cdc_clk_rsc_get_clk_muxsel(priv, clk_id); + if (!clk_muxsel) { + ret = -EINVAL; + goto done; + } + + if (enable) { + if (priv->clk_cnt[clk_id] == 0) { + if (clk_id != VA_CORE_CLK) { + ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, + default_clk_id, + true); + if (ret < 0) + goto done; + } + + ret = clk_prepare_enable(priv->clk[clk_id]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, clk_id); + goto err_clk; + } + if (priv->clk[clk_id + NPL_CLK_OFFSET]) { + ret = clk_prepare_enable( + priv->clk[clk_id + NPL_CLK_OFFSET]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, + clk_id + NPL_CLK_OFFSET); + goto err_npl_clk; + } + } + + /* + * Temp SW workaround to address a glitch issue of + * VA GFMux instance responsible for switching from + * TX MCLK to VA MCLK. This configuration would be taken + * care in DSP itself + */ + if (clk_id != VA_CORE_CLK) { + if (priv->dev_up_gfmux) { + iowrite32(0x1, clk_muxsel); + muxsel = ioread32(clk_muxsel); + trace_printk("%s: muxsel value after enable: %d\n", + __func__, muxsel); + } + lpass_cdc_clk_rsc_mux0_clk_request(priv, + default_clk_id, + false); + } + } + priv->clk_cnt[clk_id]++; + } else { + if (priv->clk_cnt[clk_id] <= 0) { + dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n", + __func__, clk_id); + priv->clk_cnt[clk_id] = 0; + goto done; + } + priv->clk_cnt[clk_id]--; + if (priv->clk_cnt[clk_id] == 0) { + if (clk_id != VA_CORE_CLK) { + ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, + default_clk_id, true); + + if (!ret) { + /* + * Temp SW workaround to address a glitch issue + * of VA GFMux instance responsible for + * switching from TX MCLK to VA MCLK. + * This configuration would be taken + * care in DSP itself. + */ + if (priv->dev_up_gfmux) { + iowrite32(0x0, clk_muxsel); + muxsel = ioread32(clk_muxsel); + trace_printk("%s: muxsel value after disable: %d\n", + __func__, muxsel); + } + } + } + if (priv->clk[clk_id + NPL_CLK_OFFSET]) + clk_disable_unprepare( + priv->clk[clk_id + NPL_CLK_OFFSET]); + clk_disable_unprepare(priv->clk[clk_id]); + + if (clk_id != VA_CORE_CLK) { + if (!ret) + lpass_cdc_clk_rsc_mux0_clk_request(priv, + default_clk_id, false); + } + } + } + return ret; + +err_npl_clk: + clk_disable_unprepare(priv->clk[clk_id]); + +err_clk: + if (clk_id != VA_CORE_CLK) + lpass_cdc_clk_rsc_mux0_clk_request(priv, default_clk_id, false); +done: + return ret; +} + +static int lpass_cdc_clk_rsc_check_and_update_va_clk(struct lpass_cdc_clk_rsc *priv, + bool mux_switch, + int clk_id, + bool enable) +{ + int ret = 0; + + if (enable) { + if (clk_id == VA_CORE_CLK && mux_switch) { + /* + * Handle the following usecase scenarios during enable + * 1. VA only, Active clk is VA_CORE_CLK + * 2. record -> record + VA, Active clk is TX_CORE_CLK + */ + if (priv->clk_cnt[TX_CORE_CLK] == 0) { + ret = lpass_cdc_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, enable); + if (ret < 0) + goto err; + } else { + ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, enable); + if (ret < 0) + goto err; + priv->va_tx_clk_cnt++; + } + } else if ((priv->clk_cnt[TX_CORE_CLK] > 0) && + (priv->clk_cnt[VA_CORE_CLK] > 0)) { + /* + * Handle following concurrency scenario during enable + * 1. VA-> Record+VA, Increment TX CLK and Disable VA + * 2. VA-> Playback+VA, Increment TX CLK and Disable VA + */ + while (priv->clk_cnt[VA_CORE_CLK] > 0) { + ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, true); + if (ret < 0) + goto err; + + lpass_cdc_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, false); + priv->va_tx_clk_cnt++; + } + } + } else { + if (clk_id == VA_CORE_CLK && mux_switch) { + /* + * Handle the following usecase scenarios during disable + * 1. VA only, disable VA_CORE_CLK + * 2. Record + VA -> Record, decrement TX CLK count + */ + if (priv->clk_cnt[VA_CORE_CLK]) { + lpass_cdc_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, enable); + } else if (priv->va_tx_clk_cnt) { + lpass_cdc_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, enable); + priv->va_tx_clk_cnt--; + } + } else if (priv->va_tx_clk_cnt == priv->clk_cnt[TX_CORE_CLK]) { + /* + * Handle the following usecase scenarios during disable + * Record+VA-> VA: enable VA CLK, decrement TX CLK count + */ + while (priv->va_tx_clk_cnt) { + ret = lpass_cdc_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, true); + if (ret < 0) + goto err; + + lpass_cdc_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, false); + priv->va_tx_clk_cnt--; + } + } + } + +err: + return ret; +} + +/** + * lpass_cdc_clk_rsc_fs_gen_request - request to enable/disable fs generation + * sequence + * + * @dev: Macro device pointer + * @enable: enable or disable flag + */ +void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev, bool enable) +{ + int i; + struct regmap *regmap; + struct device *clk_dev = NULL; + struct lpass_cdc_clk_rsc *priv = NULL; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return; + } + clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return; + } + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk priviate data\n", __func__); + return; + } + regmap = dev_get_regmap(priv->dev->parent, NULL); + if (!regmap) { + pr_err("%s: regmap is null\n", __func__); + return; + } + mutex_lock(&priv->fs_gen_lock); + if (enable) { + if (priv->reg_seq_en_cnt++ == 0) { + for (i = 0; i < (priv->num_fs_reg * 2); i += 2) { + dev_dbg(priv->dev, "%s: Register: %d, value: %d\n", + __func__, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1]); + regmap_update_bits(regmap, + priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1], + priv->fs_gen_seq[i + 1]); + } + } + } else { + if (priv->reg_seq_en_cnt <= 0) { + dev_err_ratelimited(priv->dev, "%s: req_seq_cnt: %d is already disabled\n", + __func__, priv->reg_seq_en_cnt); + priv->reg_seq_en_cnt = 0; + mutex_unlock(&priv->fs_gen_lock); + return; + } + if (--priv->reg_seq_en_cnt == 0) { + for (i = ((priv->num_fs_reg - 1) * 2); i >= 0; i -= 2) { + dev_dbg(priv->dev, "%s: Register: %d, value: %d\n", + __func__, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1]); + regmap_update_bits(regmap, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1], 0x0); + } + } + } + mutex_unlock(&priv->fs_gen_lock); +} +EXPORT_SYMBOL(lpass_cdc_clk_rsc_fs_gen_request); + +/** + * lpass_cdc_clk_rsc_request_clock - request for clock to + * enable/disable + * + * @dev: Macro device pointer. + * @default_clk_id: mux0 Core clock ID input. + * @clk_id_req: Core clock ID requested to enable/disable + * @enable: enable or disable clock flag + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable) +{ + int ret = 0; + struct device *clk_dev = NULL; + struct lpass_cdc_clk_rsc *priv = NULL; + bool mux_switch = false; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return -EINVAL; + } + if ((clk_id_req < 0 || clk_id_req >= MAX_CLK) && + (default_clk_id < 0 || default_clk_id >= MAX_CLK)) { + pr_err("%s: Invalid clk_id_req: %d or default_clk_id: %d\n", + __func__, clk_id_req, default_clk_id); + return -EINVAL; + } + clk_dev = lpass_cdc_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return -EINVAL; + } + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk priviate data\n", __func__); + return -EINVAL; + } + + mutex_lock(&priv->rsc_clk_lock); + if (!priv->dev_up && enable) { + dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n", + __func__); + trace_printk("%s: SSR is in progress..\n", __func__); + ret = -EINVAL; + goto err; + } + priv->default_clk_id[clk_id_req] = default_clk_id; + if (default_clk_id != clk_id_req) + mux_switch = true; + + if (mux_switch) { + if (clk_id_req != VA_CORE_CLK) { + ret = lpass_cdc_clk_rsc_mux1_clk_request(priv, clk_id_req, + enable); + if (ret < 0) + goto err; + } + } else { + ret = lpass_cdc_clk_rsc_mux0_clk_request(priv, clk_id_req, enable); + if (ret < 0) + goto err; + } + + ret = lpass_cdc_clk_rsc_check_and_update_va_clk(priv, mux_switch, + clk_id_req, + enable); + if (ret < 0) + goto err; + + dev_dbg(priv->dev, "%s: clk_cnt: %d for requested clk: %d, enable: %d\n", + __func__, priv->clk_cnt[clk_id_req], clk_id_req, + enable); + trace_printk("%s: clk_cnt: %d for requested clk: %d, enable: %d\n", + __func__, priv->clk_cnt[clk_id_req], clk_id_req, + enable); + + mutex_unlock(&priv->rsc_clk_lock); + + return 0; + +err: + mutex_unlock(&priv->rsc_clk_lock); + return ret; +} +EXPORT_SYMBOL(lpass_cdc_clk_rsc_request_clock); + + +static int lpass_cdc_clk_rsc_probe(struct platform_device *pdev) +{ + int ret = 0, fs_gen_size, i, j; + const char **clk_name_array; + int clk_cnt; + struct clk *clk; + struct lpass_cdc_clk_rsc *priv = NULL; + u32 muxsel = 0; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_clk_rsc), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Get clk fs gen sequence from device tree */ + if (!of_find_property(pdev->dev.of_node, "qcom,fs-gen-sequence", + &fs_gen_size)) { + dev_err(&pdev->dev, "%s: unable to find qcom,fs-gen-sequence property\n", + __func__); + ret = -EINVAL; + goto err; + } + priv->num_fs_reg = fs_gen_size/(2 * sizeof(u32)); + priv->fs_gen_seq = devm_kzalloc(&pdev->dev, fs_gen_size, GFP_KERNEL); + if (!priv->fs_gen_seq) { + ret = -ENOMEM; + goto err; + } + dev_dbg(&pdev->dev, "%s: num_fs_reg %d\n", __func__, priv->num_fs_reg); + /* Parse fs-gen-sequence */ + ret = of_property_read_u32_array(pdev->dev.of_node, + "qcom,fs-gen-sequence", + priv->fs_gen_seq, + priv->num_fs_reg * 2); + if (ret < 0) { + dev_err(&pdev->dev, "%s: unable to parse fs-gen-sequence, ret = %d\n", + __func__, ret); + goto err; + } + + /* Get clk details from device tree */ + clk_cnt = of_property_count_strings(pdev->dev.of_node, "clock-names"); + if (clk_cnt <= 0 || clk_cnt > MAX_CLK) { + dev_err(&pdev->dev, "%s: Invalid number of clocks %d", + __func__, clk_cnt); + ret = -EINVAL; + goto err; + } + clk_name_array = devm_kzalloc(&pdev->dev, clk_cnt * sizeof(char *), + GFP_KERNEL); + if (!clk_name_array) { + ret = -ENOMEM; + goto err; + } + + ret = of_property_read_string_array(pdev->dev.of_node, "clock-names", + clk_name_array, clk_cnt); + + for (i = 0; i < MAX_CLK; i++) { + priv->clk[i] = NULL; + for (j = 0; j < clk_cnt; j++) { + if (!strcmp(clk_src_name[i], clk_name_array[j])) { + clk = devm_clk_get(&pdev->dev, clk_src_name[i]); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + dev_err(&pdev->dev, "%s: clk get failed for %s with ret %d\n", + __func__, clk_src_name[i], ret); + goto err; + } + priv->clk[i] = clk; + dev_dbg(&pdev->dev, "%s: clk get success for clk name %s\n", + __func__, clk_src_name[i]); + } + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,rx_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,rx_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->rx_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->rx_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for rx muxsel\n", + __func__); + return -ENOMEM; + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wsa_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,wsa_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->wsa_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->wsa_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for wsa muxsel\n", + __func__); + return -ENOMEM; + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,va_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,va_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->va_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->va_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for va muxsel\n", + __func__); + return -ENOMEM; + } + } + + ret = lpass_cdc_register_res_clk(&pdev->dev, lpass_cdc_clk_rsc_cb); + if (ret < 0) { + dev_err(&pdev->dev, "%s: Failed to register cb %d", + __func__, ret); + goto err; + } + priv->dev = &pdev->dev; + priv->dev_up = true; + priv->dev_up_gfmux = true; + mutex_init(&priv->rsc_clk_lock); + mutex_init(&priv->fs_gen_lock); + dev_set_drvdata(&pdev->dev, priv); + +err: + return ret; +} + +static int lpass_cdc_clk_rsc_remove(struct platform_device *pdev) +{ + struct lpass_cdc_clk_rsc *priv = dev_get_drvdata(&pdev->dev); + + lpass_cdc_unregister_res_clk(&pdev->dev); + of_platform_depopulate(&pdev->dev); + if (!priv) + return -EINVAL; + mutex_destroy(&priv->rsc_clk_lock); + mutex_destroy(&priv->fs_gen_lock); + + return 0; +} + +static const struct of_device_id lpass_cdc_clk_rsc_dt_match[] = { + {.compatible = "qcom,lpass-cdc-clk-rsc-mngr"}, + {} +}; +MODULE_DEVICE_TABLE(of, lpass_cdc_clk_rsc_dt_match); + +static struct platform_driver lpass_cdc_clk_rsc_mgr = { + .driver = { + .name = "lpass-cdc-clk-rsc-mngr", + .owner = THIS_MODULE, + .of_match_table = lpass_cdc_clk_rsc_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_clk_rsc_probe, + .remove = lpass_cdc_clk_rsc_remove, +}; + +int lpass_cdc_clk_rsc_mgr_init(void) +{ + return platform_driver_register(&lpass_cdc_clk_rsc_mgr); +} + +void lpass_cdc_clk_rsc_mgr_exit(void) +{ + platform_driver_unregister(&lpass_cdc_clk_rsc_mgr); +} +MODULE_DESCRIPTION("LPASS codec clock resource manager driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.h b/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.h new file mode 100644 index 0000000000..08e3e54ad6 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-clk-rsc.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef LPASS_CDC_CLK_RSC_H +#define LPASS_CDC_CLK_RSC_H + +#include +#include + +#if IS_ENABLED(CONFIG_SND_SOC_LPASS_CDC) +int lpass_cdc_clk_rsc_mgr_init(void); +void lpass_cdc_clk_rsc_mgr_exit(void); +void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev, + bool enable); +int lpass_cdc_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable); +int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id); +void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev, bool enable); +#else +static inline void lpass_cdc_clk_rsc_fs_gen_request(struct device *dev, + bool enable) +{ +} +static inline int lpass_cdc_clk_rsc_mgr_init(void) +{ + return 0; +} +static inline void lpass_cdc_clk_rsc_mgr_exit(void) +{ +} +static inline int lpass_cdc_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable) +{ + return 0; +} +static inline int lpass_cdc_rsc_clk_reset(struct device *dev, int clk_id) +{ + return 0; +} +static inline void lpass_cdc_clk_rsc_enable_all_clocks(struct device *dev, + bool enable) +{ + return; +} +#endif /* CONFIG_SND_SOC_LPASS_CDC */ +#endif /* LPASS_CDC_CLK_RSC_H */ diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-registers.h b/asoc/codecs/lpass-cdc/lpass-cdc-registers.h new file mode 100644 index 0000000000..78eb9872a4 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-registers.h @@ -0,0 +1,844 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _LPASS_CDC_REGISTERS_H +#define _LPASS_CDC_REGISTERS_H + +#define TX_START_OFFSET 0x0000 + +#define LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (TX_START_OFFSET + 0x0000) +#define LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (TX_START_OFFSET + 0x0004) +#define LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL (TX_START_OFFSET + 0x0008) +#define LPASS_CDC_TX_TOP_CSR_TOP_CFG0 (TX_START_OFFSET + 0x0080) +#define LPASS_CDC_TX_TOP_CSR_ANC_CFG (TX_START_OFFSET + 0x0084) +#define LPASS_CDC_TX_TOP_CSR_SWR_CTRL (TX_START_OFFSET + 0x0088) +#define LPASS_CDC_TX_TOP_CSR_FREQ_MCLK (TX_START_OFFSET + 0x0090) +#define LPASS_CDC_TX_TOP_CSR_DEBUG_BUS (TX_START_OFFSET + 0x0094) +#define LPASS_CDC_TX_TOP_CSR_DEBUG_EN (TX_START_OFFSET + 0x0098) +#define LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL (TX_START_OFFSET + 0x00A4) +#define LPASS_CDC_TX_TOP_CSR_I2S_CLK (TX_START_OFFSET + 0x00A8) +#define LPASS_CDC_TX_TOP_CSR_I2S_RESET (TX_START_OFFSET + 0x00AC) +#define LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL (TX_START_OFFSET + 0x00C0) +#define LPASS_CDC_TX_TOP_CSR_SWR_DMIC1_CTL (TX_START_OFFSET + 0x00C4) +#define LPASS_CDC_TX_TOP_CSR_SWR_DMIC2_CTL (TX_START_OFFSET + 0x00C8) +#define LPASS_CDC_TX_TOP_CSR_SWR_DMIC3_CTL (TX_START_OFFSET + 0x00CC) +#define LPASS_CDC_TX_TOP_CSR_SWR_AMIC0_CTL (TX_START_OFFSET + 0x00D0) +#define LPASS_CDC_TX_TOP_CSR_SWR_AMIC1_CTL (TX_START_OFFSET + 0x00D4) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL (TX_START_OFFSET + 0x00C0) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL (TX_START_OFFSET + 0x00C4) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL (TX_START_OFFSET + 0x00C8) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL (TX_START_OFFSET + 0x00CC) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL (TX_START_OFFSET + 0x00D0) +#define LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL (TX_START_OFFSET + 0x00D4) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0 (TX_START_OFFSET + 0x0100) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1 (TX_START_OFFSET + 0x0104) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0 (TX_START_OFFSET + 0x0108) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1 (TX_START_OFFSET + 0x010C) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0 (TX_START_OFFSET + 0x0110) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1 (TX_START_OFFSET + 0x0114) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0 (TX_START_OFFSET + 0x0118) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1 (TX_START_OFFSET + 0x011C) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0 (TX_START_OFFSET + 0x0120) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1 (TX_START_OFFSET + 0x0124) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0 (TX_START_OFFSET + 0x0128) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1 (TX_START_OFFSET + 0x012C) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0 (TX_START_OFFSET + 0x0130) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1 (TX_START_OFFSET + 0x0134) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0 (TX_START_OFFSET + 0x0138) +#define LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1 (TX_START_OFFSET + 0x013C) +#define LPASS_CDC_TX_ANC0_CLK_RESET_CTL (TX_START_OFFSET + 0x0200) +#define LPASS_CDC_TX_ANC0_MODE_1_CTL (TX_START_OFFSET + 0x0204) +#define LPASS_CDC_TX_ANC0_MODE_2_CTL (TX_START_OFFSET + 0x0208) +#define LPASS_CDC_TX_ANC0_FF_SHIFT (TX_START_OFFSET + 0x020C) +#define LPASS_CDC_TX_ANC0_FB_SHIFT (TX_START_OFFSET + 0x0210) +#define LPASS_CDC_TX_ANC0_LPF_FF_A_CTL (TX_START_OFFSET + 0x0214) +#define LPASS_CDC_TX_ANC0_LPF_FF_B_CTL (TX_START_OFFSET + 0x0218) +#define LPASS_CDC_TX_ANC0_LPF_FB_CTL (TX_START_OFFSET + 0x021C) +#define LPASS_CDC_TX_ANC0_SMLPF_CTL (TX_START_OFFSET + 0x0220) +#define LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL (TX_START_OFFSET + 0x0224) +#define LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL (TX_START_OFFSET + 0x0228) +#define LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL (TX_START_OFFSET + 0x022C) +#define LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL (TX_START_OFFSET + 0x0230) +#define LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL (TX_START_OFFSET + 0x0234) +#define LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL (TX_START_OFFSET + 0x0238) +#define LPASS_CDC_TX_ANC0_FB_GAIN_CTL (TX_START_OFFSET + 0x023C) +#define LPASS_CDC_TX0_TX_PATH_CTL (TX_START_OFFSET + 0x0400) +#define LPASS_CDC_TX0_TX_PATH_CFG0 (TX_START_OFFSET + 0x0404) +#define LPASS_CDC_TX0_TX_PATH_CFG1 (TX_START_OFFSET + 0x0408) +#define LPASS_CDC_TX0_TX_VOL_CTL (TX_START_OFFSET + 0x040C) +#define LPASS_CDC_TX0_TX_PATH_SEC0 (TX_START_OFFSET + 0x0410) +#define LPASS_CDC_TX0_TX_PATH_SEC1 (TX_START_OFFSET + 0x0414) +#define LPASS_CDC_TX0_TX_PATH_SEC2 (TX_START_OFFSET + 0x0418) +#define LPASS_CDC_TX0_TX_PATH_SEC3 (TX_START_OFFSET + 0x041C) +#define LPASS_CDC_TX0_TX_PATH_SEC4 (TX_START_OFFSET + 0x0420) +#define LPASS_CDC_TX0_TX_PATH_SEC5 (TX_START_OFFSET + 0x0424) +#define LPASS_CDC_TX0_TX_PATH_SEC6 (TX_START_OFFSET + 0x0428) +#define LPASS_CDC_TX0_TX_PATH_SEC7 (TX_START_OFFSET + 0x042C) +#define LPASS_CDC_TX1_TX_PATH_CTL (TX_START_OFFSET + 0x0480) +#define LPASS_CDC_TX1_TX_PATH_CFG0 (TX_START_OFFSET + 0x0484) +#define LPASS_CDC_TX1_TX_PATH_CFG1 (TX_START_OFFSET + 0x0488) +#define LPASS_CDC_TX1_TX_VOL_CTL (TX_START_OFFSET + 0x048C) +#define LPASS_CDC_TX1_TX_PATH_SEC0 (TX_START_OFFSET + 0x0490) +#define LPASS_CDC_TX1_TX_PATH_SEC1 (TX_START_OFFSET + 0x0494) +#define LPASS_CDC_TX1_TX_PATH_SEC2 (TX_START_OFFSET + 0x0498) +#define LPASS_CDC_TX1_TX_PATH_SEC3 (TX_START_OFFSET + 0x049C) +#define LPASS_CDC_TX1_TX_PATH_SEC4 (TX_START_OFFSET + 0x04A0) +#define LPASS_CDC_TX1_TX_PATH_SEC5 (TX_START_OFFSET + 0x04A4) +#define LPASS_CDC_TX1_TX_PATH_SEC6 (TX_START_OFFSET + 0x04A8) +#define LPASS_CDC_TX2_TX_PATH_CTL (TX_START_OFFSET + 0x0500) +#define LPASS_CDC_TX2_TX_PATH_CFG0 (TX_START_OFFSET + 0x0504) +#define LPASS_CDC_TX2_TX_PATH_CFG1 (TX_START_OFFSET + 0x0508) +#define LPASS_CDC_TX2_TX_VOL_CTL (TX_START_OFFSET + 0x050C) +#define LPASS_CDC_TX2_TX_PATH_SEC0 (TX_START_OFFSET + 0x0510) +#define LPASS_CDC_TX2_TX_PATH_SEC1 (TX_START_OFFSET + 0x0514) +#define LPASS_CDC_TX2_TX_PATH_SEC2 (TX_START_OFFSET + 0x0518) +#define LPASS_CDC_TX2_TX_PATH_SEC3 (TX_START_OFFSET + 0x051C) +#define LPASS_CDC_TX2_TX_PATH_SEC4 (TX_START_OFFSET + 0x0520) +#define LPASS_CDC_TX2_TX_PATH_SEC5 (TX_START_OFFSET + 0x0524) +#define LPASS_CDC_TX2_TX_PATH_SEC6 (TX_START_OFFSET + 0x0528) +#define LPASS_CDC_TX3_TX_PATH_CTL (TX_START_OFFSET + 0x0580) +#define LPASS_CDC_TX3_TX_PATH_CFG0 (TX_START_OFFSET + 0x0584) +#define LPASS_CDC_TX3_TX_PATH_CFG1 (TX_START_OFFSET + 0x0588) +#define LPASS_CDC_TX3_TX_VOL_CTL (TX_START_OFFSET + 0x058C) +#define LPASS_CDC_TX3_TX_PATH_SEC0 (TX_START_OFFSET + 0x0590) +#define LPASS_CDC_TX3_TX_PATH_SEC1 (TX_START_OFFSET + 0x0594) +#define LPASS_CDC_TX3_TX_PATH_SEC2 (TX_START_OFFSET + 0x0598) +#define LPASS_CDC_TX3_TX_PATH_SEC3 (TX_START_OFFSET + 0x059C) +#define LPASS_CDC_TX3_TX_PATH_SEC4 (TX_START_OFFSET + 0x05A0) +#define LPASS_CDC_TX3_TX_PATH_SEC5 (TX_START_OFFSET + 0x05A4) +#define LPASS_CDC_TX3_TX_PATH_SEC6 (TX_START_OFFSET + 0x05A8) +#define LPASS_CDC_TX4_TX_PATH_CTL (TX_START_OFFSET + 0x0600) +#define LPASS_CDC_TX4_TX_PATH_CFG0 (TX_START_OFFSET + 0x0604) +#define LPASS_CDC_TX4_TX_PATH_CFG1 (TX_START_OFFSET + 0x0608) +#define LPASS_CDC_TX4_TX_VOL_CTL (TX_START_OFFSET + 0x060C) +#define LPASS_CDC_TX4_TX_PATH_SEC0 (TX_START_OFFSET + 0x0610) +#define LPASS_CDC_TX4_TX_PATH_SEC1 (TX_START_OFFSET + 0x0614) +#define LPASS_CDC_TX4_TX_PATH_SEC2 (TX_START_OFFSET + 0x0618) +#define LPASS_CDC_TX4_TX_PATH_SEC3 (TX_START_OFFSET + 0x061C) +#define LPASS_CDC_TX4_TX_PATH_SEC4 (TX_START_OFFSET + 0x0620) +#define LPASS_CDC_TX4_TX_PATH_SEC5 (TX_START_OFFSET + 0x0624) +#define LPASS_CDC_TX4_TX_PATH_SEC6 (TX_START_OFFSET + 0x0628) +#define LPASS_CDC_TX5_TX_PATH_CTL (TX_START_OFFSET + 0x0680) +#define LPASS_CDC_TX5_TX_PATH_CFG0 (TX_START_OFFSET + 0x0684) +#define LPASS_CDC_TX5_TX_PATH_CFG1 (TX_START_OFFSET + 0x0688) +#define LPASS_CDC_TX5_TX_VOL_CTL (TX_START_OFFSET + 0x068C) +#define LPASS_CDC_TX5_TX_PATH_SEC0 (TX_START_OFFSET + 0x0690) +#define LPASS_CDC_TX5_TX_PATH_SEC1 (TX_START_OFFSET + 0x0694) +#define LPASS_CDC_TX5_TX_PATH_SEC2 (TX_START_OFFSET + 0x0698) +#define LPASS_CDC_TX5_TX_PATH_SEC3 (TX_START_OFFSET + 0x069C) +#define LPASS_CDC_TX5_TX_PATH_SEC4 (TX_START_OFFSET + 0x06A0) +#define LPASS_CDC_TX5_TX_PATH_SEC5 (TX_START_OFFSET + 0x06A4) +#define LPASS_CDC_TX5_TX_PATH_SEC6 (TX_START_OFFSET + 0x06A8) +#define LPASS_CDC_TX6_TX_PATH_CTL (TX_START_OFFSET + 0x0700) +#define LPASS_CDC_TX6_TX_PATH_CFG0 (TX_START_OFFSET + 0x0704) +#define LPASS_CDC_TX6_TX_PATH_CFG1 (TX_START_OFFSET + 0x0708) +#define LPASS_CDC_TX6_TX_VOL_CTL (TX_START_OFFSET + 0x070C) +#define LPASS_CDC_TX6_TX_PATH_SEC0 (TX_START_OFFSET + 0x0710) +#define LPASS_CDC_TX6_TX_PATH_SEC1 (TX_START_OFFSET + 0x0714) +#define LPASS_CDC_TX6_TX_PATH_SEC2 (TX_START_OFFSET + 0x0718) +#define LPASS_CDC_TX6_TX_PATH_SEC3 (TX_START_OFFSET + 0x071C) +#define LPASS_CDC_TX6_TX_PATH_SEC4 (TX_START_OFFSET + 0x0720) +#define LPASS_CDC_TX6_TX_PATH_SEC5 (TX_START_OFFSET + 0x0724) +#define LPASS_CDC_TX6_TX_PATH_SEC6 (TX_START_OFFSET + 0x0728) +#define LPASS_CDC_TX7_TX_PATH_CTL (TX_START_OFFSET + 0x0780) +#define LPASS_CDC_TX7_TX_PATH_CFG0 (TX_START_OFFSET + 0x0784) +#define LPASS_CDC_TX7_TX_PATH_CFG1 (TX_START_OFFSET + 0x0788) +#define LPASS_CDC_TX7_TX_VOL_CTL (TX_START_OFFSET + 0x078C) +#define LPASS_CDC_TX7_TX_PATH_SEC0 (TX_START_OFFSET + 0x0790) +#define LPASS_CDC_TX7_TX_PATH_SEC1 (TX_START_OFFSET + 0x0794) +#define LPASS_CDC_TX7_TX_PATH_SEC2 (TX_START_OFFSET + 0x0798) +#define LPASS_CDC_TX7_TX_PATH_SEC3 (TX_START_OFFSET + 0x079C) +#define LPASS_CDC_TX7_TX_PATH_SEC4 (TX_START_OFFSET + 0x07A0) +#define LPASS_CDC_TX7_TX_PATH_SEC5 (TX_START_OFFSET + 0x07A4) +#define LPASS_CDC_TX7_TX_PATH_SEC6 (TX_START_OFFSET + 0x07A8) +#define TX_MAX_OFFSET (TX_START_OFFSET + 0x07A8) + +#define LPASS_CDC_TX_MACRO_MAX 0x1EB /* 7A8/4 = 1EA + 1 */ + +#define RX_START_OFFSET 0x1000 +#define LPASS_CDC_RX_TOP_TOP_CFG0 (RX_START_OFFSET + 0x0000) +#define LPASS_CDC_RX_TOP_SWR_CTRL (RX_START_OFFSET + 0x0008) +#define LPASS_CDC_RX_TOP_DEBUG (RX_START_OFFSET + 0x000C) +#define LPASS_CDC_RX_TOP_DEBUG_BUS (RX_START_OFFSET + 0x0010) +#define LPASS_CDC_RX_TOP_DEBUG_EN0 (RX_START_OFFSET + 0x0014) +#define LPASS_CDC_RX_TOP_DEBUG_EN1 (RX_START_OFFSET + 0x0018) +#define LPASS_CDC_RX_TOP_DEBUG_EN2 (RX_START_OFFSET + 0x001C) +#define LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB (RX_START_OFFSET + 0x0020) +#define LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB (RX_START_OFFSET + 0x0024) +#define LPASS_CDC_RX_TOP_HPHL_COMP_LUT (RX_START_OFFSET + 0x0028) +#define LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB (RX_START_OFFSET + 0x002C) +#define LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB (RX_START_OFFSET + 0x0030) +#define LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB (RX_START_OFFSET + 0x0034) +#define LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB (RX_START_OFFSET + 0x0038) +#define LPASS_CDC_RX_TOP_HPHR_COMP_LUT (RX_START_OFFSET + 0x003C) +#define LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB (RX_START_OFFSET + 0x0040) +#define LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB (RX_START_OFFSET + 0x0044) +#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0 (RX_START_OFFSET + 0x0070) +#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1 (RX_START_OFFSET + 0x0074) +#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2 (RX_START_OFFSET + 0x0078) +#define LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3 (RX_START_OFFSET + 0x007C) +#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0 (RX_START_OFFSET + 0x0080) +#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1 (RX_START_OFFSET + 0x0084) +#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2 (RX_START_OFFSET + 0x0088) +#define LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3 (RX_START_OFFSET + 0x008C) +#define LPASS_CDC_RX_TOP_RX_I2S_CTL (RX_START_OFFSET + 0x0090) +#define LPASS_CDC_RX_TOP_TX_I2S2_CTL (RX_START_OFFSET + 0x0094) +#define LPASS_CDC_RX_TOP_I2S_CLK (RX_START_OFFSET + 0x0098) +#define LPASS_CDC_RX_TOP_I2S_RESET (RX_START_OFFSET + 0x009C) +#define LPASS_CDC_RX_TOP_I2S_MUX (RX_START_OFFSET + 0x00A0) +#define LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL (RX_START_OFFSET + 0x0100) +#define LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL \ + (RX_START_OFFSET + 0x0104) +#define LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL (RX_START_OFFSET + 0x0108) +#define LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL (RX_START_OFFSET + 0x010C) +#define LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL \ + (RX_START_OFFSET + 0x0110) +#define LPASS_CDC_RX_SOFTCLIP_CRC (RX_START_OFFSET + 0x0140) +#define LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL (RX_START_OFFSET + 0x0144) +#define LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0 (RX_START_OFFSET + 0x0180) +#define LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1 (RX_START_OFFSET + 0x0184) +#define LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0 (RX_START_OFFSET + 0x0188) +#define LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1 (RX_START_OFFSET + 0x018C) +#define LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0 (RX_START_OFFSET + 0x0190) +#define LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1 (RX_START_OFFSET + 0x0194) +#define LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4 (RX_START_OFFSET + 0x0198) +#define LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5 (RX_START_OFFSET + 0x019C) +#define LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0 (RX_START_OFFSET + 0x01A0) +#define LPASS_CDC_RX_CLSH_CRC (RX_START_OFFSET + 0x0200) +#define LPASS_CDC_RX_CLSH_DLY_CTRL (RX_START_OFFSET + 0x0204) +#define LPASS_CDC_RX_CLSH_DECAY_CTRL (RX_START_OFFSET + 0x0208) +#define LPASS_CDC_RX_CLSH_HPH_V_PA (RX_START_OFFSET + 0x020C) +#define LPASS_CDC_RX_CLSH_EAR_V_PA (RX_START_OFFSET + 0x0210) +#define LPASS_CDC_RX_CLSH_HPH_V_HD (RX_START_OFFSET + 0x0214) +#define LPASS_CDC_RX_CLSH_EAR_V_HD (RX_START_OFFSET + 0x0218) +#define LPASS_CDC_RX_CLSH_K1_MSB (RX_START_OFFSET + 0x021C) +#define LPASS_CDC_RX_CLSH_K1_LSB (RX_START_OFFSET + 0x0220) +#define LPASS_CDC_RX_CLSH_K2_MSB (RX_START_OFFSET + 0x0224) +#define LPASS_CDC_RX_CLSH_K2_LSB (RX_START_OFFSET + 0x0228) +#define LPASS_CDC_RX_CLSH_IDLE_CTRL (RX_START_OFFSET + 0x022C) +#define LPASS_CDC_RX_CLSH_IDLE_HPH (RX_START_OFFSET + 0x0230) +#define LPASS_CDC_RX_CLSH_IDLE_EAR (RX_START_OFFSET + 0x0234) +#define LPASS_CDC_RX_CLSH_TEST0 (RX_START_OFFSET + 0x0238) +#define LPASS_CDC_RX_CLSH_TEST1 (RX_START_OFFSET + 0x023C) +#define LPASS_CDC_RX_CLSH_OVR_VREF (RX_START_OFFSET + 0x0240) +#define LPASS_CDC_RX_CLSH_CLSG_CTL (RX_START_OFFSET + 0x0244) +#define LPASS_CDC_RX_CLSH_CLSG_CFG1 (RX_START_OFFSET + 0x0248) +#define LPASS_CDC_RX_CLSH_CLSG_CFG2 (RX_START_OFFSET + 0x024C) +#define LPASS_CDC_RX_BCL_VBAT_PATH_CTL (RX_START_OFFSET + 0x0280) +#define LPASS_CDC_RX_BCL_VBAT_CFG (RX_START_OFFSET + 0x0284) +#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL1 (RX_START_OFFSET + 0x0288) +#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL2 (RX_START_OFFSET + 0x028C) +#define LPASS_CDC_RX_BCL_VBAT_ADC_CAL3 (RX_START_OFFSET + 0x0290) +#define LPASS_CDC_RX_BCL_VBAT_PK_EST1 (RX_START_OFFSET + 0x0294) +#define LPASS_CDC_RX_BCL_VBAT_PK_EST2 (RX_START_OFFSET + 0x0298) +#define LPASS_CDC_RX_BCL_VBAT_PK_EST3 (RX_START_OFFSET + 0x029C) +#define LPASS_CDC_RX_BCL_VBAT_RF_PROC1 (RX_START_OFFSET + 0x02A0) +#define LPASS_CDC_RX_BCL_VBAT_RF_PROC2 (RX_START_OFFSET + 0x02A4) +#define LPASS_CDC_RX_BCL_VBAT_TAC1 (RX_START_OFFSET + 0x02A8) +#define LPASS_CDC_RX_BCL_VBAT_TAC2 (RX_START_OFFSET + 0x02AC) +#define LPASS_CDC_RX_BCL_VBAT_TAC3 (RX_START_OFFSET + 0x02B0) +#define LPASS_CDC_RX_BCL_VBAT_TAC4 (RX_START_OFFSET + 0x02B4) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1 (RX_START_OFFSET + 0x02B8) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2 (RX_START_OFFSET + 0x02BC) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3 (RX_START_OFFSET + 0x02C0) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4 (RX_START_OFFSET + 0x02C4) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5 (RX_START_OFFSET + 0x02C8) +#define LPASS_CDC_RX_BCL_VBAT_DEBUG1 (RX_START_OFFSET + 0x02CC) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON (RX_START_OFFSET + 0x02D0) +#define LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL (RX_START_OFFSET + 0x02D4) +#define LPASS_CDC_RX_BCL_VBAT_BAN (RX_START_OFFSET + 0x02D8) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1 (RX_START_OFFSET + 0x02DC) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2 (RX_START_OFFSET + 0x02E0) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3 (RX_START_OFFSET + 0x02E4) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4 (RX_START_OFFSET + 0x02E8) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5 (RX_START_OFFSET + 0x02EC) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6 (RX_START_OFFSET + 0x02F0) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7 (RX_START_OFFSET + 0x02F4) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8 (RX_START_OFFSET + 0x02F8) +#define LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9 (RX_START_OFFSET + 0x02FC) +#define LPASS_CDC_RX_BCL_VBAT_ATTN1 (RX_START_OFFSET + 0x0300) +#define LPASS_CDC_RX_BCL_VBAT_ATTN2 (RX_START_OFFSET + 0x0304) +#define LPASS_CDC_RX_BCL_VBAT_ATTN3 (RX_START_OFFSET + 0x0308) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1 (RX_START_OFFSET + 0x030C) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2 (RX_START_OFFSET + 0x0310) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1 (RX_START_OFFSET + 0x0314) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2 (RX_START_OFFSET + 0x0318) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3 (RX_START_OFFSET + 0x031C) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4 (RX_START_OFFSET + 0x0320) +#define LPASS_CDC_RX_BCL_VBAT_DECODE_ST (RX_START_OFFSET + 0x0324) +#define LPASS_CDC_RX_INTR_CTRL_CFG (RX_START_OFFSET + 0x0340) +#define LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT (RX_START_OFFSET + 0x0344) +#define LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0 (RX_START_OFFSET + 0x0360) +#define LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0 (RX_START_OFFSET + 0x0368) +#define LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0 (RX_START_OFFSET + 0x0370) +#define LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0 (RX_START_OFFSET + 0x0380) +#define LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0 (RX_START_OFFSET + 0x0388) +#define LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0 (RX_START_OFFSET + 0x0390) +#define LPASS_CDC_RX_INTR_CTRL_LEVEL0 (RX_START_OFFSET + 0x03C0) +#define LPASS_CDC_RX_INTR_CTRL_BYPASS0 (RX_START_OFFSET + 0x03C8) +#define LPASS_CDC_RX_INTR_CTRL_SET0 (RX_START_OFFSET + 0x03D0) +#define LPASS_CDC_RX_RX0_RX_PATH_CTL (RX_START_OFFSET + 0x0400) +#define LPASS_CDC_RX_RX0_RX_PATH_CFG0 (RX_START_OFFSET + 0x0404) +#define LPASS_CDC_RX_RX0_RX_PATH_CFG1 (RX_START_OFFSET + 0x0408) +#define LPASS_CDC_RX_RX0_RX_PATH_CFG2 (RX_START_OFFSET + 0x040C) +#define LPASS_CDC_RX_RX0_RX_PATH_CFG3 (RX_START_OFFSET + 0x0410) +#define LPASS_CDC_RX_RX0_RX_VOL_CTL (RX_START_OFFSET + 0x0414) +#define LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL (RX_START_OFFSET + 0x0418) +#define LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG (RX_START_OFFSET + 0x041C) +#define LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL (RX_START_OFFSET + 0x0420) +#define LPASS_CDC_RX_RX0_RX_PATH_SEC1 (RX_START_OFFSET + 0x0424) +#define LPASS_CDC_RX_RX0_RX_PATH_SEC2 (RX_START_OFFSET + 0x0428) +#define LPASS_CDC_RX_RX0_RX_PATH_SEC3 (RX_START_OFFSET + 0x042C) +#define LPASS_CDC_RX_RX0_RX_PATH_SEC4 (RX_START_OFFSET + 0x0430) +#define LPASS_CDC_RX_RX0_RX_PATH_SEC7 (RX_START_OFFSET + 0x0434) +#define LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0 (RX_START_OFFSET + 0x0438) +#define LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1 (RX_START_OFFSET + 0x043C) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL (RX_START_OFFSET + 0x0440) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1 (RX_START_OFFSET + 0x0444) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2 (RX_START_OFFSET + 0x0448) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3 (RX_START_OFFSET + 0x044C) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4 (RX_START_OFFSET + 0x0450) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5 (RX_START_OFFSET + 0x0454) +#define LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6 (RX_START_OFFSET + 0x0458) +#define LPASS_CDC_RX_RX1_RX_PATH_CTL (RX_START_OFFSET + 0x0480) +#define LPASS_CDC_RX_RX1_RX_PATH_CFG0 (RX_START_OFFSET + 0x0484) +#define LPASS_CDC_RX_RX1_RX_PATH_CFG1 (RX_START_OFFSET + 0x0488) +#define LPASS_CDC_RX_RX1_RX_PATH_CFG2 (RX_START_OFFSET + 0x048C) +#define LPASS_CDC_RX_RX1_RX_PATH_CFG3 (RX_START_OFFSET + 0x0490) +#define LPASS_CDC_RX_RX1_RX_VOL_CTL (RX_START_OFFSET + 0x0494) +#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL (RX_START_OFFSET + 0x0498) +#define LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG (RX_START_OFFSET + 0x049C) +#define LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL (RX_START_OFFSET + 0x04A0) +#define LPASS_CDC_RX_RX1_RX_PATH_SEC1 (RX_START_OFFSET + 0x04A4) +#define LPASS_CDC_RX_RX1_RX_PATH_SEC2 (RX_START_OFFSET + 0x04A8) +#define LPASS_CDC_RX_RX1_RX_PATH_SEC3 (RX_START_OFFSET + 0x04AC) +#define LPASS_CDC_RX_RX1_RX_PATH_SEC4 (RX_START_OFFSET + 0x04B0) +#define LPASS_CDC_RX_RX1_RX_PATH_SEC7 (RX_START_OFFSET + 0x04B4) +#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0 (RX_START_OFFSET + 0x04B8) +#define LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1 (RX_START_OFFSET + 0x04BC) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL (RX_START_OFFSET + 0x04C0) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1 (RX_START_OFFSET + 0x04C4) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2 (RX_START_OFFSET + 0x04C8) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3 (RX_START_OFFSET + 0x04CC) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4 (RX_START_OFFSET + 0x04D0) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5 (RX_START_OFFSET + 0x04D4) +#define LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6 (RX_START_OFFSET + 0x04D8) +#define LPASS_CDC_RX_RX2_RX_PATH_CTL (RX_START_OFFSET + 0x0500) +#define LPASS_CDC_RX_RX2_RX_PATH_CFG0 (RX_START_OFFSET + 0x0504) +#define LPASS_CDC_RX_RX2_RX_PATH_CFG1 (RX_START_OFFSET + 0x0508) +#define LPASS_CDC_RX_RX2_RX_PATH_CFG2 (RX_START_OFFSET + 0x050C) +#define LPASS_CDC_RX_RX2_RX_PATH_CFG3 (RX_START_OFFSET + 0x0510) +#define LPASS_CDC_RX_RX2_RX_VOL_CTL (RX_START_OFFSET + 0x0514) +#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL (RX_START_OFFSET + 0x0518) +#define LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG (RX_START_OFFSET + 0x051C) +#define LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL (RX_START_OFFSET + 0x0520) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC0 (RX_START_OFFSET + 0x0524) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC1 (RX_START_OFFSET + 0x0528) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC2 (RX_START_OFFSET + 0x052C) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC3 (RX_START_OFFSET + 0x0530) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC4 (RX_START_OFFSET + 0x0534) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC5 (RX_START_OFFSET + 0x0538) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC6 (RX_START_OFFSET + 0x053C) +#define LPASS_CDC_RX_RX2_RX_PATH_SEC7 (RX_START_OFFSET + 0x0540) +#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0 (RX_START_OFFSET + 0x0544) +#define LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1 (RX_START_OFFSET + 0x0548) +#define LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL (RX_START_OFFSET + 0x054C) +#define LPASS_CDC_RX_IDLE_DETECT_PATH_CTL (RX_START_OFFSET + 0x0780) +#define LPASS_CDC_RX_IDLE_DETECT_CFG0 (RX_START_OFFSET + 0x0784) +#define LPASS_CDC_RX_IDLE_DETECT_CFG1 (RX_START_OFFSET + 0x0788) +#define LPASS_CDC_RX_IDLE_DETECT_CFG2 (RX_START_OFFSET + 0x078C) +#define LPASS_CDC_RX_IDLE_DETECT_CFG3 (RX_START_OFFSET + 0x0790) +#define LPASS_CDC_RX_COMPANDER0_CTL0 (RX_START_OFFSET + 0x0800) +#define LPASS_CDC_RX_COMPANDER0_CTL1 (RX_START_OFFSET + 0x0804) +#define LPASS_CDC_RX_COMPANDER0_CTL2 (RX_START_OFFSET + 0x0808) +#define LPASS_CDC_RX_COMPANDER0_CTL3 (RX_START_OFFSET + 0x080C) +#define LPASS_CDC_RX_COMPANDER0_CTL4 (RX_START_OFFSET + 0x0810) +#define LPASS_CDC_RX_COMPANDER0_CTL5 (RX_START_OFFSET + 0x0814) +#define LPASS_CDC_RX_COMPANDER0_CTL6 (RX_START_OFFSET + 0x0818) +#define LPASS_CDC_RX_COMPANDER0_CTL7 (RX_START_OFFSET + 0x081C) +#define LPASS_CDC_RX_COMPANDER1_CTL0 (RX_START_OFFSET + 0x0840) +#define LPASS_CDC_RX_COMPANDER1_CTL1 (RX_START_OFFSET + 0x0844) +#define LPASS_CDC_RX_COMPANDER1_CTL2 (RX_START_OFFSET + 0x0848) +#define LPASS_CDC_RX_COMPANDER1_CTL3 (RX_START_OFFSET + 0x084C) +#define LPASS_CDC_RX_COMPANDER1_CTL4 (RX_START_OFFSET + 0x0850) +#define LPASS_CDC_RX_COMPANDER1_CTL5 (RX_START_OFFSET + 0x0854) +#define LPASS_CDC_RX_COMPANDER1_CTL6 (RX_START_OFFSET + 0x0858) +#define LPASS_CDC_RX_COMPANDER1_CTL7 (RX_START_OFFSET + 0x085C) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL \ + (RX_START_OFFSET + 0x0A00) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL \ + (RX_START_OFFSET + 0x0A04) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL \ + (RX_START_OFFSET + 0x0A08) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL \ + (RX_START_OFFSET + 0x0A0C) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL \ + (RX_START_OFFSET + 0x0A10) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL \ + (RX_START_OFFSET + 0x0A14) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL \ + (RX_START_OFFSET + 0x0A18) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL \ + (RX_START_OFFSET + 0x0A1C) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL \ + (RX_START_OFFSET + 0x0A20) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL (RX_START_OFFSET + 0x0A24) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL \ + (RX_START_OFFSET + 0x0A28) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL \ + (RX_START_OFFSET + 0x0A2C) +#define LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL \ + (RX_START_OFFSET + 0x0A30) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL \ + (RX_START_OFFSET + 0x0A80) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL \ + (RX_START_OFFSET + 0x0A84) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL \ + (RX_START_OFFSET + 0x0A88) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL \ + (RX_START_OFFSET + 0x0A8C) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL \ + (RX_START_OFFSET + 0x0A90) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL \ + (RX_START_OFFSET + 0x0A94) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL \ + (RX_START_OFFSET + 0x0A98) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL \ + (RX_START_OFFSET + 0x0A9C) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL \ + (RX_START_OFFSET + 0x0AA0) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL (RX_START_OFFSET + 0x0AA4) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL \ + (RX_START_OFFSET + 0x0AA8) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL \ + (RX_START_OFFSET + 0x0AAC) +#define LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL \ + (RX_START_OFFSET + 0x0AB0) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0 (RX_START_OFFSET + 0x0B00) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1 (RX_START_OFFSET + 0x0B04) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2 (RX_START_OFFSET + 0x0B08) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3 (RX_START_OFFSET + 0x0B0C) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0 (RX_START_OFFSET + 0x0B10) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1 (RX_START_OFFSET + 0x0B14) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2 (RX_START_OFFSET + 0x0B18) +#define LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3 (RX_START_OFFSET + 0x0B1C) +#define LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL \ + (RX_START_OFFSET + 0x0B40) +#define LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1 \ + (RX_START_OFFSET + 0x0B44) +#define LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL \ + (RX_START_OFFSET + 0x0B50) +#define LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1 \ + (RX_START_OFFSET + 0x0B54) +#define LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL \ + (RX_START_OFFSET + 0x0C00) +#define LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 (RX_START_OFFSET + 0x0C04) +#define LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL \ + (RX_START_OFFSET + 0x0C40) +#define LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0 (RX_START_OFFSET + 0x0C44) +#define LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL \ + (RX_START_OFFSET + 0x0C80) +#define LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0 (RX_START_OFFSET + 0x0C84) +#define LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL (RX_START_OFFSET + 0x0D00) +#define LPASS_CDC_RX_EC_ASRC0_CTL0 (RX_START_OFFSET + 0x0D04) +#define LPASS_CDC_RX_EC_ASRC0_CTL1 (RX_START_OFFSET + 0x0D08) +#define LPASS_CDC_RX_EC_ASRC0_FIFO_CTL (RX_START_OFFSET + 0x0D0C) +#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB \ + (RX_START_OFFSET + 0x0D10) +#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB \ + (RX_START_OFFSET + 0x0D14) +#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB \ + (RX_START_OFFSET + 0x0D18) +#define LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB \ + (RX_START_OFFSET + 0x0D1C) +#define LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO (RX_START_OFFSET + 0x0D20) +#define LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL (RX_START_OFFSET + 0x0D40) +#define LPASS_CDC_RX_EC_ASRC1_CTL0 (RX_START_OFFSET + 0x0D44) +#define LPASS_CDC_RX_EC_ASRC1_CTL1 (RX_START_OFFSET + 0x0D48) +#define LPASS_CDC_RX_EC_ASRC1_FIFO_CTL (RX_START_OFFSET + 0x0D4C) +#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB \ + (RX_START_OFFSET + 0x0D50) +#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB \ + (RX_START_OFFSET + 0x0D54) +#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB \ + (RX_START_OFFSET + 0x0D58) +#define LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB \ + (RX_START_OFFSET + 0x0D5C) +#define LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO (RX_START_OFFSET + 0x0D60) +#define LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL (RX_START_OFFSET + 0x0D80) +#define LPASS_CDC_RX_EC_ASRC2_CTL0 (RX_START_OFFSET + 0x0D84) +#define LPASS_CDC_RX_EC_ASRC2_CTL1 (RX_START_OFFSET + 0x0D88) +#define LPASS_CDC_RX_EC_ASRC2_FIFO_CTL (RX_START_OFFSET + 0x0D8C) +#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB \ + (RX_START_OFFSET + 0x0D90) +#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB \ + (RX_START_OFFSET + 0x0D94) +#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB \ + (RX_START_OFFSET + 0x0D98) +#define LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB \ + (RX_START_OFFSET + 0x0D9C) +#define LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO (RX_START_OFFSET + 0x0DA0) +#define LPASS_CDC_RX_DSD0_PATH_CTL (RX_START_OFFSET + 0x0F00) +#define LPASS_CDC_RX_DSD0_CFG0 (RX_START_OFFSET + 0x0F04) +#define LPASS_CDC_RX_DSD0_CFG1 (RX_START_OFFSET + 0x0F08) +#define LPASS_CDC_RX_DSD0_CFG2 (RX_START_OFFSET + 0x0F0C) +#define LPASS_CDC_RX_DSD1_PATH_CTL (RX_START_OFFSET + 0x0F80) +#define LPASS_CDC_RX_DSD1_CFG0 (RX_START_OFFSET + 0x0F84) +#define LPASS_CDC_RX_DSD1_CFG1 (RX_START_OFFSET + 0x0F88) +#define LPASS_CDC_RX_DSD1_CFG2 (RX_START_OFFSET + 0x0F8C) +#define RX_MAX_OFFSET (RX_START_OFFSET + 0x0F8C) + +#define LPASS_CDC_RX_MACRO_MAX 0x3E4 /* F8C/4 = 3E3 + 1 */ + +/* WSA - macro#2 */ +#define WSA_START_OFFSET 0x2000 +#define LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL \ + (WSA_START_OFFSET + 0x0000) +#define LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL \ + (WSA_START_OFFSET + 0x0004) +#define LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL (WSA_START_OFFSET + 0x0008) +#define LPASS_CDC_WSA_TOP_TOP_CFG0 (WSA_START_OFFSET + 0x0080) +#define LPASS_CDC_WSA_TOP_TOP_CFG1 (WSA_START_OFFSET + 0x0084) +#define LPASS_CDC_WSA_TOP_FREQ_MCLK (WSA_START_OFFSET + 0x0088) +#define LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL (WSA_START_OFFSET + 0x008C) +#define LPASS_CDC_WSA_TOP_DEBUG_EN0 (WSA_START_OFFSET + 0x0090) +#define LPASS_CDC_WSA_TOP_DEBUG_EN1 (WSA_START_OFFSET + 0x0094) +#define LPASS_CDC_WSA_TOP_DEBUG_DSM_LB (WSA_START_OFFSET + 0x0098) +#define LPASS_CDC_WSA_TOP_RX_I2S_CTL (WSA_START_OFFSET + 0x009C) +#define LPASS_CDC_WSA_TOP_TX_I2S_CTL (WSA_START_OFFSET + 0x00A0) +#define LPASS_CDC_WSA_TOP_I2S_CLK (WSA_START_OFFSET + 0x00A4) +#define LPASS_CDC_WSA_TOP_I2S_RESET (WSA_START_OFFSET + 0x00A8) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (WSA_START_OFFSET + 0x0100) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (WSA_START_OFFSET + 0x0104) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (WSA_START_OFFSET + 0x0108) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (WSA_START_OFFSET + 0x010C) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (WSA_START_OFFSET + 0x0110) +#define LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0 (WSA_START_OFFSET + 0x0114) +#define LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0 (WSA_START_OFFSET + 0x0118) +/* VBAT registers */ +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL (WSA_START_OFFSET + 0x0180) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG (WSA_START_OFFSET + 0x0184) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1 (WSA_START_OFFSET + 0x0188) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2 (WSA_START_OFFSET + 0x018C) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3 (WSA_START_OFFSET + 0x0190) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1 (WSA_START_OFFSET + 0x0194) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2 (WSA_START_OFFSET + 0x0198) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3 (WSA_START_OFFSET + 0x019C) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1 (WSA_START_OFFSET + 0x01A0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2 (WSA_START_OFFSET + 0x01A4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1 (WSA_START_OFFSET + 0x01A8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2 (WSA_START_OFFSET + 0x01AC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3 (WSA_START_OFFSET + 0x01B0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4 (WSA_START_OFFSET + 0x01B4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1 (WSA_START_OFFSET + 0x01B8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2 (WSA_START_OFFSET + 0x01BC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3 (WSA_START_OFFSET + 0x01C0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4 (WSA_START_OFFSET + 0x01C4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5 (WSA_START_OFFSET + 0x01C8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1 (WSA_START_OFFSET + 0x01CC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON \ + (WSA_START_OFFSET + 0x01D0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL \ + (WSA_START_OFFSET + 0x01D4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN (WSA_START_OFFSET + 0x01D8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1 \ + (WSA_START_OFFSET + 0x01DC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2 \ + (WSA_START_OFFSET + 0x01E0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3 \ + (WSA_START_OFFSET + 0x01E4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4 \ + (WSA_START_OFFSET + 0x01E8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5 \ + (WSA_START_OFFSET + 0x01EC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6 \ + (WSA_START_OFFSET + 0x01F0) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7 \ + (WSA_START_OFFSET + 0x01F4) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8 \ + (WSA_START_OFFSET + 0x01F8) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9 \ + (WSA_START_OFFSET + 0x01FC) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1 (WSA_START_OFFSET + 0x0200) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2 (WSA_START_OFFSET + 0x0204) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3 (WSA_START_OFFSET + 0x0208) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1 \ + (WSA_START_OFFSET + 0x020C) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2 \ + (WSA_START_OFFSET + 0x0210) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1 \ + (WSA_START_OFFSET + 0x0214) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2 \ + (WSA_START_OFFSET + 0x0218) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3 \ + (WSA_START_OFFSET + 0x021C) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4 \ + (WSA_START_OFFSET + 0x0220) +#define LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST (WSA_START_OFFSET + 0x0224) +#define LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL (WSA_START_OFFSET + 0x0244) +#define LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0 (WSA_START_OFFSET + 0x0248) +#define LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL (WSA_START_OFFSET + 0x0264) +#define LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0 (WSA_START_OFFSET + 0x0268) +#define LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL (WSA_START_OFFSET + 0x0284) +#define LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0 (WSA_START_OFFSET + 0x0288) +#define LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL (WSA_START_OFFSET + 0x02A4) +#define LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0 (WSA_START_OFFSET + 0x02A8) +#define LPASS_CDC_WSA_INTR_CTRL_CFG (WSA_START_OFFSET + 0x0340) +#define LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT (WSA_START_OFFSET + 0x0344) +#define LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0 (WSA_START_OFFSET + 0x0360) +#define LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0 (WSA_START_OFFSET + 0x0368) +#define LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0 (WSA_START_OFFSET + 0x0370) +#define LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0 (WSA_START_OFFSET + 0x0380) +#define LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0 (WSA_START_OFFSET + 0x0388) +#define LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0 (WSA_START_OFFSET + 0x0390) +#define LPASS_CDC_WSA_INTR_CTRL_LEVEL0 (WSA_START_OFFSET + 0x03C0) +#define LPASS_CDC_WSA_INTR_CTRL_BYPASS0 (WSA_START_OFFSET + 0x03C8) +#define LPASS_CDC_WSA_INTR_CTRL_SET0 (WSA_START_OFFSET + 0x03D0) +#define LPASS_CDC_WSA_RX0_RX_PATH_CTL (WSA_START_OFFSET + 0x0400) +#define LPASS_CDC_WSA_RX0_RX_PATH_CFG0 (WSA_START_OFFSET + 0x0404) +#define LPASS_CDC_WSA_RX0_RX_PATH_CFG1 (WSA_START_OFFSET + 0x0408) +#define LPASS_CDC_WSA_RX0_RX_PATH_CFG2 (WSA_START_OFFSET + 0x040C) +#define LPASS_CDC_WSA_RX0_RX_PATH_CFG3 (WSA_START_OFFSET + 0x0410) +#define LPASS_CDC_WSA_RX0_RX_VOL_CTL (WSA_START_OFFSET + 0x0414) +#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL (WSA_START_OFFSET + 0x0418) +#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG (WSA_START_OFFSET + 0x041C) +#define LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL (WSA_START_OFFSET + 0x0420) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC0 (WSA_START_OFFSET + 0x0424) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC1 (WSA_START_OFFSET + 0x0428) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC2 (WSA_START_OFFSET + 0x042C) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC3 (WSA_START_OFFSET + 0x0430) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC5 (WSA_START_OFFSET + 0x0438) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC6 (WSA_START_OFFSET + 0x043C) +#define LPASS_CDC_WSA_RX0_RX_PATH_SEC7 (WSA_START_OFFSET + 0x0440) +#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0 (WSA_START_OFFSET + 0x0444) +#define LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1 (WSA_START_OFFSET + 0x0448) +#define LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL (WSA_START_OFFSET + 0x044C) +#define LPASS_CDC_WSA_RX1_RX_PATH_CTL (WSA_START_OFFSET + 0x0480) +#define LPASS_CDC_WSA_RX1_RX_PATH_CFG0 (WSA_START_OFFSET + 0x0484) +#define LPASS_CDC_WSA_RX1_RX_PATH_CFG1 (WSA_START_OFFSET + 0x0488) +#define LPASS_CDC_WSA_RX1_RX_PATH_CFG2 (WSA_START_OFFSET + 0x048C) +#define LPASS_CDC_WSA_RX1_RX_PATH_CFG3 (WSA_START_OFFSET + 0x0490) +#define LPASS_CDC_WSA_RX1_RX_VOL_CTL (WSA_START_OFFSET + 0x0494) +#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL (WSA_START_OFFSET + 0x0498) +#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG (WSA_START_OFFSET + 0x049C) +#define LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL (WSA_START_OFFSET + 0x04A0) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC0 (WSA_START_OFFSET + 0x04A4) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC1 (WSA_START_OFFSET + 0x04A8) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC2 (WSA_START_OFFSET + 0x04AC) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC3 (WSA_START_OFFSET + 0x04B0) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC5 (WSA_START_OFFSET + 0x04B8) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC6 (WSA_START_OFFSET + 0x04BC) +#define LPASS_CDC_WSA_RX1_RX_PATH_SEC7 (WSA_START_OFFSET + 0x04C0) +#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0 (WSA_START_OFFSET + 0x04C4) +#define LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1 (WSA_START_OFFSET + 0x04C8) +#define LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL (WSA_START_OFFSET + 0x04CC) +#define LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL (WSA_START_OFFSET + 0x0500) +#define LPASS_CDC_WSA_BOOST0_BOOST_CTL (WSA_START_OFFSET + 0x0504) +#define LPASS_CDC_WSA_BOOST0_BOOST_CFG1 (WSA_START_OFFSET + 0x0508) +#define LPASS_CDC_WSA_BOOST0_BOOST_CFG2 (WSA_START_OFFSET + 0x050C) +#define LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL (WSA_START_OFFSET + 0x0540) +#define LPASS_CDC_WSA_BOOST1_BOOST_CTL (WSA_START_OFFSET + 0x0544) +#define LPASS_CDC_WSA_BOOST1_BOOST_CFG1 (WSA_START_OFFSET + 0x0548) +#define LPASS_CDC_WSA_BOOST1_BOOST_CFG2 (WSA_START_OFFSET + 0x054C) +#define LPASS_CDC_WSA_COMPANDER0_CTL0 (WSA_START_OFFSET + 0x0580) +#define LPASS_CDC_WSA_COMPANDER0_CTL1 (WSA_START_OFFSET + 0x0584) +#define LPASS_CDC_WSA_COMPANDER0_CTL2 (WSA_START_OFFSET + 0x0588) +#define LPASS_CDC_WSA_COMPANDER0_CTL3 (WSA_START_OFFSET + 0x058C) +#define LPASS_CDC_WSA_COMPANDER0_CTL4 (WSA_START_OFFSET + 0x0590) +#define LPASS_CDC_WSA_COMPANDER0_CTL5 (WSA_START_OFFSET + 0x0594) +#define LPASS_CDC_WSA_COMPANDER0_CTL6 (WSA_START_OFFSET + 0x0598) +#define LPASS_CDC_WSA_COMPANDER0_CTL7 (WSA_START_OFFSET + 0x059C) +#define LPASS_CDC_WSA_COMPANDER1_CTL0 (WSA_START_OFFSET + 0x05C0) +#define LPASS_CDC_WSA_COMPANDER1_CTL1 (WSA_START_OFFSET + 0x05C4) +#define LPASS_CDC_WSA_COMPANDER1_CTL2 (WSA_START_OFFSET + 0x05C8) +#define LPASS_CDC_WSA_COMPANDER1_CTL3 (WSA_START_OFFSET + 0x05CC) +#define LPASS_CDC_WSA_COMPANDER1_CTL4 (WSA_START_OFFSET + 0x05D0) +#define LPASS_CDC_WSA_COMPANDER1_CTL5 (WSA_START_OFFSET + 0x05D4) +#define LPASS_CDC_WSA_COMPANDER1_CTL6 (WSA_START_OFFSET + 0x05D8) +#define LPASS_CDC_WSA_COMPANDER1_CTL7 (WSA_START_OFFSET + 0x05DC) +#define LPASS_CDC_WSA_SOFTCLIP0_CRC (WSA_START_OFFSET + 0x0600) +#define LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (WSA_START_OFFSET + 0x0604) +#define LPASS_CDC_WSA_SOFTCLIP1_CRC (WSA_START_OFFSET + 0x0640) +#define LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (WSA_START_OFFSET + 0x0644) +#define LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL \ + (WSA_START_OFFSET + 0x0680) +#define LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 (WSA_START_OFFSET + 0x0684) +#define LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL \ + (WSA_START_OFFSET + 0x06C0) +#define LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0 (WSA_START_OFFSET + 0x06C4) +#define LPASS_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL (WSA_START_OFFSET + 0x0700) +#define LPASS_CDC_WSA_SPLINE_ASRC0_CTL0 (WSA_START_OFFSET + 0x0704) +#define LPASS_CDC_WSA_SPLINE_ASRC0_CTL1 (WSA_START_OFFSET + 0x0708) +#define LPASS_CDC_WSA_SPLINE_ASRC0_FIFO_CTL (WSA_START_OFFSET + 0x070C) +#define LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB \ + (WSA_START_OFFSET + 0x0710) +#define LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB \ + (WSA_START_OFFSET + 0x0714) +#define LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB \ + (WSA_START_OFFSET + 0x0718) +#define LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB \ + (WSA_START_OFFSET + 0x071C) +#define LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO (WSA_START_OFFSET + 0x0720) +#define LPASS_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL (WSA_START_OFFSET + 0x0740) +#define LPASS_CDC_WSA_SPLINE_ASRC1_CTL0 (WSA_START_OFFSET + 0x0744) +#define LPASS_CDC_WSA_SPLINE_ASRC1_CTL1 (WSA_START_OFFSET + 0x0748) +#define LPASS_CDC_WSA_SPLINE_ASRC1_FIFO_CTL (WSA_START_OFFSET + 0x074C) +#define LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB \ + (WSA_START_OFFSET + 0x0750) +#define LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB \ + (WSA_START_OFFSET + 0x0754) +#define LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB \ + (WSA_START_OFFSET + 0x0758) +#define LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB \ + (WSA_START_OFFSET + 0x075C) +#define LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO (WSA_START_OFFSET + 0x0760) +#define WSA_MAX_OFFSET (WSA_START_OFFSET + 0x0760) + +#define LPASS_CDC_WSA_MACRO_MAX 0x1D9 /* 0x760/4 = 0x1D8 + 1 registers */ + +/* VA macro registers */ +#define VA_START_OFFSET 0x3000 +#define LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL (VA_START_OFFSET + 0x0000) +#define LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL \ + (VA_START_OFFSET + 0x0004) +#define LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL (VA_START_OFFSET + 0x0008) +#define LPASS_CDC_VA_TOP_CSR_TOP_CFG0 (VA_START_OFFSET + 0x0080) +#define LPASS_CDC_VA_TOP_CSR_DMIC0_CTL (VA_START_OFFSET + 0x0084) +#define LPASS_CDC_VA_TOP_CSR_DMIC1_CTL (VA_START_OFFSET + 0x0088) +#define LPASS_CDC_VA_TOP_CSR_DMIC2_CTL (VA_START_OFFSET + 0x008C) +#define LPASS_CDC_VA_TOP_CSR_DMIC3_CTL (VA_START_OFFSET + 0x0090) +#define LPASS_CDC_VA_TOP_CSR_DMIC_CFG (VA_START_OFFSET + 0x0094) +#define LPASS_CDC_VA_TOP_CSR_DEBUG_BUS (VA_START_OFFSET + 0x009C) +#define LPASS_CDC_VA_TOP_CSR_DEBUG_EN (VA_START_OFFSET + 0x00A0) +#define LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL (VA_START_OFFSET + 0x00A4) +#define LPASS_CDC_VA_TOP_CSR_I2S_CLK (VA_START_OFFSET + 0x00A8) +#define LPASS_CDC_VA_TOP_CSR_I2S_RESET (VA_START_OFFSET + 0x00AC) +#define LPASS_CDC_VA_TOP_CSR_CORE_ID_0 (VA_START_OFFSET + 0x00C0) +#define LPASS_CDC_VA_TOP_CSR_CORE_ID_1 (VA_START_OFFSET + 0x00C4) +#define LPASS_CDC_VA_TOP_CSR_CORE_ID_2 (VA_START_OFFSET + 0x00C8) +#define LPASS_CDC_VA_TOP_CSR_CORE_ID_3 (VA_START_OFFSET + 0x00CC) +#define VA_TOP_MAX_OFFSET (VA_START_OFFSET + 0x00CC) + +#define LPASS_CDC_VA_MACRO_TOP_MAX 0x34 /* 0x0CC/4 = 0x33 + 1 = 0x34 */ + +#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0 (VA_START_OFFSET + 0x00D0) +#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1 (VA_START_OFFSET + 0x00D4) +#define LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2 (VA_START_OFFSET + 0x00D8) +#define LPASS_CDC_VA_TOP_CSR_SWR_CTRL (VA_START_OFFSET + 0x00DC) + +#define LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0 (VA_START_OFFSET + 0x0100) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1 (VA_START_OFFSET + 0x0104) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0 (VA_START_OFFSET + 0x0108) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1 (VA_START_OFFSET + 0x010C) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0 (VA_START_OFFSET + 0x0110) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1 (VA_START_OFFSET + 0x0114) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0 (VA_START_OFFSET + 0x0118) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1 (VA_START_OFFSET + 0x011C) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0 (VA_START_OFFSET + 0x0120) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG1 (VA_START_OFFSET + 0x0124) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0 (VA_START_OFFSET + 0x0128) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG1 (VA_START_OFFSET + 0x012C) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0 (VA_START_OFFSET + 0x0130) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG1 (VA_START_OFFSET + 0x0134) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0 (VA_START_OFFSET + 0x0138) +#define LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG1 (VA_START_OFFSET + 0x013C) + +#define LPASS_CDC_VA_TX0_TX_PATH_CTL (VA_START_OFFSET + 0x0400) +#define LPASS_CDC_VA_TX0_TX_PATH_CFG0 (VA_START_OFFSET + 0x0404) +#define LPASS_CDC_VA_TX0_TX_PATH_CFG1 (VA_START_OFFSET + 0x0408) +#define LPASS_CDC_VA_TX0_TX_VOL_CTL (VA_START_OFFSET + 0x040C) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC0 (VA_START_OFFSET + 0x0410) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC1 (VA_START_OFFSET + 0x0414) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC2 (VA_START_OFFSET + 0x0418) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC3 (VA_START_OFFSET + 0x041C) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC4 (VA_START_OFFSET + 0x0420) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC5 (VA_START_OFFSET + 0x0424) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC6 (VA_START_OFFSET + 0x0428) +#define LPASS_CDC_VA_TX0_TX_PATH_SEC7 (VA_START_OFFSET + 0x042C) +#define LPASS_CDC_VA_TX1_TX_PATH_CTL (VA_START_OFFSET + 0x0480) +#define LPASS_CDC_VA_TX1_TX_PATH_CFG0 (VA_START_OFFSET + 0x0484) +#define LPASS_CDC_VA_TX1_TX_PATH_CFG1 (VA_START_OFFSET + 0x0488) +#define LPASS_CDC_VA_TX1_TX_VOL_CTL (VA_START_OFFSET + 0x048C) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC0 (VA_START_OFFSET + 0x0490) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC1 (VA_START_OFFSET + 0x0494) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC2 (VA_START_OFFSET + 0x0498) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC3 (VA_START_OFFSET + 0x049C) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC4 (VA_START_OFFSET + 0x04A0) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC5 (VA_START_OFFSET + 0x04A4) +#define LPASS_CDC_VA_TX1_TX_PATH_SEC6 (VA_START_OFFSET + 0x04A8) +#define LPASS_CDC_VA_TX2_TX_PATH_CTL (VA_START_OFFSET + 0x0500) +#define LPASS_CDC_VA_TX2_TX_PATH_CFG0 (VA_START_OFFSET + 0x0504) +#define LPASS_CDC_VA_TX2_TX_PATH_CFG1 (VA_START_OFFSET + 0x0508) +#define LPASS_CDC_VA_TX2_TX_VOL_CTL (VA_START_OFFSET + 0x050C) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC0 (VA_START_OFFSET + 0x0510) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC1 (VA_START_OFFSET + 0x0514) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC2 (VA_START_OFFSET + 0x0518) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC3 (VA_START_OFFSET + 0x051C) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC4 (VA_START_OFFSET + 0x0520) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC5 (VA_START_OFFSET + 0x0524) +#define LPASS_CDC_VA_TX2_TX_PATH_SEC6 (VA_START_OFFSET + 0x0528) +#define LPASS_CDC_VA_TX3_TX_PATH_CTL (VA_START_OFFSET + 0x0580) +#define LPASS_CDC_VA_TX3_TX_PATH_CFG0 (VA_START_OFFSET + 0x0584) +#define LPASS_CDC_VA_TX3_TX_PATH_CFG1 (VA_START_OFFSET + 0x0588) +#define LPASS_CDC_VA_TX3_TX_VOL_CTL (VA_START_OFFSET + 0x058C) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC0 (VA_START_OFFSET + 0x0590) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC1 (VA_START_OFFSET + 0x0594) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC2 (VA_START_OFFSET + 0x0598) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC3 (VA_START_OFFSET + 0x059C) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC4 (VA_START_OFFSET + 0x05A0) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC5 (VA_START_OFFSET + 0x05A4) +#define LPASS_CDC_VA_TX3_TX_PATH_SEC6 (VA_START_OFFSET + 0x05A8) +#define LPASS_CDC_VA_TX4_TX_PATH_CTL (VA_START_OFFSET + 0x0600) +#define LPASS_CDC_VA_TX4_TX_PATH_CFG0 (VA_START_OFFSET + 0x0604) +#define LPASS_CDC_VA_TX4_TX_PATH_CFG1 (VA_START_OFFSET + 0x0608) +#define LPASS_CDC_VA_TX4_TX_VOL_CTL (VA_START_OFFSET + 0x060C) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC0 (VA_START_OFFSET + 0x0610) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC1 (VA_START_OFFSET + 0x0614) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC2 (VA_START_OFFSET + 0x0618) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC3 (VA_START_OFFSET + 0x061C) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC4 (VA_START_OFFSET + 0x0620) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC5 (VA_START_OFFSET + 0x0624) +#define LPASS_CDC_VA_TX4_TX_PATH_SEC6 (VA_START_OFFSET + 0x0628) +#define LPASS_CDC_VA_TX5_TX_PATH_CTL (VA_START_OFFSET + 0x0680) +#define LPASS_CDC_VA_TX5_TX_PATH_CFG0 (VA_START_OFFSET + 0x0684) +#define LPASS_CDC_VA_TX5_TX_PATH_CFG1 (VA_START_OFFSET + 0x0688) +#define LPASS_CDC_VA_TX5_TX_VOL_CTL (VA_START_OFFSET + 0x068C) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC0 (VA_START_OFFSET + 0x0690) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC1 (VA_START_OFFSET + 0x0694) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC2 (VA_START_OFFSET + 0x0698) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC3 (VA_START_OFFSET + 0x069C) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC4 (VA_START_OFFSET + 0x06A0) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC5 (VA_START_OFFSET + 0x06A4) +#define LPASS_CDC_VA_TX5_TX_PATH_SEC6 (VA_START_OFFSET + 0x06A8) +#define LPASS_CDC_VA_TX6_TX_PATH_CTL (VA_START_OFFSET + 0x0700) +#define LPASS_CDC_VA_TX6_TX_PATH_CFG0 (VA_START_OFFSET + 0x0704) +#define LPASS_CDC_VA_TX6_TX_PATH_CFG1 (VA_START_OFFSET + 0x0708) +#define LPASS_CDC_VA_TX6_TX_VOL_CTL (VA_START_OFFSET + 0x070C) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC0 (VA_START_OFFSET + 0x0710) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC1 (VA_START_OFFSET + 0x0714) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC2 (VA_START_OFFSET + 0x0718) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC3 (VA_START_OFFSET + 0x071C) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC4 (VA_START_OFFSET + 0x0720) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC5 (VA_START_OFFSET + 0x0724) +#define LPASS_CDC_VA_TX6_TX_PATH_SEC6 (VA_START_OFFSET + 0x0728) +#define LPASS_CDC_VA_TX7_TX_PATH_CTL (VA_START_OFFSET + 0x0780) +#define LPASS_CDC_VA_TX7_TX_PATH_CFG0 (VA_START_OFFSET + 0x0784) +#define LPASS_CDC_VA_TX7_TX_PATH_CFG1 (VA_START_OFFSET + 0x0788) +#define LPASS_CDC_VA_TX7_TX_VOL_CTL (VA_START_OFFSET + 0x078C) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC0 (VA_START_OFFSET + 0x0790) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC1 (VA_START_OFFSET + 0x0794) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC2 (VA_START_OFFSET + 0x0798) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC3 (VA_START_OFFSET + 0x079C) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC4 (VA_START_OFFSET + 0x07A0) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC5 (VA_START_OFFSET + 0x07A4) +#define LPASS_CDC_VA_TX7_TX_PATH_SEC6 (VA_START_OFFSET + 0x07A8) +#define VA_MAX_OFFSET (VA_START_OFFSET + 0x07A8) + +#define LPASS_CDC_VA_MACRO_MAX 0x1EB /* 7A8/4 = 1EA + 1 = 1EB */ + +#define LPASS_CDC_MAX_REGISTER VA_MAX_OFFSET + +#define LPASS_CDC_REG(reg) (((reg) & 0x0FFF)/4) + +#endif diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-regmap.c b/asoc/codecs/lpass-cdc/lpass-cdc-regmap.c new file mode 100644 index 0000000000..b7c2f38aa3 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-regmap.c @@ -0,0 +1,873 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "lpass-cdc.h" +#include "internal.h" + +static const struct reg_default lpass_cdc_defaults[] = { + /* TX Macro */ + { LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 }, + { LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 }, + { LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_TOP_CFG0, 0x00}, + { LPASS_CDC_TX_TOP_CSR_ANC_CFG, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_FREQ_MCLK, 0x00}, + { LPASS_CDC_TX_TOP_CSR_DEBUG_BUS, 0x00}, + { LPASS_CDC_TX_TOP_CSR_DEBUG_EN, 0x00}, + { LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C}, + { LPASS_CDC_TX_TOP_CSR_I2S_CLK, 0x00}, + { LPASS_CDC_TX_TOP_CSR_I2S_RESET, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_DMIC1_CTL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_DMIC2_CTL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_DMIC3_CTL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_AMIC0_CTL, 0x00}, + { LPASS_CDC_TX_TOP_CSR_SWR_AMIC1_CTL, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00}, + { LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00}, + { LPASS_CDC_TX_ANC0_CLK_RESET_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_MODE_1_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_MODE_2_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_FF_SHIFT, 0x00}, + { LPASS_CDC_TX_ANC0_FB_SHIFT, 0x00}, + { LPASS_CDC_TX_ANC0_LPF_FF_A_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_LPF_FF_B_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_LPF_FB_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_SMLPF_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00}, + { LPASS_CDC_TX_ANC0_FB_GAIN_CTL, 0x00}, + { LPASS_CDC_TX0_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX0_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX0_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX0_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX0_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX0_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX0_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX0_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX0_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX0_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX0_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX0_TX_PATH_SEC7, 0x25}, + { LPASS_CDC_TX1_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX1_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX1_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX1_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX1_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX1_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX1_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX1_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX1_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX1_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX1_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX2_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX2_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX2_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX2_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX2_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX2_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX2_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX2_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX2_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX2_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX2_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX3_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX3_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX3_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX3_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX3_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX3_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX3_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX3_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX3_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX3_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX3_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX4_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX4_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX4_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX4_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX4_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX4_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX4_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX4_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX4_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX4_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX4_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX5_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX5_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX5_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX5_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX5_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX5_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX5_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX5_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX5_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX5_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX5_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX6_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX6_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX6_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX6_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX6_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX6_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX6_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX6_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX6_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX6_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX6_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_TX7_TX_PATH_CTL, 0x04}, + { LPASS_CDC_TX7_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_TX7_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_TX7_TX_VOL_CTL, 0x00}, + { LPASS_CDC_TX7_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_TX7_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_TX7_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_TX7_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_TX7_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_TX7_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_TX7_TX_PATH_SEC6, 0x00}, + + /* RX Macro */ + { LPASS_CDC_RX_TOP_TOP_CFG0, 0x00}, + { LPASS_CDC_RX_TOP_SWR_CTRL, 0x00}, + { LPASS_CDC_RX_TOP_DEBUG, 0x00}, + { LPASS_CDC_RX_TOP_DEBUG_BUS, 0x00}, + { LPASS_CDC_RX_TOP_DEBUG_EN0, 0x00}, + { LPASS_CDC_RX_TOP_DEBUG_EN1, 0x00}, + { LPASS_CDC_RX_TOP_DEBUG_EN2, 0x00}, + { LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHL_COMP_LUT, 0x00}, + { LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHR_COMP_LUT, 0x00}, + { LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00}, + { LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00}, + { LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11}, + { LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20}, + { LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00}, + { LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00}, + { LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11}, + { LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20}, + { LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00}, + { LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00}, + { LPASS_CDC_RX_TOP_RX_I2S_CTL, 0x0C}, + { LPASS_CDC_RX_TOP_TX_I2S2_CTL, 0x0C}, + { LPASS_CDC_RX_TOP_I2S_CLK, 0x0C}, + { LPASS_CDC_RX_TOP_I2S_RESET, 0x00}, + { LPASS_CDC_RX_TOP_I2S_MUX, 0x00}, + { LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00}, + { LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08}, + { LPASS_CDC_RX_SOFTCLIP_CRC, 0x00}, + { LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38}, + { LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00}, + { LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00}, + { LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00}, + { LPASS_CDC_RX_CLSH_CRC, 0x00}, + { LPASS_CDC_RX_CLSH_DLY_CTRL, 0x03}, + { LPASS_CDC_RX_CLSH_DECAY_CTRL, 0x02}, + { LPASS_CDC_RX_CLSH_HPH_V_PA, 0x1C}, + { LPASS_CDC_RX_CLSH_EAR_V_PA, 0x39}, + { LPASS_CDC_RX_CLSH_HPH_V_HD, 0x0C}, + { LPASS_CDC_RX_CLSH_EAR_V_HD, 0x0C}, + { LPASS_CDC_RX_CLSH_K1_MSB, 0x01}, + { LPASS_CDC_RX_CLSH_K1_LSB, 0x00}, + { LPASS_CDC_RX_CLSH_K2_MSB, 0x00}, + { LPASS_CDC_RX_CLSH_K2_LSB, 0x80}, + { LPASS_CDC_RX_CLSH_IDLE_CTRL, 0x00}, + { LPASS_CDC_RX_CLSH_IDLE_HPH, 0x00}, + { LPASS_CDC_RX_CLSH_IDLE_EAR, 0x00}, + { LPASS_CDC_RX_CLSH_TEST0, 0x07}, + { LPASS_CDC_RX_CLSH_TEST1, 0x00}, + { LPASS_CDC_RX_CLSH_OVR_VREF, 0x00}, + { LPASS_CDC_RX_CLSH_CLSG_CTL, 0x02}, + { LPASS_CDC_RX_CLSH_CLSG_CFG1, 0x9A}, + { LPASS_CDC_RX_CLSH_CLSG_CFG2, 0x10}, + { LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_CFG, 0x10}, + { LPASS_CDC_RX_BCL_VBAT_ADC_CAL1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_ADC_CAL2, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_ADC_CAL3, 0x04}, + { LPASS_CDC_RX_BCL_VBAT_PK_EST1, 0xE0}, + { LPASS_CDC_RX_BCL_VBAT_PK_EST2, 0x01}, + { LPASS_CDC_RX_BCL_VBAT_PK_EST3, 0x40}, + { LPASS_CDC_RX_BCL_VBAT_RF_PROC1, 0x2A}, + { LPASS_CDC_RX_BCL_VBAT_RF_PROC1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_TAC1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_TAC2, 0x18}, + { LPASS_CDC_RX_BCL_VBAT_TAC3, 0x18}, + { LPASS_CDC_RX_BCL_VBAT_TAC4, 0x03}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01}, + { LPASS_CDC_RX_BCL_VBAT_DEBUG1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_BAN, 0x0C}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_ATTN1, 0x04}, + { LPASS_CDC_RX_BCL_VBAT_ATTN2, 0x08}, + { LPASS_CDC_RX_BCL_VBAT_ATTN3, 0x0C}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00}, + { LPASS_CDC_RX_BCL_VBAT_DECODE_ST, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_CFG, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF}, + { LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF}, + { LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_LEVEL0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_BYPASS0, 0x00}, + { LPASS_CDC_RX_INTR_CTRL_SET0, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_CTL, 0x04}, + { LPASS_CDC_RX_RX0_RX_PATH_CFG0, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_CFG1, 0x64}, + { LPASS_CDC_RX_RX0_RX_PATH_CFG2, 0x8F}, + { LPASS_CDC_RX_RX0_RX_PATH_CFG3, 0x00}, + { LPASS_CDC_RX_RX0_RX_VOL_CTL, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04}, + { LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E}, + { LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x08}, + { LPASS_CDC_RX_RX0_RX_PATH_SEC2, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_SEC3, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_SEC4, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_SEC7, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08}, + { LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55}, + { LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55}, + { LPASS_CDC_RX_RX1_RX_PATH_CTL, 0x04}, + { LPASS_CDC_RX_RX1_RX_PATH_CFG0, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_CFG1, 0x64}, + { LPASS_CDC_RX_RX1_RX_PATH_CFG2, 0x8F}, + { LPASS_CDC_RX_RX1_RX_PATH_CFG3, 0x00}, + { LPASS_CDC_RX_RX1_RX_VOL_CTL, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04}, + { LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E}, + { LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x08}, + { LPASS_CDC_RX_RX1_RX_PATH_SEC2, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_SEC3, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_SEC4, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_SEC7, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08}, + { LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55}, + { LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55}, + { LPASS_CDC_RX_RX2_RX_PATH_CTL, 0x04}, + { LPASS_CDC_RX_RX2_RX_PATH_CFG0, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x64}, + { LPASS_CDC_RX_RX2_RX_PATH_CFG2, 0x8F}, + { LPASS_CDC_RX_RX2_RX_PATH_CFG3, 0x00}, + { LPASS_CDC_RX_RX2_RX_VOL_CTL, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04}, + { LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E}, + { LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC0, 0x04}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC1, 0x08}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC2, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC3, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC4, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC5, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC6, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08}, + { LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00}, + { LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00}, + { LPASS_CDC_RX_IDLE_DETECT_PATH_CTL, 0x00}, + { LPASS_CDC_RX_IDLE_DETECT_CFG0, 0x07}, + { LPASS_CDC_RX_IDLE_DETECT_CFG1, 0x3C}, + { LPASS_CDC_RX_IDLE_DETECT_CFG2, 0x00}, + { LPASS_CDC_RX_IDLE_DETECT_CFG3, 0x00}, + { LPASS_CDC_RX_COMPANDER0_CTL0, 0x60}, + { LPASS_CDC_RX_COMPANDER0_CTL1, 0xDB}, + { LPASS_CDC_RX_COMPANDER0_CTL2, 0xFF}, + { LPASS_CDC_RX_COMPANDER0_CTL3, 0x35}, + { LPASS_CDC_RX_COMPANDER0_CTL4, 0xFF}, + { LPASS_CDC_RX_COMPANDER0_CTL5, 0x00}, + { LPASS_CDC_RX_COMPANDER0_CTL6, 0x01}, + { LPASS_CDC_RX_COMPANDER0_CTL7, 0x28}, + { LPASS_CDC_RX_COMPANDER1_CTL0, 0x60}, + { LPASS_CDC_RX_COMPANDER1_CTL1, 0xDB}, + { LPASS_CDC_RX_COMPANDER1_CTL2, 0xFF}, + { LPASS_CDC_RX_COMPANDER1_CTL3, 0x35}, + { LPASS_CDC_RX_COMPANDER1_CTL4, 0xFF}, + { LPASS_CDC_RX_COMPANDER1_CTL5, 0x00}, + { LPASS_CDC_RX_COMPANDER1_CTL6, 0x01}, + { LPASS_CDC_RX_COMPANDER1_CTL7, 0x28}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00}, + { LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00}, + { LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00}, + { LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04}, + { LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00}, + { LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04}, + { LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00}, + { LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00}, + { LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01}, + { LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00}, + { LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01}, + { LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00}, + { LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01}, + { LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_CTL0, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_CTL1, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8}, + { LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_CTL0, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_CTL1, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8}, + { LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_CTL0, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_CTL1, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8}, + { LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00}, + { LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00}, + { LPASS_CDC_RX_DSD0_PATH_CTL, 0x00}, + { LPASS_CDC_RX_DSD0_CFG0, 0x00}, + { LPASS_CDC_RX_DSD0_CFG1, 0x62}, + { LPASS_CDC_RX_DSD0_CFG2, 0x96}, + { LPASS_CDC_RX_DSD1_PATH_CTL, 0x00}, + { LPASS_CDC_RX_DSD1_CFG0, 0x00}, + { LPASS_CDC_RX_DSD1_CFG1, 0x62}, + { LPASS_CDC_RX_DSD1_CFG2, 0x96}, + + /* WSA Macro */ + { LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { LPASS_CDC_WSA_TOP_TOP_CFG0, 0x00}, + { LPASS_CDC_WSA_TOP_TOP_CFG1, 0x00}, + { LPASS_CDC_WSA_TOP_FREQ_MCLK, 0x00}, + { LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL, 0x00}, + { LPASS_CDC_WSA_TOP_DEBUG_EN0, 0x00}, + { LPASS_CDC_WSA_TOP_DEBUG_EN1, 0x00}, + { LPASS_CDC_WSA_TOP_DEBUG_DSM_LB, 0x88}, + { LPASS_CDC_WSA_TOP_RX_I2S_CTL, 0x0C}, + { LPASS_CDC_WSA_TOP_TX_I2S_CTL, 0x0C}, + { LPASS_CDC_WSA_TOP_I2S_CLK, 0x02}, + { LPASS_CDC_WSA_TOP_I2S_RESET, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00}, + { LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x10}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3, 0x04}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1, 0xE0}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2, 0x01}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3, 0x40}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1, 0x2A}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2, 0x18}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3, 0x18}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4, 0x03}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1, 0x01}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4, 0x64}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5, 0x01}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN, 0x0C}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2, 0x77}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3, 0x01}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5, 0x4B}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7, 0x01}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1, 0x04}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2, 0x08}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3, 0x0C}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0xE0}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0x00}, + { LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST, 0x00}, + { LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, + { LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, + { LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, + { LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, + { LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_CFG, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF}, + { LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0, 0xFF}, + { LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_LEVEL0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_BYPASS0, 0x00}, + { LPASS_CDC_WSA_INTR_CTRL_SET0, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_CTL, 0x04}, + { LPASS_CDC_WSA_RX0_RX_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x64}, + { LPASS_CDC_WSA_RX0_RX_PATH_CFG2, 0x8F}, + { LPASS_CDC_WSA_RX0_RX_PATH_CFG3, 0x00}, + { LPASS_CDC_WSA_RX0_RX_VOL_CTL, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL, 0x04}, + { LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x7E}, + { LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC0, 0x04}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC1, 0x08}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC2, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC3, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC5, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC6, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_SEC7, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0, 0x08}, + { LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1, 0x00}, + { LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_CFG0, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_CFG1, 0x64}, + { LPASS_CDC_WSA_RX1_RX_PATH_CFG2, 0x8F}, + { LPASS_CDC_WSA_RX1_RX_PATH_CFG3, 0x00}, + { LPASS_CDC_WSA_RX1_RX_VOL_CTL, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL, 0x04}, + { LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x7E}, + { LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC0, 0x04}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC1, 0x08}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC2, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC3, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC5, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC6, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_SEC7, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0, 0x08}, + { LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1, 0x00}, + { LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL, 0x00}, + { LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL, 0x00}, + { LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0xD0}, + { LPASS_CDC_WSA_BOOST0_BOOST_CFG1, 0x89}, + { LPASS_CDC_WSA_BOOST0_BOOST_CFG2, 0x04}, + { LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL, 0x00}, + { LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0xD0}, + { LPASS_CDC_WSA_BOOST1_BOOST_CFG1, 0x89}, + { LPASS_CDC_WSA_BOOST1_BOOST_CFG2, 0x04}, + { LPASS_CDC_WSA_COMPANDER0_CTL0, 0x60}, + { LPASS_CDC_WSA_COMPANDER0_CTL1, 0xDB}, + { LPASS_CDC_WSA_COMPANDER0_CTL2, 0xFF}, + { LPASS_CDC_WSA_COMPANDER0_CTL3, 0x35}, + { LPASS_CDC_WSA_COMPANDER0_CTL4, 0xFF}, + { LPASS_CDC_WSA_COMPANDER0_CTL5, 0x00}, + { LPASS_CDC_WSA_COMPANDER0_CTL6, 0x01}, + { LPASS_CDC_WSA_COMPANDER0_CTL7, 0x28}, + { LPASS_CDC_WSA_COMPANDER1_CTL0, 0x60}, + { LPASS_CDC_WSA_COMPANDER1_CTL1, 0xDB}, + { LPASS_CDC_WSA_COMPANDER1_CTL2, 0xFF}, + { LPASS_CDC_WSA_COMPANDER1_CTL3, 0x35}, + { LPASS_CDC_WSA_COMPANDER1_CTL4, 0xFF}, + { LPASS_CDC_WSA_COMPANDER1_CTL5, 0x00}, + { LPASS_CDC_WSA_COMPANDER1_CTL6, 0x01}, + { LPASS_CDC_WSA_COMPANDER1_CTL7, 0x28}, + { LPASS_CDC_WSA_SOFTCLIP0_CRC, 0x00}, + { LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, + { LPASS_CDC_WSA_SOFTCLIP1_CRC, 0x00}, + { LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, + { LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00}, + { LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01}, + { LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00}, + { LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0, 0x01}, + { LPASS_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_CTL0, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_CTL1, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_FIFO_CTL, 0xA8}, + { LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_CTL0, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_CTL1, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_FIFO_CTL, 0xA8}, + { LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00}, + { LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO, 0x00}, + + /* VA macro */ + { LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { LPASS_CDC_VA_TOP_CSR_TOP_CFG0, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DMIC0_CTL, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DMIC1_CTL, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DMIC2_CTL, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DMIC3_CTL, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DMIC_CFG, 0x80}, + { LPASS_CDC_VA_TOP_CSR_DEBUG_BUS, 0x00}, + { LPASS_CDC_VA_TOP_CSR_DEBUG_EN, 0x00}, + { LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C}, + { LPASS_CDC_VA_TOP_CSR_I2S_CLK, 0x00}, + { LPASS_CDC_VA_TOP_CSR_I2S_RESET, 0x00}, + { LPASS_CDC_VA_TOP_CSR_CORE_ID_0, 0x00}, + { LPASS_CDC_VA_TOP_CSR_CORE_ID_1, 0x00}, + { LPASS_CDC_VA_TOP_CSR_CORE_ID_2, 0x00}, + { LPASS_CDC_VA_TOP_CSR_CORE_ID_3, 0x00}, + { LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE}, + { LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE}, + { LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE}, + { LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x06}, + + /* VA core */ + { LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG1, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0, 0x00}, + { LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG1, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX0_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX0_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX0_TX_PATH_SEC7, 0x25}, + { LPASS_CDC_VA_TX1_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX1_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX1_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX1_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX1_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX2_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX2_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX2_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX2_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX2_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX3_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX3_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX3_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX3_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX3_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX4_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX4_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX4_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX4_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX4_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX5_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX5_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX5_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX5_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX5_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX6_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX6_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX6_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX6_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX6_TX_PATH_SEC6, 0x00}, + { LPASS_CDC_VA_TX7_TX_PATH_CTL, 0x04}, + { LPASS_CDC_VA_TX7_TX_PATH_CFG0, 0x10}, + { LPASS_CDC_VA_TX7_TX_PATH_CFG1, 0x0B}, + { LPASS_CDC_VA_TX7_TX_VOL_CTL, 0x00}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC0, 0x00}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC1, 0x00}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC2, 0x01}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC3, 0x3C}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC4, 0x20}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC5, 0x00}, + { LPASS_CDC_VA_TX7_TX_PATH_SEC6, 0x00}, +}; + +static bool lpass_cdc_is_readable_register(struct device *dev, + unsigned int reg) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(dev); + u16 reg_offset; + int macro_id; + u8 *reg_tbl = NULL; + + if (!priv) + return false; + + macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation, + reg); + if (macro_id < 0 || !priv->macros_supported[macro_id]) + return false; + + reg_tbl = lpass_cdc_reg_access[macro_id]; + reg_offset = (reg - macro_id_base_offset[macro_id])/4; + + if (reg_tbl) + return (reg_tbl[reg_offset] & RD_REG); + + return false; +} + +static bool lpass_cdc_is_writeable_register(struct device *dev, + unsigned int reg) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(dev); + u16 reg_offset; + int macro_id; + const u8 *reg_tbl = NULL; + + if (!priv) + return false; + + macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation, + reg); + if (macro_id < 0 || !priv->macros_supported[macro_id]) + return false; + + reg_tbl = lpass_cdc_reg_access[macro_id]; + reg_offset = (reg - macro_id_base_offset[macro_id])/4; + + if (reg_tbl) + return (reg_tbl[reg_offset] & WR_REG); + + return false; +} + +static bool lpass_cdc_is_volatile_register(struct device *dev, + unsigned int reg) +{ + /* Update volatile list for rx/tx macros */ + switch (reg) { + case LPASS_CDC_VA_TOP_CSR_CORE_ID_0: + case LPASS_CDC_VA_TOP_CSR_CORE_ID_1: + case LPASS_CDC_VA_TOP_CSR_CORE_ID_2: + case LPASS_CDC_VA_TOP_CSR_CORE_ID_3: + case LPASS_CDC_VA_TOP_CSR_DMIC0_CTL: + case LPASS_CDC_VA_TOP_CSR_DMIC1_CTL: + case LPASS_CDC_VA_TOP_CSR_DMIC2_CTL: + case LPASS_CDC_VA_TOP_CSR_DMIC3_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_DMIC1_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_DMIC2_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_DMIC3_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL: + case LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL: + case LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL: + case LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST: + case LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0: + case LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0: + case LPASS_CDC_WSA_COMPANDER0_CTL6: + case LPASS_CDC_WSA_COMPANDER1_CTL6: + case LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: + case LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: + case LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: + case LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB: + case LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO: + case LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB: + case LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB: + case LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB: + case LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB: + case LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO: + case LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB: + case LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB: + case LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB: + case LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB: + case LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB: + case LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB: + case LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB: + case LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB: + case LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2: + case LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2: + case LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL: + case LPASS_CDC_RX_BCL_VBAT_DECODE_ST: + case LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0: + case LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0: + case LPASS_CDC_RX_COMPANDER0_CTL6: + case LPASS_CDC_RX_COMPANDER1_CTL6: + case LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO: + case LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO: + case LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB: + case LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB: + case LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO: + return true; + } + return false; +} + +const struct regmap_config lpass_cdc_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .reg_stride = 4, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = lpass_cdc_defaults, + .num_reg_defaults = ARRAY_SIZE(lpass_cdc_defaults), + .max_register = LPASS_CDC_MAX_REGISTER, + .writeable_reg = lpass_cdc_is_writeable_register, + .volatile_reg = lpass_cdc_is_volatile_register, + .readable_reg = lpass_cdc_is_readable_register, +}; diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c new file mode 100644 index 0000000000..edba7f0f13 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c @@ -0,0 +1,4302 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "lpass-cdc.h" +#include "lpass-cdc-registers.h" +#include "lpass-cdc-clk-rsc.h" + +#define AUTO_SUSPEND_DELAY 50 /* delay in msec */ +#define LPASS_CDC_RX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_384000) +/* Fractional Rates */ +#define LPASS_CDC_RX_MACRO_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define LPASS_CDC_RX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define LPASS_CDC_RX_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_48000) +#define LPASS_CDC_RX_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define SAMPLING_RATE_44P1KHZ 44100 +#define SAMPLING_RATE_88P2KHZ 88200 +#define SAMPLING_RATE_176P4KHZ 176400 +#define SAMPLING_RATE_352P8KHZ 352800 + +#define LPASS_CDC_RX_MACRO_MAX_OFFSET 0x1000 + +#define LPASS_CDC_RX_MACRO_MAX_DMA_CH_PER_PORT 2 +#define RX_SWR_STRING_LEN 80 +#define LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX 3 + +#define LPASS_CDC_RX_MACRO_INTERP_MUX_NUM_INPUTS 3 +#define LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX 5 + +#define STRING(name) #name +#define LPASS_CDC_RX_MACRO_DAPM_ENUM(name, reg, offset, text) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM(STRING(name), name##_enum) + +#define LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname) + +#define LPASS_CDC_RX_MACRO_DAPM_MUX(name, shift, kctl) \ + SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux) + +#define LPASS_CDC_RX_MACRO_RX_PATH_OFFSET 0x80 +#define LPASS_CDC_RX_MACRO_COMP_OFFSET 0x40 + +#define MAX_IMPED_PARAMS 6 + +#define LPASS_CDC_RX_MACRO_EC_MIX_TX0_MASK 0xf0 +#define LPASS_CDC_RX_MACRO_EC_MIX_TX1_MASK 0x0f +#define LPASS_CDC_RX_MACRO_EC_MIX_TX2_MASK 0x0f + +#define LPASS_CDC_RX_MACRO_GAIN_MAX_VAL 0x28 +#define LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY 0x0 +/* Define macros to increase PA Gain by half */ +#define LPASS_CDC_RX_MACRO_MOD_GAIN (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY + 6) + +#define COMP_MAX_COEFF 25 + +struct wcd_imped_val { + u32 imped_val; + u8 index; +}; + +static const struct wcd_imped_val imped_index[] = { + {4, 0}, + {5, 1}, + {6, 2}, + {7, 3}, + {8, 4}, + {9, 5}, + {10, 6}, + {11, 7}, + {12, 8}, + {13, 9}, +}; + +struct comp_coeff_val { + u8 lsb; + u8 msb; +}; + +enum { + HPH_ULP, + HPH_LOHIFI, + HPH_MODE_MAX, +}; + +static const struct comp_coeff_val + comp_coeff_table [HPH_MODE_MAX][COMP_MAX_COEFF] = { + { + {0x40, 0x00}, + {0x4C, 0x00}, + {0x5A, 0x00}, + {0x6B, 0x00}, + {0x7F, 0x00}, + {0x97, 0x00}, + {0xB3, 0x00}, + {0xD5, 0x00}, + {0xFD, 0x00}, + {0x2D, 0x01}, + {0x66, 0x01}, + {0xA7, 0x01}, + {0xF8, 0x01}, + {0x57, 0x02}, + {0xC7, 0x02}, + {0x4B, 0x03}, + {0xE9, 0x03}, + {0xA3, 0x04}, + {0x7D, 0x05}, + {0x90, 0x06}, + {0xD1, 0x07}, + {0x49, 0x09}, + {0x00, 0x0B}, + {0x01, 0x0D}, + {0x59, 0x0F}, + }, + { + {0x40, 0x00}, + {0x4C, 0x00}, + {0x5A, 0x00}, + {0x6B, 0x00}, + {0x80, 0x00}, + {0x98, 0x00}, + {0xB4, 0x00}, + {0xD5, 0x00}, + {0xFE, 0x00}, + {0x2E, 0x01}, + {0x66, 0x01}, + {0xA9, 0x01}, + {0xF8, 0x01}, + {0x56, 0x02}, + {0xC4, 0x02}, + {0x4F, 0x03}, + {0xF0, 0x03}, + {0xAE, 0x04}, + {0x8B, 0x05}, + {0x8E, 0x06}, + {0xBC, 0x07}, + {0x56, 0x09}, + {0x0F, 0x0B}, + {0x13, 0x0D}, + {0x6F, 0x0F}, + }, +}; + +struct lpass_cdc_rx_macro_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +static const struct lpass_cdc_rx_macro_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = { + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf2}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf2}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf2}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf4}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf4}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf4}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf7}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf7}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf7}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf9}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf9}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf9}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfa}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfa}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfa}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfb}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfb}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfb}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfc}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfc}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfc}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00}, + }, + { + {LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01}, + {LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01}, + }, +}; + +enum { + INTERP_HPHL, + INTERP_HPHR, + INTERP_AUX, + INTERP_MAX +}; + +enum { + LPASS_CDC_RX_MACRO_RX0, + LPASS_CDC_RX_MACRO_RX1, + LPASS_CDC_RX_MACRO_RX2, + LPASS_CDC_RX_MACRO_RX3, + LPASS_CDC_RX_MACRO_RX4, + LPASS_CDC_RX_MACRO_RX5, + LPASS_CDC_RX_MACRO_PORTS_MAX +}; + +enum { + LPASS_CDC_RX_MACRO_COMP1, /* HPH_L */ + LPASS_CDC_RX_MACRO_COMP2, /* HPH_R */ + LPASS_CDC_RX_MACRO_COMP_MAX +}; + +enum { + LPASS_CDC_RX_MACRO_EC0_MUX = 0, + LPASS_CDC_RX_MACRO_EC1_MUX, + LPASS_CDC_RX_MACRO_EC2_MUX, + LPASS_CDC_RX_MACRO_EC_MUX_MAX, +}; + +enum { + INTn_1_INP_SEL_ZERO = 0, + INTn_1_INP_SEL_DEC0, + INTn_1_INP_SEL_DEC1, + INTn_1_INP_SEL_IIR0, + INTn_1_INP_SEL_IIR1, + INTn_1_INP_SEL_RX0, + INTn_1_INP_SEL_RX1, + INTn_1_INP_SEL_RX2, + INTn_1_INP_SEL_RX3, + INTn_1_INP_SEL_RX4, + INTn_1_INP_SEL_RX5, +}; + +enum { + INTn_2_INP_SEL_ZERO = 0, + INTn_2_INP_SEL_RX0, + INTn_2_INP_SEL_RX1, + INTn_2_INP_SEL_RX2, + INTn_2_INP_SEL_RX3, + INTn_2_INP_SEL_RX4, + INTn_2_INP_SEL_RX5, +}; + +enum { + INTERP_MAIN_PATH, + INTERP_MIX_PATH, +}; + +/* Codec supports 2 IIR filters */ +enum { + IIR0 = 0, + IIR1, + IIR_MAX, +}; + +/* Each IIR has 5 Filter Stages */ +enum { + BAND1 = 0, + BAND2, + BAND3, + BAND4, + BAND5, + BAND_MAX, +}; + +struct lpass_cdc_rx_macro_idle_detect_config { + u8 hph_idle_thr; + u8 hph_idle_detect_en; +}; + +struct interp_sample_rate { + int sample_rate; + int rate_val; +}; + +static struct interp_sample_rate sr_val_tbl[] = { + {8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5}, + {192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA}, + {176400, 0xB}, {352800, 0xC}, +}; + +struct lpass_cdc_rx_macro_bcl_pmic_params { + u8 id; + u8 sid; + u8 ppid; +}; + +static int lpass_cdc_rx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); +static int lpass_cdc_rx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot); +static int lpass_cdc_rx_macro_digital_mute(struct snd_soc_dai *dai, int mute); +static int lpass_cdc_rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int lpass_cdc_rx_macro_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int lpass_cdc_rx_macro_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *component, + int event, int interp_idx); + +/* Hold instance to soundwire platform device */ +struct rx_swr_ctrl_data { + struct platform_device *rx_swr_pdev; +}; + +struct rx_swr_ctrl_platform_data { + void *handle; /* holds codec private data */ + int (*read)(void *handle, int reg); + int (*write)(void *handle, int reg, int val); + int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len); + int (*clk)(void *handle, bool enable); + int (*core_vote)(void *handle, bool enable); + int (*handle_irq)(void *handle, + irqreturn_t (*swrm_irq_handler)(int irq, + void *data), + void *swrm_handle, + int action); +}; + +enum { + RX_MACRO_AIF_INVALID = 0, + RX_MACRO_AIF1_PB, + RX_MACRO_AIF2_PB, + RX_MACRO_AIF3_PB, + RX_MACRO_AIF4_PB, + RX_MACRO_AIF_ECHO, + RX_MACRO_AIF5_PB, + RX_MACRO_AIF6_PB, + LPASS_CDC_RX_MACRO_MAX_DAIS, +}; + +enum { + RX_MACRO_AIF1_CAP = 0, + RX_MACRO_AIF2_CAP, + RX_MACRO_AIF3_CAP, + LPASS_CDC_RX_MACRO_MAX_AIF_CAP_DAIS +}; +/* + * @dev: rx macro device pointer + * @comp_enabled: compander enable mixer value set + * @prim_int_users: Users of interpolator + * @rx_mclk_users: RX MCLK users count + * @vi_feed_value: VI sense mask + * @swr_clk_lock: to lock swr master clock operations + * @swr_ctrl_data: SoundWire data structure + * @swr_plat_data: Soundwire platform data + * @lpass_cdc_rx_macro_add_child_devices_work: work for adding child devices + * @rx_swr_gpio_p: used by pinctrl API + * @component: codec handle + */ +struct lpass_cdc_rx_macro_priv { + struct device *dev; + int comp_enabled[LPASS_CDC_RX_MACRO_COMP_MAX]; + /* Main path clock users count */ + int main_clk_users[INTERP_MAX]; + int rx_port_value[LPASS_CDC_RX_MACRO_PORTS_MAX]; + u16 prim_int_users[INTERP_MAX]; + int rx_mclk_users; + int swr_clk_users; + bool dapm_mclk_enable; + bool reset_swr; + int clsh_users; + int rx_mclk_cnt; + bool is_native_on; + bool is_ear_mode_on; + bool dev_up; + bool hph_pwr_mode; + bool hph_hd2_mode; + struct mutex mclk_lock; + struct mutex swr_clk_lock; + struct rx_swr_ctrl_data *swr_ctrl_data; + struct rx_swr_ctrl_platform_data swr_plat_data; + struct work_struct lpass_cdc_rx_macro_add_child_devices_work; + struct device_node *rx_swr_gpio_p; + struct snd_soc_component *component; + unsigned long active_ch_mask[LPASS_CDC_RX_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[LPASS_CDC_RX_MACRO_MAX_DAIS]; + u16 bit_width[LPASS_CDC_RX_MACRO_MAX_DAIS]; + char __iomem *rx_io_base; + char __iomem *rx_mclk_mode_muxsel; + struct lpass_cdc_rx_macro_idle_detect_config idle_det_cfg; + u8 sidetone_coeff_array[IIR_MAX][BAND_MAX] + [LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX * 4]; + + struct platform_device *pdev_child_devices + [LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX]; + int child_count; + int is_softclip_on; + int is_aux_hpf_on; + int softclip_clk_users; + struct lpass_cdc_rx_macro_bcl_pmic_params bcl_pmic_params; + u16 clk_id; + u16 default_clk_id; + int8_t rx0_gain_val; + int8_t rx1_gain_val; +}; + +static struct snd_soc_dai_driver lpass_cdc_rx_macro_dai[]; +static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); + +static const char * const rx_int_mix_mux_text[] = { + "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5" +}; + +static const char * const rx_prim_mix_text[] = { + "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2", + "RX3", "RX4", "RX5" +}; + +static const char * const rx_sidetone_mix_text[] = { + "ZERO", "SRC0", "SRC1", "SRC_SUM" +}; + +static const char * const iir_inp_mux_text[] = { + "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", + "RX0", "RX1", "RX2", "RX3", "RX4", "RX5" +}; + +static const char * const rx_int_dem_inp_mux_text[] = { + "NORMAL_DSM_OUT", "CLSH_DSM_OUT", +}; + +static const char * const rx_int0_1_interp_mux_text[] = { + "ZERO", "RX INT0_1 MIX1", +}; + +static const char * const rx_int1_1_interp_mux_text[] = { + "ZERO", "RX INT1_1 MIX1", +}; + +static const char * const rx_int2_1_interp_mux_text[] = { + "ZERO", "RX INT2_1 MIX1", +}; + +static const char * const rx_int0_2_interp_mux_text[] = { + "ZERO", "RX INT0_2 MUX", +}; + +static const char * const rx_int1_2_interp_mux_text[] = { + "ZERO", "RX INT1_2 MUX", +}; + +static const char * const rx_int2_2_interp_mux_text[] = { + "ZERO", "RX INT2_2 MUX", +}; + +static const char *const lpass_cdc_rx_macro_mux_text[] = { + "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB" +}; + +static const char *const lpass_cdc_rx_macro_ear_mode_text[] = {"OFF", "ON"}; +static const struct soc_enum lpass_cdc_rx_macro_ear_mode_enum = + SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_ear_mode_text); + +static const char *const lpass_cdc_rx_macro_hph_hd2_mode_text[] = {"OFF", "ON"}; +static const struct soc_enum lpass_cdc_rx_macro_hph_hd2_mode_enum = + SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_hph_hd2_mode_text); + +static const char *const lpass_cdc_rx_macro_hph_pwr_mode_text[] = {"ULP", "LOHIFI"}; +static const struct soc_enum lpass_cdc_rx_macro_hph_pwr_mode_enum = + SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_hph_pwr_mode_text); + +static const char * const lpass_cdc_rx_macro_vbat_bcl_gsm_mode_text[] = {"OFF", "ON"}; +static const struct soc_enum lpass_cdc_rx_macro_vbat_bcl_gsm_mode_enum = + SOC_ENUM_SINGLE_EXT(2, lpass_cdc_rx_macro_vbat_bcl_gsm_mode_text); + +static const struct snd_kcontrol_new rx_int2_1_vbat_mix_switch[] = { + SOC_DAPM_SINGLE("RX AUX VBAT Enable", SND_SOC_NOPM, 0, 1, 0) +}; + +static const char * const hph_idle_detect_text[] = {"OFF", "ON"}; + +static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_2, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 0, + rx_int_mix_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_2, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 0, + rx_int_mix_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_2, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 0, + rx_int_mix_mux_text); + + +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 0, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0, 4, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1, 4, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 0, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0, 4, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1, 4, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp0, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 0, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp1, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0, 4, + rx_prim_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_mix_inp2, LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1, 4, + rx_prim_mix_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, + rx_sidetone_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4, + rx_sidetone_mix_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_mix2_inp, LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6, + rx_sidetone_mix_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp0, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp1, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp2, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir0_inp3, LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp0, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp1, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp2, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0, + iir_inp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(iir1_inp3, LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0, + iir_inp_mux_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0, + rx_int0_1_interp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0, + rx_int1_1_interp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0, + rx_int2_1_interp_mux_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0, + rx_int0_2_interp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0, + rx_int1_2_interp_mux_text); +LPASS_CDC_RX_MACRO_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0, + rx_int2_2_interp_mux_text); + +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(rx_int0_dem_inp, LPASS_CDC_RX_RX0_RX_PATH_CFG1, 0, + rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_rx_macro_int_dem_inp_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(rx_int1_dem_inp, LPASS_CDC_RX_RX1_RX_PATH_CFG1, 0, + rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_rx_macro_int_dem_inp_mux_put); + +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx0, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx1, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx2, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx3, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx4, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); +LPASS_CDC_RX_MACRO_DAPM_ENUM_EXT(lpass_cdc_rx_macro_rx5, SND_SOC_NOPM, 0, lpass_cdc_rx_macro_mux_text, + lpass_cdc_rx_macro_mux_get, lpass_cdc_rx_macro_mux_put); + +static const char * const rx_echo_mux_text[] = { + "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2" +}; + +static const struct soc_enum rx_mix_tx2_mux_enum = + SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4, + rx_echo_mux_text); + +static const struct snd_kcontrol_new rx_mix_tx2_mux = + SOC_DAPM_ENUM("RX MIX TX2_MUX Mux", rx_mix_tx2_mux_enum); + +static const struct soc_enum rx_mix_tx1_mux_enum = + SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4, + rx_echo_mux_text); + +static const struct snd_kcontrol_new rx_mix_tx1_mux = + SOC_DAPM_ENUM("RX MIX TX1_MUX Mux", rx_mix_tx1_mux_enum); + +static const struct soc_enum rx_mix_tx0_mux_enum = + SOC_ENUM_SINGLE(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4, + rx_echo_mux_text); + +static const struct snd_kcontrol_new rx_mix_tx0_mux = + SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum); + +static struct snd_soc_dai_ops lpass_cdc_rx_macro_dai_ops = { + .hw_params = lpass_cdc_rx_macro_hw_params, + .get_channel_map = lpass_cdc_rx_macro_get_channel_map, + .digital_mute = lpass_cdc_rx_macro_digital_mute, +}; + +static struct snd_soc_dai_driver lpass_cdc_rx_macro_dai[] = { + { + .name = "rx_macro_rx1", + .id = RX_MACRO_AIF1_PB, + .playback = { + .stream_name = "RX_MACRO_AIF1 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx2", + .id = RX_MACRO_AIF2_PB, + .playback = { + .stream_name = "RX_MACRO_AIF2 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx3", + .id = RX_MACRO_AIF3_PB, + .playback = { + .stream_name = "RX_MACRO_AIF3 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx4", + .id = RX_MACRO_AIF4_PB, + .playback = { + .stream_name = "RX_MACRO_AIF4 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "lpass_cdc_rx_macro_echo", + .id = RX_MACRO_AIF_ECHO, + .capture = { + .stream_name = "RX_AIF_ECHO Capture", + .rates = LPASS_CDC_RX_MACRO_ECHO_RATES, + .formats = LPASS_CDC_RX_MACRO_ECHO_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 3, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx5", + .id = RX_MACRO_AIF5_PB, + .playback = { + .stream_name = "RX_MACRO_AIF5 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx6", + .id = RX_MACRO_AIF6_PB, + .playback = { + .stream_name = "RX_MACRO_AIF6 Playback", + .rates = LPASS_CDC_RX_MACRO_RATES | LPASS_CDC_RX_MACRO_FRAC_RATES, + .formats = LPASS_CDC_RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &lpass_cdc_rx_macro_dai_ops, + }, +}; + +static int get_impedance_index(int imped) +{ + int i = 0; + + if (imped < imped_index[i].imped_val) { + pr_debug("%s, detected impedance is less than %d Ohm\n", + __func__, imped_index[i].imped_val); + i = 0; + goto ret; + } + if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) { + pr_debug("%s, detected impedance is greater than %d Ohm\n", + __func__, + imped_index[ARRAY_SIZE(imped_index) - 1].imped_val); + i = ARRAY_SIZE(imped_index) - 1; + goto ret; + } + for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) { + if (imped >= imped_index[i].imped_val && + imped < imped_index[i + 1].imped_val) + break; + } +ret: + pr_debug("%s: selected impedance index = %d\n", + __func__, imped_index[i].index); + return imped_index[i].index; +} + +/* + * lpass_cdc_rx_macro_wcd_clsh_imped_config - + * This function updates HPHL and HPHR gain settings + * according to the impedance value. + * + * @component: codec pointer handle + * @imped: impedance value of HPHL/R + * @reset: bool variable to reset registers when teardown + */ +static void lpass_cdc_rx_macro_wcd_clsh_imped_config(struct snd_soc_component *component, + int imped, bool reset) +{ + int i; + int index = 0; + int table_size; + + static const struct lpass_cdc_rx_macro_reg_mask_val + (*imped_table_ptr)[MAX_IMPED_PARAMS]; + + table_size = ARRAY_SIZE(imped_table); + imped_table_ptr = imped_table; + /* reset = 1, which means request is to reset the register values */ + if (reset) { + for (i = 0; i < MAX_IMPED_PARAMS; i++) + snd_soc_component_update_bits(component, + imped_table_ptr[index][i].reg, + imped_table_ptr[index][i].mask, 0); + return; + } + index = get_impedance_index(imped); + if (index >= (ARRAY_SIZE(imped_index) - 1)) { + pr_debug("%s, impedance not in range = %d\n", __func__, imped); + return; + } + if (index >= table_size) { + pr_debug("%s, impedance index not in range = %d\n", __func__, + index); + return; + } + for (i = 0; i < MAX_IMPED_PARAMS; i++) + snd_soc_component_update_bits(component, + imped_table_ptr[index][i].reg, + imped_table_ptr[index][i].mask, + imped_table_ptr[index][i].val); +} + +static bool lpass_cdc_rx_macro_get_data(struct snd_soc_component *component, + struct device **rx_dev, + struct lpass_cdc_rx_macro_priv **rx_priv, + const char *func_name) +{ + *rx_dev = lpass_cdc_get_device_ptr(component->dev, RX_MACRO); + + if (!(*rx_dev)) { + dev_err(component->dev, + "%s: null device for macro!\n", func_name); + return false; + } + + *rx_priv = dev_get_drvdata((*rx_dev)); + if (!(*rx_priv)) { + dev_err(component->dev, + "%s: priv is null for macro!\n", func_name); + return false; + } + + if (!(*rx_priv)->component) { + dev_err(component->dev, + "%s: rx_priv component is not initialized!\n", func_name); + return false; + } + + return true; +} + +static int lpass_cdc_rx_macro_set_port_map(struct snd_soc_component *component, + u32 usecase, u32 size, void *data) +{ + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + struct swrm_port_config port_cfg; + int ret = 0; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + memset(&port_cfg, 0, sizeof(port_cfg)); + port_cfg.uc = usecase; + port_cfg.size = size; + port_cfg.params = data; + + if (rx_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + rx_priv->swr_ctrl_data[0].rx_swr_pdev, + SWR_SET_PORT_MAP, &port_cfg); + + return ret; +} + +static int lpass_cdc_rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val = 0; + unsigned short look_ahead_dly_reg = + LPASS_CDC_RX_RX0_RX_PATH_CFG0; + + val = ucontrol->value.enumerated.item[0]; + if (val >= e->items) + return -EINVAL; + + dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__, + widget->name, val); + + if (e->reg == LPASS_CDC_RX_RX0_RX_PATH_CFG1) + look_ahead_dly_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0; + else if (e->reg == LPASS_CDC_RX_RX1_RX_PATH_CFG1) + look_ahead_dly_reg = LPASS_CDC_RX_RX1_RX_PATH_CFG0; + + /* Set Look Ahead Delay */ + snd_soc_component_update_bits(component, look_ahead_dly_reg, + 0x08, (val ? 0x08 : 0x00)); + /* Set DEM INP Select */ + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static int lpass_cdc_rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, + u8 rate_reg_val, + u32 sample_rate) +{ + u8 int_1_mix1_inp = 0; + u32 j = 0, port = 0; + u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0; + u16 int_fs_reg = 0; + u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0; + u8 inp0_sel = 0, inp1_sel = 0, inp2_sel = 0; + struct snd_soc_component *component = dai->component; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id], + LPASS_CDC_RX_MACRO_PORTS_MAX) { + int_1_mix1_inp = port; + if ((int_1_mix1_inp < LPASS_CDC_RX_MACRO_RX0) || + (int_1_mix1_inp > LPASS_CDC_RX_MACRO_PORTS_MAX)) { + pr_err("%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg0 = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0; + + /* + * Loop through all interpolator MUX inputs and find out + * to which interpolator input, the rx port + * is connected + */ + for (j = 0; j < INTERP_MAX; j++) { + int_mux_cfg1 = int_mux_cfg0 + 4; + + int_mux_cfg0_val = snd_soc_component_read32( + component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32( + component, int_mux_cfg1); + inp0_sel = int_mux_cfg0_val & 0x0F; + inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F; + inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F; + if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { + int_fs_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + + 0x80 * j; + pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_1\n", + __func__, dai->id, j); + pr_debug("%s: set INT%u_1 sample rate to %u\n", + __func__, j, sample_rate); + /* sample_rate is in Hz */ + snd_soc_component_update_bits(component, + int_fs_reg, + 0x0F, rate_reg_val); + } + int_mux_cfg0 += 8; + } + } + + return 0; +} + +static int lpass_cdc_rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, + u8 rate_reg_val, + u32 sample_rate) +{ + u8 int_2_inp = 0; + u32 j = 0, port = 0; + u16 int_mux_cfg1 = 0, int_fs_reg = 0; + u8 int_mux_cfg1_val = 0; + struct snd_soc_component *component = dai->component; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + for_each_set_bit(port, &rx_priv->active_ch_mask[dai->id], + LPASS_CDC_RX_MACRO_PORTS_MAX) { + int_2_inp = port; + if ((int_2_inp < LPASS_CDC_RX_MACRO_RX0) || + (int_2_inp > LPASS_CDC_RX_MACRO_PORTS_MAX)) { + pr_err("%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg1 = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1; + for (j = 0; j < INTERP_MAX; j++) { + int_mux_cfg1_val = snd_soc_component_read32( + component, int_mux_cfg1) & + 0x0F; + if (int_mux_cfg1_val == int_2_inp + + INTn_2_INP_SEL_RX0) { + int_fs_reg = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL + + 0x80 * j; + pr_debug("%s: AIF_PB DAI(%d) connected to INT%u_2\n", + __func__, dai->id, j); + pr_debug("%s: set INT%u_2 sample rate to %u\n", + __func__, j, sample_rate); + snd_soc_component_update_bits( + component, int_fs_reg, + 0x0F, rate_reg_val); + } + int_mux_cfg1 += 8; + } + } + return 0; +} + +static bool lpass_cdc_rx_macro_is_fractional_sample_rate(u32 sample_rate) +{ + switch (sample_rate) { + case SAMPLING_RATE_44P1KHZ: + case SAMPLING_RATE_88P2KHZ: + case SAMPLING_RATE_176P4KHZ: + case SAMPLING_RATE_352P8KHZ: + return true; + default: + return false; + } + return false; +} + +static int lpass_cdc_rx_macro_set_interpolator_rate(struct snd_soc_dai *dai, + u32 sample_rate) +{ + struct snd_soc_component *component = dai->component; + int rate_val = 0; + int i = 0, ret = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + + for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) { + if (sample_rate == sr_val_tbl[i].sample_rate) { + rate_val = sr_val_tbl[i].rate_val; + if (lpass_cdc_rx_macro_is_fractional_sample_rate(sample_rate)) + rx_priv->is_native_on = true; + else + rx_priv->is_native_on = false; + break; + } + } + if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) { + dev_err(component->dev, "%s: Unsupported sample rate: %d\n", + __func__, sample_rate); + return -EINVAL; + } + + ret = lpass_cdc_rx_macro_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate); + if (ret) + return ret; + ret = lpass_cdc_rx_macro_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate); + if (ret) + return ret; + + return ret; +} + +static int lpass_cdc_rx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, + "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__, + dai->name, dai->id, params_rate(params), + params_channels(params)); + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = lpass_cdc_rx_macro_set_interpolator_rate(dai, params_rate(params)); + if (ret) { + pr_err("%s: cannot set sample rate: %u\n", + __func__, params_rate(params)); + return ret; + } + rx_priv->bit_width[dai->id] = params_width(params); + break; + case SNDRV_PCM_STREAM_CAPTURE: + default: + break; + } + return 0; +} + +static int lpass_cdc_rx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + unsigned int temp = 0, ch_mask = 0; + u16 val = 0, mask = 0, cnt = 0, i = 0; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + switch (dai->id) { + case RX_MACRO_AIF1_PB: + case RX_MACRO_AIF2_PB: + case RX_MACRO_AIF3_PB: + case RX_MACRO_AIF4_PB: + for_each_set_bit(temp, &rx_priv->active_ch_mask[dai->id], + LPASS_CDC_RX_MACRO_PORTS_MAX) { + ch_mask |= (1 << temp); + if (++i == LPASS_CDC_RX_MACRO_MAX_DMA_CH_PER_PORT) + break; + } + /* + * CDC_DMA_RX_0 port drives RX0/RX1 -- ch_mask 0x1/0x2/0x3 + * CDC_DMA_RX_1 port drives RX2/RX3 -- ch_mask 0x1/0x2/0x3 + * CDC_DMA_RX_2 port drives RX4 -- ch_mask 0x1 + * CDC_DMA_RX_3 port drives RX5 -- ch_mask 0x1 + * AIFn can pair to any CDC_DMA_RX_n port. + * In general, below convention is used:: + * CDC_DMA_RX_0(AIF1)/CDC_DMA_RX_1(AIF2)/ + * CDC_DMA_RX_2(AIF3)/CDC_DMA_RX_3(AIF4) + * Above is reflected in machine driver BE dailink + */ + if (ch_mask & 0x0C) + ch_mask = ch_mask >> 2; + if ((ch_mask & 0x10) || (ch_mask & 0x20)) + ch_mask = 0x1; + *rx_slot = ch_mask; + *rx_num = rx_priv->active_ch_cnt[dai->id]; + dev_dbg(rx_priv->dev, + "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n", + __func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]); + break; + case RX_MACRO_AIF5_PB: + *rx_slot = 0x1; + *rx_num = 0x01; + dev_dbg(rx_priv->dev, + "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n", + __func__, dai->id, *rx_slot, *rx_num); + break; + case RX_MACRO_AIF6_PB: + *rx_slot = 0x1; + *rx_num = 0x01; + dev_dbg(rx_priv->dev, + "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n", + __func__, dai->id, *rx_slot, *rx_num); + break; + case RX_MACRO_AIF_ECHO: + val = snd_soc_component_read32(component, + LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4); + if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX0_MASK) { + mask |= 0x1; + cnt++; + } + if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX1_MASK) { + mask |= 0x2; + cnt++; + } + val = snd_soc_component_read32(component, + LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5); + if (val & LPASS_CDC_RX_MACRO_EC_MIX_TX2_MASK) { + mask |= 0x4; + cnt++; + } + *tx_slot = mask; + *tx_num = cnt; + break; + default: + dev_err(rx_dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static int lpass_cdc_rx_macro_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_component *component = dai->component; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0; + u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0; + u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0; + + if (mute) + return 0; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + switch (dai->id) { + case RX_MACRO_AIF1_PB: + case RX_MACRO_AIF2_PB: + case RX_MACRO_AIF3_PB: + case RX_MACRO_AIF4_PB: + for (j = 0; j < INTERP_MAX; j++) { + reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + + (j * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + mix_reg = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL + + (j * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + dsm_reg = LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL + + (j * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + if (j == INTERP_AUX) + dsm_reg = LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL; + int_mux_cfg0 = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read32(component, + int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32(component, + int_mux_cfg1); + if (snd_soc_component_read32(component, dsm_reg) & 0x01) { + if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0)) + snd_soc_component_update_bits(component, + reg, 0x20, 0x20); + if (int_mux_cfg1_val & 0x0F) { + snd_soc_component_update_bits(component, + reg, 0x20, 0x20); + snd_soc_component_update_bits(component, + mix_reg, 0x20, 0x20); + } + } + } + break; + default: + break; + } + return 0; +} + +static int lpass_cdc_rx_macro_mclk_enable( + struct lpass_cdc_rx_macro_priv *rx_priv, + bool mclk_enable, bool dapm) +{ + struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + dev_dbg(rx_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n", + __func__, mclk_enable, dapm, rx_priv->rx_mclk_users); + + mutex_lock(&rx_priv->mclk_lock); + if (mclk_enable) { + if (rx_priv->rx_mclk_users == 0) { + if (rx_priv->is_native_on) + rx_priv->clk_id = RX_CORE_CLK; + ret = lpass_cdc_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + rx_priv->clk_id, + true); + if (ret < 0) { + dev_err(rx_priv->dev, + "%s: rx request clock enable failed\n", + __func__); + goto exit; + } + lpass_cdc_clk_rsc_fs_gen_request(rx_priv->dev, + true); + regcache_mark_dirty(regmap); + regcache_sync_region(regmap, + RX_START_OFFSET, + RX_MAX_OFFSET); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x02, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x01); + } + rx_priv->rx_mclk_users++; + } else { + if (rx_priv->rx_mclk_users <= 0) { + dev_err(rx_priv->dev, "%s: clock already disabled\n", + __func__); + rx_priv->rx_mclk_users = 0; + goto exit; + } + rx_priv->rx_mclk_users--; + if (rx_priv->rx_mclk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + 0x02, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x00); + lpass_cdc_clk_rsc_fs_gen_request(rx_priv->dev, + false); + lpass_cdc_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + rx_priv->clk_id, + false); + rx_priv->clk_id = rx_priv->default_clk_id; + } + } +exit: + trace_printk("%s: mclk_enable = %u, dapm = %d clk_users= %d\n", + __func__, mclk_enable, dapm, rx_priv->rx_mclk_users); + mutex_unlock(&rx_priv->mclk_lock); + return ret; +} + +static int lpass_cdc_rx_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + int mclk_freq = MCLK_FREQ; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + dev_dbg(rx_dev, "%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (rx_priv->is_native_on) + mclk_freq = MCLK_FREQ_NATIVE; + if (rx_priv->swr_ctrl_data) + swrm_wcd_notify( + rx_priv->swr_ctrl_data[0].rx_swr_pdev, + SWR_CLK_FREQ, &mclk_freq); + ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 1, true); + if (ret) + rx_priv->dapm_mclk_enable = false; + else + rx_priv->dapm_mclk_enable = true; + break; + case SND_SOC_DAPM_POST_PMD: + if (rx_priv->dapm_mclk_enable) + ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 0, true); + break; + default: + dev_err(rx_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_rx_macro_event_handler(struct snd_soc_component *component, + u16 event, u32 data) +{ + u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0, val = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + int ret = 0; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + switch (event) { + case LPASS_CDC_MACRO_EVT_RX_MUTE: + rx_idx = data >> 0x10; + mute = data & 0xffff; + val = mute ? 0x10 : 0x00; + reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + (rx_idx * + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + reg_mix = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL + (rx_idx * + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + snd_soc_component_update_bits(component, reg, + 0x10, val); + snd_soc_component_update_bits(component, reg_mix, + 0x10, val); + break; + case LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST: + rx_idx = data >> 0x10; + if (rx_idx == INTERP_AUX) + goto done; + reg = LPASS_CDC_RX_COMPANDER0_CTL0 + + (rx_idx * LPASS_CDC_RX_MACRO_COMP_OFFSET); + snd_soc_component_write(component, reg, + snd_soc_component_read32(component, reg)); + break; + case LPASS_CDC_MACRO_EVT_IMPED_TRUE: + lpass_cdc_rx_macro_wcd_clsh_imped_config(component, data, true); + break; + case LPASS_CDC_MACRO_EVT_IMPED_FALSE: + lpass_cdc_rx_macro_wcd_clsh_imped_config(component, data, false); + break; + case LPASS_CDC_MACRO_EVT_SSR_DOWN: + trace_printk("%s, enter SSR down\n", __func__); + rx_priv->dev_up = false; + if (rx_priv->swr_ctrl_data) { + swrm_wcd_notify( + rx_priv->swr_ctrl_data[0].rx_swr_pdev, + SWR_DEVICE_SSR_DOWN, NULL); + } + if ((!pm_runtime_enabled(rx_dev) || + !pm_runtime_suspended(rx_dev))) { + ret = lpass_cdc_runtime_suspend(rx_dev); + if (!ret) { + pm_runtime_disable(rx_dev); + pm_runtime_set_suspended(rx_dev); + pm_runtime_enable(rx_dev); + } + } + break; + case LPASS_CDC_MACRO_EVT_PRE_SSR_UP: + /* enable&disable RX_CORE_CLK to reset GFMUX reg */ + ret = lpass_cdc_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + RX_CORE_CLK, true); + if (ret < 0) + dev_err_ratelimited(rx_priv->dev, + "%s, failed to enable clk, ret:%d\n", + __func__, ret); + else + lpass_cdc_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + RX_CORE_CLK, false); + break; + case LPASS_CDC_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + rx_priv->dev_up = true; + /* reset swr after ssr/pdr */ + rx_priv->reset_swr = true; + + if (rx_priv->swr_ctrl_data) + swrm_wcd_notify( + rx_priv->swr_ctrl_data[0].rx_swr_pdev, + SWR_DEVICE_SSR_UP, NULL); + break; + case LPASS_CDC_MACRO_EVT_CLK_RESET: + lpass_cdc_rsc_clk_reset(rx_dev, RX_CORE_CLK); + break; + case LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE: + rx_priv->rx0_gain_val = snd_soc_component_read32(component, + LPASS_CDC_RX_RX0_RX_VOL_CTL); + rx_priv->rx1_gain_val = snd_soc_component_read32(component, + LPASS_CDC_RX_RX1_RX_VOL_CTL); + if (data) { + /* Reduce gain by half only if its greater than -6DB */ + if ((rx_priv->rx0_gain_val >= LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY) + && (rx_priv->rx0_gain_val <= LPASS_CDC_RX_MACRO_GAIN_MAX_VAL)) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xFF, + (rx_priv->rx0_gain_val - + LPASS_CDC_RX_MACRO_MOD_GAIN)); + if ((rx_priv->rx1_gain_val >= LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY) + && (rx_priv->rx1_gain_val <= LPASS_CDC_RX_MACRO_GAIN_MAX_VAL)) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xFF, + (rx_priv->rx1_gain_val - + LPASS_CDC_RX_MACRO_MOD_GAIN)); + } + else { + /* Reset gain value to default */ + if ((rx_priv->rx0_gain_val >= + (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY - LPASS_CDC_RX_MACRO_MOD_GAIN)) && + (rx_priv->rx0_gain_val <= (LPASS_CDC_RX_MACRO_GAIN_MAX_VAL - + LPASS_CDC_RX_MACRO_MOD_GAIN))) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_VOL_CTL, 0xFF, + (rx_priv->rx0_gain_val + + LPASS_CDC_RX_MACRO_MOD_GAIN)); + if ((rx_priv->rx1_gain_val >= + (LPASS_CDC_RX_MACRO_GAIN_VAL_UNITY - LPASS_CDC_RX_MACRO_MOD_GAIN)) && + (rx_priv->rx1_gain_val <= (LPASS_CDC_RX_MACRO_GAIN_MAX_VAL - + LPASS_CDC_RX_MACRO_MOD_GAIN))) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX1_RX_VOL_CTL, 0xFF, + (rx_priv->rx1_gain_val + + LPASS_CDC_RX_MACRO_MOD_GAIN)); + } + break; + case LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE: + /* Enable hd2 config for hphl*/ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_PATH_CFG0, 0x04, data); + break; + case LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE: + /* Enable hd2 config for hphr*/ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX1_RX_PATH_CFG0, 0x04, data); + break; + } +done: + return ret; +} + +static int lpass_cdc_rx_macro_find_playback_dai_id_for_port(int port_id, + struct lpass_cdc_rx_macro_priv *rx_priv) +{ + int i = 0; + + for (i = RX_MACRO_AIF1_PB; i < LPASS_CDC_RX_MACRO_MAX_DAIS; i++) { + if (test_bit(port_id, &rx_priv->active_ch_mask[i])) + return i; + } + + return -EINVAL; +} + +static int lpass_cdc_rx_macro_set_idle_detect_thr(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int interp, int path_type) +{ + int port_id[4] = { 0, 0, 0, 0 }; + int *port_ptr = NULL; + int num_ports = 0; + int bit_width = 0, i = 0; + int mux_reg = 0, mux_reg_val = 0; + int dai_id = 0, idle_thr = 0; + + if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR)) + return 0; + + if (!rx_priv->idle_det_cfg.hph_idle_detect_en) + return 0; + + port_ptr = &port_id[0]; + num_ports = 0; + + /* + * Read interpolator MUX input registers and find + * which cdc_dma port is connected and store the port + * numbers in port_id array. + */ + if (path_type == INTERP_MIX_PATH) { + mux_reg = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1 + + 2 * interp; + mux_reg_val = snd_soc_component_read32(component, mux_reg) & + 0x0f; + + if ((mux_reg_val >= INTn_2_INP_SEL_RX0) && + (mux_reg_val <= INTn_2_INP_SEL_RX5)) { + *port_ptr++ = mux_reg_val - 1; + num_ports++; + } + } + + if (path_type == INTERP_MAIN_PATH) { + mux_reg = LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0 + + 2 * (interp - 1); + mux_reg_val = snd_soc_component_read32(component, mux_reg) & + 0x0f; + i = LPASS_CDC_RX_MACRO_INTERP_MUX_NUM_INPUTS; + + while (i) { + if ((mux_reg_val >= INTn_1_INP_SEL_RX0) && + (mux_reg_val <= INTn_1_INP_SEL_RX5)) { + *port_ptr++ = mux_reg_val - + INTn_1_INP_SEL_RX0; + num_ports++; + } + mux_reg_val = + (snd_soc_component_read32(component, mux_reg) & + 0xf0) >> 4; + mux_reg += 1; + i--; + } + } + + dev_dbg(component->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n", + __func__, num_ports, port_id[0], port_id[1], + port_id[2], port_id[3]); + + i = 0; + while (num_ports) { + dai_id = lpass_cdc_rx_macro_find_playback_dai_id_for_port(port_id[i++], + rx_priv); + + if ((dai_id >= 0) && (dai_id < LPASS_CDC_RX_MACRO_MAX_DAIS)) { + dev_dbg(component->dev, "%s: dai_id: %d bit_width: %d\n", + __func__, dai_id, + rx_priv->bit_width[dai_id]); + + if (rx_priv->bit_width[dai_id] > bit_width) + bit_width = rx_priv->bit_width[dai_id]; + } + num_ports--; + } + + switch (bit_width) { + case 16: + idle_thr = 0xff; /* F16 */ + break; + case 24: + case 32: + idle_thr = 0x03; /* F22 */ + break; + default: + idle_thr = 0x00; + break; + } + + dev_dbg(component->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n", + __func__, idle_thr, rx_priv->idle_det_cfg.hph_idle_thr); + + if ((rx_priv->idle_det_cfg.hph_idle_thr == 0) || + (idle_thr < rx_priv->idle_det_cfg.hph_idle_thr)) { + snd_soc_component_write(component, + LPASS_CDC_RX_IDLE_DETECT_CFG3, idle_thr); + rx_priv->idle_det_cfg.hph_idle_thr = idle_thr; + } + + return 0; +} + +static int lpass_cdc_rx_macro_enable_mix_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 gain_reg = 0, mix_reg = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + if (w->shift >= INTERP_MAX) { + dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n", + __func__, w->shift, w->name); + return -EINVAL; + } + + gain_reg = LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL + + (w->shift * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + mix_reg = LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL + + (w->shift * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + + dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_rx_macro_set_idle_detect_thr(component, rx_priv, w->shift, + INTERP_MIX_PATH); + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_write(component, gain_reg, + snd_soc_component_read32(component, gain_reg)); + break; + case SND_SOC_DAPM_POST_PMD: + /* Clk Disable */ + snd_soc_component_update_bits(component, mix_reg, 0x20, 0x00); + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + /* Reset enable and disable */ + snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40); + snd_soc_component_update_bits(component, mix_reg, 0x40, 0x00); + break; + } + + return 0; +} + +static bool lpass_cdc_rx_macro_adie_lb(struct snd_soc_component *component, + int interp_idx) +{ + u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0; + u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0; + u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0; + + int_mux_cfg0 = LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read32(component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32(component, int_mux_cfg1); + + int_n_inp0 = int_mux_cfg0_val & 0x0F; + if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || + int_n_inp0 == INTn_1_INP_SEL_DEC1 || + int_n_inp0 == INTn_1_INP_SEL_IIR0 || + int_n_inp0 == INTn_1_INP_SEL_IIR1) + return true; + + int_n_inp1 = int_mux_cfg0_val >> 4; + if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || + int_n_inp1 == INTn_1_INP_SEL_DEC1 || + int_n_inp1 == INTn_1_INP_SEL_IIR0 || + int_n_inp1 == INTn_1_INP_SEL_IIR1) + return true; + + int_n_inp2 = int_mux_cfg1_val >> 4; + if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || + int_n_inp2 == INTn_1_INP_SEL_DEC1 || + int_n_inp2 == INTn_1_INP_SEL_IIR0 || + int_n_inp2 == INTn_1_INP_SEL_IIR1) + return true; + + return false; +} + +static int lpass_cdc_rx_macro_enable_main_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 gain_reg = 0; + u16 reg = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); + + if (w->shift >= INTERP_MAX) { + dev_err(component->dev, "%s: Invalid Interpolator value %d for name %s\n", + __func__, w->shift, w->name); + return -EINVAL; + } + + reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + (w->shift * + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + gain_reg = LPASS_CDC_RX_RX0_RX_VOL_CTL + (w->shift * + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_rx_macro_set_idle_detect_thr(component, rx_priv, w->shift, + INTERP_MAIN_PATH); + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + if (lpass_cdc_rx_macro_adie_lb(component, w->shift)) + snd_soc_component_update_bits(component, + reg, 0x20, 0x20); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_write(component, gain_reg, + snd_soc_component_read32(component, gain_reg)); + break; + case SND_SOC_DAPM_POST_PMD: + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + break; + } + + return 0; +} + +static int lpass_cdc_rx_macro_config_compander(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int interp_n, int event) +{ + int comp = 0; + u16 comp_ctl0_reg = 0, rx_path_cfg0_reg = 0, rx_path_cfg3_reg = 0; + u16 rx0_path_ctl_reg = 0; + u8 pcm_rate = 0, val = 0; + + /* AUX does not have compander */ + if (interp_n == INTERP_AUX) + return 0; + + comp = interp_n; + dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n", + __func__, event, comp + 1, rx_priv->comp_enabled[comp]); + + rx_path_cfg3_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG3 + + (comp * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + rx0_path_ctl_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + + (comp * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + pcm_rate = (snd_soc_component_read32(component, rx0_path_ctl_reg) + & 0x0F); + if (pcm_rate < 0x06) + val = 0x03; + else if (pcm_rate < 0x08) + val = 0x01; + else if (pcm_rate < 0x0B) + val = 0x02; + else + val = 0x00; + + if (SND_SOC_DAPM_EVENT_ON(event)) + snd_soc_component_update_bits(component, rx_path_cfg3_reg, + 0x03, val); + if (SND_SOC_DAPM_EVENT_OFF(event)) + snd_soc_component_update_bits(component, rx_path_cfg3_reg, + 0x03, 0x03); + if (!rx_priv->comp_enabled[comp]) + return 0; + + comp_ctl0_reg = LPASS_CDC_RX_COMPANDER0_CTL0 + + (comp * LPASS_CDC_RX_MACRO_COMP_OFFSET); + rx_path_cfg0_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0 + + (comp * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Compander Clock */ + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x01, 0x01); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x02); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x00); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + 0x02, 0x02); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x04, 0x04); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + 0x02, 0x00); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x01, 0x00); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x04, 0x00); + } + + return 0; +} + +static int lpass_cdc_rx_macro_load_compander_coeff(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int interp_n, int event) +{ + int comp = 0; + u16 comp_coeff_lsb_reg = 0, comp_coeff_msb_reg = 0; + int i = 0; + int hph_pwr_mode = HPH_LOHIFI; + + if (!rx_priv->comp_enabled[comp]) + return 0; + + if (interp_n == INTERP_HPHL) { + comp_coeff_lsb_reg = LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB; + comp_coeff_msb_reg = LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB; + } else if (interp_n == INTERP_HPHR) { + comp_coeff_lsb_reg = LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB; + comp_coeff_msb_reg = LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB; + } else { + /* compander coefficients are loaded only for hph path */ + return 0; + } + + comp = interp_n; + hph_pwr_mode = rx_priv->hph_pwr_mode; + dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n", + __func__, event, comp + 1, rx_priv->comp_enabled[comp]); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Load Compander Coeff */ + for (i = 0; i < COMP_MAX_COEFF; i++) { + snd_soc_component_write(component, comp_coeff_lsb_reg, + comp_coeff_table[hph_pwr_mode][i].lsb); + snd_soc_component_write(component, comp_coeff_msb_reg, + comp_coeff_table[hph_pwr_mode][i].msb); + } + } + + return 0; +} + +static void lpass_cdc_rx_macro_enable_softclip_clk(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + bool enable) +{ + if (enable) { + if (rx_priv->softclip_clk_users == 0) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_SOFTCLIP_CRC, + 0x01, 0x01); + rx_priv->softclip_clk_users++; + } else { + rx_priv->softclip_clk_users--; + if (rx_priv->softclip_clk_users == 0) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_SOFTCLIP_CRC, + 0x01, 0x00); + } +} + +static int lpass_cdc_rx_macro_config_softclip(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int event) +{ + dev_dbg(component->dev, "%s: event %d, enabled %d\n", + __func__, event, rx_priv->is_softclip_on); + + if (!rx_priv->is_softclip_on) + return 0; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Softclip clock */ + lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, true); + /* Enable Softclip control */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x01); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, + LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x00); + lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, false); + } + + return 0; +} + +static int lpass_cdc_rx_macro_config_aux_hpf(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int event) +{ + dev_dbg(component->dev, "%s: event %d, enabled %d\n", + __func__, event, rx_priv->is_aux_hpf_on); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Update Aux HPF control */ + if (!rx_priv->is_aux_hpf_on) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x00); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + /* Reset to default (HPF=ON) */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04); + } + + return 0; +} + + +static inline void +lpass_cdc_rx_macro_enable_clsh_block(struct lpass_cdc_rx_macro_priv *rx_priv, bool enable) +{ + if ((enable && ++rx_priv->clsh_users == 1) || + (!enable && --rx_priv->clsh_users == 0)) + snd_soc_component_update_bits(rx_priv->component, + LPASS_CDC_RX_CLSH_CRC, 0x01, + (u8) enable); + if (rx_priv->clsh_users < 0) + rx_priv->clsh_users = 0; + dev_dbg(rx_priv->dev, "%s: clsh_users %d, enable %d", __func__, + rx_priv->clsh_users, enable); +} + +static int lpass_cdc_rx_macro_config_classh(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int interp_n, int event) +{ + if (SND_SOC_DAPM_EVENT_OFF(event)) { + lpass_cdc_rx_macro_enable_clsh_block(rx_priv, false); + return 0; + } + + if (!SND_SOC_DAPM_EVENT_ON(event)) + return 0; + + lpass_cdc_rx_macro_enable_clsh_block(rx_priv, true); + if (interp_n == INTERP_HPHL || + interp_n == INTERP_HPHR) { + /* + * These K1 values depend on the Headphone Impedance + * For now it is assumed to be 16 ohm + */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_K1_LSB, + 0xFF, 0xC0); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_K1_MSB, + 0x0F, 0x00); + } + switch (interp_n) { + case INTERP_HPHL: + if (rx_priv->is_ear_mode_on) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_HPH_V_PA, + 0x3F, 0x39); + else + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_HPH_V_PA, + 0x3F, 0x1C); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_DECAY_CTRL, + 0x07, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_PATH_CFG0, + 0x40, 0x40); + break; + case INTERP_HPHR: + if (rx_priv->is_ear_mode_on) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_HPH_V_PA, + 0x3F, 0x39); + else + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_HPH_V_PA, + 0x3F, 0x1C); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_CLSH_DECAY_CTRL, + 0x07, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX1_RX_PATH_CFG0, + 0x40, 0x40); + break; + case INTERP_AUX: + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG0, + 0x08, 0x08); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG0, + 0x10, 0x10); + break; + } + + return 0; +} + +static void lpass_cdc_rx_macro_hd2_control(struct snd_soc_component *component, + u16 interp_idx, int event) +{ + u16 hd2_scale_reg = 0; + u16 hd2_enable_reg = 0; + + switch (interp_idx) { + case INTERP_HPHL: + hd2_scale_reg = LPASS_CDC_RX_RX0_RX_PATH_SEC3; + hd2_enable_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG0; + break; + case INTERP_HPHR: + hd2_scale_reg = LPASS_CDC_RX_RX1_RX_PATH_SEC3; + hd2_enable_reg = LPASS_CDC_RX_RX1_RX_PATH_CFG0; + break; + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x3C, 0x14); + snd_soc_component_update_bits(component, hd2_enable_reg, + 0x04, 0x04); + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, hd2_enable_reg, + 0x04, 0x00); + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x3C, 0x00); + } +} + +static int lpass_cdc_rx_macro_hph_idle_detect_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + struct device *rx_dev = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = + rx_priv->idle_det_cfg.hph_idle_detect_en; + + return 0; +} + +static int lpass_cdc_rx_macro_hph_idle_detect_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + struct device *rx_dev = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->idle_det_cfg.hph_idle_detect_en = + ucontrol->value.integer.value[0]; + + return 0; +} + +static int lpass_cdc_rx_macro_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->comp_enabled[comp]; + return 0; +} + +static int lpass_cdc_rx_macro_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n", + __func__, comp + 1, rx_priv->comp_enabled[comp], value); + rx_priv->comp_enabled[comp] = value; + + return 0; +} + +static int lpass_cdc_rx_macro_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = + rx_priv->rx_port_value[widget->shift]; + return 0; +} + +static int lpass_cdc_rx_macro_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + u32 rx_port_value = ucontrol->value.integer.value[0]; + u32 aif_rst = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + aif_rst = rx_priv->rx_port_value[widget->shift]; + if (!rx_port_value) { + if (aif_rst == 0) { + dev_err(rx_dev, "%s:AIF reset already\n", __func__); + return 0; + } + if (aif_rst > RX_MACRO_AIF4_PB) { + dev_err(rx_dev, "%s: Invalid AIF reset\n", __func__); + return 0; + } + } + rx_priv->rx_port_value[widget->shift] = rx_port_value; + + dev_dbg(rx_dev, "%s: mux input: %d, mux output: %d, aif_rst: %d\n", + __func__, rx_port_value, widget->shift, aif_rst); + + switch (rx_port_value) { + case 0: + if (rx_priv->active_ch_cnt[aif_rst]) { + clear_bit(widget->shift, + &rx_priv->active_ch_mask[aif_rst]); + rx_priv->active_ch_cnt[aif_rst]--; + } + break; + case 1: + case 2: + case 3: + case 4: + set_bit(widget->shift, + &rx_priv->active_ch_mask[rx_port_value]); + rx_priv->active_ch_cnt[rx_port_value]++; + break; + default: + dev_err(component->dev, + "%s:Invalid AIF_ID for LPASS_CDC_RX_MACRO MUX %d\n", + __func__, rx_port_value); + goto err; + } + + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + rx_port_value, e, update); + return 0; +err: + return -EINVAL; +} + +static int lpass_cdc_rx_macro_get_ear_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->is_ear_mode_on; + return 0; +} + +static int lpass_cdc_rx_macro_put_ear_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->is_ear_mode_on = + (!ucontrol->value.integer.value[0] ? false : true); + return 0; +} + +static int lpass_cdc_rx_macro_get_hph_hd2_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->hph_hd2_mode; + return 0; +} + +static int lpass_cdc_rx_macro_put_hph_hd2_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->hph_hd2_mode = ucontrol->value.integer.value[0]; + return 0; +} + +static int lpass_cdc_rx_macro_get_hph_pwr_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->hph_pwr_mode; + return 0; +} + +static int lpass_cdc_rx_macro_put_hph_pwr_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->hph_pwr_mode = ucontrol->value.integer.value[0]; + return 0; +} + +static int lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + ucontrol->value.integer.value[0] = + ((snd_soc_component_read32( + component, LPASS_CDC_RX_BCL_VBAT_CFG) & 0x04) ? + 1 : 0); + + dev_dbg(component->dev, "%s: value: %lu\n", __func__, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + dev_dbg(component->dev, "%s: value: %lu\n", __func__, + ucontrol->value.integer.value[0]); + + /* Set Vbat register configuration for GSM mode bit based on value */ + if (ucontrol->value.integer.value[0]) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, + 0x04, 0x04); + else + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, + 0x04, 0x00); + + return 0; +} + +static int lpass_cdc_rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->is_softclip_on; + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->is_softclip_on = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: soft clip enable = %d\n", __func__, + rx_priv->is_softclip_on); + + return 0; +} + +static int lpass_cdc_rx_macro_aux_hpf_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = rx_priv->is_aux_hpf_on; + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_rx_macro_aux_hpf_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->is_aux_hpf_on = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: aux hpf enable = %d\n", __func__, + rx_priv->is_aux_hpf_on); + + return 0; +} + + +static int lpass_cdc_rx_macro_enable_vbat(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event); + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable clock for VBAT block */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x10); + /* Enable VBAT block */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, 0x01, 0x01); + /* Update interpolator with 384K path */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x80, 0x80); + /* Update DSM FS rate */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x02, 0x02); + /* Use attenuation mode */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, 0x02, 0x00); + /* BCL block needs softclip clock to be enabled */ + lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, true); + /* Enable VBAT at channel level */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, 0x02, 0x02); + /* Set the ATTK1 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, + 0xFF, 0x00); + /* Set the ATTK2 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, + 0xFF, 0x00); + /* Set the ATTK3 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, + 0xFF, 0x00); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, + 0x80, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_SEC7, + 0x02, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, + 0x02, 0x02); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX2_RX_PATH_CFG1, + 0x02, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, + 0xFF, 0x00); + lpass_cdc_rx_macro_enable_softclip_clk(component, rx_priv, false); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_CFG, 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x00); + break; + default: + dev_err(rx_dev, "%s: Invalid event %d\n", __func__, event); + break; + } + return 0; +} + +static void lpass_cdc_rx_macro_idle_detect_control(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + int interp, int event) +{ + int reg = 0, mask = 0, val = 0; + + if (!rx_priv->idle_det_cfg.hph_idle_detect_en) + return; + + if (interp == INTERP_HPHL) { + reg = LPASS_CDC_RX_IDLE_DETECT_PATH_CTL; + mask = 0x01; + val = 0x01; + } + if (interp == INTERP_HPHR) { + reg = LPASS_CDC_RX_IDLE_DETECT_PATH_CTL; + mask = 0x02; + val = 0x02; + } + + if (reg && SND_SOC_DAPM_EVENT_ON(event)) + snd_soc_component_update_bits(component, reg, mask, val); + + if (reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, reg, mask, 0x00); + rx_priv->idle_det_cfg.hph_idle_thr = 0; + snd_soc_component_write(component, + LPASS_CDC_RX_IDLE_DETECT_CFG3, 0x0); + } +} + +static void lpass_cdc_rx_macro_hphdelay_lutbypass(struct snd_soc_component *component, + struct lpass_cdc_rx_macro_priv *rx_priv, + u16 interp_idx, int event) +{ + u16 hph_lut_bypass_reg = 0; + u16 hph_comp_ctrl7 = 0; + + switch (interp_idx) { + case INTERP_HPHL: + hph_lut_bypass_reg = LPASS_CDC_RX_TOP_HPHL_COMP_LUT; + hph_comp_ctrl7 = LPASS_CDC_RX_COMPANDER0_CTL7; + break; + case INTERP_HPHR: + hph_lut_bypass_reg = LPASS_CDC_RX_TOP_HPHR_COMP_LUT; + hph_comp_ctrl7 = LPASS_CDC_RX_COMPANDER1_CTL7; + break; + default: + break; + } + + if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) { + if (interp_idx == INTERP_HPHL) { + if (rx_priv->is_ear_mode_on) + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_PATH_CFG1, + 0x02, 0x02); + else + snd_soc_component_update_bits(component, + hph_lut_bypass_reg, + 0x80, 0x80); + } else { + snd_soc_component_update_bits(component, + hph_lut_bypass_reg, + 0x80, 0x80); + } + if (rx_priv->hph_pwr_mode) + snd_soc_component_update_bits(component, + hph_comp_ctrl7, + 0x20, 0x00); + } + + if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, + LPASS_CDC_RX_RX0_RX_PATH_CFG1, + 0x02, 0x00); + snd_soc_component_update_bits(component, hph_lut_bypass_reg, + 0x80, 0x00); + snd_soc_component_update_bits(component, hph_comp_ctrl7, + 0x20, 0x20); + } +} + +static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *component, + int event, int interp_idx) +{ + u16 main_reg = 0, dsm_reg = 0, rx_cfg2_reg = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!component) { + pr_err("%s: component is NULL\n", __func__); + return -EINVAL; + } + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + main_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + + (interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + dsm_reg = LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL + + (interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + if (interp_idx == INTERP_AUX) + dsm_reg = LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL; + rx_cfg2_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG2 + + (interp_idx * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + if (rx_priv->main_clk_users[interp_idx] == 0) { + /* Main path PGA mute enable */ + snd_soc_component_update_bits(component, main_reg, + 0x10, 0x10); + snd_soc_component_update_bits(component, dsm_reg, + 0x01, 0x01); + snd_soc_component_update_bits(component, rx_cfg2_reg, + 0x03, 0x03); + lpass_cdc_rx_macro_load_compander_coeff(component, rx_priv, + interp_idx, event); + lpass_cdc_rx_macro_idle_detect_control(component, rx_priv, + interp_idx, event); + if (rx_priv->hph_hd2_mode) + lpass_cdc_rx_macro_hd2_control( + component, interp_idx, event); + lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv, + interp_idx, event); + lpass_cdc_rx_macro_config_compander(component, rx_priv, + interp_idx, event); + if (interp_idx == INTERP_AUX) { + lpass_cdc_rx_macro_config_softclip(component, rx_priv, + event); + lpass_cdc_rx_macro_config_aux_hpf(component, rx_priv, + event); + } + lpass_cdc_rx_macro_config_classh(component, rx_priv, + interp_idx, event); + } + rx_priv->main_clk_users[interp_idx]++; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + rx_priv->main_clk_users[interp_idx]--; + if (rx_priv->main_clk_users[interp_idx] <= 0) { + rx_priv->main_clk_users[interp_idx] = 0; + /* Main path PGA mute enable */ + snd_soc_component_update_bits(component, main_reg, + 0x10, 0x10); + /* Clk Disable */ + snd_soc_component_update_bits(component, dsm_reg, + 0x01, 0x00); + snd_soc_component_update_bits(component, main_reg, + 0x20, 0x00); + /* Reset enable and disable */ + snd_soc_component_update_bits(component, main_reg, + 0x40, 0x40); + snd_soc_component_update_bits(component, main_reg, + 0x40, 0x00); + /* Reset rate to 48K*/ + snd_soc_component_update_bits(component, main_reg, + 0x0F, 0x04); + snd_soc_component_update_bits(component, rx_cfg2_reg, + 0x03, 0x00); + lpass_cdc_rx_macro_config_classh(component, rx_priv, + interp_idx, event); + lpass_cdc_rx_macro_config_compander(component, rx_priv, + interp_idx, event); + if (interp_idx == INTERP_AUX) { + lpass_cdc_rx_macro_config_softclip(component, rx_priv, + event); + lpass_cdc_rx_macro_config_aux_hpf(component, rx_priv, + event); + } + lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv, + interp_idx, event); + if (rx_priv->hph_hd2_mode) + lpass_cdc_rx_macro_hd2_control(component, interp_idx, + event); + lpass_cdc_rx_macro_idle_detect_control(component, rx_priv, + interp_idx, event); + } + } + + dev_dbg(component->dev, "%s event %d main_clk_users %d\n", + __func__, event, rx_priv->main_clk_users[interp_idx]); + + return rx_priv->main_clk_users[interp_idx]; +} + +static int lpass_cdc_rx_macro_enable_rx_path_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 sidetone_reg = 0, fs_reg = 0; + + dev_dbg(component->dev, "%s %d %d\n", __func__, event, w->shift); + sidetone_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG1 + + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * (w->shift); + fs_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL + + LPASS_CDC_RX_MACRO_RX_PATH_OFFSET * (w->shift); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + snd_soc_component_update_bits(component, sidetone_reg, + 0x10, 0x10); + snd_soc_component_update_bits(component, fs_reg, + 0x20, 0x20); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, sidetone_reg, + 0x10, 0x00); + lpass_cdc_rx_macro_enable_interp_clk(component, event, w->shift); + break; + default: + break; + }; + return 0; +} + +static void lpass_cdc_rx_macro_restore_iir_coeff(struct lpass_cdc_rx_macro_priv *rx_priv, int iir_idx, + int band_idx) +{ + u16 reg_add = 0, coeff_idx = 0, idx = 0; + struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL); + + if (regmap == NULL) { + dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__); + return; + } + + regmap_write(regmap, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx), + (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F); + + reg_add = LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; + + /* 5 coefficients per band and 4 writes per coefficient */ + for (coeff_idx = 0; coeff_idx < LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX; + coeff_idx++) { + /* Four 8 bit values(one 32 bit) per coefficient */ + regmap_write(regmap, reg_add, + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]); + regmap_write(regmap, reg_add, + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]); + regmap_write(regmap, reg_add, + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]); + regmap_write(regmap, reg_add, + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++]); + } +} + +static int lpass_cdc_rx_macro_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int iir_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->reg; + int band_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + /* IIR filter band registers are at integer multiples of 0x80 */ + u16 iir_reg = LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx; + + ucontrol->value.integer.value[0] = ( + snd_soc_component_read32(component, iir_reg) & + (1 << band_idx)) != 0; + + dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__, + iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[0]); + return 0; +} + +static int lpass_cdc_rx_macro_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int iir_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->reg; + int band_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + bool iir_band_en_status = 0; + int value = ucontrol->value.integer.value[0]; + u16 iir_reg = LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL + 0x80 * iir_idx; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + lpass_cdc_rx_macro_restore_iir_coeff(rx_priv, iir_idx, band_idx); + + /* Mask first 5 bits, 6-8 are reserved */ + snd_soc_component_update_bits(component, iir_reg, (1 << band_idx), + (value << band_idx)); + + iir_band_en_status = ((snd_soc_component_read32(component, iir_reg) & + (1 << band_idx)) != 0); + dev_dbg(component->dev, "%s: IIR #%d band #%d enable %d\n", __func__, + iir_idx, band_idx, iir_band_en_status); + return 0; +} + +static uint32_t get_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, + int coeff_idx) +{ + uint32_t value = 0; + + /* Address does not automatically update if reading */ + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t)) & 0x7F); + + value |= snd_soc_component_read32(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx)); + + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 1) & 0x7F); + + value |= (snd_soc_component_read32(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + + 0x80 * iir_idx)) << 8); + + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 2) & 0x7F); + + value |= (snd_soc_component_read32(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + + 0x80 * iir_idx)) << 16); + + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx), + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 3) & 0x7F); + + /* Mask bits top 2 bits since they are reserved */ + value |= ((snd_soc_component_read32(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + + 16 * iir_idx)) & 0x3F) << 24); + + return value; +} + +static int lpass_cdc_rx_macro_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int iir_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->reg; + int band_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + + ucontrol->value.integer.value[0] = + get_iir_band_coeff(component, iir_idx, band_idx, 0); + ucontrol->value.integer.value[1] = + get_iir_band_coeff(component, iir_idx, band_idx, 1); + ucontrol->value.integer.value[2] = + get_iir_band_coeff(component, iir_idx, band_idx, 2); + ucontrol->value.integer.value[3] = + get_iir_band_coeff(component, iir_idx, band_idx, 3); + ucontrol->value.integer.value[4] = + get_iir_band_coeff(component, iir_idx, band_idx, 4); + + dev_dbg(component->dev, "%s: IIR #%d band #%d b0 = 0x%x\n" + "%s: IIR #%d band #%d b1 = 0x%x\n" + "%s: IIR #%d band #%d b2 = 0x%x\n" + "%s: IIR #%d band #%d a1 = 0x%x\n" + "%s: IIR #%d band #%d a2 = 0x%x\n", + __func__, iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[0], + __func__, iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[1], + __func__, iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[2], + __func__, iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[3], + __func__, iir_idx, band_idx, + (uint32_t)ucontrol->value.integer.value[4]); + return 0; +} + +static void set_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, + uint32_t value) +{ + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx), + (value & 0xFF)); + + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx), + (value >> 8) & 0xFF); + + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx), + (value >> 16) & 0xFF); + + /* Mask top 2 bits, 7-8 are reserved */ + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx), + (value >> 24) & 0x3F); +} + +static int lpass_cdc_rx_macro_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int iir_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->reg; + int band_idx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int coeff_idx, idx = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + /* + * Mask top bit it is reserved + * Updates addr automatically for each B2 write + */ + snd_soc_component_write(component, + (LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx), + (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F); + + /* Store the coefficients in sidetone coeff array */ + for (coeff_idx = 0; coeff_idx < LPASS_CDC_RX_MACRO_SIDETONE_IIR_COEFF_MAX; + coeff_idx++) { + uint32_t value = ucontrol->value.integer.value[coeff_idx]; + + set_iir_band_coeff(component, iir_idx, band_idx, value); + + /* Four 8 bit values(one 32 bit) per coefficient */ + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] = + (value & 0xFF); + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] = + (value >> 8) & 0xFF; + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] = + (value >> 16) & 0xFF; + rx_priv->sidetone_coeff_array[iir_idx][band_idx][idx++] = + (value >> 24) & 0xFF; + } + + pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n" + "%s: IIR #%d band #%d b1 = 0x%x\n" + "%s: IIR #%d band #%d b2 = 0x%x\n" + "%s: IIR #%d band #%d a1 = 0x%x\n" + "%s: IIR #%d band #%d a2 = 0x%x\n", + __func__, iir_idx, band_idx, + get_iir_band_coeff(component, iir_idx, band_idx, 0), + __func__, iir_idx, band_idx, + get_iir_band_coeff(component, iir_idx, band_idx, 1), + __func__, iir_idx, band_idx, + get_iir_band_coeff(component, iir_idx, band_idx, 2), + __func__, iir_idx, band_idx, + get_iir_band_coeff(component, iir_idx, band_idx, 3), + __func__, iir_idx, band_idx, + get_iir_band_coeff(component, iir_idx, band_idx, 4)); + return 0; +} + +static int lpass_cdc_rx_macro_set_iir_gain(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + dev_dbg(component->dev, "%s: event = %d\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: /* fall through */ + case SND_SOC_DAPM_PRE_PMD: + if (strnstr(w->name, "IIR0", sizeof("IIR0"))) { + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL)); + } else { + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL)); + snd_soc_component_write(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, + snd_soc_component_read32(component, + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL)); + } + break; + } + return 0; +} + +static const struct snd_kcontrol_new lpass_cdc_rx_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", + LPASS_CDC_RX_RX0_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", + LPASS_CDC_RX_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", + LPASS_CDC_RX_RX2_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", + LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", + LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", + LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + + SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, LPASS_CDC_RX_MACRO_COMP1, 1, 0, + lpass_cdc_rx_macro_get_compander, lpass_cdc_rx_macro_set_compander), + SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_RX_MACRO_COMP2, 1, 0, + lpass_cdc_rx_macro_get_compander, lpass_cdc_rx_macro_set_compander), + + SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum, + lpass_cdc_rx_macro_hph_idle_detect_get, lpass_cdc_rx_macro_hph_idle_detect_put), + + SOC_ENUM_EXT("RX_EAR Mode", lpass_cdc_rx_macro_ear_mode_enum, + lpass_cdc_rx_macro_get_ear_mode, lpass_cdc_rx_macro_put_ear_mode), + + SOC_ENUM_EXT("RX_HPH HD2 Mode", lpass_cdc_rx_macro_hph_hd2_mode_enum, + lpass_cdc_rx_macro_get_hph_hd2_mode, lpass_cdc_rx_macro_put_hph_hd2_mode), + + SOC_ENUM_EXT("RX_HPH_PWR_MODE", lpass_cdc_rx_macro_hph_pwr_mode_enum, + lpass_cdc_rx_macro_get_hph_pwr_mode, lpass_cdc_rx_macro_put_hph_pwr_mode), + + SOC_ENUM_EXT("RX_GSM mode Enable", lpass_cdc_rx_macro_vbat_bcl_gsm_mode_enum, + lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_get, + lpass_cdc_rx_macro_vbat_bcl_gsm_mode_func_put), + SOC_SINGLE_EXT("RX_Softclip Enable", SND_SOC_NOPM, 0, 1, 0, + lpass_cdc_rx_macro_soft_clip_enable_get, + lpass_cdc_rx_macro_soft_clip_enable_put), + SOC_SINGLE_EXT("AUX_HPF Enable", SND_SOC_NOPM, 0, 1, 0, + lpass_cdc_rx_macro_aux_hpf_mode_get, + lpass_cdc_rx_macro_aux_hpf_mode_put), + + SOC_SINGLE_S8_TLV("IIR0 INP0 Volume", + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP1 Volume", + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP2 Volume", + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP3 Volume", + LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP0 Volume", + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", + LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40, + digital_gain), + + SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0, + lpass_cdc_rx_macro_iir_enable_audio_mixer_get, + lpass_cdc_rx_macro_iir_enable_audio_mixer_put), + + SOC_SINGLE_MULTI_EXT("IIR0 Band1", IIR0, BAND1, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR0 Band2", IIR0, BAND2, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR0 Band3", IIR0, BAND3, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR0 Band4", IIR0, BAND4, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR0 Band5", IIR0, BAND5, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), + SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5, + lpass_cdc_rx_macro_iir_band_audio_mixer_get, + lpass_cdc_rx_macro_iir_band_audio_mixer_put), +}; + +static int lpass_cdc_rx_macro_enable_echo(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + u16 val = 0, ec_hq_reg = 0; + int ec_tx = 0; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + dev_dbg(rx_dev, "%s %d %s\n", __func__, event, w->name); + + val = snd_soc_component_read32(component, + LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4); + if (!(strcmp(w->name, "RX MIX TX0 MUX"))) + ec_tx = ((val & 0xf0) >> 0x4) - 1; + else if (!(strcmp(w->name, "RX MIX TX1 MUX"))) + ec_tx = (val & 0x0f) - 1; + + val = snd_soc_component_read32(component, + LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5); + if (!(strcmp(w->name, "RX MIX TX2 MUX"))) + ec_tx = (val & 0x0f) - 1; + + if (ec_tx < 0 || (ec_tx >= LPASS_CDC_RX_MACRO_EC_MUX_MAX)) { + dev_err(rx_dev, "%s: EC mix control not set correctly\n", + __func__); + return -EINVAL; + } + ec_hq_reg = LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL + + 0x40 * ec_tx; + snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01); + ec_hq_reg = LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 + + 0x40 * ec_tx; + /* default set to 48k */ + snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08); + + return 0; +} + +static const struct snd_soc_dapm_widget lpass_cdc_rx_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("RX AIF1 PB", "RX_MACRO_AIF1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF2 PB", "RX_MACRO_AIF2 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF3 PB", "RX_MACRO_AIF3 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF4 PB", "RX_MACRO_AIF4 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0, + SND_SOC_NOPM, 0, 0), + + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX0 MUX", LPASS_CDC_RX_MACRO_RX0, lpass_cdc_rx_macro_rx0), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX1 MUX", LPASS_CDC_RX_MACRO_RX1, lpass_cdc_rx_macro_rx1), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX2 MUX", LPASS_CDC_RX_MACRO_RX2, lpass_cdc_rx_macro_rx2), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX3 MUX", LPASS_CDC_RX_MACRO_RX3, lpass_cdc_rx_macro_rx3), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX4 MUX", LPASS_CDC_RX_MACRO_RX4, lpass_cdc_rx_macro_rx4), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX_MACRO RX5 MUX", LPASS_CDC_RX_MACRO_RX5, lpass_cdc_rx_macro_rx5), + + SND_SOC_DAPM_MIXER("RX_RX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX3", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX4", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX5", SND_SOC_NOPM, 0, 0, NULL, 0), + + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2), + LPASS_CDC_RX_MACRO_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3), + + SND_SOC_DAPM_MUX_E("RX MIX TX0 MUX", SND_SOC_NOPM, + LPASS_CDC_RX_MACRO_EC0_MUX, 0, + &rx_mix_tx0_mux, lpass_cdc_rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX MIX TX1 MUX", SND_SOC_NOPM, + LPASS_CDC_RX_MACRO_EC1_MUX, 0, + &rx_mix_tx1_mux, lpass_cdc_rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX MIX TX2 MUX", SND_SOC_NOPM, + LPASS_CDC_RX_MACRO_EC2_MUX, 0, + &rx_mix_tx2_mux, lpass_cdc_rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("IIR0", LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, + 4, 0, NULL, 0, lpass_cdc_rx_macro_set_iir_gain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MIXER_E("IIR1", LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, + 4, 0, NULL, 0, lpass_cdc_rx_macro_set_iir_gain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MIXER("SRC0", LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, + 4, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SRC1", LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, + 4, 0, NULL, 0), + + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp), + + SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0, + &rx_int0_2_mux, lpass_cdc_rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0, + &rx_int1_2_mux, lpass_cdc_rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_AUX, 0, + &rx_int2_2_mux, lpass_cdc_rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2), + + SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0, + &rx_int0_1_interp_mux, lpass_cdc_rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0, + &rx_int1_1_interp_mux, lpass_cdc_rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_AUX, 0, + &rx_int2_1_interp_mux, lpass_cdc_rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp), + LPASS_CDC_RX_MACRO_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp), + + SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL, + 0, &rx_int0_mix2_inp_mux, lpass_cdc_rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR, + 0, &rx_int1_mix2_inp_mux, lpass_cdc_rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_AUX, + 0, &rx_int2_mix2_inp_mux, lpass_cdc_rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("RX INT2_1 VBAT", SND_SOC_NOPM, + 0, 0, rx_int2_1_vbat_mix_switch, + ARRAY_SIZE(rx_int2_1_vbat_mix_switch), + lpass_cdc_rx_macro_enable_vbat, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPHL_OUT"), + SND_SOC_DAPM_OUTPUT("HPHR_OUT"), + SND_SOC_DAPM_OUTPUT("AUX_OUT"), + SND_SOC_DAPM_OUTPUT("PCM_OUT"), + + SND_SOC_DAPM_INPUT("RX_TX DEC0_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC1_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC2_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC3_INP"), + + SND_SOC_DAPM_SUPPLY_S("RX_MCLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_rx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route rx_audio_map[] = { + {"RX AIF1 PB", NULL, "RX_MCLK"}, + {"RX AIF2 PB", NULL, "RX_MCLK"}, + {"RX AIF3 PB", NULL, "RX_MCLK"}, + {"RX AIF4 PB", NULL, "RX_MCLK"}, + + {"RX AIF6 PB", NULL, "RX_MCLK"}, + {"PCM_OUT", NULL, "RX AIF6 PB"}, + + {"RX_MACRO RX0 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX1 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX2 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX3 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX4 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX5 MUX", "AIF1_PB", "RX AIF1 PB"}, + + {"RX_MACRO RX0 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX1 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX2 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX3 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX4 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX5 MUX", "AIF2_PB", "RX AIF2 PB"}, + + {"RX_MACRO RX0 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX1 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX2 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX3 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX4 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX5 MUX", "AIF3_PB", "RX AIF3 PB"}, + + {"RX_MACRO RX0 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX1 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX2 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX3 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX4 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX5 MUX", "AIF4_PB", "RX AIF4 PB"}, + + {"RX_RX0", NULL, "RX_MACRO RX0 MUX"}, + {"RX_RX1", NULL, "RX_MACRO RX1 MUX"}, + {"RX_RX2", NULL, "RX_MACRO RX2 MUX"}, + {"RX_RX3", NULL, "RX_MACRO RX3 MUX"}, + {"RX_RX4", NULL, "RX_MACRO RX4 MUX"}, + {"RX_RX5", NULL, "RX_MACRO RX5 MUX"}, + + {"RX INT0_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT0_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT0_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT1_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT1_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT1_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT2_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT2_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT2_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP0"}, + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP1"}, + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP2"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP0"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP1"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP2"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP0"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP1"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP2"}, + + {"RX MIX TX0 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX0 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX0 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX0 MUX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX1 MUX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX2 MUX"}, + {"RX AIF_ECHO", NULL, "RX_MCLK"}, + + /* Mixing path INT0 */ + {"RX INT0_2 MUX", "RX0", "RX_RX0"}, + {"RX INT0_2 MUX", "RX1", "RX_RX1"}, + {"RX INT0_2 MUX", "RX2", "RX_RX2"}, + {"RX INT0_2 MUX", "RX3", "RX_RX3"}, + {"RX INT0_2 MUX", "RX4", "RX_RX4"}, + {"RX INT0_2 MUX", "RX5", "RX_RX5"}, + {"RX INT0_2 INTERP", NULL, "RX INT0_2 MUX"}, + {"RX INT0 SEC MIX", NULL, "RX INT0_2 INTERP"}, + + /* Mixing path INT1 */ + {"RX INT1_2 MUX", "RX0", "RX_RX0"}, + {"RX INT1_2 MUX", "RX1", "RX_RX1"}, + {"RX INT1_2 MUX", "RX2", "RX_RX2"}, + {"RX INT1_2 MUX", "RX3", "RX_RX3"}, + {"RX INT1_2 MUX", "RX4", "RX_RX4"}, + {"RX INT1_2 MUX", "RX5", "RX_RX5"}, + {"RX INT1_2 INTERP", NULL, "RX INT1_2 MUX"}, + {"RX INT1 SEC MIX", NULL, "RX INT1_2 INTERP"}, + + /* Mixing path INT2 */ + {"RX INT2_2 MUX", "RX0", "RX_RX0"}, + {"RX INT2_2 MUX", "RX1", "RX_RX1"}, + {"RX INT2_2 MUX", "RX2", "RX_RX2"}, + {"RX INT2_2 MUX", "RX3", "RX_RX3"}, + {"RX INT2_2 MUX", "RX4", "RX_RX4"}, + {"RX INT2_2 MUX", "RX5", "RX_RX5"}, + {"RX INT2_2 INTERP", NULL, "RX INT2_2 MUX"}, + {"RX INT2 SEC MIX", NULL, "RX INT2_2 INTERP"}, + + {"RX INT0_1 INTERP", NULL, "RX INT0_1 MIX1"}, + {"RX INT0 SEC MIX", NULL, "RX INT0_1 INTERP"}, + {"RX INT0 MIX2", NULL, "RX INT0 SEC MIX"}, + {"RX INT0 MIX2", NULL, "RX INT0 MIX2 INP"}, + {"RX INT0 DEM MUX", "CLSH_DSM_OUT", "RX INT0 MIX2"}, + {"HPHL_OUT", NULL, "RX INT0 DEM MUX"}, + {"HPHL_OUT", NULL, "RX_MCLK"}, + + {"RX INT1_1 INTERP", NULL, "RX INT1_1 MIX1"}, + {"RX INT1 SEC MIX", NULL, "RX INT1_1 INTERP"}, + {"RX INT1 MIX2", NULL, "RX INT1 SEC MIX"}, + {"RX INT1 MIX2", NULL, "RX INT1 MIX2 INP"}, + {"RX INT1 DEM MUX", "CLSH_DSM_OUT", "RX INT1 MIX2"}, + {"HPHR_OUT", NULL, "RX INT1 DEM MUX"}, + {"HPHR_OUT", NULL, "RX_MCLK"}, + + {"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"}, + + {"RX INT2_1 VBAT", "RX AUX VBAT Enable", "RX INT2_1 INTERP"}, + {"RX INT2 SEC MIX", NULL, "RX INT2_1 VBAT"}, + + {"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"}, + {"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"}, + {"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"}, + {"AUX_OUT", NULL, "RX INT2 MIX2"}, + {"AUX_OUT", NULL, "RX_MCLK"}, + + {"IIR0", NULL, "RX_MCLK"}, + {"IIR0", NULL, "IIR0 INP0 MUX"}, + {"IIR0 INP0 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP0 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP0 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP0 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP0 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP0 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP0 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP0 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP0 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP0 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP1 MUX"}, + {"IIR0 INP1 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP1 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP1 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP1 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP1 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP1 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP1 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP1 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP1 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP1 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP2 MUX"}, + {"IIR0 INP2 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP2 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP2 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP2 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP2 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP2 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP2 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP2 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP2 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP2 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP3 MUX"}, + {"IIR0 INP3 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP3 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP3 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP3 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP3 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP3 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP3 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP3 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP3 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP3 MUX", "RX5", "RX_RX5"}, + + {"IIR1", NULL, "RX_MCLK"}, + {"IIR1", NULL, "IIR1 INP0 MUX"}, + {"IIR1 INP0 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP0 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP0 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP0 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP0 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP0 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP0 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP0 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP0 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP0 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP1 MUX"}, + {"IIR1 INP1 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP1 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP1 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP1 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP1 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP1 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP1 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP1 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP1 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP1 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP2 MUX"}, + {"IIR1 INP2 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP2 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP2 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP2 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP2 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP2 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP2 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP2 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP2 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP2 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP3 MUX"}, + {"IIR1 INP3 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP3 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP3 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP3 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP3 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP3 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP3 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP3 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP3 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP3 MUX", "RX5", "RX_RX5"}, + + {"SRC0", NULL, "IIR0"}, + {"SRC1", NULL, "IIR1"}, + {"RX INT0 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT0 MIX2 INP", "SRC1", "SRC1"}, + {"RX INT1 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT1 MIX2 INP", "SRC1", "SRC1"}, + {"RX INT2 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT2 MIX2 INP", "SRC1", "SRC1"}, +}; + +static int lpass_cdc_rx_macro_core_vote(void *handle, bool enable) +{ + struct lpass_cdc_rx_macro_priv *rx_priv = (struct lpass_cdc_rx_macro_priv *) handle; + + if (rx_priv == NULL) { + pr_err("%s: rx priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) { + pm_runtime_get_sync(rx_priv->dev); + pm_runtime_put_autosuspend(rx_priv->dev); + pm_runtime_mark_last_busy(rx_priv->dev); + } + + if (lpass_cdc_check_core_votes(rx_priv->dev)) + return 0; + else + return -EINVAL; +} + +static int rx_swrm_clock(void *handle, bool enable) +{ + struct lpass_cdc_rx_macro_priv *rx_priv = (struct lpass_cdc_rx_macro_priv *) handle; + struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&rx_priv->swr_clk_lock); + + trace_printk("%s: swrm clock %s\n", + __func__, (enable ? "enable" : "disable")); + dev_dbg(rx_priv->dev, "%s: swrm clock %s\n", + __func__, (enable ? "enable" : "disable")); + if (enable) { + pm_runtime_get_sync(rx_priv->dev); + if (rx_priv->swr_clk_users == 0) { + ret = msm_cdc_pinctrl_select_active_state( + rx_priv->rx_swr_gpio_p); + if (ret < 0) { + dev_err(rx_priv->dev, + "%s: rx swr pinctrl enable failed\n", + __func__); + pm_runtime_mark_last_busy(rx_priv->dev); + pm_runtime_put_autosuspend(rx_priv->dev); + goto exit; + } + ret = lpass_cdc_rx_macro_mclk_enable(rx_priv, 1, true); + if (ret < 0) { + msm_cdc_pinctrl_select_sleep_state( + rx_priv->rx_swr_gpio_p); + dev_err(rx_priv->dev, + "%s: rx request clock enable failed\n", + __func__); + pm_runtime_mark_last_busy(rx_priv->dev); + pm_runtime_put_autosuspend(rx_priv->dev); + goto exit; + } + if (rx_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x01); + if (rx_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x00); + rx_priv->reset_swr = false; + } + pm_runtime_mark_last_busy(rx_priv->dev); + pm_runtime_put_autosuspend(rx_priv->dev); + rx_priv->swr_clk_users++; + } else { + if (rx_priv->swr_clk_users <= 0) { + dev_err(rx_priv->dev, + "%s: rx swrm clock users already reset\n", + __func__); + rx_priv->swr_clk_users = 0; + goto exit; + } + rx_priv->swr_clk_users--; + if (rx_priv->swr_clk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x00); + lpass_cdc_rx_macro_mclk_enable(rx_priv, 0, true); + ret = msm_cdc_pinctrl_select_sleep_state( + rx_priv->rx_swr_gpio_p); + if (ret < 0) { + dev_err(rx_priv->dev, + "%s: rx swr pinctrl disable failed\n", + __func__); + goto exit; + } + } + } + trace_printk("%s: swrm clock users %d\n", + __func__, rx_priv->swr_clk_users); + dev_dbg(rx_priv->dev, "%s: swrm clock users %d\n", + __func__, rx_priv->swr_clk_users); +exit: + mutex_unlock(&rx_priv->swr_clk_lock); + return ret; +} + +static const struct lpass_cdc_rx_macro_reg_mask_val + lpass_cdc_rx_macro_reg_init[] = { + {LPASS_CDC_RX_RX0_RX_PATH_SEC7, 0x07, 0x02}, + {LPASS_CDC_RX_RX1_RX_PATH_SEC7, 0x07, 0x02}, + {LPASS_CDC_RX_RX2_RX_PATH_SEC7, 0x07, 0x02}, + {LPASS_CDC_RX_RX0_RX_PATH_CFG3, 0x03, 0x02}, + {LPASS_CDC_RX_RX1_RX_PATH_CFG3, 0x03, 0x02}, + {LPASS_CDC_RX_RX2_RX_PATH_CFG3, 0x03, 0x02}, +}; + +static void lpass_cdc_rx_macro_init_bcl_pmic_reg(struct snd_soc_component *component) +{ + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!component) { + pr_err("%s: NULL component pointer!\n", __func__); + return; + } + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return; + + switch (rx_priv->bcl_pmic_params.id) { + case 0: + /* Enable ID0 to listen to respective PMIC group interrupts */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x02, 0x02); + /* Update MC_SID0 */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x0F, + rx_priv->bcl_pmic_params.sid); + /* Update MC_PPID0 */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2, 0xFF, + rx_priv->bcl_pmic_params.ppid); + break; + case 1: + /* Enable ID1 to listen to respective PMIC group interrupts */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x01, 0x01); + /* Update MC_SID1 */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x0F, + rx_priv->bcl_pmic_params.sid); + /* Update MC_PPID1 */ + snd_soc_component_update_bits(component, + LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1, 0xFF, + rx_priv->bcl_pmic_params.ppid); + break; + default: + dev_err(rx_dev, "%s: PMIC ID is invalid %d\n", + __func__, rx_priv->bcl_pmic_params.id); + break; + } +} + +static int lpass_cdc_rx_macro_init(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + int ret = 0; + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + int i; + + rx_dev = lpass_cdc_get_device_ptr(component->dev, RX_MACRO); + if (!rx_dev) { + dev_err(component->dev, + "%s: null device for macro!\n", __func__); + return -EINVAL; + } + rx_priv = dev_get_drvdata(rx_dev); + if (!rx_priv) { + dev_err(component->dev, + "%s: priv is null for macro!\n", __func__); + return -EINVAL; + } + + ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_rx_macro_dapm_widgets, + ARRAY_SIZE(lpass_cdc_rx_macro_dapm_widgets)); + if (ret < 0) { + dev_err(rx_dev, "%s: failed to add controls\n", __func__); + return ret; + } + ret = snd_soc_dapm_add_routes(dapm, rx_audio_map, + ARRAY_SIZE(rx_audio_map)); + if (ret < 0) { + dev_err(rx_dev, "%s: failed to add routes\n", __func__); + return ret; + } + ret = snd_soc_dapm_new_widgets(dapm->card); + if (ret < 0) { + dev_err(rx_dev, "%s: failed to add widgets\n", __func__); + return ret; + } + ret = snd_soc_add_component_controls(component, lpass_cdc_rx_macro_snd_controls, + ARRAY_SIZE(lpass_cdc_rx_macro_snd_controls)); + if (ret < 0) { + dev_err(rx_dev, "%s: failed to add snd_ctls\n", __func__); + return ret; + } + rx_priv->dev_up = true; + rx_priv->rx0_gain_val = 0; + rx_priv->rx1_gain_val = 0; + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "AUX_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "PCM_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC0_INP"); + snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC1_INP"); + snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC2_INP"); + snd_soc_dapm_ignore_suspend(dapm, "RX_TX DEC3_INP"); + snd_soc_dapm_sync(dapm); + + for (i = 0; i < ARRAY_SIZE(lpass_cdc_rx_macro_reg_init); i++) + snd_soc_component_update_bits(component, + lpass_cdc_rx_macro_reg_init[i].reg, + lpass_cdc_rx_macro_reg_init[i].mask, + lpass_cdc_rx_macro_reg_init[i].val); + + rx_priv->component = component; + lpass_cdc_rx_macro_init_bcl_pmic_reg(component); + + return 0; +} + +static int lpass_cdc_rx_macro_deinit(struct snd_soc_component *component) +{ + struct device *rx_dev = NULL; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + + if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) + return -EINVAL; + + rx_priv->component = NULL; + + return 0; +} + +static void lpass_cdc_rx_macro_add_child_devices(struct work_struct *work) +{ + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + struct platform_device *pdev = NULL; + struct device_node *node = NULL; + struct rx_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL; + int ret = 0; + u16 count = 0, ctrl_num = 0; + struct rx_swr_ctrl_platform_data *platdata = NULL; + char plat_dev_name[RX_SWR_STRING_LEN] = ""; + bool rx_swr_master_node = false; + + rx_priv = container_of(work, struct lpass_cdc_rx_macro_priv, + lpass_cdc_rx_macro_add_child_devices_work); + if (!rx_priv) { + pr_err("%s: Memory for rx_priv does not exist\n", + __func__); + return; + } + + if (!rx_priv->dev) { + pr_err("%s: RX device does not exist\n", __func__); + return; + } + + if(!rx_priv->dev->of_node) { + dev_err(rx_priv->dev, + "%s: DT node for RX dev does not exist\n", __func__); + return; + } + + platdata = &rx_priv->swr_plat_data; + rx_priv->child_count = 0; + + for_each_available_child_of_node(rx_priv->dev->of_node, node) { + rx_swr_master_node = false; + if (strnstr(node->name, "rx_swr_master", + strlen("rx_swr_master")) != NULL) + rx_swr_master_node = true; + + if(rx_swr_master_node) + strlcpy(plat_dev_name, "rx_swr_ctrl", + (RX_SWR_STRING_LEN - 1)); + else + strlcpy(plat_dev_name, node->name, + (RX_SWR_STRING_LEN - 1)); + + pdev = platform_device_alloc(plat_dev_name, -1); + if (!pdev) { + dev_err(rx_priv->dev, "%s: pdev memory alloc failed\n", + __func__); + ret = -ENOMEM; + goto err; + } + pdev->dev.parent = rx_priv->dev; + pdev->dev.of_node = node; + + if (rx_swr_master_node) { + ret = platform_device_add_data(pdev, platdata, + sizeof(*platdata)); + if (ret) { + dev_err(&pdev->dev, + "%s: cannot add plat data ctrl:%d\n", + __func__, ctrl_num); + goto fail_pdev_add; + } + } + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, + "%s: Cannot add platform device\n", + __func__); + goto fail_pdev_add; + } + + if (rx_swr_master_node) { + temp = krealloc(swr_ctrl_data, + (ctrl_num + 1) * sizeof( + struct rx_swr_ctrl_data), + GFP_KERNEL); + if (!temp) { + ret = -ENOMEM; + goto fail_pdev_add; + } + swr_ctrl_data = temp; + swr_ctrl_data[ctrl_num].rx_swr_pdev = pdev; + ctrl_num++; + dev_dbg(&pdev->dev, + "%s: Added soundwire ctrl device(s)\n", + __func__); + rx_priv->swr_ctrl_data = swr_ctrl_data; + } + if (rx_priv->child_count < LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX) + rx_priv->pdev_child_devices[ + rx_priv->child_count++] = pdev; + else + goto err; + } + return; +fail_pdev_add: + for (count = 0; count < rx_priv->child_count; count++) + platform_device_put(rx_priv->pdev_child_devices[count]); +err: + return; +} + +static void lpass_cdc_rx_macro_init_ops(struct macro_ops *ops, char __iomem *rx_io_base) +{ + memset(ops, 0, sizeof(struct macro_ops)); + ops->init = lpass_cdc_rx_macro_init; + ops->exit = lpass_cdc_rx_macro_deinit; + ops->io_base = rx_io_base; + ops->dai_ptr = lpass_cdc_rx_macro_dai; + ops->num_dais = ARRAY_SIZE(lpass_cdc_rx_macro_dai); + ops->event_handler = lpass_cdc_rx_macro_event_handler; + ops->set_port_map = lpass_cdc_rx_macro_set_port_map; +} + +static int lpass_cdc_rx_macro_probe(struct platform_device *pdev) +{ + struct macro_ops ops = {0}; + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + u32 rx_base_addr = 0, muxsel = 0; + char __iomem *rx_io_base = NULL, *muxsel_io = NULL; + int ret = 0; + u8 bcl_pmic_params[3]; + u32 default_clk_id = 0; + u32 is_used_rx_swr_gpio = 1; + const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio"; + + if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + + rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_rx_macro_priv), + GFP_KERNEL); + if (!rx_priv) + return -ENOMEM; + + rx_priv->dev = &pdev->dev; + ret = of_property_read_u32(pdev->dev.of_node, "reg", + &rx_base_addr); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "reg"); + return ret; + } + ret = of_property_read_u32(pdev->dev.of_node, "qcom,rx_mclk_mode_muxsel", + &muxsel); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "reg"); + return ret; + } + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,default-clk-id"); + default_clk_id = RX_CORE_CLK; + } + if (of_find_property(pdev->dev.of_node, is_used_rx_swr_gpio_dt, + NULL)) { + ret = of_property_read_u32(pdev->dev.of_node, + is_used_rx_swr_gpio_dt, + &is_used_rx_swr_gpio); + if (ret) { + dev_err(&pdev->dev, "%s: error reading %s in dt\n", + __func__, is_used_rx_swr_gpio_dt); + is_used_rx_swr_gpio = 1; + } + } + rx_priv->rx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,rx-swr-gpios", 0); + if (!rx_priv->rx_swr_gpio_p && is_used_rx_swr_gpio) { + dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n", + __func__); + return -EINVAL; + } + if (msm_cdc_pinctrl_get_state(rx_priv->rx_swr_gpio_p) < 0 && + is_used_rx_swr_gpio) { + dev_err(&pdev->dev, "%s: failed to get swr pin state\n", + __func__); + return -EPROBE_DEFER; + } + msm_cdc_pinctrl_set_wakeup_capable( + rx_priv->rx_swr_gpio_p, false); + + rx_io_base = devm_ioremap(&pdev->dev, rx_base_addr, + LPASS_CDC_RX_MACRO_MAX_OFFSET); + if (!rx_io_base) { + dev_err(&pdev->dev, "%s: ioremap failed\n", __func__); + return -ENOMEM; + } + rx_priv->rx_io_base = rx_io_base; + muxsel_io = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!muxsel_io) { + dev_err(&pdev->dev, "%s: ioremap failed for muxsel\n", + __func__); + return -ENOMEM; + } + rx_priv->rx_mclk_mode_muxsel = muxsel_io; + rx_priv->reset_swr = true; + INIT_WORK(&rx_priv->lpass_cdc_rx_macro_add_child_devices_work, + lpass_cdc_rx_macro_add_child_devices); + rx_priv->swr_plat_data.handle = (void *) rx_priv; + rx_priv->swr_plat_data.read = NULL; + rx_priv->swr_plat_data.write = NULL; + rx_priv->swr_plat_data.bulk_write = NULL; + rx_priv->swr_plat_data.clk = rx_swrm_clock; + rx_priv->swr_plat_data.core_vote = lpass_cdc_rx_macro_core_vote; + rx_priv->swr_plat_data.handle_irq = NULL; + + ret = of_property_read_u8_array(pdev->dev.of_node, + "qcom,rx-bcl-pmic-params", bcl_pmic_params, + sizeof(bcl_pmic_params)); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,rx-bcl-pmic-params"); + } else { + rx_priv->bcl_pmic_params.id = bcl_pmic_params[0]; + rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1]; + rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2]; + } + rx_priv->clk_id = default_clk_id; + rx_priv->default_clk_id = default_clk_id; + ops.clk_id_req = rx_priv->clk_id; + ops.default_clk_id = default_clk_id; + + rx_priv->is_aux_hpf_on = 1; + + dev_set_drvdata(&pdev->dev, rx_priv); + mutex_init(&rx_priv->mclk_lock); + mutex_init(&rx_priv->swr_clk_lock); + lpass_cdc_rx_macro_init_ops(&ops, rx_io_base); + + ret = lpass_cdc_register_macro(&pdev->dev, RX_MACRO, &ops); + if (ret) { + dev_err(&pdev->dev, + "%s: register macro failed\n", __func__); + goto err_reg_macro; + } + schedule_work(&rx_priv->lpass_cdc_rx_macro_add_child_devices_work); + pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_suspend_ignore_children(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); + + return 0; + +err_reg_macro: + mutex_destroy(&rx_priv->mclk_lock); + mutex_destroy(&rx_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_rx_macro_remove(struct platform_device *pdev) +{ + struct lpass_cdc_rx_macro_priv *rx_priv = NULL; + u16 count = 0; + + rx_priv = dev_get_drvdata(&pdev->dev); + + if (!rx_priv) + return -EINVAL; + + for (count = 0; count < rx_priv->child_count && + count < LPASS_CDC_RX_MACRO_CHILD_DEVICES_MAX; count++) + platform_device_unregister(rx_priv->pdev_child_devices[count]); + + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + lpass_cdc_unregister_macro(&pdev->dev, RX_MACRO); + mutex_destroy(&rx_priv->mclk_lock); + mutex_destroy(&rx_priv->swr_clk_lock); + kfree(rx_priv->swr_ctrl_data); + return 0; +} + +static const struct of_device_id lpass_cdc_rx_macro_dt_match[] = { + {.compatible = "qcom,lpass-cdc-rx-macro"}, + {} +}; + +static const struct dev_pm_ops lpass_cdc_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + pm_runtime_force_suspend, + pm_runtime_force_resume + ) + SET_RUNTIME_PM_OPS( + lpass_cdc_runtime_suspend, + lpass_cdc_runtime_resume, + NULL + ) +}; + +static struct platform_driver lpass_cdc_rx_macro_driver = { + .driver = { + .name = "lpass_cdc_rx_macro", + .owner = THIS_MODULE, + .pm = &lpass_cdc_dev_pm_ops, + .of_match_table = lpass_cdc_rx_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_rx_macro_probe, + .remove = lpass_cdc_rx_macro_remove, +}; + +module_platform_driver(lpass_cdc_rx_macro_driver); + +MODULE_DESCRIPTION("RX macro driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-tables.c b/asoc/codecs/lpass-cdc/lpass-cdc-tables.c new file mode 100644 index 0000000000..fd79ff5a27 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-tables.c @@ -0,0 +1,982 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "lpass-cdc.h" +#include "internal.h" + +u8 lpass_cdc_tx_reg_access[LPASS_CDC_TX_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX4_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX5_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX6_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX7_TX_PATH_SEC6)] = RD_WR_REG, +}; + +u8 lpass_cdc_tx_reg_access_v2[LPASS_CDC_TX_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG, +}; + +u8 lpass_cdc_rx_reg_access[LPASS_CDC_RX_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_SWR_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DEBUG_EN2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_WR_LSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_WR_MSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_LUT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_RD_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHL_COMP_RD_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_WR_LSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_WR_MSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_LUT)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_RD_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_HPHR_COMP_RD_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD0_DEBUG_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_DSD1_DEBUG_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_RX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_TX_I2S2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_TOP_I2S_MUX)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_DSD_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SOFTCLIP_CRC)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT2_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_INT2_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_RX_MIX_CFG5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CRC)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_DLY_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_DECAY_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_HPH_V_PA)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_EAR_V_PA)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_HPH_V_HD)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_EAR_V_HD)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K1_MSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K1_LSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K2_MSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_K2_LSB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_HPH)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_IDLE_EAR)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_TEST0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_TEST1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_OVR_VREF)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_CLSH_CLSG_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ADC_CAL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_PK_EST3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_RF_PROC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_RF_PROC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_TAC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DEBUG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_UPD_MON)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_GAIN_MON_VAL)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BAN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_ATTN3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_CFG4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_BCL_VBAT_DECODE_ST)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_CLR_COMMIT)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_STATUS0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN1_CLEAR0)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_STATUS0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_PIN2_CLEAR0)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_LEVEL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_BYPASS0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_INTR_CTRL_SET0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX0_RX_PATH_DSM_DATA6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX1_RX_PATH_DSM_DATA6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_VOL_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_MIX_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_RX2_RX_PATH_DSM_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IDLE_DETECT_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL6)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER0_CTL7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL6)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_COMPANDER1_CTL7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] = + RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL)] = + RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CLK_RST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_FIFO_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC0_STATUS_FIFO)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CLK_RST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_FIFO_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC1_STATUS_FIFO)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CLK_RST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_FIFO_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_EC_ASRC2_STATUS_FIFO)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD0_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD0_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD1_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_RX_DSD1_CFG2)] = RD_WR_REG, +}; + +u8 lpass_cdc_va_reg_access[LPASS_CDC_VA_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX4_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX5_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX6_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX7_TX_PATH_SEC6)] = RD_WR_REG, +}; + +u8 lpass_cdc_va_top_reg_access[LPASS_CDC_VA_MACRO_TOP_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG, +}; + +u8 lpass_cdc_va_reg_access_v2[LPASS_CDC_VA_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG, +}; + +u8 lpass_cdc_va_reg_access_v3[LPASS_CDC_VA_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG, +}; + +u8 lpass_cdc_wsa_reg_access[LPASS_CDC_WSA_MACRO_MAX] = { + [LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TOP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TOP_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_FREQ_MCLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_BUS_SEL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_EN0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_EN1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_DEBUG_DSM_LB)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_RX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_TX_I2S_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_I2S_CLK)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TOP_I2S_RESET)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_RX_EC_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_ADC_CAL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_PK_EST3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_RF_PROC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_TAC4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DEBUG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_UPD_MON)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BAN)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_ATTN3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_CLR_COMMIT)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_MASK0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_STATUS0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN1_CLEAR0)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_MASK0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_STATUS0)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_PIN2_CLEAR0)] = WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_LEVEL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_BYPASS0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_INTR_CTRL_SET0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX0_RX_PATH_DSMDEM_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_CFG3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_VOL_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC6)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_SEC7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_RX1_RX_PATH_DSMDEM_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST0_BOOST_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CFG1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_BOOST1_BOOST_CFG2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL6)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER0_CTL7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL2)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL3)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL4)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL5)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL6)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_COMPANDER1_CTL7)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP0_CRC)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP1_CRC)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_FIFO_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC0_STATUS_FIFO)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_CTL0)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_CTL1)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_FIFO_CTL)] = RD_WR_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB)] = RD_REG, + [LPASS_CDC_REG(LPASS_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO)] = RD_REG, +}; + +u8 *lpass_cdc_reg_access[MAX_MACRO] = { + [TX_MACRO] = lpass_cdc_tx_reg_access, + [RX_MACRO] = lpass_cdc_rx_reg_access, + [WSA_MACRO] = lpass_cdc_wsa_reg_access, + [VA_MACRO] = lpass_cdc_va_reg_access, +}; diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c new file mode 100644 index 0000000000..b2c17c8524 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c @@ -0,0 +1,3518 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lpass-cdc.h" +#include "lpass-cdc-registers.h" +#include "lpass-cdc-clk-rsc.h" + +#define AUTO_SUSPEND_DELAY 50 /* delay in msec */ +#define LPASS_CDC_TX_MACRO_MAX_OFFSET 0x1000 + +#define NUM_DECIMATORS 8 + +#define LPASS_CDC_TX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define LPASS_CDC_TX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define TX_HPF_CUT_OFF_FREQ_MASK 0x60 +#define CF_MIN_3DB_4HZ 0x0 +#define CF_MIN_3DB_75HZ 0x1 +#define CF_MIN_3DB_150HZ 0x2 + +#define LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0 +#define LPASS_CDC_TX_MACRO_MCLK_FREQ 9600000 +#define LPASS_CDC_TX_MACRO_TX_PATH_OFFSET 0x80 +#define LPASS_CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK 0xF +#define LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET 0x8 +#define LPASS_CDC_TX_MACRO_ADC_MODE_CFG0_SHIFT 1 + +#define LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS 40 +#define LPASS_CDC_TX_MACRO_AMIC_UNMUTE_DELAY_MS 100 +#define LPASS_CDC_TX_MACRO_DMIC_HPF_DELAY_MS 300 +#define LPASS_CDC_TX_MACRO_AMIC_HPF_DELAY_MS 300 + +static int tx_unmute_delay = LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS; +module_param(tx_unmute_delay, int, 0664); +MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path"); + +static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); + +static int lpass_cdc_tx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); +static int lpass_cdc_tx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot); + +#define LPASS_CDC_TX_MACRO_SWR_STRING_LEN 80 +#define LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX 3 + +/* Hold instance to soundwire platform device */ +struct lpass_cdc_tx_macro_swr_ctrl_data { + struct platform_device *tx_swr_pdev; +}; + +struct lpass_cdc_tx_macro_swr_ctrl_platform_data { + void *handle; /* holds codec private data */ + int (*read)(void *handle, int reg); + int (*write)(void *handle, int reg, int val); + int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len); + int (*clk)(void *handle, bool enable); + int (*core_vote)(void *handle, bool enable); + int (*handle_irq)(void *handle, + irqreturn_t (*swrm_irq_handler)(int irq, + void *data), + void *swrm_handle, + int action); +}; + +enum { + LPASS_CDC_TX_MACRO_AIF_INVALID = 0, + LPASS_CDC_TX_MACRO_AIF1_CAP, + LPASS_CDC_TX_MACRO_AIF2_CAP, + LPASS_CDC_TX_MACRO_AIF3_CAP, + LPASS_CDC_TX_MACRO_MAX_DAIS +}; + +enum { + LPASS_CDC_TX_MACRO_DEC0, + LPASS_CDC_TX_MACRO_DEC1, + LPASS_CDC_TX_MACRO_DEC2, + LPASS_CDC_TX_MACRO_DEC3, + LPASS_CDC_TX_MACRO_DEC4, + LPASS_CDC_TX_MACRO_DEC5, + LPASS_CDC_TX_MACRO_DEC6, + LPASS_CDC_TX_MACRO_DEC7, + LPASS_CDC_TX_MACRO_DEC_MAX, +}; + +enum { + LPASS_CDC_TX_MACRO_CLK_DIV_2, + LPASS_CDC_TX_MACRO_CLK_DIV_3, + LPASS_CDC_TX_MACRO_CLK_DIV_4, + LPASS_CDC_TX_MACRO_CLK_DIV_6, + LPASS_CDC_TX_MACRO_CLK_DIV_8, + LPASS_CDC_TX_MACRO_CLK_DIV_16, +}; + +enum { + MSM_DMIC, + SWR_MIC, + ANC_FB_TUNE1 +}; + +enum { + TX_MCLK, + VA_MCLK, +}; + +struct lpass_cdc_tx_macro_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +struct tx_mute_work { + struct lpass_cdc_tx_macro_priv *tx_priv; + u32 decimator; + struct delayed_work dwork; +}; + +struct hpf_work { + struct lpass_cdc_tx_macro_priv *tx_priv; + u8 decimator; + u8 hpf_cut_off_freq; + struct delayed_work dwork; +}; + +struct lpass_cdc_tx_macro_priv { + struct device *dev; + bool dec_active[NUM_DECIMATORS]; + int tx_mclk_users; + int swr_clk_users; + bool dapm_mclk_enable; + bool reset_swr; + struct mutex mclk_lock; + struct mutex swr_clk_lock; + struct snd_soc_component *component; + struct device_node *tx_swr_gpio_p; + struct lpass_cdc_tx_macro_swr_ctrl_data *swr_ctrl_data; + struct lpass_cdc_tx_macro_swr_ctrl_platform_data swr_plat_data; + struct work_struct lpass_cdc_tx_macro_add_child_devices_work; + struct hpf_work tx_hpf_work[NUM_DECIMATORS]; + struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS]; + u16 dmic_clk_div; + u32 version; + u32 is_used_tx_swr_gpio; + unsigned long active_ch_mask[LPASS_CDC_TX_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[LPASS_CDC_TX_MACRO_MAX_DAIS]; + char __iomem *tx_io_base; + struct platform_device *pdev_child_devices + [LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX]; + int child_count; + int tx_swr_clk_cnt; + int va_swr_clk_cnt; + int va_clk_status; + int tx_clk_status; + bool bcs_enable; + int dec_mode[NUM_DECIMATORS]; + int bcs_ch; + bool bcs_clk_en; + bool hs_slow_insert_complete; + int amic_sample_rate; + bool lpi_enable; + bool register_event_listener; +}; + +static bool lpass_cdc_tx_macro_get_data(struct snd_soc_component *component, + struct device **tx_dev, + struct lpass_cdc_tx_macro_priv **tx_priv, + const char *func_name) +{ + *tx_dev = lpass_cdc_get_device_ptr(component->dev, TX_MACRO); + if (!(*tx_dev)) { + dev_err(component->dev, + "%s: null device for macro!\n", func_name); + return false; + } + + *tx_priv = dev_get_drvdata((*tx_dev)); + if (!(*tx_priv)) { + dev_err(component->dev, + "%s: priv is null for macro!\n", func_name); + return false; + } + + if (!(*tx_priv)->component) { + dev_err(component->dev, + "%s: tx_priv->component not initialized!\n", func_name); + return false; + } + + return true; +} + +static int lpass_cdc_tx_macro_mclk_enable( + struct lpass_cdc_tx_macro_priv *tx_priv, + bool mclk_enable) +{ + struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + dev_dbg(tx_priv->dev, "%s: mclk_enable = %u,clk_users= %d\n", + __func__, mclk_enable, tx_priv->tx_mclk_users); + + mutex_lock(&tx_priv->mclk_lock); + if (mclk_enable) { + ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + if (ret < 0) { + dev_err_ratelimited(tx_priv->dev, + "%s: request clock enable failed\n", + __func__); + goto exit; + } + lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev, + true); + regcache_mark_dirty(regmap); + regcache_sync_region(regmap, + TX_START_OFFSET, + TX_MAX_OFFSET); + if (tx_priv->tx_mclk_users == 0) { + /* 9.6MHz MCLK, set value 0x00 if other frequency */ + regmap_update_bits(regmap, + LPASS_CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x01); + } + tx_priv->tx_mclk_users++; + } else { + if (tx_priv->tx_mclk_users <= 0) { + dev_err(tx_priv->dev, "%s: clock already disabled\n", + __func__); + tx_priv->tx_mclk_users = 0; + goto exit; + } + tx_priv->tx_mclk_users--; + if (tx_priv->tx_mclk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x00); + } + + lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev, + false); + lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + } +exit: + mutex_unlock(&tx_priv->mclk_lock); + return ret; +} + +static int __lpass_cdc_tx_macro_mclk_enable(struct snd_soc_component *component, + bool enable) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + return lpass_cdc_tx_macro_mclk_enable(tx_priv, enable); +} + +static int lpass_cdc_tx_macro_va_swr_clk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (SND_SOC_DAPM_EVENT_ON(event)) + ++tx_priv->va_swr_clk_cnt; + if (SND_SOC_DAPM_EVENT_OFF(event)) + --tx_priv->va_swr_clk_cnt; + + return 0; +} + +static int lpass_cdc_tx_macro_tx_swr_clk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (SND_SOC_DAPM_EVENT_ON(event)) + ++tx_priv->tx_swr_clk_cnt; + if (SND_SOC_DAPM_EVENT_OFF(event)) + --tx_priv->tx_swr_clk_cnt; + + return 0; +} + +static int lpass_cdc_tx_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + dev_dbg(tx_dev, "%s: event = %d, lpi_enable = %d\n", + __func__, event, tx_priv->lpi_enable); + + if (!tx_priv->lpi_enable) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (tx_priv->lpi_enable) { + lpass_cdc_register_event_listener(component, true); + tx_priv->register_event_listener = true; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (tx_priv->register_event_listener) { + tx_priv->register_event_listener = false; + lpass_cdc_register_event_listener(component, false); + } + break; + default: + dev_err(tx_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_tx_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + dev_dbg(tx_dev, "%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = lpass_cdc_tx_macro_mclk_enable(tx_priv, 1); + if (ret) + tx_priv->dapm_mclk_enable = false; + else + tx_priv->dapm_mclk_enable = true; + break; + case SND_SOC_DAPM_POST_PMD: + if (tx_priv->dapm_mclk_enable) + ret = lpass_cdc_tx_macro_mclk_enable(tx_priv, 0); + break; + default: + dev_err(tx_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_tx_macro_event_handler(struct snd_soc_component *component, + u16 event, u32 data) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + int ret = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + switch (event) { + case LPASS_CDC_MACRO_EVT_SSR_DOWN: + trace_printk("%s, enter SSR down\n", __func__); + if (tx_priv->swr_ctrl_data) { + swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_DEVICE_SSR_DOWN, NULL); + } + if ((!pm_runtime_enabled(tx_dev) || + !pm_runtime_suspended(tx_dev))) { + ret = lpass_cdc_runtime_suspend(tx_dev); + if (!ret) { + pm_runtime_disable(tx_dev); + pm_runtime_set_suspended(tx_dev); + pm_runtime_enable(tx_dev); + } + } + break; + case LPASS_CDC_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + /* reset swr after ssr/pdr */ + tx_priv->reset_swr = true; + if (tx_priv->swr_ctrl_data) + swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_DEVICE_SSR_UP, NULL); + break; + case LPASS_CDC_MACRO_EVT_CLK_RESET: + lpass_cdc_rsc_clk_reset(tx_dev, TX_CORE_CLK); + break; + case LPASS_CDC_MACRO_EVT_BCS_CLK_OFF: + if (tx_priv->bcs_clk_en) + snd_soc_component_update_bits(component, + LPASS_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6); + if (data) + tx_priv->hs_slow_insert_complete = true; + else + tx_priv->hs_slow_insert_complete = false; + break; + default: + pr_debug("%s Invalid Event\n", __func__); + break; + } + return 0; +} + +static int lpass_cdc_tx_macro_reg_wake_irq(struct snd_soc_component *component, + u32 data) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + u32 ipc_wakeup = data; + int ret = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (tx_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_REGISTER_WAKE_IRQ, &ipc_wakeup); + + return ret; +} + +static bool is_amic_enabled(struct snd_soc_component *component, int decimator) +{ + u16 adc_mux_reg = 0, adc_reg = 0; + u16 adc_n = LPASS_CDC_ADC_MAX; + bool ret = false; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return ret; + + adc_mux_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + + LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; + if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) { + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + return true; + adc_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0 + + LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; + adc_n = snd_soc_component_read32(component, adc_reg) & + LPASS_CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK; + if (adc_n < LPASS_CDC_ADC_MAX) + return true; + } + + return ret; +} + +static void lpass_cdc_tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work) +{ + struct delayed_work *hpf_delayed_work = NULL; + struct hpf_work *hpf_work = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct snd_soc_component *component = NULL; + u16 dec_cfg_reg = 0, hpf_gate_reg = 0; + u8 hpf_cut_off_freq = 0; + u16 adc_reg = 0, adc_n = 0; + + hpf_delayed_work = to_delayed_work(work); + hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork); + tx_priv = hpf_work->tx_priv; + component = tx_priv->component; + hpf_cut_off_freq = hpf_work->hpf_cut_off_freq; + + dec_cfg_reg = LPASS_CDC_TX0_TX_PATH_CFG0 + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator; + hpf_gate_reg = LPASS_CDC_TX0_TX_PATH_SEC2 + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * hpf_work->decimator; + + dev_dbg(component->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n", + __func__, hpf_work->decimator, hpf_cut_off_freq); + + if (is_amic_enabled(component, hpf_work->decimator)) { + adc_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0 + + LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator; + adc_n = snd_soc_component_read32(component, adc_reg) & + LPASS_CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK; + /* analog mic clear TX hold */ + lpass_cdc_clear_amic_tx_hold(component->dev, adc_n); + snd_soc_component_update_bits(component, + dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x03, 0x02); + /* Add delay between toggle hpf gate based on sample rate */ + switch(tx_priv->amic_sample_rate) { + case 8000: + usleep_range(125, 130); + break; + case 16000: + usleep_range(62, 65); + break; + case 32000: + usleep_range(31, 32); + break; + case 48000: + usleep_range(20, 21); + break; + case 96000: + usleep_range(10, 11); + break; + case 192000: + usleep_range(5, 6); + break; + default: + usleep_range(125, 130); + } + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x03, 0x01); + } else { + snd_soc_component_update_bits(component, + dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x02, 0x02); + /* Minimum 1 clk cycle delay is required as per HW spec */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x02, 0x00); + } +} + +static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work) +{ + struct tx_mute_work *tx_mute_dwork = NULL; + struct snd_soc_component *component = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct delayed_work *delayed_work = NULL; + u16 tx_vol_ctl_reg = 0; + u8 decimator = 0; + + delayed_work = to_delayed_work(work); + tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork); + tx_priv = tx_mute_dwork->tx_priv; + component = tx_priv->component; + decimator = tx_mute_dwork->decimator; + + tx_vol_ctl_reg = + LPASS_CDC_TX0_TX_PATH_CTL + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); + dev_dbg(tx_priv->dev, "%s: decimator %u unmute\n", + __func__, decimator); +} + +static int lpass_cdc_tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val = 0; + u16 mic_sel_reg = 0; + u16 dmic_clk_reg = 0; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + val = ucontrol->value.enumerated.item[0]; + if (val > e->items - 1) + return -EINVAL; + + dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__, + widget->name, val); + + switch (e->reg) { + case LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0: + mic_sel_reg = LPASS_CDC_TX0_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0: + mic_sel_reg = LPASS_CDC_TX1_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0: + mic_sel_reg = LPASS_CDC_TX2_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0: + mic_sel_reg = LPASS_CDC_TX3_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0: + mic_sel_reg = LPASS_CDC_TX4_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0: + mic_sel_reg = LPASS_CDC_TX5_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0: + mic_sel_reg = LPASS_CDC_TX6_TX_PATH_CFG0; + break; + case LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0: + mic_sel_reg = LPASS_CDC_TX7_TX_PATH_CFG0; + break; + default: + dev_err(component->dev, "%s: e->reg: 0x%x not expected\n", + __func__, e->reg); + return -EINVAL; + } + if (strnstr(widget->name, "SMIC", strlen(widget->name))) { + if (val != 0) { + if (val < 5) { + snd_soc_component_update_bits(component, + mic_sel_reg, + 1 << 7, 0x0 << 7); + } else { + snd_soc_component_update_bits(component, + mic_sel_reg, + 1 << 7, 0x1 << 7); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + 0x80, 0x00); + dmic_clk_reg = + LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL + + ((val - 5)/2) * 4; + snd_soc_component_update_bits(component, + dmic_clk_reg, + 0x0E, tx_priv->dmic_clk_div << 0x1); + } + } + } else { + /* DMIC selected */ + if (val != 0) + snd_soc_component_update_bits(component, mic_sel_reg, + 1 << 7, 1 << 7); + } + + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static int lpass_cdc_tx_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 dai_id = widget->shift; + u32 dec_id = mixer->shift; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (test_bit(dec_id, &tx_priv->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + return 0; +} + +static int lpass_cdc_tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct snd_soc_dapm_update *update = NULL; + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 dai_id = widget->shift; + u32 dec_id = mixer->shift; + u32 enable = ucontrol->value.integer.value[0]; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (enable) { + set_bit(dec_id, &tx_priv->active_ch_mask[dai_id]); + tx_priv->active_ch_cnt[dai_id]++; + } else { + tx_priv->active_ch_cnt[dai_id]--; + clear_bit(dec_id, &tx_priv->active_ch_mask[dai_id]); + } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); + + return 0; +} + +static inline int lpass_cdc_tx_macro_path_get(const char *wname, + unsigned int *path_num) +{ + int ret = 0; + char *widget_name = NULL; + char *w_name = NULL; + char *path_num_char = NULL; + char *path_name = NULL; + + widget_name = kstrndup(wname, 10, GFP_KERNEL); + if (!widget_name) + return -EINVAL; + + w_name = widget_name; + + path_name = strsep(&widget_name, " "); + if (!path_name) { + pr_err("%s: Invalid widget name = %s\n", + __func__, widget_name); + ret = -EINVAL; + goto err; + } + path_num_char = strpbrk(path_name, "01234567"); + if (!path_num_char) { + pr_err("%s: tx path index not found\n", + __func__); + ret = -EINVAL; + goto err; + } + ret = kstrtouint(path_num_char, 10, path_num); + if (ret < 0) + pr_err("%s: Invalid tx path = %s\n", + __func__, w_name); + +err: + kfree(w_name); + return ret; +} + +static int lpass_cdc_tx_macro_dec_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int ret = 0; + int path = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + ret = lpass_cdc_tx_macro_path_get(kcontrol->id.name, &path); + if (ret) + return ret; + + ucontrol->value.integer.value[0] = tx_priv->dec_mode[path]; + + return 0; +} + +static int lpass_cdc_tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int value = ucontrol->value.integer.value[0]; + int ret = 0; + int path = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + ret = lpass_cdc_tx_macro_path_get(kcontrol->id.name, &path); + if (ret) + return ret; + + tx_priv->dec_mode[path] = value; + + return 0; +} + +static int lpass_cdc_tx_macro_lpi_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = tx_priv->lpi_enable; + + return 0; +} + +static int lpass_cdc_tx_macro_lpi_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + tx_priv->lpi_enable = ucontrol->value.integer.value[0]; + + return 0; +} + +static int lpass_cdc_tx_macro_bcs_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + ucontrol->value.enumerated.item[0] = tx_priv->bcs_ch; + + return 0; +} + +static int lpass_cdc_tx_macro_bcs_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int value = ucontrol->value.enumerated.item[0]; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + tx_priv->bcs_ch = value; + + return 0; +} + +static int lpass_cdc_tx_macro_get_bcs(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = tx_priv->bcs_enable; + + return 0; +} + +static int lpass_cdc_tx_macro_set_bcs(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int value = ucontrol->value.integer.value[0]; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + tx_priv->bcs_enable = value; + + return 0; +} + +static const char * const bcs_ch_sel_mux_text[] = { + "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3", + "SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7", + "SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11", +}; + +static const struct soc_enum bcs_ch_sel_mux_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_sel_mux_text), + bcs_ch_sel_mux_text); + +static int lpass_cdc_tx_macro_get_bcs_ch_sel(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int value = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + value = (snd_soc_component_read32(component, + LPASS_CDC_VA_TOP_CSR_SWR_CTRL)) & 0x0F; + else if (tx_priv->version == LPASS_CDC_VERSION_2_0) + value = (snd_soc_component_read32(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL)) & 0x0F; + + ucontrol->value.integer.value[0] = value; + return 0; +} + +static int lpass_cdc_tx_macro_put_bcs_ch_sel(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct device *tx_dev = NULL; + int value; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + if (ucontrol->value.integer.value[0] < 0 || + ucontrol->value.integer.value[0] > ARRAY_SIZE(bcs_ch_sel_mux_text)) + return -EINVAL; + + value = ucontrol->value.integer.value[0]; + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F, value); + else if (tx_priv->version == LPASS_CDC_VERSION_2_0) + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0x0F, value); + + return 0; +} + +static int lpass_cdc_tx_macro_enable_dmic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int dmic = 0; + int ret = 0; + char *wname = NULL; + + wname = strpbrk(w->name, "01234567"); + if (!wname) { + dev_err(component->dev, "%s: widget not found\n", __func__); + return -EINVAL; + } + + ret = kstrtouint(wname, 10, &dmic); + if (ret < 0) { + dev_err(component->dev, "%s: Invalid DMIC line on the codec\n", + __func__); + return -EINVAL; + } + + dev_dbg(component->dev, "%s: event %d DMIC%d\n", + __func__, event, dmic); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_dmic_clk_enable(component, dmic, DMIC_TX, true); + break; + case SND_SOC_DAPM_POST_PMD: + lpass_cdc_dmic_clk_enable(component, dmic, DMIC_TX, false); + break; + } + + return 0; +} + +static int lpass_cdc_tx_macro_enable_dec(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int decimator = 0; + u16 tx_vol_ctl_reg = 0; + u16 dec_cfg_reg = 0; + u16 hpf_gate_reg = 0; + u16 tx_gain_ctl_reg = 0; + u16 tx_fs_reg = 0; + u8 hpf_cut_off_freq = 0; + u16 adc_mux_reg = 0; + int hpf_delay = LPASS_CDC_TX_MACRO_DMIC_HPF_DELAY_MS; + int unmute_delay = LPASS_CDC_TX_MACRO_DMIC_UNMUTE_DELAY_MS; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + decimator = w->shift; + + dev_dbg(component->dev, "%s(): widget = %s decimator = %u\n", __func__, + w->name, decimator); + + tx_vol_ctl_reg = LPASS_CDC_TX0_TX_PATH_CTL + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + hpf_gate_reg = LPASS_CDC_TX0_TX_PATH_SEC2 + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + dec_cfg_reg = LPASS_CDC_TX0_TX_PATH_CFG0 + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + tx_gain_ctl_reg = LPASS_CDC_TX0_TX_VOL_CTL + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + adc_mux_reg = LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + + LPASS_CDC_TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; + tx_fs_reg = LPASS_CDC_TX0_TX_PATH_CTL + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + + tx_priv->amic_sample_rate = (snd_soc_component_read32(component, + tx_fs_reg) & 0x0F); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, + dec_cfg_reg, 0x06, tx_priv->dec_mode[decimator] << + LPASS_CDC_TX_MACRO_ADC_MODE_CFG0_SHIFT); + /* Enable TX PGA Mute */ + snd_soc_component_update_bits(component, + tx_vol_ctl_reg, 0x10, 0x10); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_update_bits(component, + tx_vol_ctl_reg, 0x20, 0x20); + if (!is_amic_enabled(component, decimator)) { + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x01, 0x00); + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + } + hpf_cut_off_freq = ( + snd_soc_component_read32(component, dec_cfg_reg) & + TX_HPF_CUT_OFF_FREQ_MASK) >> 5; + + tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq = + hpf_cut_off_freq; + + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) + snd_soc_component_update_bits(component, dec_cfg_reg, + TX_HPF_CUT_OFF_FREQ_MASK, + CF_MIN_3DB_150HZ << 5); + + if (is_amic_enabled(component, decimator)) { + hpf_delay = LPASS_CDC_TX_MACRO_AMIC_HPF_DELAY_MS; + unmute_delay = LPASS_CDC_TX_MACRO_AMIC_UNMUTE_DELAY_MS; + } + if (tx_unmute_delay < unmute_delay) + tx_unmute_delay = unmute_delay; + /* schedule work queue to Remove Mute */ + queue_delayed_work(system_freezable_wq, + &tx_priv->tx_mute_dwork[decimator].dwork, + msecs_to_jiffies(tx_unmute_delay)); + if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq != + CF_MIN_3DB_150HZ) { + queue_delayed_work(system_freezable_wq, + &tx_priv->tx_hpf_work[decimator].dwork, + msecs_to_jiffies(hpf_delay)); + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x02); + if (!is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x00); + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x01); + /* + * 6ms delay is required as per HW spec + */ + usleep_range(6000, 6010); + } + /* apply gain after decimator is enabled */ + snd_soc_component_write(component, tx_gain_ctl_reg, + snd_soc_component_read32(component, + tx_gain_ctl_reg)); + if (tx_priv->bcs_enable) { + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F, + tx_priv->bcs_ch); + else if (tx_priv->version == LPASS_CDC_VERSION_2_0) + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0, + (tx_priv->bcs_ch << 4)); + + snd_soc_component_update_bits(component, dec_cfg_reg, + 0x01, 0x01); + tx_priv->bcs_clk_en = true; + if (tx_priv->hs_slow_insert_complete) + snd_soc_component_update_bits(component, + LPASS_CDC_TX0_TX_PATH_SEC7, 0x40, + 0x40); + } + if (tx_priv->version == LPASS_CDC_VERSION_2_0) { + if (snd_soc_component_read32(component, adc_mux_reg) + & SWR_MIC) { + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, + 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL, + 0x0E, 0x0C); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL, + 0x0E, 0x0C); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL, + 0x0E, 0x00); + } + } + break; + case SND_SOC_DAPM_PRE_PMD: + hpf_cut_off_freq = + tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq; + snd_soc_component_update_bits(component, + tx_vol_ctl_reg, 0x10, 0x10); + if (cancel_delayed_work_sync( + &tx_priv->tx_hpf_work[decimator].dwork)) { + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + snd_soc_component_update_bits( + component, dec_cfg_reg, + TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + if (is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x02); + else + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x03); + + /* + * Minimum 1 clk cycle delay is required + * as per HW spec + */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x01); + } + } + cancel_delayed_work_sync( + &tx_priv->tx_mute_dwork[decimator].dwork); + + if (tx_priv->version == LPASS_CDC_VERSION_2_0) { + if (snd_soc_component_read32(component, adc_mux_reg) + & SWR_MIC) + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, + 0x01, 0x00); + } + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x20, 0x00); + snd_soc_component_update_bits(component, + dec_cfg_reg, 0x06, 0x00); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x10, 0x00); + if (tx_priv->bcs_enable) { + snd_soc_component_update_bits(component, dec_cfg_reg, + 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00); + tx_priv->bcs_clk_en = false; + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_CTRL, 0x0F, + 0x00); + else if (tx_priv->version == LPASS_CDC_VERSION_2_0) + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0, + 0x00); + } + break; + } + return 0; +} + +static int lpass_cdc_tx_macro_enable_micbias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + return 0; +} + +/* Cutoff frequency for high pass filter */ +static const char * const cf_text[] = { + "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ" +}; + +static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, LPASS_CDC_TX0_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, LPASS_CDC_TX1_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, LPASS_CDC_TX2_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, LPASS_CDC_TX3_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, LPASS_CDC_TX4_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, LPASS_CDC_TX5_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, LPASS_CDC_TX6_TX_PATH_CFG0, 5, + cf_text); +static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, LPASS_CDC_TX7_TX_PATH_CFG0, 5, + cf_text); + +static int lpass_cdc_tx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int tx_fs_rate = -EINVAL; + struct snd_soc_component *component = dai->component; + u32 decimator = 0; + u32 sample_rate = 0; + u16 tx_fs_reg = 0; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__, + dai->name, dai->id, params_rate(params), + params_channels(params)); + + sample_rate = params_rate(params); + switch (sample_rate) { + case 8000: + tx_fs_rate = 0; + break; + case 16000: + tx_fs_rate = 1; + break; + case 32000: + tx_fs_rate = 3; + break; + case 48000: + tx_fs_rate = 4; + break; + case 96000: + tx_fs_rate = 5; + break; + case 192000: + tx_fs_rate = 6; + break; + case 384000: + tx_fs_rate = 7; + break; + default: + dev_err(component->dev, "%s: Invalid TX sample rate: %d\n", + __func__, params_rate(params)); + return -EINVAL; + } + for_each_set_bit(decimator, &tx_priv->active_ch_mask[dai->id], + LPASS_CDC_TX_MACRO_DEC_MAX) { + if (decimator >= 0) { + tx_fs_reg = LPASS_CDC_TX0_TX_PATH_CTL + + LPASS_CDC_TX_MACRO_TX_PATH_OFFSET * decimator; + dev_dbg(component->dev, "%s: set DEC%u rate to %u\n", + __func__, decimator, sample_rate); + snd_soc_component_update_bits(component, tx_fs_reg, + 0x0F, tx_fs_rate); + } else { + dev_err(component->dev, + "%s: ERROR: Invalid decimator: %d\n", + __func__, decimator); + return -EINVAL; + } + } + return 0; +} + +static int lpass_cdc_tx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + switch (dai->id) { + case LPASS_CDC_TX_MACRO_AIF1_CAP: + case LPASS_CDC_TX_MACRO_AIF2_CAP: + case LPASS_CDC_TX_MACRO_AIF3_CAP: + *tx_slot = tx_priv->active_ch_mask[dai->id]; + *tx_num = tx_priv->active_ch_cnt[dai->id]; + break; + default: + dev_err(tx_dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static struct snd_soc_dai_ops lpass_cdc_tx_macro_dai_ops = { + .hw_params = lpass_cdc_tx_macro_hw_params, + .get_channel_map = lpass_cdc_tx_macro_get_channel_map, +}; + +static struct snd_soc_dai_driver lpass_cdc_tx_macro_dai[] = { + { + .name = "lpass_cdc_tx_macro_tx1", + .id = LPASS_CDC_TX_MACRO_AIF1_CAP, + .capture = { + .stream_name = "TX_AIF1 Capture", + .rates = LPASS_CDC_TX_MACRO_RATES, + .formats = LPASS_CDC_TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_tx_macro_dai_ops, + }, + { + .name = "lpass_cdc_tx_macro_tx2", + .id = LPASS_CDC_TX_MACRO_AIF2_CAP, + .capture = { + .stream_name = "TX_AIF2 Capture", + .rates = LPASS_CDC_TX_MACRO_RATES, + .formats = LPASS_CDC_TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_tx_macro_dai_ops, + }, + { + .name = "lpass_cdc_tx_macro_tx3", + .id = LPASS_CDC_TX_MACRO_AIF3_CAP, + .capture = { + .stream_name = "TX_AIF3 Capture", + .rates = LPASS_CDC_TX_MACRO_RATES, + .formats = LPASS_CDC_TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_tx_macro_dai_ops, + }, +}; + +#define STRING(name) #name +#define LPASS_CDC_TX_MACRO_DAPM_ENUM(name, reg, offset, text) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM(STRING(name), name##_enum) + +#define LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname) + +#define LPASS_CDC_TX_MACRO_DAPM_MUX(name, shift, kctl) \ + SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux) + +static const char * const adc_mux_text[] = { + "MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1" +}; + +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG1, + 0, adc_mux_text); +LPASS_CDC_TX_MACRO_DAPM_ENUM(tx_dec7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG1, + 0, adc_mux_text); + + +static const char * const dmic_mux_text[] = { + "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", + "DMIC4", "DMIC5", "DMIC6", "DMIC7" +}; + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_dmic7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +static const char * const smic_mux_text[] = { + "ZERO", "ADC0", "ADC1", "ADC2", "ADC3", "SWR_DMIC0", + "SWR_DMIC1", "SWR_DMIC2", "SWR_DMIC3", "SWR_DMIC4", + "SWR_DMIC5", "SWR_DMIC6", "SWR_DMIC7" +}; + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic0, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic1, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic3, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic4, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic5, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic6, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic7, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +static const char * const smic_mux_text_v2[] = { + "ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3", + "SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7", + "SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11" +}; + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic0_v2, LPASS_CDC_TX_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic1_v2, LPASS_CDC_TX_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic2_v2, LPASS_CDC_TX_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic3_v2, LPASS_CDC_TX_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic4_v3, LPASS_CDC_TX_INP_MUX_ADC_MUX4_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic5_v3, LPASS_CDC_TX_INP_MUX_ADC_MUX5_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic6_v3, LPASS_CDC_TX_INP_MUX_ADC_MUX6_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +LPASS_CDC_TX_MACRO_DAPM_ENUM_EXT(tx_smic7_v3, LPASS_CDC_TX_INP_MUX_ADC_MUX7_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_tx_macro_put_dec_enum); + +static const char * const dec_mode_mux_text[] = { + "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", +}; + +static const struct soc_enum dec_mode_mux_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text); + +static const char * const bcs_ch_enum_text[] = { + "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8", "CH9", + "CH10", "CH11", +}; + +static const struct soc_enum bcs_ch_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bcs_ch_enum_text), + bcs_ch_enum_text); + +static const struct snd_kcontrol_new tx_aif1_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif2_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif3_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC4, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC5, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC6, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC7, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif1_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif2_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif3_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC0, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC1, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC2, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_DEC3, 1, 0, + lpass_cdc_tx_macro_tx_mixer_get, lpass_cdc_tx_macro_tx_mixer_put), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_tx_macro_dapm_widgets_common[] = { + SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF1_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF2_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF3_CAP, 0), + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3), + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v2), + + SND_SOC_DAPM_SUPPLY("TX MIC BIAS1", SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("TX SWR_INPUT"), + + SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC0, 0, + &tx_dec0_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC1, 0, + &tx_dec1_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC2, 0, + &tx_dec2_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC3, 0, + &tx_dec3_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_swr_pwr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_tx_macro_dapm_widgets_v2[] = { + SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF1_CAP, 0, + tx_aif1_cap_mixer_v2, ARRAY_SIZE(tx_aif1_cap_mixer_v2)), + + SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF2_CAP, 0, + tx_aif2_cap_mixer_v2, ARRAY_SIZE(tx_aif2_cap_mixer_v2)), + + SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF3_CAP, 0, + tx_aif3_cap_mixer_v2, ARRAY_SIZE(tx_aif3_cap_mixer_v2)), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_tx_macro_dapm_widgets_v3[] = { + SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF1_CAP, 0, + tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF2_CAP, 0, + tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_AIF3_CAP, 0, + tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)), + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7), + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4_v3), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5_v3), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6_v3), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7_v3), + + SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC4, 0, + &tx_dec4_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC5, 0, + &tx_dec5_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC6, 0, + &tx_dec6_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC7, 0, + &tx_dec7_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_tx_swr_clk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_va_swr_clk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_tx_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF1_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF2_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF3_CAP, 0), + + SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF1_CAP, 0, + tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF2_CAP, 0, + tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, LPASS_CDC_TX_MACRO_AIF3_CAP, 0, + tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)), + + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7), + + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6), + LPASS_CDC_TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7), + + SND_SOC_DAPM_SUPPLY("TX MIC BIAS1", SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("TX SWR_ADC0"), + SND_SOC_DAPM_INPUT("TX SWR_ADC1"), + SND_SOC_DAPM_INPUT("TX SWR_ADC2"), + SND_SOC_DAPM_INPUT("TX SWR_ADC3"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC0"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC1"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC2"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC3"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC4"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC5"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC6"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC7"), + + SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC0, 0, + &tx_dec0_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC1, 0, + &tx_dec1_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC2, 0, + &tx_dec2_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC3, 0, + &tx_dec3_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC4, 0, + &tx_dec4_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC5, 0, + &tx_dec5_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC6, 0, + &tx_dec6_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM, + LPASS_CDC_TX_MACRO_DEC7, 0, + &tx_dec7_mux, lpass_cdc_tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_tx_swr_clk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_tx_macro_va_swr_clk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route tx_audio_map_common[] = { + {"TX_AIF1 CAP", NULL, "TX_MCLK"}, + {"TX_AIF2 CAP", NULL, "TX_MCLK"}, + {"TX_AIF3 CAP", NULL, "TX_MCLK"}, + + {"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"}, + {"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"}, + {"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"}, + + {"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + + {"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + + {"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + + {"TX DEC0 MUX", NULL, "TX_MCLK"}, + {"TX DEC1 MUX", NULL, "TX_MCLK"}, + {"TX DEC2 MUX", NULL, "TX_MCLK"}, + {"TX DEC3 MUX", NULL, "TX_MCLK"}, + + {"TX DEC0 MUX", "MSM_DMIC", "TX DMIC MUX0"}, + {"TX DMIC MUX0", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX0", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX0", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX0", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX0", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX0", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX0", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX0", "DMIC7", "TX DMIC7"}, + + {"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"}, + {"TX SMIC MUX0", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX0", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"}, + {"TX DMIC MUX1", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX1", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX1", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX1", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX1", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX1", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX1", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX1", "DMIC7", "TX DMIC7"}, + + {"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"}, + {"TX SMIC MUX1", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX1", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"}, + {"TX DMIC MUX2", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX2", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX2", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX2", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX2", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX2", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX2", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX2", "DMIC7", "TX DMIC7"}, + + {"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"}, + {"TX SMIC MUX2", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX2", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"}, + {"TX DMIC MUX3", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX3", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX3", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX3", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX3", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX3", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX3", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX3", "DMIC7", "TX DMIC7"}, + + {"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"}, + {"TX SMIC MUX3", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX3", "SWR_MIC11", "TX SWR_INPUT"}, +}; + +static const struct snd_soc_dapm_route tx_audio_map_v3[] = { + {"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX DEC4 MUX", NULL, "TX_MCLK"}, + {"TX DEC5 MUX", NULL, "TX_MCLK"}, + {"TX DEC6 MUX", NULL, "TX_MCLK"}, + {"TX DEC7 MUX", NULL, "TX_MCLK"}, + + {"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"}, + {"TX DMIC MUX4", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX4", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX4", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX4", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX4", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX4", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX4", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX4", "DMIC7", "TX DMIC7"}, + + {"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"}, + {"TX SMIC MUX4", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX4", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"}, + {"TX DMIC MUX5", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX5", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX5", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX5", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX5", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX5", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX5", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX5", "DMIC7", "TX DMIC7"}, + + {"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"}, + {"TX SMIC MUX5", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX5", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"}, + {"TX DMIC MUX6", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX6", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX6", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX6", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX6", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX6", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX6", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX6", "DMIC7", "TX DMIC7"}, + + {"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"}, + {"TX SMIC MUX6", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX6", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"}, + {"TX DMIC MUX7", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX7", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX7", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX7", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX7", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX7", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX7", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX7", "DMIC7", "TX DMIC7"}, + + {"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"}, + {"TX SMIC MUX7", "SWR_MIC0", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC1", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC2", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC3", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC4", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC5", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC6", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC7", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC8", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC9", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC10", "TX SWR_INPUT"}, + {"TX SMIC MUX7", "SWR_MIC11", "TX SWR_INPUT"}, + + {"TX SMIC MUX0", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX1", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX2", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX3", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX4", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX5", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX6", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX7", NULL, "TX_SWR_CLK"}, + + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, + {"TX SWR_INPUT", NULL, "TX_SWR_PWR"}, +}; + +static const struct snd_soc_dapm_route tx_audio_map[] = { + {"TX_AIF1 CAP", NULL, "TX_MCLK"}, + {"TX_AIF2 CAP", NULL, "TX_MCLK"}, + {"TX_AIF3 CAP", NULL, "TX_MCLK"}, + + {"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"}, + {"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"}, + {"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"}, + + {"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX DEC0 MUX", NULL, "TX_MCLK"}, + {"TX DEC1 MUX", NULL, "TX_MCLK"}, + {"TX DEC2 MUX", NULL, "TX_MCLK"}, + {"TX DEC3 MUX", NULL, "TX_MCLK"}, + {"TX DEC4 MUX", NULL, "TX_MCLK"}, + {"TX DEC5 MUX", NULL, "TX_MCLK"}, + {"TX DEC6 MUX", NULL, "TX_MCLK"}, + {"TX DEC7 MUX", NULL, "TX_MCLK"}, + + {"TX DEC0 MUX", "MSM_DMIC", "TX DMIC MUX0"}, + {"TX DMIC MUX0", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX0", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX0", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX0", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX0", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX0", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX0", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX0", "DMIC7", "TX DMIC7"}, + + {"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"}, + {"TX SMIC MUX0", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX0", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX0", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX0", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX0", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX0", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX0", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX0", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX0", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX0", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX0", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX0", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX0", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"}, + {"TX DMIC MUX1", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX1", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX1", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX1", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX1", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX1", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX1", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX1", "DMIC7", "TX DMIC7"}, + + {"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"}, + {"TX SMIC MUX1", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX1", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX1", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX1", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX1", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX1", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX1", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX1", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX1", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX1", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX1", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX1", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX1", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"}, + {"TX DMIC MUX2", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX2", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX2", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX2", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX2", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX2", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX2", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX2", "DMIC7", "TX DMIC7"}, + + {"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"}, + {"TX SMIC MUX2", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX2", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX2", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX2", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX2", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX2", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX2", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX2", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX2", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX2", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX2", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX2", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX2", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"}, + {"TX DMIC MUX3", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX3", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX3", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX3", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX3", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX3", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX3", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX3", "DMIC7", "TX DMIC7"}, + + {"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"}, + {"TX SMIC MUX3", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX3", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX3", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX3", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX3", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX3", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX3", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX3", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX3", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX3", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX3", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX3", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX3", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"}, + {"TX DMIC MUX4", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX4", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX4", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX4", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX4", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX4", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX4", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX4", "DMIC7", "TX DMIC7"}, + + {"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"}, + {"TX SMIC MUX4", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX4", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX4", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX4", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX4", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX4", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX4", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX4", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX4", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX4", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX4", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX4", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX4", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"}, + {"TX DMIC MUX5", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX5", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX5", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX5", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX5", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX5", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX5", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX5", "DMIC7", "TX DMIC7"}, + + {"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"}, + {"TX SMIC MUX5", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX5", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX5", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX5", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX5", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX5", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX5", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX5", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX5", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX5", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX5", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX5", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX5", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"}, + {"TX DMIC MUX6", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX6", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX6", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX6", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX6", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX6", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX6", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX6", "DMIC7", "TX DMIC7"}, + + {"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"}, + {"TX SMIC MUX6", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX6", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX6", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX6", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX6", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX6", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX6", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX6", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX6", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX6", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX6", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX6", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX6", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"}, + {"TX DMIC MUX7", "DMIC0", "TX DMIC0"}, + {"TX DMIC MUX7", "DMIC1", "TX DMIC1"}, + {"TX DMIC MUX7", "DMIC2", "TX DMIC2"}, + {"TX DMIC MUX7", "DMIC3", "TX DMIC3"}, + {"TX DMIC MUX7", "DMIC4", "TX DMIC4"}, + {"TX DMIC MUX7", "DMIC5", "TX DMIC5"}, + {"TX DMIC MUX7", "DMIC6", "TX DMIC6"}, + {"TX DMIC MUX7", "DMIC7", "TX DMIC7"}, + + {"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"}, + {"TX SMIC MUX7", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX7", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX7", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX7", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX7", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX7", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX7", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX7", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX7", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX7", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX7", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX7", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"}, +}; + +static const struct snd_kcontrol_new lpass_cdc_tx_macro_snd_controls_common[] = { + SOC_SINGLE_S8_TLV("TX_DEC0 Volume", + LPASS_CDC_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC1 Volume", + LPASS_CDC_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC2 Volume", + LPASS_CDC_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC3 Volume", + LPASS_CDC_TX3_TX_VOL_CTL, + -84, 40, digital_gain), + + SOC_SINGLE_EXT("TX LPI Enable", 0, 0, 1, 0, + lpass_cdc_tx_macro_lpi_get, lpass_cdc_tx_macro_lpi_put), + + SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0, + lpass_cdc_tx_macro_get_bcs, lpass_cdc_tx_macro_set_bcs), + + SOC_ENUM_EXT("BCS Channel", bcs_ch_enum, + lpass_cdc_tx_macro_bcs_ch_get, lpass_cdc_tx_macro_bcs_ch_put), + + SOC_ENUM_EXT("BCS CH_SEL", bcs_ch_sel_mux_enum, + lpass_cdc_tx_macro_get_bcs_ch_sel, lpass_cdc_tx_macro_put_bcs_ch_sel), +}; + +static const struct snd_kcontrol_new lpass_cdc_tx_macro_snd_controls_v3[] = { + SOC_SINGLE_S8_TLV("TX_DEC4 Volume", + LPASS_CDC_TX4_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC5 Volume", + LPASS_CDC_TX5_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC6 Volume", + LPASS_CDC_TX6_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC7 Volume", + LPASS_CDC_TX7_TX_VOL_CTL, + -84, 40, digital_gain), + + SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), +}; + +static const struct snd_kcontrol_new lpass_cdc_tx_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("TX_DEC0 Volume", + LPASS_CDC_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC1 Volume", + LPASS_CDC_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC2 Volume", + LPASS_CDC_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC3 Volume", + LPASS_CDC_TX3_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC4 Volume", + LPASS_CDC_TX4_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC5 Volume", + LPASS_CDC_TX5_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC6 Volume", + LPASS_CDC_TX6_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC7 Volume", + LPASS_CDC_TX7_TX_VOL_CTL, + -84, 40, digital_gain), + + SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum, + lpass_cdc_tx_macro_dec_mode_get, lpass_cdc_tx_macro_dec_mode_put), + SOC_ENUM("TX0 HPF cut off", cf_dec0_enum), + + SOC_ENUM("TX1 HPF cut off", cf_dec1_enum), + + SOC_ENUM("TX2 HPF cut off", cf_dec2_enum), + + SOC_ENUM("TX3 HPF cut off", cf_dec3_enum), + + SOC_ENUM("TX4 HPF cut off", cf_dec4_enum), + + SOC_ENUM("TX5 HPF cut off", cf_dec5_enum), + + SOC_ENUM("TX6 HPF cut off", cf_dec6_enum), + + SOC_ENUM("TX7 HPF cut off", cf_dec7_enum), + + SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0, + lpass_cdc_tx_macro_get_bcs, lpass_cdc_tx_macro_set_bcs), +}; + +static int lpass_cdc_tx_macro_register_event_listener(struct snd_soc_component *component, + bool enable) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + int ret = 0; + + if (!component) + return -EINVAL; + + tx_dev = lpass_cdc_get_device_ptr(component->dev, TX_MACRO); + if (!tx_dev) { + dev_err(component->dev, + "%s: null device for macro!\n", __func__); + return -EINVAL; + } + tx_priv = dev_get_drvdata(tx_dev); + if (!tx_priv) { + dev_err(component->dev, + "%s: priv is null for macro!\n", __func__); + return -EINVAL; + } + if (tx_priv->swr_ctrl_data && + (!tx_priv->tx_swr_clk_cnt || !tx_priv->va_swr_clk_cnt)) { + if (enable) { + ret = swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_REGISTER_WAKEUP, NULL); + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, false); + } else { + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, true); + ret = swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_DEREGISTER_WAKEUP, NULL); + } + } + + return ret; +} + +static int lpass_cdc_tx_macro_tx_va_mclk_enable( + struct lpass_cdc_tx_macro_priv *tx_priv, + struct regmap *regmap, int clk_type, + bool enable) +{ + int ret = 0, clk_tx_ret = 0; + + trace_printk("%s: clock type %s, enable: %s tx_mclk_users: %d\n", + __func__, (clk_type ? "VA_MCLK" : "TX_MCLK"), + (enable ? "enable" : "disable"), tx_priv->tx_mclk_users); + dev_dbg(tx_priv->dev, + "%s: clock type %s, enable: %s tx_mclk_users: %d\n", + __func__, (clk_type ? "VA_MCLK" : "TX_MCLK"), + (enable ? "enable" : "disable"), tx_priv->tx_mclk_users); + + if (enable) { + if (tx_priv->swr_clk_users == 0) { + trace_printk("%s: tx swr clk users 0\n", __func__); + ret = msm_cdc_pinctrl_select_active_state( + tx_priv->tx_swr_gpio_p); + if (ret < 0) { + dev_err_ratelimited(tx_priv->dev, + "%s: tx swr pinctrl enable failed\n", + __func__); + goto exit; + } + } + + clk_tx_ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + if (clk_type == TX_MCLK) { + trace_printk("%s: requesting TX_MCLK\n", __func__); + ret = lpass_cdc_tx_macro_mclk_enable(tx_priv, 1); + if (ret < 0) { + if (tx_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_sleep_state( + tx_priv->tx_swr_gpio_p); + dev_err_ratelimited(tx_priv->dev, + "%s: request clock enable failed\n", + __func__); + goto done; + } + } + if (clk_type == VA_MCLK) { + trace_printk("%s: requesting VA_MCLK\n", __func__); + ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + VA_CORE_CLK, + true); + if (ret < 0) { + if (tx_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_sleep_state( + tx_priv->tx_swr_gpio_p); + dev_err_ratelimited(tx_priv->dev, + "%s: swr request clk failed\n", + __func__); + goto done; + } + lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev, + true); + if (tx_priv->tx_mclk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_TX_TOP_CSR_FREQ_MCLK, + 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x01); + } + tx_priv->tx_mclk_users++; + } + if (tx_priv->swr_clk_users == 0) { + dev_dbg(tx_priv->dev, "%s: reset_swr: %d\n", + __func__, tx_priv->reset_swr); + trace_printk("%s: reset_swr: %d\n", + __func__, tx_priv->reset_swr); + if (tx_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x01); + if (tx_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x00); + tx_priv->reset_swr = false; + } + if (!clk_tx_ret) + ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + tx_priv->swr_clk_users++; + } else { + if (tx_priv->swr_clk_users <= 0) { + dev_err_ratelimited(tx_priv->dev, + "tx swrm clock users already 0\n"); + tx_priv->swr_clk_users = 0; + return 0; + } + clk_tx_ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + tx_priv->swr_clk_users--; + if (tx_priv->swr_clk_users == 0) + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x00); + if (clk_type == TX_MCLK) + lpass_cdc_tx_macro_mclk_enable(tx_priv, 0); + if (clk_type == VA_MCLK) { + if (tx_priv->tx_mclk_users <= 0) { + dev_err(tx_priv->dev, "%s: clock already disabled\n", + __func__); + tx_priv->tx_mclk_users = 0; + goto tx_clk; + } + tx_priv->tx_mclk_users--; + if (tx_priv->tx_mclk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x00); + } + + lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev, + false); + ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + VA_CORE_CLK, + false); + if (ret < 0) { + dev_err_ratelimited(tx_priv->dev, + "%s: swr request clk failed\n", + __func__); + goto done; + } + } +tx_clk: + if (!clk_tx_ret) + ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + if (tx_priv->swr_clk_users == 0) { + ret = msm_cdc_pinctrl_select_sleep_state( + tx_priv->tx_swr_gpio_p); + if (ret < 0) { + dev_err_ratelimited(tx_priv->dev, + "%s: tx swr pinctrl disable failed\n", + __func__); + goto exit; + } + } + } + return 0; + +done: + if (!clk_tx_ret) + lpass_cdc_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); +exit: + trace_printk("%s: exit\n", __func__); + return ret; +} + +static int lpass_cdc_tx_macro_clk_div_get(struct snd_soc_component *component) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + return tx_priv->dmic_clk_div; +} + +static int lpass_cdc_tx_macro_core_vote(void *handle, bool enable) +{ + struct lpass_cdc_tx_macro_priv *tx_priv = (struct lpass_cdc_tx_macro_priv *) handle; + + if (tx_priv == NULL) { + pr_err("%s: tx priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) { + pm_runtime_get_sync(tx_priv->dev); + pm_runtime_put_autosuspend(tx_priv->dev); + pm_runtime_mark_last_busy(tx_priv->dev); + } + + if (lpass_cdc_check_core_votes(tx_priv->dev)) + return 0; + else + return -EINVAL; +} + +static int lpass_cdc_tx_macro_swrm_clock(void *handle, bool enable) +{ + struct lpass_cdc_tx_macro_priv *tx_priv = (struct lpass_cdc_tx_macro_priv *) handle; + struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&tx_priv->swr_clk_lock); + trace_printk("%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n", + __func__, + (enable ? "enable" : "disable"), + tx_priv->tx_swr_clk_cnt, tx_priv->va_swr_clk_cnt); + dev_dbg(tx_priv->dev, + "%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n", + __func__, (enable ? "enable" : "disable"), + tx_priv->tx_swr_clk_cnt, tx_priv->va_swr_clk_cnt); + + if (enable) { + pm_runtime_get_sync(tx_priv->dev); + if (tx_priv->va_swr_clk_cnt && !tx_priv->tx_swr_clk_cnt) { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + VA_MCLK, enable); + if (ret) { + pm_runtime_mark_last_busy(tx_priv->dev); + pm_runtime_put_autosuspend(tx_priv->dev); + goto done; + } + tx_priv->va_clk_status++; + } else { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + TX_MCLK, enable); + if (ret) { + pm_runtime_mark_last_busy(tx_priv->dev); + pm_runtime_put_autosuspend(tx_priv->dev); + goto done; + } + tx_priv->tx_clk_status++; + } + pm_runtime_mark_last_busy(tx_priv->dev); + pm_runtime_put_autosuspend(tx_priv->dev); + } else { + if (tx_priv->va_clk_status && !tx_priv->tx_clk_status) { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + VA_MCLK, enable); + if (ret) + goto done; + --tx_priv->va_clk_status; + } else if (!tx_priv->va_clk_status && tx_priv->tx_clk_status) { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + TX_MCLK, enable); + if (ret) + goto done; + --tx_priv->tx_clk_status; + } else if (tx_priv->va_clk_status && tx_priv->tx_clk_status) { + if (!tx_priv->va_swr_clk_cnt && tx_priv->tx_swr_clk_cnt) { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + VA_MCLK, enable); + if (ret) + goto done; + --tx_priv->va_clk_status; + } else { + ret = lpass_cdc_tx_macro_tx_va_mclk_enable(tx_priv, regmap, + TX_MCLK, enable); + if (ret) + goto done; + --tx_priv->tx_clk_status; + } + + } else { + dev_dbg(tx_priv->dev, + "%s: Both clocks are disabled\n", __func__); + } + } + + trace_printk("%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n", + __func__, tx_priv->swr_clk_users, tx_priv->tx_clk_status, + tx_priv->va_clk_status); + dev_dbg(tx_priv->dev, + "%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n", + __func__, tx_priv->swr_clk_users, tx_priv->tx_clk_status, + tx_priv->va_clk_status); +done: + mutex_unlock(&tx_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_tx_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, + struct lpass_cdc_tx_macro_priv *tx_priv) +{ + u32 div_factor = LPASS_CDC_TX_MACRO_CLK_DIV_2; + u32 mclk_rate = LPASS_CDC_TX_MACRO_MCLK_FREQ; + + if (dmic_sample_rate == LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED || + mclk_rate % dmic_sample_rate != 0) + goto undefined_rate; + + div_factor = mclk_rate / dmic_sample_rate; + + switch (div_factor) { + case 2: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_2; + break; + case 3: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_3; + break; + case 4: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_4; + break; + case 6: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_6; + break; + case 8: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_8; + break; + case 16: + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_16; + break; + default: + /* Any other DIV factor is invalid */ + goto undefined_rate; + } + + /* Valid dmic DIV factors */ + dev_dbg(tx_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n", + __func__, div_factor, mclk_rate); + + return dmic_sample_rate; + +undefined_rate: + dev_dbg(tx_priv->dev, "%s: Invalid rate %d, for mclk %d\n", + __func__, dmic_sample_rate, mclk_rate); + dmic_sample_rate = LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED; + + return dmic_sample_rate; +} + +static const struct lpass_cdc_tx_macro_reg_mask_val + lpass_cdc_tx_macro_reg_init[] = { + {LPASS_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x0A}, +}; + +static int lpass_cdc_tx_macro_init(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + int ret = 0, i = 0; + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + tx_dev = lpass_cdc_get_device_ptr(component->dev, TX_MACRO); + if (!tx_dev) { + dev_err(component->dev, + "%s: null device for macro!\n", __func__); + return -EINVAL; + } + tx_priv = dev_get_drvdata(tx_dev); + if (!tx_priv) { + dev_err(component->dev, + "%s: priv is null for macro!\n", __func__); + return -EINVAL; + } + tx_priv->lpi_enable = false; + tx_priv->register_event_listener = false; + tx_priv->version = lpass_cdc_get_version(tx_dev); + if (tx_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_tx_macro_dapm_widgets_common, + ARRAY_SIZE(lpass_cdc_tx_macro_dapm_widgets_common)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + if (tx_priv->version == LPASS_CDC_VERSION_2_1) + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_tx_macro_dapm_widgets_v2, + ARRAY_SIZE(lpass_cdc_tx_macro_dapm_widgets_v2)); + else if (tx_priv->version == LPASS_CDC_VERSION_2_0) + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_tx_macro_dapm_widgets_v3, + ARRAY_SIZE(lpass_cdc_tx_macro_dapm_widgets_v3)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + } else { + ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_tx_macro_dapm_widgets, + ARRAY_SIZE(lpass_cdc_tx_macro_dapm_widgets)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + } + + if (tx_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_dapm_add_routes(dapm, + tx_audio_map_common, + ARRAY_SIZE(tx_audio_map_common)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + if (tx_priv->version == LPASS_CDC_VERSION_2_0) + ret = snd_soc_dapm_add_routes(dapm, + tx_audio_map_v3, + ARRAY_SIZE(tx_audio_map_v3)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + } else { + ret = snd_soc_dapm_add_routes(dapm, tx_audio_map, + ARRAY_SIZE(tx_audio_map)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + } + + ret = snd_soc_dapm_new_widgets(dapm->card); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add widgets\n", __func__); + return ret; + } + + if (tx_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_add_component_controls(component, + lpass_cdc_tx_macro_snd_controls_common, + ARRAY_SIZE(lpass_cdc_tx_macro_snd_controls_common)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + if (tx_priv->version == LPASS_CDC_VERSION_2_0) + ret = snd_soc_add_component_controls(component, + lpass_cdc_tx_macro_snd_controls_v3, + ARRAY_SIZE(lpass_cdc_tx_macro_snd_controls_v3)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + } else { + ret = snd_soc_add_component_controls(component, + lpass_cdc_tx_macro_snd_controls, + ARRAY_SIZE(lpass_cdc_tx_macro_snd_controls)); + if (ret < 0) { + dev_err(tx_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + } + + snd_soc_dapm_ignore_suspend(dapm, "TX_AIF1 Capture"); + snd_soc_dapm_ignore_suspend(dapm, "TX_AIF2 Capture"); + snd_soc_dapm_ignore_suspend(dapm, "TX_AIF3 Capture"); + if (tx_priv->version >= LPASS_CDC_VERSION_2_0) { + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_INPUT"); + } else { + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6"); + snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7"); + } + snd_soc_dapm_sync(dapm); + + for (i = 0; i < NUM_DECIMATORS; i++) { + tx_priv->tx_hpf_work[i].tx_priv = tx_priv; + tx_priv->tx_hpf_work[i].decimator = i; + INIT_DELAYED_WORK(&tx_priv->tx_hpf_work[i].dwork, + lpass_cdc_tx_macro_tx_hpf_corner_freq_callback); + } + + for (i = 0; i < NUM_DECIMATORS; i++) { + tx_priv->tx_mute_dwork[i].tx_priv = tx_priv; + tx_priv->tx_mute_dwork[i].decimator = i; + INIT_DELAYED_WORK(&tx_priv->tx_mute_dwork[i].dwork, + lpass_cdc_tx_macro_mute_update_callback); + } + tx_priv->component = component; + + for (i = 0; i < ARRAY_SIZE(lpass_cdc_tx_macro_reg_init); i++) + snd_soc_component_update_bits(component, + lpass_cdc_tx_macro_reg_init[i].reg, + lpass_cdc_tx_macro_reg_init[i].mask, + lpass_cdc_tx_macro_reg_init[i].val); + + return 0; +} + +static int lpass_cdc_tx_macro_deinit(struct snd_soc_component *component) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + tx_priv->component = NULL; + return 0; +} + +static void lpass_cdc_tx_macro_add_child_devices(struct work_struct *work) +{ + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct platform_device *pdev = NULL; + struct device_node *node = NULL; + struct lpass_cdc_tx_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL; + int ret = 0; + u16 count = 0, ctrl_num = 0; + struct lpass_cdc_tx_macro_swr_ctrl_platform_data *platdata = NULL; + char plat_dev_name[LPASS_CDC_TX_MACRO_SWR_STRING_LEN] = ""; + bool tx_swr_master_node = false; + + tx_priv = container_of(work, struct lpass_cdc_tx_macro_priv, + lpass_cdc_tx_macro_add_child_devices_work); + if (!tx_priv) { + pr_err("%s: Memory for tx_priv does not exist\n", + __func__); + return; + } + + if (!tx_priv->dev) { + pr_err("%s: tx dev does not exist\n", __func__); + return; + } + + if (!tx_priv->dev->of_node) { + dev_err(tx_priv->dev, + "%s: DT node for tx_priv does not exist\n", __func__); + return; + } + + platdata = &tx_priv->swr_plat_data; + tx_priv->child_count = 0; + + for_each_available_child_of_node(tx_priv->dev->of_node, node) { + tx_swr_master_node = false; + if (strnstr(node->name, "tx_swr_master", + strlen("tx_swr_master")) != NULL) + tx_swr_master_node = true; + + if (tx_swr_master_node) + strlcpy(plat_dev_name, "tx_swr_ctrl", + (LPASS_CDC_TX_MACRO_SWR_STRING_LEN - 1)); + else + strlcpy(plat_dev_name, node->name, + (LPASS_CDC_TX_MACRO_SWR_STRING_LEN - 1)); + + pdev = platform_device_alloc(plat_dev_name, -1); + if (!pdev) { + dev_err(tx_priv->dev, "%s: pdev memory alloc failed\n", + __func__); + ret = -ENOMEM; + goto err; + } + pdev->dev.parent = tx_priv->dev; + pdev->dev.of_node = node; + + if (tx_swr_master_node) { + ret = platform_device_add_data(pdev, platdata, + sizeof(*platdata)); + if (ret) { + dev_err(&pdev->dev, + "%s: cannot add plat data ctrl:%d\n", + __func__, ctrl_num); + goto fail_pdev_add; + } + } + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, + "%s: Cannot add platform device\n", + __func__); + goto fail_pdev_add; + } + + if (tx_swr_master_node) { + temp = krealloc(swr_ctrl_data, + (ctrl_num + 1) * sizeof( + struct lpass_cdc_tx_macro_swr_ctrl_data), + GFP_KERNEL); + if (!temp) { + ret = -ENOMEM; + goto fail_pdev_add; + } + swr_ctrl_data = temp; + swr_ctrl_data[ctrl_num].tx_swr_pdev = pdev; + ctrl_num++; + dev_dbg(&pdev->dev, + "%s: Added soundwire ctrl device(s)\n", + __func__); + tx_priv->swr_ctrl_data = swr_ctrl_data; + } + if (tx_priv->child_count < LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX) + tx_priv->pdev_child_devices[ + tx_priv->child_count++] = pdev; + else + goto err; + } + return; +fail_pdev_add: + for (count = 0; count < tx_priv->child_count; count++) + platform_device_put(tx_priv->pdev_child_devices[count]); +err: + return; +} + +static int lpass_cdc_tx_macro_set_port_map(struct snd_soc_component *component, + u32 usecase, u32 size, void *data) +{ + struct device *tx_dev = NULL; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + struct swrm_port_config port_cfg; + int ret = 0; + + if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) + return -EINVAL; + + memset(&port_cfg, 0, sizeof(port_cfg)); + port_cfg.uc = usecase; + port_cfg.size = size; + port_cfg.params = data; + + if (tx_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + tx_priv->swr_ctrl_data[0].tx_swr_pdev, + SWR_SET_PORT_MAP, &port_cfg); + + return ret; +} + +static void lpass_cdc_tx_macro_init_ops(struct macro_ops *ops, + char __iomem *tx_io_base) +{ + memset(ops, 0, sizeof(struct macro_ops)); + ops->init = lpass_cdc_tx_macro_init; + ops->exit = lpass_cdc_tx_macro_deinit; + ops->io_base = tx_io_base; + ops->dai_ptr = lpass_cdc_tx_macro_dai; + ops->num_dais = ARRAY_SIZE(lpass_cdc_tx_macro_dai); + ops->event_handler = lpass_cdc_tx_macro_event_handler; + ops->reg_wake_irq = lpass_cdc_tx_macro_reg_wake_irq; + ops->set_port_map = lpass_cdc_tx_macro_set_port_map; + ops->clk_div_get = lpass_cdc_tx_macro_clk_div_get; + ops->reg_evt_listener = lpass_cdc_tx_macro_register_event_listener; + ops->clk_enable = __lpass_cdc_tx_macro_mclk_enable; +} + +static int lpass_cdc_tx_macro_probe(struct platform_device *pdev) +{ + struct macro_ops ops = {0}; + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + u32 tx_base_addr = 0, sample_rate = 0; + char __iomem *tx_io_base = NULL; + int ret = 0; + const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate"; + u32 is_used_tx_swr_gpio = 1; + const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio"; + + if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + + tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_tx_macro_priv), + GFP_KERNEL); + if (!tx_priv) + return -ENOMEM; + platform_set_drvdata(pdev, tx_priv); + + tx_priv->dev = &pdev->dev; + ret = of_property_read_u32(pdev->dev.of_node, "reg", + &tx_base_addr); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "reg"); + return ret; + } + dev_set_drvdata(&pdev->dev, tx_priv); + if (of_find_property(pdev->dev.of_node, is_used_tx_swr_gpio_dt, + NULL)) { + ret = of_property_read_u32(pdev->dev.of_node, + is_used_tx_swr_gpio_dt, + &is_used_tx_swr_gpio); + if (ret) { + dev_err(&pdev->dev, "%s: error reading %s in dt\n", + __func__, is_used_tx_swr_gpio_dt); + is_used_tx_swr_gpio = 1; + } + } + tx_priv->tx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,tx-swr-gpios", 0); + if (!tx_priv->tx_swr_gpio_p && is_used_tx_swr_gpio) { + dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n", + __func__); + return -EINVAL; + } + if (msm_cdc_pinctrl_get_state(tx_priv->tx_swr_gpio_p) < 0 && + is_used_tx_swr_gpio) { + dev_err(&pdev->dev, "%s: failed to get swr pin state\n", + __func__); + return -EPROBE_DEFER; + } + + tx_io_base = devm_ioremap(&pdev->dev, + tx_base_addr, LPASS_CDC_TX_MACRO_MAX_OFFSET); + if (!tx_io_base) { + dev_err(&pdev->dev, "%s: ioremap failed\n", __func__); + return -ENOMEM; + } + tx_priv->tx_io_base = tx_io_base; + ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate, + &sample_rate); + if (ret) { + dev_err(&pdev->dev, + "%s: could not find sample_rate entry in dt\n", + __func__); + tx_priv->dmic_clk_div = LPASS_CDC_TX_MACRO_CLK_DIV_2; + } else { + if (lpass_cdc_tx_macro_validate_dmic_sample_rate( + sample_rate, tx_priv) == LPASS_CDC_TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED) + return -EINVAL; + } + if (is_used_tx_swr_gpio) { + tx_priv->reset_swr = true; + INIT_WORK(&tx_priv->lpass_cdc_tx_macro_add_child_devices_work, + lpass_cdc_tx_macro_add_child_devices); + tx_priv->swr_plat_data.handle = (void *) tx_priv; + tx_priv->swr_plat_data.read = NULL; + tx_priv->swr_plat_data.write = NULL; + tx_priv->swr_plat_data.bulk_write = NULL; + tx_priv->swr_plat_data.clk = lpass_cdc_tx_macro_swrm_clock; + tx_priv->swr_plat_data.core_vote = lpass_cdc_tx_macro_core_vote; + tx_priv->swr_plat_data.handle_irq = NULL; + mutex_init(&tx_priv->swr_clk_lock); + } + tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio; + mutex_init(&tx_priv->mclk_lock); + lpass_cdc_tx_macro_init_ops(&ops, tx_io_base); + ops.clk_id_req = TX_CORE_CLK; + ops.default_clk_id = TX_CORE_CLK; + ret = lpass_cdc_register_macro(&pdev->dev, TX_MACRO, &ops); + if (ret) { + dev_err(&pdev->dev, + "%s: register macro failed\n", __func__); + goto err_reg_macro; + } + if (is_used_tx_swr_gpio) + schedule_work(&tx_priv->lpass_cdc_tx_macro_add_child_devices_work); + pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_suspend_ignore_children(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); + + return 0; +err_reg_macro: + mutex_destroy(&tx_priv->mclk_lock); + if (is_used_tx_swr_gpio) + mutex_destroy(&tx_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_tx_macro_remove(struct platform_device *pdev) +{ + struct lpass_cdc_tx_macro_priv *tx_priv = NULL; + u16 count = 0; + + tx_priv = platform_get_drvdata(pdev); + + if (!tx_priv) + return -EINVAL; + + if (tx_priv->is_used_tx_swr_gpio) { + if (tx_priv->swr_ctrl_data) + kfree(tx_priv->swr_ctrl_data); + for (count = 0; count < tx_priv->child_count && + count < LPASS_CDC_TX_MACRO_CHILD_DEVICES_MAX; count++) + platform_device_unregister( + tx_priv->pdev_child_devices[count]); + } + + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + mutex_destroy(&tx_priv->mclk_lock); + if (tx_priv->is_used_tx_swr_gpio) + mutex_destroy(&tx_priv->swr_clk_lock); + lpass_cdc_unregister_macro(&pdev->dev, TX_MACRO); + return 0; +} + + +static const struct of_device_id lpass_cdc_tx_macro_dt_match[] = { + {.compatible = "qcom,lpass-cdc-tx-macro"}, + {} +}; + +static const struct dev_pm_ops lpass_cdc_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + pm_runtime_force_suspend, + pm_runtime_force_resume + ) + SET_RUNTIME_PM_OPS( + lpass_cdc_runtime_suspend, + lpass_cdc_runtime_resume, + NULL + ) +}; + +static struct platform_driver lpass_cdc_tx_macro_driver = { + .driver = { + .name = "lpass_cdc_tx_macro", + .owner = THIS_MODULE, + .pm = &lpass_cdc_dev_pm_ops, + .of_match_table = lpass_cdc_tx_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_tx_macro_probe, + .remove = lpass_cdc_tx_macro_remove, +}; + +module_platform_driver(lpass_cdc_tx_macro_driver); + +MODULE_DESCRIPTION("TX macro driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-utils.c b/asoc/codecs/lpass-cdc/lpass-cdc-utils.c new file mode 100644 index 0000000000..95615c24f0 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-utils.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "lpass-cdc.h" +#include "internal.h" + +#define REG_BYTES 2 +#define VAL_BYTES 1 + +const u16 macro_id_base_offset[MAX_MACRO] = { + TX_START_OFFSET, + RX_START_OFFSET, + WSA_START_OFFSET, + VA_START_OFFSET, +}; + +int lpass_cdc_get_macro_id(bool va_no_dec_flag, u16 reg) +{ + if (reg >= TX_START_OFFSET + && reg <= TX_MAX_OFFSET) + return TX_MACRO; + if (reg >= RX_START_OFFSET + && reg <= RX_MAX_OFFSET) + return RX_MACRO; + if (reg >= WSA_START_OFFSET + && reg <= WSA_MAX_OFFSET) + return WSA_MACRO; + if (!va_no_dec_flag && + (reg >= VA_START_OFFSET && + reg <= VA_MAX_OFFSET)) + return VA_MACRO; + if (va_no_dec_flag && + (reg >= VA_START_OFFSET && + reg <= VA_TOP_MAX_OFFSET)) + return VA_MACRO; + + return -EINVAL; +} + +static int regmap_bus_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct device *dev = context; + struct lpass_cdc_priv *priv = dev_get_drvdata(dev); + u16 *reg_p; + u16 __reg; + int macro_id, i; + u8 temp = 0; + int ret = -EINVAL; + + if (!priv) { + dev_err(dev, "%s: priv is NULL\n", __func__); + return ret; + } + if (!reg || !val) { + dev_err(dev, "%s: reg or val is NULL\n", __func__); + return ret; + } + if (reg_size != REG_BYTES) { + dev_err(dev, "%s: register size %zd bytes, not supported\n", + __func__, reg_size); + return ret; + } + + reg_p = (u16 *)reg; + macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation, + reg_p[0]); + if (macro_id < 0 || !priv->macros_supported[macro_id]) + return 0; + + mutex_lock(&priv->io_lock); + for (i = 0; i < val_size; i++) { + __reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id]; + ret = priv->read_dev(priv, macro_id, __reg, &temp); + if (ret < 0) { + dev_err_ratelimited(dev, + "%s: Codec read failed (%d), reg: 0x%x, size:%zd\n", + __func__, ret, reg_p[0] + i * 4, val_size); + break; + } + ((u8 *)val)[i] = temp; + dev_dbg(dev, "%s: Read 0x%02x from reg 0x%x\n", + __func__, temp, reg_p[0] + i * 4); + } + mutex_unlock(&priv->io_lock); + + return ret; +} + +static int regmap_bus_gather_write(void *context, + const void *reg, size_t reg_size, + const void *val, size_t val_size) +{ + struct device *dev = context; + struct lpass_cdc_priv *priv = dev_get_drvdata(dev); + u16 *reg_p; + u16 __reg; + int macro_id, i; + int ret = -EINVAL; + + if (!priv) { + dev_err(dev, "%s: priv is NULL\n", __func__); + return ret; + } + if (!reg || !val) { + dev_err(dev, "%s: reg or val is NULL\n", __func__); + return ret; + } + if (reg_size != REG_BYTES) { + dev_err(dev, "%s: register size %zd bytes, not supported\n", + __func__, reg_size); + return ret; + } + + reg_p = (u16 *)reg; + macro_id = lpass_cdc_get_macro_id(priv->va_without_decimation, + reg_p[0]); + if (macro_id < 0 || !priv->macros_supported[macro_id]) + return 0; + + mutex_lock(&priv->io_lock); + for (i = 0; i < val_size; i++) { + __reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id]; + ret = priv->write_dev(priv, macro_id, __reg, ((u8 *)val)[i]); + if (ret < 0) { + dev_err_ratelimited(dev, + "%s: Codec write failed (%d), reg:0x%x, size:%zd\n", + __func__, ret, reg_p[0] + i * 4, val_size); + break; + } + dev_dbg(dev, "Write %02x to reg 0x%x\n", ((u8 *)val)[i], + reg_p[0] + i * 4); + } + mutex_unlock(&priv->io_lock); + return ret; +} + +static int regmap_bus_write(void *context, const void *data, size_t count) +{ + struct device *dev = context; + struct lpass_cdc_priv *priv = dev_get_drvdata(dev); + + if (!priv) + return -EINVAL; + + if (count < REG_BYTES) { + dev_err(dev, "%s: count %zd bytes < %d, not supported\n", + __func__, count, REG_BYTES); + return -EINVAL; + } + + return regmap_bus_gather_write(context, data, REG_BYTES, + data + REG_BYTES, + count - REG_BYTES); +} + +static struct regmap_bus regmap_bus_config = { + .write = regmap_bus_write, + .gather_write = regmap_bus_gather_write, + .read = regmap_bus_read, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +struct regmap *lpass_cdc_regmap_init(struct device *dev, + const struct regmap_config *config) +{ + return devm_regmap_init(dev, ®map_bus_config, dev, config); +} diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c new file mode 100644 index 0000000000..3e249cfbef --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c @@ -0,0 +1,3268 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lpass-cdc.h" +#include "lpass-cdc-registers.h" +#include "lpass-cdc-clk-rsc.h" + +/* pm runtime auto suspend timer in msecs */ +#define VA_AUTO_SUSPEND_DELAY 100 /* delay in msec */ +#define LPASS_CDC_VA_MACRO_MAX_OFFSET 0x1000 + +#define LPASS_CDC_VA_MACRO_NUM_DECIMATORS 8 + +#define LPASS_CDC_VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define LPASS_CDC_VA_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define TX_HPF_CUT_OFF_FREQ_MASK 0x60 +#define CF_MIN_3DB_4HZ 0x0 +#define CF_MIN_3DB_75HZ 0x1 +#define CF_MIN_3DB_150HZ 0x2 + +#define LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0 +#define LPASS_CDC_VA_MACRO_MCLK_FREQ 9600000 +#define LPASS_CDC_VA_MACRO_TX_PATH_OFFSET 0x80 +#define LPASS_CDC_VA_MACRO_TX_DMIC_CLK_DIV_MASK 0x0E +#define LPASS_CDC_VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01 +#define LPASS_CDC_VA_MACRO_SWR_MIC_MUX_SEL_MASK 0xF +#define LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET 0x8 +#define LPASS_CDC_VA_MACRO_ADC_MODE_CFG0_SHIFT 1 + +#define LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS 40 +#define LPASS_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS 100 +#define LPASS_CDC_VA_TX_DMIC_HPF_DELAY_MS 300 +#define LPASS_CDC_VA_TX_AMIC_HPF_DELAY_MS 300 +#define MAX_RETRY_ATTEMPTS 500 +#define LPASS_CDC_VA_MACRO_SWR_STRING_LEN 80 +#define LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX 3 + +static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); +static int va_tx_unmute_delay = LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS; +module_param(va_tx_unmute_delay, int, 0664); +MODULE_PARM_DESC(va_tx_unmute_delay, "delay to unmute the tx path"); + +enum { + LPASS_CDC_VA_MACRO_AIF_INVALID = 0, + LPASS_CDC_VA_MACRO_AIF1_CAP, + LPASS_CDC_VA_MACRO_AIF2_CAP, + LPASS_CDC_VA_MACRO_AIF3_CAP, + LPASS_CDC_VA_MACRO_MAX_DAIS, +}; + +enum { + LPASS_CDC_VA_MACRO_DEC0, + LPASS_CDC_VA_MACRO_DEC1, + LPASS_CDC_VA_MACRO_DEC2, + LPASS_CDC_VA_MACRO_DEC3, + LPASS_CDC_VA_MACRO_DEC4, + LPASS_CDC_VA_MACRO_DEC5, + LPASS_CDC_VA_MACRO_DEC6, + LPASS_CDC_VA_MACRO_DEC7, + LPASS_CDC_VA_MACRO_DEC_MAX, +}; + +enum { + LPASS_CDC_VA_MACRO_CLK_DIV_2, + LPASS_CDC_VA_MACRO_CLK_DIV_3, + LPASS_CDC_VA_MACRO_CLK_DIV_4, + LPASS_CDC_VA_MACRO_CLK_DIV_6, + LPASS_CDC_VA_MACRO_CLK_DIV_8, + LPASS_CDC_VA_MACRO_CLK_DIV_16, +}; + +enum { + MSM_DMIC, + SWR_MIC, +}; + +enum { + TX_MCLK, + VA_MCLK, +}; + +struct va_mute_work { + struct lpass_cdc_va_macro_priv *va_priv; + u32 decimator; + struct delayed_work dwork; +}; + +struct hpf_work { + struct lpass_cdc_va_macro_priv *va_priv; + u8 decimator; + u8 hpf_cut_off_freq; + struct delayed_work dwork; +}; + +/* Hold instance to soundwire platform device */ +struct lpass_cdc_va_macro_swr_ctrl_data { + struct platform_device *va_swr_pdev; +}; + +struct lpass_cdc_va_macro_swr_ctrl_platform_data { + void *handle; /* holds codec private data */ + int (*read)(void *handle, int reg); + int (*write)(void *handle, int reg, int val); + int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len); + int (*clk)(void *handle, bool enable); + int (*core_vote)(void *handle, bool enable); + int (*handle_irq)(void *handle, + irqreturn_t (*swrm_irq_handler)(int irq, + void *data), + void *swrm_handle, + int action); +}; + +struct lpass_cdc_va_macro_priv { + struct device *dev; + bool dec_active[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; + bool va_without_decimation; + struct clk *lpass_audio_hw_vote; + struct mutex mclk_lock; + struct mutex swr_clk_lock; + struct snd_soc_component *component; + struct hpf_work va_hpf_work[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; + struct va_mute_work va_mute_dwork[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; + unsigned long active_ch_mask[LPASS_CDC_VA_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[LPASS_CDC_VA_MACRO_MAX_DAIS]; + u16 dmic_clk_div; + u16 va_mclk_users; + int swr_clk_users; + bool reset_swr; + struct device_node *va_swr_gpio_p; + struct lpass_cdc_va_macro_swr_ctrl_data *swr_ctrl_data; + struct lpass_cdc_va_macro_swr_ctrl_platform_data swr_plat_data; + struct work_struct lpass_cdc_va_macro_add_child_devices_work; + int child_count; + u16 mclk_mux_sel; + char __iomem *va_io_base; + char __iomem *va_island_mode_muxsel; + struct platform_device *pdev_child_devices + [LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX]; + struct regulator *micb_supply; + u32 micb_voltage; + u32 micb_current; + u32 version; + u32 is_used_va_swr_gpio; + int micb_users; + u16 default_clk_id; + u16 clk_id; + int tx_swr_clk_cnt; + int va_swr_clk_cnt; + int va_clk_status; + int tx_clk_status; + bool lpi_enable; + bool register_event_listener; + int dec_mode[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; + int disable_afe_wakeup_event_listener; +}; + +static bool lpass_cdc_va_macro_get_data(struct snd_soc_component *component, + struct device **va_dev, + struct lpass_cdc_va_macro_priv **va_priv, + const char *func_name) +{ + *va_dev = lpass_cdc_get_device_ptr(component->dev, VA_MACRO); + if (!(*va_dev)) { + dev_err(component->dev, + "%s: null device for macro!\n", func_name); + return false; + } + *va_priv = dev_get_drvdata((*va_dev)); + if (!(*va_priv) || !(*va_priv)->component) { + dev_err(component->dev, + "%s: priv is null for macro!\n", func_name); + return false; + } + return true; +} + +static int lpass_cdc_va_macro_clk_div_get(struct snd_soc_component *component) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if ((va_priv->version >= LPASS_CDC_VERSION_2_0) + && !va_priv->lpi_enable + && (va_priv->dmic_clk_div == LPASS_CDC_VA_MACRO_CLK_DIV_16)) + return LPASS_CDC_VA_MACRO_CLK_DIV_8; + + return va_priv->dmic_clk_div; +} + +static int lpass_cdc_va_macro_mclk_enable( + struct lpass_cdc_va_macro_priv *va_priv, + bool mclk_enable, bool dapm) +{ + struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + dev_dbg(va_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n", + __func__, mclk_enable, dapm, va_priv->va_mclk_users); + + mutex_lock(&va_priv->mclk_lock); + if (mclk_enable) { + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + va_priv->clk_id, + true); + if (ret < 0) { + dev_err(va_priv->dev, + "%s: va request clock en failed\n", + __func__); + goto exit; + } + lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev, + true); + if (va_priv->va_mclk_users == 0) { + regcache_mark_dirty(regmap); + regcache_sync_region(regmap, + VA_START_OFFSET, + VA_MAX_OFFSET); + } + va_priv->va_mclk_users++; + } else { + if (va_priv->va_mclk_users <= 0) { + dev_err(va_priv->dev, "%s: clock already disabled\n", + __func__); + va_priv->va_mclk_users = 0; + goto exit; + } + va_priv->va_mclk_users--; + lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev, + false); + lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + va_priv->clk_id, + false); + } +exit: + mutex_unlock(&va_priv->mclk_lock); + return ret; +} + +static int lpass_cdc_va_macro_event_handler(struct snd_soc_component *component, + u16 event, u32 data) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + int retry_cnt = MAX_RETRY_ATTEMPTS; + int ret = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + switch (event) { + case LPASS_CDC_MACRO_EVT_WAIT_VA_CLK_RESET: + while ((va_priv->va_mclk_users != 0) && (retry_cnt != 0)) { + dev_dbg_ratelimited(va_dev, "%s:retry_cnt: %d\n", + __func__, retry_cnt); + /* + * Userspace takes 10 seconds to close + * the session when pcm_start fails due to concurrency + * with PDR/SSR. Loop and check every 20ms till 10 + * seconds for va_mclk user count to get reset to 0 + * which ensures userspace teardown is done and SSR + * powerup seq can proceed. + */ + msleep(20); + retry_cnt--; + } + if (retry_cnt == 0) + dev_err(va_dev, + "%s: va_mclk_users non-zero, SSR fail!!\n", + __func__); + break; + case LPASS_CDC_MACRO_EVT_PRE_SSR_UP: + /* enable&disable VA_CORE_CLK to reset GFMUX reg */ + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + VA_CORE_CLK, true); + if (ret < 0) + dev_err_ratelimited(va_priv->dev, + "%s, failed to enable clk, ret:%d\n", + __func__, ret); + else + lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + VA_CORE_CLK, false); + break; + case LPASS_CDC_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + /* reset swr after ssr/pdr */ + va_priv->reset_swr = true; + if (va_priv->swr_ctrl_data) + swrm_wcd_notify( + va_priv->swr_ctrl_data[0].va_swr_pdev, + SWR_DEVICE_SSR_UP, NULL); + break; + case LPASS_CDC_MACRO_EVT_CLK_RESET: + lpass_cdc_rsc_clk_reset(va_dev, VA_CORE_CLK); + break; + case LPASS_CDC_MACRO_EVT_SSR_DOWN: + if (va_priv->swr_ctrl_data) { + swrm_wcd_notify( + va_priv->swr_ctrl_data[0].va_swr_pdev, + SWR_DEVICE_SSR_DOWN, NULL); + } + if ((!pm_runtime_enabled(va_dev) || + !pm_runtime_suspended(va_dev))) { + ret = lpass_cdc_runtime_suspend(va_dev); + if (!ret) { + pm_runtime_disable(va_dev); + pm_runtime_set_suspended(va_dev); + pm_runtime_enable(va_dev); + } + } + break; + default: + break; + } + return 0; +} + +static int lpass_cdc_va_macro_swr_clk_event_v2(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + va_priv->va_swr_clk_cnt++; + break; + case SND_SOC_DAPM_POST_PMD: + va_priv->va_swr_clk_cnt--; + break; + default: + break; + } + return 0; +} + +static int lpass_cdc_va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", + __func__, event, va_priv->lpi_enable); + + if (!va_priv->lpi_enable) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + msm_cdc_pinctrl_set_wakeup_capable( + va_priv->va_swr_gpio_p, false); + break; + case SND_SOC_DAPM_POST_PMD: + msm_cdc_pinctrl_set_wakeup_capable( + va_priv->va_swr_gpio_p, true); + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", + __func__, event, va_priv->lpi_enable); + + if (!va_priv->lpi_enable) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (va_priv->lpass_audio_hw_vote) { + ret = digital_cdc_rsc_mgr_hw_vote_enable( + va_priv->lpass_audio_hw_vote); + if (ret) + dev_err(va_dev, + "%s: lpass audio hw enable failed\n", + __func__); + } + if (va_priv->lpi_enable && + !va_priv->disable_afe_wakeup_event_listener) { + lpass_cdc_register_event_listener(component, true); + va_priv->register_event_listener = true; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (va_priv->register_event_listener) { + va_priv->register_event_listener = false; + lpass_cdc_register_event_listener(component, false); + } + if (va_priv->lpass_audio_hw_vote) + digital_cdc_rsc_mgr_hw_vote_disable( + va_priv->lpass_audio_hw_vote); + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if (SND_SOC_DAPM_EVENT_ON(event)) + ++va_priv->tx_swr_clk_cnt; + if (SND_SOC_DAPM_EVENT_OFF(event)) + --va_priv->tx_swr_clk_cnt; + + return 0; +} + +static int lpass_cdc_va_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + TX_CORE_CLK, + true); + if (!ret) + va_priv->tx_clk_status++; + + if (va_priv->lpi_enable) + ret = lpass_cdc_va_macro_mclk_enable(va_priv, 1, true); + else + ret = lpass_cdc_tx_mclk_enable(component, 1); + break; + case SND_SOC_DAPM_POST_PMD: + if (va_priv->lpi_enable) + lpass_cdc_va_macro_mclk_enable(va_priv, 0, true); + else + lpass_cdc_tx_mclk_enable(component, 0); + + if (va_priv->tx_clk_status > 0) { + lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + TX_CORE_CLK, + false); + va_priv->tx_clk_status--; + } + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_va_macro_tx_va_mclk_enable( + struct lpass_cdc_va_macro_priv *va_priv, + struct regmap *regmap, int clk_type, + bool enable) +{ + int ret = 0, clk_tx_ret = 0; + + dev_dbg(va_priv->dev, + "%s: clock type %s, enable: %s tx_mclk_users: %d\n", + __func__, (clk_type ? "VA_MCLK" : "TX_MCLK"), + (enable ? "enable" : "disable"), va_priv->va_mclk_users); + + if (enable) { + if (va_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_active_state( + va_priv->va_swr_gpio_p); + clk_tx_ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + if (clk_type == TX_MCLK) { + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + if (ret < 0) { + if (va_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_sleep_state( + va_priv->va_swr_gpio_p); + dev_err_ratelimited(va_priv->dev, + "%s: swr request clk failed\n", + __func__); + goto done; + } + lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev, + true); + } + if (clk_type == VA_MCLK) { + ret = lpass_cdc_va_macro_mclk_enable(va_priv, 1, true); + if (ret < 0) { + if (va_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_sleep_state( + va_priv->va_swr_gpio_p); + dev_err_ratelimited(va_priv->dev, + "%s: request clock enable failed\n", + __func__); + goto done; + } + } + if (va_priv->swr_clk_users == 0) { + dev_dbg(va_priv->dev, "%s: reset_swr: %d\n", + __func__, va_priv->reset_swr); + if (va_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x01); + if (va_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x00); + va_priv->reset_swr = false; + } + if (!clk_tx_ret) + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + va_priv->swr_clk_users++; + } else { + if (va_priv->swr_clk_users <= 0) { + dev_err_ratelimited(va_priv->dev, + "va swrm clock users already 0\n"); + va_priv->swr_clk_users = 0; + return 0; + } + clk_tx_ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); + va_priv->swr_clk_users--; + if (va_priv->swr_clk_users == 0) + regmap_update_bits(regmap, + LPASS_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x00); + if (clk_type == VA_MCLK) + lpass_cdc_va_macro_mclk_enable(va_priv, 0, true); + if (clk_type == TX_MCLK) { + lpass_cdc_clk_rsc_fs_gen_request(va_priv->dev, + false); + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + if (ret < 0) { + dev_err_ratelimited(va_priv->dev, + "%s: swr request clk failed\n", + __func__); + goto done; + } + } + if (!clk_tx_ret) + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + if (va_priv->swr_clk_users == 0) + msm_cdc_pinctrl_select_sleep_state( + va_priv->va_swr_gpio_p); + } + return 0; + +done: + if (!clk_tx_ret) + lpass_cdc_clk_rsc_request_clock(va_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); + return ret; +} + +static int lpass_cdc_va_macro_core_vote(void *handle, bool enable) +{ + struct lpass_cdc_va_macro_priv *va_priv = + (struct lpass_cdc_va_macro_priv *) handle; + + if (va_priv == NULL) { + pr_err("%s: va priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) { + pm_runtime_get_sync(va_priv->dev); + pm_runtime_put_autosuspend(va_priv->dev); + pm_runtime_mark_last_busy(va_priv->dev); + } + + if (lpass_cdc_check_core_votes(va_priv->dev)) + return 0; + else + return -EINVAL; +} + +static int lpass_cdc_va_macro_swrm_clock(void *handle, bool enable) +{ + struct lpass_cdc_va_macro_priv *va_priv = + (struct lpass_cdc_va_macro_priv *) handle; + struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&va_priv->swr_clk_lock); + dev_dbg(va_priv->dev, + "%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n", + __func__, (enable ? "enable" : "disable"), + va_priv->tx_swr_clk_cnt, va_priv->va_swr_clk_cnt); + + if (enable) { + pm_runtime_get_sync(va_priv->dev); + if (va_priv->va_swr_clk_cnt && !va_priv->tx_swr_clk_cnt) { + ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv, + regmap, VA_MCLK, enable); + if (ret) { + pm_runtime_mark_last_busy(va_priv->dev); + pm_runtime_put_autosuspend(va_priv->dev); + goto done; + } + va_priv->va_clk_status++; + } else { + ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv, + regmap, TX_MCLK, enable); + if (ret) { + pm_runtime_mark_last_busy(va_priv->dev); + pm_runtime_put_autosuspend(va_priv->dev); + goto done; + } + va_priv->tx_clk_status++; + } + pm_runtime_mark_last_busy(va_priv->dev); + pm_runtime_put_autosuspend(va_priv->dev); + } else { + if (va_priv->va_clk_status && !va_priv->tx_clk_status) { + ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv, + regmap, + VA_MCLK, enable); + if (ret) + goto done; + --va_priv->va_clk_status; + } else if (!va_priv->va_clk_status && va_priv->tx_clk_status) { + ret = lpass_cdc_va_macro_tx_va_mclk_enable(va_priv, + regmap, + TX_MCLK, enable); + if (ret) + goto done; + --va_priv->tx_clk_status; + } else if (va_priv->va_clk_status && va_priv->tx_clk_status) { + if (!va_priv->va_swr_clk_cnt && + va_priv->tx_swr_clk_cnt) { + ret = lpass_cdc_va_macro_tx_va_mclk_enable( + va_priv, regmap, + VA_MCLK, enable); + if (ret) + goto done; + --va_priv->va_clk_status; + } else { + ret = lpass_cdc_va_macro_tx_va_mclk_enable( + va_priv, regmap, + TX_MCLK, enable); + if (ret) + goto done; + --va_priv->tx_clk_status; + } + + } else { + dev_dbg(va_priv->dev, + "%s: Both clocks are disabled\n", __func__); + } + } + dev_dbg(va_priv->dev, + "%s: swrm clock usr %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n", + __func__, va_priv->swr_clk_users, va_priv->tx_clk_status, + va_priv->va_clk_status); +done: + mutex_unlock(&va_priv->swr_clk_lock); + return ret; +} + +static bool is_amic_enabled(struct snd_soc_component *component, int decimator) +{ + u16 adc_mux_reg = 0, adc_reg = 0; + u16 adc_n = LPASS_CDC_ADC_MAX; + bool ret = false; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return ret; + + adc_mux_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1 + + LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) { + if (va_priv->version == LPASS_CDC_VERSION_2_1) + return true; + adc_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0 + + LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + adc_n = snd_soc_component_read32(component, adc_reg) & + LPASS_CDC_VA_MACRO_SWR_MIC_MUX_SEL_MASK; + if (adc_n < LPASS_CDC_ADC_MAX) + return true; + } + + return ret; +} + +static void lpass_cdc_va_macro_tx_hpf_corner_freq_callback( + struct work_struct *work) +{ + struct delayed_work *hpf_delayed_work; + struct hpf_work *hpf_work; + struct lpass_cdc_va_macro_priv *va_priv; + struct snd_soc_component *component; + u16 dec_cfg_reg, hpf_gate_reg; + u8 hpf_cut_off_freq; + u16 adc_reg = 0, adc_n = 0; + + hpf_delayed_work = to_delayed_work(work); + hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork); + va_priv = hpf_work->va_priv; + component = va_priv->component; + hpf_cut_off_freq = hpf_work->hpf_cut_off_freq; + + dec_cfg_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0 + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator; + hpf_gate_reg = LPASS_CDC_VA_TX0_TX_PATH_SEC2 + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * hpf_work->decimator; + + dev_dbg(va_priv->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n", + __func__, hpf_work->decimator, hpf_cut_off_freq); + + if (is_amic_enabled(component, hpf_work->decimator)) { + adc_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0 + + LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * + hpf_work->decimator; + adc_n = snd_soc_component_read32(component, adc_reg) & + LPASS_CDC_VA_MACRO_SWR_MIC_MUX_SEL_MASK; + /* analog mic clear TX hold */ + lpass_cdc_clear_amic_tx_hold(component->dev, adc_n); + snd_soc_component_update_bits(component, + dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x03, 0x02); + /* Minimum 1 clk cycle delay is required as per HW spec */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x03, 0x01); + } else { + snd_soc_component_update_bits(component, + dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x02, 0x02); + /* Minimum 1 clk cycle delay is required as per HW spec */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, hpf_gate_reg, + 0x02, 0x00); + } +} + +static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work) +{ + struct va_mute_work *va_mute_dwork; + struct snd_soc_component *component = NULL; + struct lpass_cdc_va_macro_priv *va_priv; + struct delayed_work *delayed_work; + u16 tx_vol_ctl_reg, decimator; + + delayed_work = to_delayed_work(work); + va_mute_dwork = container_of(delayed_work, struct va_mute_work, dwork); + va_priv = va_mute_dwork->va_priv; + component = va_priv->component; + decimator = va_mute_dwork->decimator; + + tx_vol_ctl_reg = + LPASS_CDC_VA_TX0_TX_PATH_CTL + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); + dev_dbg(va_priv->dev, "%s: decimator %u unmute\n", + __func__, decimator); +} + +static int lpass_cdc_va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val; + u16 mic_sel_reg, dmic_clk_reg; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + val = ucontrol->value.enumerated.item[0]; + if (val > e->items - 1) + return -EINVAL; + + dev_dbg(component->dev, "%s: wname: %s, val: 0x%x\n", __func__, + widget->name, val); + + switch (e->reg) { + case LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX1_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX2_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX3_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX4_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX5_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX6_TX_PATH_CFG0; + break; + case LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0: + mic_sel_reg = LPASS_CDC_VA_TX7_TX_PATH_CFG0; + break; + default: + dev_err(component->dev, "%s: e->reg: 0x%x not expected\n", + __func__, e->reg); + return -EINVAL; + } + if (strnstr(widget->name, "SMIC", strlen(widget->name))) { + if (val != 0) { + if (val < 5) { + snd_soc_component_update_bits(component, + mic_sel_reg, + 1 << 7, 0x0 << 7); + } else { + snd_soc_component_update_bits(component, + mic_sel_reg, + 1 << 7, 0x1 << 7); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + 0x80, 0x00); + dmic_clk_reg = + LPASS_CDC_TX_TOP_CSR_SWR_DMIC0_CTL + + ((val - 5)/2) * 4; + snd_soc_component_update_bits(component, + dmic_clk_reg, + 0x0E, va_priv->dmic_clk_div << 0x1); + } + } + } else { + /* DMIC selected */ + if (val != 0) + snd_soc_component_update_bits(component, mic_sel_reg, + 1 << 7, 1 << 7); + } + + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static int lpass_cdc_va_macro_lpi_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = va_priv->lpi_enable; + + return 0; +} + +static int lpass_cdc_va_macro_lpi_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + va_priv->lpi_enable = ucontrol->value.integer.value[0]; + + return 0; +} + +static int lpass_cdc_va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 dai_id = widget->shift; + u32 dec_id = mixer->shift; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if (test_bit(dec_id, &va_priv->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + return 0; +} + +static int lpass_cdc_va_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct snd_soc_dapm_update *update = NULL; + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 dai_id = widget->shift; + u32 dec_id = mixer->shift; + u32 enable = ucontrol->value.integer.value[0]; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if (enable) { + set_bit(dec_id, &va_priv->active_ch_mask[dai_id]); + va_priv->active_ch_cnt[dai_id]++; + } else { + clear_bit(dec_id, &va_priv->active_ch_mask[dai_id]); + va_priv->active_ch_cnt[dai_id]--; + } + + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); + + return 0; +} + +static int lpass_cdc_va_macro_enable_dmic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int dmic = 0; + int ret = 0; + char *wname; + + wname = strpbrk(w->name, "01234567"); + if (!wname) { + dev_err(component->dev, "%s: widget not found\n", __func__); + return -EINVAL; + } + + ret = kstrtouint(wname, 10, &dmic); + if (ret < 0) { + dev_err(component->dev, "%s: Invalid DMIC line on the codec\n", + __func__); + return -EINVAL; + } + + dev_dbg(component->dev, "%s: event %d DMIC%d\n", + __func__, event, dmic); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_dmic_clk_enable(component, dmic, DMIC_VA, true); + break; + case SND_SOC_DAPM_POST_PMD: + lpass_cdc_dmic_clk_enable(component, dmic, DMIC_VA, false); + break; + } + + return 0; +} + +static int lpass_cdc_va_macro_enable_dec(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + unsigned int decimator; + u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; + u16 tx_gain_ctl_reg; + u8 hpf_cut_off_freq; + u16 adc_mux_reg = 0; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + int hpf_delay = LPASS_CDC_VA_TX_DMIC_HPF_DELAY_MS; + int unmute_delay = LPASS_CDC_VA_TX_DMIC_UNMUTE_DELAY_MS; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + decimator = w->shift; + + dev_dbg(va_dev, "%s(): widget = %s decimator = %u\n", __func__, + w->name, decimator); + + tx_vol_ctl_reg = LPASS_CDC_VA_TX0_TX_PATH_CTL + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + hpf_gate_reg = LPASS_CDC_VA_TX0_TX_PATH_SEC2 + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + dec_cfg_reg = LPASS_CDC_VA_TX0_TX_PATH_CFG0 + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + tx_gain_ctl_reg = LPASS_CDC_VA_TX0_TX_VOL_CTL + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + adc_mux_reg = LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1 + + LPASS_CDC_VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, + dec_cfg_reg, 0x06, va_priv->dec_mode[decimator] << + LPASS_CDC_VA_MACRO_ADC_MODE_CFG0_SHIFT); + /* Enable TX PGA Mute */ + snd_soc_component_update_bits(component, + tx_vol_ctl_reg, 0x10, 0x10); + break; + case SND_SOC_DAPM_POST_PMU: + /* Enable TX CLK */ + snd_soc_component_update_bits(component, + tx_vol_ctl_reg, 0x20, 0x20); + if (!is_amic_enabled(component, decimator)) { + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x01, 0x00); + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + } + hpf_cut_off_freq = (snd_soc_component_read32( + component, dec_cfg_reg) & + TX_HPF_CUT_OFF_FREQ_MASK) >> 5; + va_priv->va_hpf_work[decimator].hpf_cut_off_freq = + hpf_cut_off_freq; + + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + snd_soc_component_update_bits(component, dec_cfg_reg, + TX_HPF_CUT_OFF_FREQ_MASK, + CF_MIN_3DB_150HZ << 5); + } + if (is_amic_enabled(component, decimator) < LPASS_CDC_ADC_MAX) { + hpf_delay = LPASS_CDC_VA_TX_AMIC_HPF_DELAY_MS; + unmute_delay = LPASS_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS; + if (va_tx_unmute_delay < unmute_delay) + va_tx_unmute_delay = unmute_delay; + } + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x02); + if (!is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x00); + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, + hpf_gate_reg, 0x03, 0x01); + /* + * 6ms delay is required as per HW spec + */ + usleep_range(6000, 6010); + /* schedule work queue to Remove Mute */ + queue_delayed_work(system_freezable_wq, + &va_priv->va_mute_dwork[decimator].dwork, + msecs_to_jiffies(va_tx_unmute_delay)); + if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq != + CF_MIN_3DB_150HZ) + queue_delayed_work(system_freezable_wq, + &va_priv->va_hpf_work[decimator].dwork, + msecs_to_jiffies(hpf_delay)); + /* apply gain after decimator is enabled */ + snd_soc_component_write(component, tx_gain_ctl_reg, + snd_soc_component_read32(component, tx_gain_ctl_reg)); + if (va_priv->version == LPASS_CDC_VERSION_2_0) { + if (snd_soc_component_read32(component, adc_mux_reg) + & SWR_MIC) { + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, + 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC0_CTL, + 0x0E, 0x0C); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC1_CTL, + 0x0E, 0x0C); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC2_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC3_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC4_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_MIC5_CTL, + 0x0E, 0x00); + } + } + break; + case SND_SOC_DAPM_PRE_PMD: + hpf_cut_off_freq = + va_priv->va_hpf_work[decimator].hpf_cut_off_freq; + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x10, 0x10); + if (cancel_delayed_work_sync( + &va_priv->va_hpf_work[decimator].dwork)) { + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + snd_soc_component_update_bits(component, + dec_cfg_reg, + TX_HPF_CUT_OFF_FREQ_MASK, + hpf_cut_off_freq << 5); + if (is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x02); + else + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x03); + /* + * Minimum 1 clk cycle delay is required + * as per HW spec + */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, + hpf_gate_reg, + 0x03, 0x01); + } + } + cancel_delayed_work_sync( + &va_priv->va_mute_dwork[decimator].dwork); + if (va_priv->version == LPASS_CDC_VERSION_2_0) { + if (snd_soc_component_read32(component, adc_mux_reg) + & SWR_MIC) + snd_soc_component_update_bits(component, + LPASS_CDC_TX_TOP_CSR_SWR_CTRL, + 0x01, 0x00); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable TX CLK */ + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x20, 0x00); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x10, 0x00); + break; + } + return 0; +} + +static int lpass_cdc_va_macro_enable_tx(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + int ret = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (va_priv->tx_clk_status > 0) { + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + TX_CORE_CLK, + false); + va_priv->tx_clk_status--; + } + break; + case SND_SOC_DAPM_PRE_PMD: + ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + TX_CORE_CLK, + true); + if (!ret) + va_priv->tx_clk_status++; + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + break; + } + + return ret; +} + +static int lpass_cdc_va_macro_enable_micbias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + int ret = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if (!va_priv->micb_supply) { + dev_err(va_dev, + "%s:regulator not provided in dtsi\n", __func__); + return -EINVAL; + } + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (va_priv->micb_users++ > 0) + return 0; + ret = regulator_set_voltage(va_priv->micb_supply, + va_priv->micb_voltage, + va_priv->micb_voltage); + if (ret) { + dev_err(va_dev, "%s: Setting voltage failed, err = %d\n", + __func__, ret); + return ret; + } + ret = regulator_set_load(va_priv->micb_supply, + va_priv->micb_current); + if (ret) { + dev_err(va_dev, "%s: Setting current failed, err = %d\n", + __func__, ret); + return ret; + } + ret = regulator_enable(va_priv->micb_supply); + if (ret) { + dev_err(va_dev, "%s: regulator enable failed, err = %d\n", + __func__, ret); + return ret; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (--va_priv->micb_users > 0) + return 0; + if (va_priv->micb_users < 0) { + va_priv->micb_users = 0; + dev_dbg(va_dev, "%s: regulator already disabled\n", + __func__); + return 0; + } + ret = regulator_disable(va_priv->micb_supply); + if (ret) { + dev_err(va_dev, "%s: regulator disable failed, err = %d\n", + __func__, ret); + return ret; + } + regulator_set_voltage(va_priv->micb_supply, 0, + va_priv->micb_voltage); + regulator_set_load(va_priv->micb_supply, 0); + break; + } + return 0; +} + +static inline int lpass_cdc_va_macro_path_get(const char *wname, + unsigned int *path_num) +{ + int ret = 0; + char *widget_name = NULL; + char *w_name = NULL; + char *path_num_char = NULL; + char *path_name = NULL; + + widget_name = kstrndup(wname, 10, GFP_KERNEL); + if (!widget_name) + return -EINVAL; + + w_name = widget_name; + + path_name = strsep(&widget_name, " "); + if (!path_name) { + pr_err("%s: Invalid widget name = %s\n", + __func__, widget_name); + ret = -EINVAL; + goto err; + } + path_num_char = strpbrk(path_name, "01234567"); + if (!path_num_char) { + pr_err("%s: va path index not found\n", + __func__); + ret = -EINVAL; + goto err; + } + ret = kstrtouint(path_num_char, 10, path_num); + if (ret < 0) + pr_err("%s: Invalid tx path = %s\n", + __func__, w_name); + +err: + kfree(w_name); + return ret; +} + +static int lpass_cdc_va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_va_macro_priv *priv = NULL; + struct device *va_dev = NULL; + int ret = 0; + int path = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, &priv, __func__)) + return -EINVAL; + + ret = lpass_cdc_va_macro_path_get(kcontrol->id.name, &path); + if (ret) + return ret; + + ucontrol->value.integer.value[0] = priv->dec_mode[path]; + + return 0; +} + +static int lpass_cdc_va_macro_dec_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct lpass_cdc_va_macro_priv *priv = NULL; + struct device *va_dev = NULL; + int value = ucontrol->value.integer.value[0]; + int ret = 0; + int path = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, &priv, __func__)) + return -EINVAL; + + ret = lpass_cdc_va_macro_path_get(kcontrol->id.name, &path); + if (ret) + return ret; + + priv->dec_mode[path] = value; + + return 0; +} + +static int lpass_cdc_va_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int tx_fs_rate = -EINVAL; + struct snd_soc_component *component = dai->component; + u32 decimator, sample_rate; + u16 tx_fs_reg = 0; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, + "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__, + dai->name, dai->id, params_rate(params), + params_channels(params)); + + sample_rate = params_rate(params); + switch (sample_rate) { + case 8000: + tx_fs_rate = 0; + break; + case 16000: + tx_fs_rate = 1; + break; + case 32000: + tx_fs_rate = 3; + break; + case 48000: + tx_fs_rate = 4; + break; + case 96000: + tx_fs_rate = 5; + break; + case 192000: + tx_fs_rate = 6; + break; + case 384000: + tx_fs_rate = 7; + break; + default: + dev_err(va_dev, "%s: Invalid TX sample rate: %d\n", + __func__, params_rate(params)); + return -EINVAL; + } + for_each_set_bit(decimator, &va_priv->active_ch_mask[dai->id], + LPASS_CDC_VA_MACRO_DEC_MAX) { + if (decimator >= 0) { + tx_fs_reg = LPASS_CDC_VA_TX0_TX_PATH_CTL + + LPASS_CDC_VA_MACRO_TX_PATH_OFFSET * decimator; + dev_dbg(va_dev, "%s: set DEC%u rate to %u\n", + __func__, decimator, sample_rate); + snd_soc_component_update_bits(component, tx_fs_reg, + 0x0F, tx_fs_rate); + } else { + dev_err(va_dev, + "%s: ERROR: Invalid decimator: %d\n", + __func__, decimator); + return -EINVAL; + } + } + return 0; +} + +static int lpass_cdc_va_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + switch (dai->id) { + case LPASS_CDC_VA_MACRO_AIF1_CAP: + case LPASS_CDC_VA_MACRO_AIF2_CAP: + case LPASS_CDC_VA_MACRO_AIF3_CAP: + *tx_slot = va_priv->active_ch_mask[dai->id]; + *tx_num = va_priv->active_ch_cnt[dai->id]; + break; + default: + dev_err(va_dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static struct snd_soc_dai_ops lpass_cdc_va_macro_dai_ops = { + .hw_params = lpass_cdc_va_macro_hw_params, + .get_channel_map = lpass_cdc_va_macro_get_channel_map, +}; + +static struct snd_soc_dai_driver lpass_cdc_va_macro_dai[] = { + { + .name = "lpass_cdc_va_macro_tx1", + .id = LPASS_CDC_VA_MACRO_AIF1_CAP, + .capture = { + .stream_name = "VA_AIF1 Capture", + .rates = LPASS_CDC_VA_MACRO_RATES, + .formats = LPASS_CDC_VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_va_macro_dai_ops, + }, + { + .name = "lpass_cdc_va_macro_tx2", + .id = LPASS_CDC_VA_MACRO_AIF2_CAP, + .capture = { + .stream_name = "VA_AIF2 Capture", + .rates = LPASS_CDC_VA_MACRO_RATES, + .formats = LPASS_CDC_VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_va_macro_dai_ops, + }, + { + .name = "lpass_cdc_va_macro_tx3", + .id = LPASS_CDC_VA_MACRO_AIF3_CAP, + .capture = { + .stream_name = "VA_AIF3 Capture", + .rates = LPASS_CDC_VA_MACRO_RATES, + .formats = LPASS_CDC_VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &lpass_cdc_va_macro_dai_ops, + }, +}; + +#define STRING(name) #name +#define LPASS_CDC_VA_MACRO_DAPM_ENUM(name, reg, offset, text) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM(STRING(name), name##_enum) + +#define LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \ +static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \ +static const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname) + +#define LPASS_CDC_VA_MACRO_DAPM_MUX(name, shift, kctl) \ + SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux) + +static const char * const adc_mux_text[] = { + "MSM_DMIC", "SWR_MIC" +}; + +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec4, LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec5, LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec6, LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG1, + 0, adc_mux_text); +LPASS_CDC_VA_MACRO_DAPM_ENUM(va_dec7, LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG1, + 0, adc_mux_text); + +static const char * const dmic_mux_text[] = { + "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", + "DMIC4", "DMIC5", "DMIC6", "DMIC7" +}; + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic4, LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic5, LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic6, LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_dmic7, LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0, + 4, dmic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +static const char * const smic_mux_text[] = { + "ZERO", "ADC0", "ADC1", "ADC2", "ADC3", + "SWR_DMIC0", "SWR_DMIC1", "SWR_DMIC2", "SWR_DMIC3", + "SWR_DMIC4", "SWR_DMIC5", "SWR_DMIC6", "SWR_DMIC7" +}; + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic0, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic1, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic2, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic4, LPASS_CDC_VA_INP_MUX_ADC_MUX4_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic5, LPASS_CDC_VA_INP_MUX_ADC_MUX5_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic6, LPASS_CDC_VA_INP_MUX_ADC_MUX6_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic7, LPASS_CDC_VA_INP_MUX_ADC_MUX7_CFG0, + 0, smic_mux_text, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +static const char * const smic_mux_text_v2[] = { + "ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3", + "SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7", + "SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11" +}; + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic0_v2, LPASS_CDC_VA_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic1_v2, LPASS_CDC_VA_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic2_v3, LPASS_CDC_VA_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +LPASS_CDC_VA_MACRO_DAPM_ENUM_EXT(va_smic3_v3, LPASS_CDC_VA_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text_v2, snd_soc_dapm_get_enum_double, + lpass_cdc_va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_aif1_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC4, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC5, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC6, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC7, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif2_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC4, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC5, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC6, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC7, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif3_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC4, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC5, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC6, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC7, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif1_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif2_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif3_cap_mixer_v2[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif1_cap_mixer_v3[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif2_cap_mixer_v3[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif3_cap_mixer_v3[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 1, 0, + lpass_cdc_va_macro_tx_mixer_get, lpass_cdc_va_macro_tx_mixer_put), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_va_macro_dapm_widgets_common[] = { + SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF1_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF2_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF3_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0_v2), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1_v2), + + SND_SOC_DAPM_INPUT("VA SWR_INPUT"), + + SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 0, + &va_dec0_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC1 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 0, + &va_dec1_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_mclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_va_macro_dapm_widgets_v2[] = { + SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF1_CAP, 0, + va_aif1_cap_mixer_v2, ARRAY_SIZE(va_aif1_cap_mixer_v2)), + + SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF2_CAP, 0, + va_aif2_cap_mixer_v2, ARRAY_SIZE(va_aif2_cap_mixer_v2)), + + SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF3_CAP, 0, + va_aif3_cap_mixer_v2, ARRAY_SIZE(va_aif3_cap_mixer_v2)), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_swr_pwr_event_v2, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_tx_swr_clk_event_v2, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_swr_clk_event_v2, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_va_macro_dapm_widgets_v3[] = { + SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF1_CAP, 0, + va_aif1_cap_mixer_v3, ARRAY_SIZE(va_aif1_cap_mixer_v3)), + + SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF2_CAP, 0, + va_aif2_cap_mixer_v3, ARRAY_SIZE(va_aif2_cap_mixer_v3)), + + SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF3_CAP, 0, + va_aif3_cap_mixer_v3, ARRAY_SIZE(va_aif3_cap_mixer_v3)), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2_v3), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3_v3), + + SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 0, + &va_dec2_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC3 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 0, + &va_dec3_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_swr_pwr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_va_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF1_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF2_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0, + SND_SOC_NOPM, LPASS_CDC_VA_MACRO_AIF3_CAP, 0, + lpass_cdc_va_macro_enable_tx, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF1_CAP, 0, + va_aif1_cap_mixer, ARRAY_SIZE(va_aif1_cap_mixer)), + + SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF2_CAP, 0, + va_aif2_cap_mixer, ARRAY_SIZE(va_aif2_cap_mixer)), + + SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM, + LPASS_CDC_VA_MACRO_AIF3_CAP, 0, + va_aif3_cap_mixer, ARRAY_SIZE(va_aif3_cap_mixer)), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX4", 0, va_dmic4), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX5", 0, va_dmic5), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX6", 0, va_dmic6), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA DMIC MUX7", 0, va_dmic7), + + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX4", 0, va_smic4), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX5", 0, va_smic5), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX6", 0, va_smic6), + LPASS_CDC_VA_MACRO_DAPM_MUX("VA SMIC MUX7", 0, va_smic7), + + SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_micbias, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("VA SWR_ADC0"), + SND_SOC_DAPM_INPUT("VA SWR_ADC1"), + SND_SOC_DAPM_INPUT("VA SWR_ADC2"), + SND_SOC_DAPM_INPUT("VA SWR_ADC3"), + SND_SOC_DAPM_INPUT("VA SWR_MIC0"), + SND_SOC_DAPM_INPUT("VA SWR_MIC1"), + SND_SOC_DAPM_INPUT("VA SWR_MIC2"), + SND_SOC_DAPM_INPUT("VA SWR_MIC3"), + SND_SOC_DAPM_INPUT("VA SWR_MIC4"), + SND_SOC_DAPM_INPUT("VA SWR_MIC5"), + SND_SOC_DAPM_INPUT("VA SWR_MIC6"), + SND_SOC_DAPM_INPUT("VA SWR_MIC7"), + + SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC0, 0, + &va_dec0_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC1 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC1, 0, + &va_dec1_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC2, 0, + &va_dec2_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC3 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC3, 0, + &va_dec3_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC4 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC4, 0, + &va_dec4_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC5 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC5, 0, + &va_dec5_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC6 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC6, 0, + &va_dec6_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC7 MUX", SND_SOC_NOPM, LPASS_CDC_VA_MACRO_DEC7, 0, + &va_dec7_mux, lpass_cdc_va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_swr_pwr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_mclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_va_macro_wod_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, + lpass_cdc_va_macro_mclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route va_audio_map_common[] = { + {"VA_AIF1 CAP", NULL, "VA_MCLK"}, + {"VA_AIF2 CAP", NULL, "VA_MCLK"}, + {"VA_AIF3 CAP", NULL, "VA_MCLK"}, + + {"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"}, + {"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"}, + {"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"}, + + {"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + + {"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + + {"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + + {"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"}, + {"VA DMIC MUX0", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX0", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX0", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX0", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX0", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX0", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX0", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX0", "DMIC7", "VA DMIC7"}, + + {"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"}, + {"VA SMIC MUX0", "SWR_MIC0", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC1", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC2", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC3", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC4", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC5", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC6", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC7", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC8", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC9", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC10", "VA SWR_INPUT"}, + {"VA SMIC MUX0", "SWR_MIC11", "VA SWR_INPUT"}, + + {"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"}, + {"VA DMIC MUX1", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX1", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX1", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX1", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX1", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX1", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX1", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX1", "DMIC7", "VA DMIC7"}, + + {"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"}, + {"VA SMIC MUX1", "SWR_MIC0", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC1", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC2", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC3", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC4", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC5", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC6", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC7", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC8", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC9", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC10", "VA SWR_INPUT"}, + {"VA SMIC MUX1", "SWR_MIC11", "VA SWR_INPUT"}, + + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + {"VA SWR_INPUT", NULL, "VA_SWR_PWR"}, + +}; + +static const struct snd_soc_dapm_route va_audio_map_v3[] = { + {"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"}, + {"VA DMIC MUX2", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX2", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX2", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX2", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX2", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX2", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX2", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX2", "DMIC7", "VA DMIC7"}, + + {"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"}, + {"VA SMIC MUX2", "SWR_MIC0", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC1", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC2", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC3", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC4", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC5", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC6", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC7", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC8", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC9", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC10", "VA SWR_INPUT"}, + {"VA SMIC MUX2", "SWR_MIC11", "VA SWR_INPUT"}, + + {"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"}, + {"VA DMIC MUX3", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX3", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX3", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX3", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX3", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX3", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + + {"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"}, + {"VA SMIC MUX3", "SWR_MIC0", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC1", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC2", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC3", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC4", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC5", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC6", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC7", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC8", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"}, + {"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"}, +}; + +static const struct snd_soc_dapm_route va_audio_map_v2[] = { + {"VA_AIF1 CAP", NULL, "VA_SWR_CLK"}, + {"VA_AIF2 CAP", NULL, "VA_SWR_CLK"}, + {"VA_AIF3 CAP", NULL, "VA_SWR_CLK"}, +}; + +static const struct snd_soc_dapm_route va_audio_map[] = { + {"VA_AIF1 CAP", NULL, "VA_MCLK"}, + {"VA_AIF2 CAP", NULL, "VA_MCLK"}, + {"VA_AIF3 CAP", NULL, "VA_MCLK"}, + + {"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"}, + {"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"}, + {"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"}, + + {"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC4", "VA DEC4 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC5", "VA DEC5 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC6", "VA DEC6 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC7", "VA DEC7 MUX"}, + + {"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC4", "VA DEC4 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC5", "VA DEC5 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC6", "VA DEC6 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC7", "VA DEC7 MUX"}, + + {"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC4", "VA DEC4 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC5", "VA DEC5 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC6", "VA DEC6 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC7", "VA DEC7 MUX"}, + + {"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"}, + {"VA DMIC MUX0", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX0", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX0", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX0", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX0", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX0", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX0", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX0", "DMIC7", "VA DMIC7"}, + + {"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"}, + {"VA SMIC MUX0", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX0", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX0", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX0", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX0", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX0", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX0", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX0", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX0", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX0", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX0", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX0", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"}, + {"VA DMIC MUX1", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX1", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX1", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX1", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX1", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX1", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX1", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX1", "DMIC7", "VA DMIC7"}, + + {"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"}, + {"VA SMIC MUX1", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX1", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX1", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX1", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX1", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX1", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX1", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX1", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX1", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX1", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX1", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX1", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"}, + {"VA DMIC MUX2", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX2", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX2", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX2", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX2", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX2", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX2", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX2", "DMIC7", "VA DMIC7"}, + + {"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"}, + {"VA SMIC MUX2", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX2", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX2", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX2", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX2", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX2", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX2", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX2", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX2", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX2", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX2", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX2", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"}, + {"VA DMIC MUX3", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX3", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX3", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX3", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX3", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX3", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + + {"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"}, + {"VA SMIC MUX3", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX3", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX3", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX3", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX3", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX3", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX3", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX3", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX3", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX3", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX3", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX3", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC4 MUX", "MSM_DMIC", "VA DMIC MUX4"}, + {"VA DMIC MUX4", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX4", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX4", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX4", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX4", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX4", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX4", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX4", "DMIC7", "VA DMIC7"}, + + {"VA DEC4 MUX", "SWR_MIC", "VA SMIC MUX4"}, + {"VA SMIC MUX4", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX4", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX4", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX4", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX4", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX4", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX4", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX4", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX4", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX4", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX4", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX4", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC5 MUX", "MSM_DMIC", "VA DMIC MUX5"}, + {"VA DMIC MUX5", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX5", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX5", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX5", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX5", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX5", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX5", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX5", "DMIC7", "VA DMIC7"}, + + {"VA DEC5 MUX", "SWR_MIC", "VA SMIC MUX5"}, + {"VA SMIC MUX5", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX5", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX5", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX5", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX5", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX5", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX5", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX5", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX5", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX5", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX5", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX5", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC6 MUX", "MSM_DMIC", "VA DMIC MUX6"}, + {"VA DMIC MUX6", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX6", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX6", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX6", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX6", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX6", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX6", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX6", "DMIC7", "VA DMIC7"}, + + {"VA DEC6 MUX", "SWR_MIC", "VA SMIC MUX6"}, + {"VA SMIC MUX6", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX6", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX6", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX6", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX6", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX6", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX6", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX6", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX6", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX6", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX6", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX6", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA DEC7 MUX", "MSM_DMIC", "VA DMIC MUX7"}, + {"VA DMIC MUX7", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX7", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX7", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX7", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX7", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX7", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX7", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX7", "DMIC7", "VA DMIC7"}, + + {"VA DEC7 MUX", "SWR_MIC", "VA SMIC MUX7"}, + {"VA SMIC MUX7", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX7", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX7", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX7", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX7", "SWR_DMIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX7", "SWR_DMIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX7", "SWR_DMIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX7", "SWR_DMIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX7", "SWR_DMIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX7", "SWR_DMIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"}, + + {"VA SWR_ADC0", NULL, "VA_SWR_PWR"}, + {"VA SWR_ADC1", NULL, "VA_SWR_PWR"}, + {"VA SWR_ADC2", NULL, "VA_SWR_PWR"}, + {"VA SWR_ADC3", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC0", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC1", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC2", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC3", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC4", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC5", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC6", NULL, "VA_SWR_PWR"}, + {"VA SWR_MIC7", NULL, "VA_SWR_PWR"}, +}; + +static const char * const dec_mode_mux_text[] = { + "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", +}; + +static const struct soc_enum dec_mode_mux_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text); + +static const struct snd_kcontrol_new lpass_cdc_va_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("VA_DEC0 Volume", + LPASS_CDC_VA_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC1 Volume", + LPASS_CDC_VA_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC2 Volume", + LPASS_CDC_VA_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC3 Volume", + LPASS_CDC_VA_TX3_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC4 Volume", + LPASS_CDC_VA_TX4_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC5 Volume", + LPASS_CDC_VA_TX5_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC6 Volume", + LPASS_CDC_VA_TX6_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC7 Volume", + LPASS_CDC_VA_TX7_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, + lpass_cdc_va_macro_lpi_get, lpass_cdc_va_macro_lpi_put), + + SOC_ENUM_EXT("VA_DEC0 MODE", dec_mode_mux_enum, + lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put), + + SOC_ENUM_EXT("VA_DEC1 MODE", dec_mode_mux_enum, + lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put), + + SOC_ENUM_EXT("VA_DEC2 MODE", dec_mode_mux_enum, + lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put), + + SOC_ENUM_EXT("VA_DEC3 MODE", dec_mode_mux_enum, + lpass_cdc_va_macro_dec_mode_get, lpass_cdc_va_macro_dec_mode_put), +}; + +static const struct snd_kcontrol_new lpass_cdc_va_macro_snd_controls_common[] = +{ + SOC_SINGLE_S8_TLV("VA_DEC0 Volume", + LPASS_CDC_VA_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC1 Volume", + LPASS_CDC_VA_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, + lpass_cdc_va_macro_lpi_get, lpass_cdc_va_macro_lpi_put), +}; + +static const struct snd_kcontrol_new lpass_cdc_va_macro_snd_controls_v3[] = { + SOC_SINGLE_S8_TLV("VA_DEC2 Volume", + LPASS_CDC_VA_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC3 Volume", + LPASS_CDC_VA_TX3_TX_VOL_CTL, + -84, 40, digital_gain), +}; + +static int lpass_cdc_va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, + struct lpass_cdc_va_macro_priv *va_priv) +{ + u32 div_factor; + u32 mclk_rate = LPASS_CDC_VA_MACRO_MCLK_FREQ; + + if (dmic_sample_rate == LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED || + mclk_rate % dmic_sample_rate != 0) + goto undefined_rate; + + div_factor = mclk_rate / dmic_sample_rate; + + switch (div_factor) { + case 2: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_2; + break; + case 3: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_3; + break; + case 4: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_4; + break; + case 6: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_6; + break; + case 8: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_8; + break; + case 16: + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_16; + break; + default: + /* Any other DIV factor is invalid */ + goto undefined_rate; + } + + /* Valid dmic DIV factors */ + dev_dbg(va_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n", + __func__, div_factor, mclk_rate); + + return dmic_sample_rate; + +undefined_rate: + dev_dbg(va_priv->dev, "%s: Invalid rate %d, for mclk %d\n", + __func__, dmic_sample_rate, mclk_rate); + dmic_sample_rate = LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED; + + return dmic_sample_rate; +} + +static int lpass_cdc_va_macro_init(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + int ret, i; + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + va_dev = lpass_cdc_get_device_ptr(component->dev, VA_MACRO); + if (!va_dev) { + dev_err(component->dev, + "%s: null device for macro!\n", __func__); + return -EINVAL; + } + va_priv = dev_get_drvdata(va_dev); + if (!va_priv) { + dev_err(component->dev, + "%s: priv is null for macro!\n", __func__); + return -EINVAL; + } + + va_priv->lpi_enable = false; + va_priv->register_event_listener = false; + + if (va_priv->va_without_decimation) { + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_va_macro_wod_dapm_widgets, + ARRAY_SIZE(lpass_cdc_va_macro_wod_dapm_widgets)); + if (ret < 0) { + dev_err(va_dev, + "%s: Failed to add without dec controls\n", + __func__); + return ret; + } + va_priv->component = component; + return 0; + } + + va_priv->version = lpass_cdc_get_version(va_dev); + if (va_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_va_macro_dapm_widgets_common, + ARRAY_SIZE(lpass_cdc_va_macro_dapm_widgets_common)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + if (va_priv->version == LPASS_CDC_VERSION_2_1) + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_va_macro_dapm_widgets_v2, + ARRAY_SIZE(lpass_cdc_va_macro_dapm_widgets_v2)); + else if (va_priv->version == LPASS_CDC_VERSION_2_0) + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_va_macro_dapm_widgets_v3, + ARRAY_SIZE(lpass_cdc_va_macro_dapm_widgets_v3)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + } else { + ret = snd_soc_dapm_new_controls(dapm, + lpass_cdc_va_macro_dapm_widgets, + ARRAY_SIZE(lpass_cdc_va_macro_dapm_widgets)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add controls\n", + __func__); + return ret; + } + } + + if (va_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_dapm_add_routes(dapm, + va_audio_map_common, + ARRAY_SIZE(va_audio_map_common)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + if (va_priv->version == LPASS_CDC_VERSION_2_0) { + ret = snd_soc_dapm_add_routes(dapm, + va_audio_map_v3, + ARRAY_SIZE(va_audio_map_v3)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + } + if (va_priv->version == LPASS_CDC_VERSION_2_1) { + ret = snd_soc_dapm_add_routes(dapm, + va_audio_map_v2, + ARRAY_SIZE(va_audio_map_v2)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + } + } else { + ret = snd_soc_dapm_add_routes(dapm, va_audio_map, + ARRAY_SIZE(va_audio_map)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add routes\n", + __func__); + return ret; + } + } + + ret = snd_soc_dapm_new_widgets(dapm->card); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add widgets\n", __func__); + return ret; + } + if (va_priv->version >= LPASS_CDC_VERSION_2_0) { + ret = snd_soc_add_component_controls(component, + lpass_cdc_va_macro_snd_controls_common, + ARRAY_SIZE(lpass_cdc_va_macro_snd_controls_common)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + if (va_priv->version == LPASS_CDC_VERSION_2_0) + ret = snd_soc_add_component_controls(component, + lpass_cdc_va_macro_snd_controls_v3, + ARRAY_SIZE(lpass_cdc_va_macro_snd_controls_v3)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + } else { + ret = snd_soc_add_component_controls(component, + lpass_cdc_va_macro_snd_controls, + ARRAY_SIZE(lpass_cdc_va_macro_snd_controls)); + if (ret < 0) { + dev_err(va_dev, "%s: Failed to add snd_ctls\n", + __func__); + return ret; + } + } + + snd_soc_dapm_ignore_suspend(dapm, "VA_AIF1 Capture"); + snd_soc_dapm_ignore_suspend(dapm, "VA_AIF2 Capture"); + snd_soc_dapm_ignore_suspend(dapm, "VA_AIF3 Capture"); + if (va_priv->version >= LPASS_CDC_VERSION_2_0) { + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_INPUT"); + } else { + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6"); + snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7"); + } + snd_soc_dapm_sync(dapm); + + for (i = 0; i < LPASS_CDC_VA_MACRO_NUM_DECIMATORS; i++) { + va_priv->va_hpf_work[i].va_priv = va_priv; + va_priv->va_hpf_work[i].decimator = i; + INIT_DELAYED_WORK(&va_priv->va_hpf_work[i].dwork, + lpass_cdc_va_macro_tx_hpf_corner_freq_callback); + } + + for (i = 0; i < LPASS_CDC_VA_MACRO_NUM_DECIMATORS; i++) { + va_priv->va_mute_dwork[i].va_priv = va_priv; + va_priv->va_mute_dwork[i].decimator = i; + INIT_DELAYED_WORK(&va_priv->va_mute_dwork[i].dwork, + lpass_cdc_va_macro_mute_update_callback); + } + va_priv->component = component; + + if (va_priv->version == LPASS_CDC_VERSION_2_1) { + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE, 0xCC); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE, 0xCC); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE, 0xCC); + } + + return 0; +} + +static int lpass_cdc_va_macro_deinit(struct snd_soc_component *component) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + va_priv->component = NULL; + return 0; +} + +static void lpass_cdc_va_macro_add_child_devices(struct work_struct *work) +{ + struct lpass_cdc_va_macro_priv *va_priv = NULL; + struct platform_device *pdev = NULL; + struct device_node *node = NULL; + struct lpass_cdc_va_macro_swr_ctrl_data *swr_ctrl_data = NULL; + struct lpass_cdc_va_macro_swr_ctrl_data *temp = NULL; + int ret = 0; + u16 count = 0, ctrl_num = 0; + struct lpass_cdc_va_macro_swr_ctrl_platform_data *platdata = NULL; + char plat_dev_name[LPASS_CDC_VA_MACRO_SWR_STRING_LEN] = ""; + bool va_swr_master_node = false; + + va_priv = container_of(work, struct lpass_cdc_va_macro_priv, + lpass_cdc_va_macro_add_child_devices_work); + if (!va_priv) { + pr_err("%s: Memory for va_priv does not exist\n", + __func__); + return; + } + + if (!va_priv->dev) { + pr_err("%s: VA dev does not exist\n", __func__); + return; + } + + if (!va_priv->dev->of_node) { + dev_err(va_priv->dev, + "%s: DT node for va_priv does not exist\n", __func__); + return; + } + + platdata = &va_priv->swr_plat_data; + va_priv->child_count = 0; + + for_each_available_child_of_node(va_priv->dev->of_node, node) { + va_swr_master_node = false; + if (strnstr(node->name, "va_swr_master", + strlen("va_swr_master")) != NULL) + va_swr_master_node = true; + + if (va_swr_master_node) + strlcpy(plat_dev_name, "va_swr_ctrl", + (LPASS_CDC_VA_MACRO_SWR_STRING_LEN - 1)); + else + strlcpy(plat_dev_name, node->name, + (LPASS_CDC_VA_MACRO_SWR_STRING_LEN - 1)); + + pdev = platform_device_alloc(plat_dev_name, -1); + if (!pdev) { + dev_err(va_priv->dev, "%s: pdev memory alloc failed\n", + __func__); + ret = -ENOMEM; + goto err; + } + pdev->dev.parent = va_priv->dev; + pdev->dev.of_node = node; + + if (va_swr_master_node) { + ret = platform_device_add_data(pdev, platdata, + sizeof(*platdata)); + if (ret) { + dev_err(&pdev->dev, + "%s: cannot add plat data ctrl:%d\n", + __func__, ctrl_num); + goto fail_pdev_add; + } + } + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, + "%s: Cannot add platform device\n", + __func__); + goto fail_pdev_add; + } + + if (va_swr_master_node) { + temp = krealloc(swr_ctrl_data, + (ctrl_num + 1) * sizeof( + struct lpass_cdc_va_macro_swr_ctrl_data), + GFP_KERNEL); + if (!temp) { + ret = -ENOMEM; + goto fail_pdev_add; + } + swr_ctrl_data = temp; + swr_ctrl_data[ctrl_num].va_swr_pdev = pdev; + ctrl_num++; + dev_dbg(&pdev->dev, + "%s: Added soundwire ctrl device(s)\n", + __func__); + va_priv->swr_ctrl_data = swr_ctrl_data; + } + if (va_priv->child_count < LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX) + va_priv->pdev_child_devices[ + va_priv->child_count++] = pdev; + else + goto err; + } + return; +fail_pdev_add: + for (count = 0; count < va_priv->child_count; count++) + platform_device_put(va_priv->pdev_child_devices[count]); +err: + return; +} + +static int lpass_cdc_va_macro_set_port_map(struct snd_soc_component *component, + u32 usecase, u32 size, void *data) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + struct swrm_port_config port_cfg; + int ret = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, &va_priv, __func__)) + return -EINVAL; + + memset(&port_cfg, 0, sizeof(port_cfg)); + port_cfg.uc = usecase; + port_cfg.size = size; + port_cfg.params = data; + + if (va_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + va_priv->swr_ctrl_data[0].va_swr_pdev, + SWR_SET_PORT_MAP, &port_cfg); + + return ret; +} + +static int lpass_cdc_va_macro_reg_wake_irq(struct snd_soc_component *component, + u32 data) +{ + struct device *va_dev = NULL; + struct lpass_cdc_va_macro_priv *va_priv = NULL; + u32 ipc_wakeup = data; + int ret = 0; + + if (!lpass_cdc_va_macro_get_data(component, &va_dev, + &va_priv, __func__)) + return -EINVAL; + + if (va_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + va_priv->swr_ctrl_data[0].va_swr_pdev, + SWR_REGISTER_WAKE_IRQ, &ipc_wakeup); + + return ret; +} + +static void lpass_cdc_va_macro_init_ops(struct macro_ops *ops, + char __iomem *va_io_base, + bool va_without_decimation) +{ + memset(ops, 0, sizeof(struct macro_ops)); + if (!va_without_decimation) { + ops->dai_ptr = lpass_cdc_va_macro_dai; + ops->num_dais = ARRAY_SIZE(lpass_cdc_va_macro_dai); + } else { + ops->dai_ptr = NULL; + ops->num_dais = 0; + } + ops->init = lpass_cdc_va_macro_init; + ops->exit = lpass_cdc_va_macro_deinit; + ops->io_base = va_io_base; + ops->event_handler = lpass_cdc_va_macro_event_handler; + ops->set_port_map = lpass_cdc_va_macro_set_port_map; + ops->reg_wake_irq = lpass_cdc_va_macro_reg_wake_irq; + ops->clk_div_get = lpass_cdc_va_macro_clk_div_get; +} + +static int lpass_cdc_va_macro_probe(struct platform_device *pdev) +{ + struct macro_ops ops; + struct lpass_cdc_va_macro_priv *va_priv; + u32 va_base_addr, sample_rate = 0; + char __iomem *va_io_base; + bool va_without_decimation = false; + const char *micb_supply_str = "va-vdd-micb-supply"; + const char *micb_supply_str1 = "va-vdd-micb"; + const char *micb_voltage_str = "qcom,va-vdd-micb-voltage"; + const char *micb_current_str = "qcom,va-vdd-micb-current"; + int ret = 0; + const char *dmic_sample_rate = "qcom,va-dmic-sample-rate"; + u32 default_clk_id = 0; + struct clk *lpass_audio_hw_vote = NULL; + u32 is_used_va_swr_gpio = 0; + u32 disable_afe_wakeup_event_listener = 0; + const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio"; + const char *disable_afe_wakeup_event_listener_dt = + "qcom,disable-afe-wakeup-event-listener"; + + va_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_va_macro_priv), + GFP_KERNEL); + if (!va_priv) + return -ENOMEM; + + va_priv->dev = &pdev->dev; + ret = of_property_read_u32(pdev->dev.of_node, "reg", + &va_base_addr); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "reg"); + return ret; + } + va_without_decimation = of_property_read_bool(pdev->dev.parent->of_node, + "qcom,va-without-decimation"); + + va_priv->va_without_decimation = va_without_decimation; + ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate, + &sample_rate); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %d entry in dt\n", + __func__, sample_rate); + va_priv->dmic_clk_div = LPASS_CDC_VA_MACRO_CLK_DIV_2; + } else { + if (lpass_cdc_va_macro_validate_dmic_sample_rate( + sample_rate, va_priv) == + LPASS_CDC_VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED) + return -EINVAL; + } + + if (of_find_property(pdev->dev.of_node, is_used_va_swr_gpio_dt, + NULL)) { + ret = of_property_read_u32(pdev->dev.of_node, + is_used_va_swr_gpio_dt, + &is_used_va_swr_gpio); + if (ret) { + dev_err(&pdev->dev, "%s: error reading %s in dt\n", + __func__, is_used_va_swr_gpio_dt); + is_used_va_swr_gpio = 0; + } + } + + if (of_find_property(pdev->dev.of_node, + disable_afe_wakeup_event_listener_dt, NULL)) { + ret = of_property_read_u32(pdev->dev.of_node, + disable_afe_wakeup_event_listener_dt, + &disable_afe_wakeup_event_listener); + if (ret) + dev_dbg(&pdev->dev, "%s: error reading %s in dt\n", + __func__, disable_afe_wakeup_event_listener_dt); + } + va_priv->disable_afe_wakeup_event_listener = + disable_afe_wakeup_event_listener; + + va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,va-swr-gpios", 0); + if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) { + dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n", + __func__); + return -EINVAL; + } + if ((msm_cdc_pinctrl_get_state(va_priv->va_swr_gpio_p) < 0) && + is_used_va_swr_gpio) { + dev_err(&pdev->dev, "%s: failed to get swr pin state\n", + __func__); + return -EPROBE_DEFER; + } + + va_io_base = devm_ioremap(&pdev->dev, va_base_addr, + LPASS_CDC_VA_MACRO_MAX_OFFSET); + if (!va_io_base) { + dev_err(&pdev->dev, "%s: ioremap failed\n", __func__); + return -EINVAL; + } + va_priv->va_io_base = va_io_base; + + lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote"); + if (IS_ERR(lpass_audio_hw_vote)) { + ret = PTR_ERR(lpass_audio_hw_vote); + dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n", + __func__, "lpass_audio_hw_vote", ret); + lpass_audio_hw_vote = NULL; + ret = 0; + } + va_priv->lpass_audio_hw_vote = lpass_audio_hw_vote; + + if (of_parse_phandle(pdev->dev.of_node, micb_supply_str, 0)) { + va_priv->micb_supply = devm_regulator_get(&pdev->dev, + micb_supply_str1); + if (IS_ERR(va_priv->micb_supply)) { + ret = PTR_ERR(va_priv->micb_supply); + dev_err(&pdev->dev, + "%s:Failed to get micbias supply for VA Mic %d\n", + __func__, ret); + return ret; + } + ret = of_property_read_u32(pdev->dev.of_node, + micb_voltage_str, + &va_priv->micb_voltage); + if (ret) { + dev_err(&pdev->dev, + "%s:Looking up %s property in node %s failed\n", + __func__, micb_voltage_str, + pdev->dev.of_node->full_name); + return ret; + } + ret = of_property_read_u32(pdev->dev.of_node, + micb_current_str, + &va_priv->micb_current); + if (ret) { + dev_err(&pdev->dev, + "%s:Looking up %s property in node %s failed\n", + __func__, micb_current_str, + pdev->dev.of_node->full_name); + return ret; + } + } + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,default-clk-id"); + default_clk_id = VA_CORE_CLK; + } + va_priv->clk_id = VA_CORE_CLK; + va_priv->default_clk_id = default_clk_id; + + if (is_used_va_swr_gpio) { + va_priv->reset_swr = true; + INIT_WORK(&va_priv->lpass_cdc_va_macro_add_child_devices_work, + lpass_cdc_va_macro_add_child_devices); + va_priv->swr_plat_data.handle = (void *) va_priv; + va_priv->swr_plat_data.read = NULL; + va_priv->swr_plat_data.write = NULL; + va_priv->swr_plat_data.bulk_write = NULL; + va_priv->swr_plat_data.clk = lpass_cdc_va_macro_swrm_clock; + va_priv->swr_plat_data.core_vote = lpass_cdc_va_macro_core_vote; + va_priv->swr_plat_data.handle_irq = NULL; + mutex_init(&va_priv->swr_clk_lock); + } + va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio; + + mutex_init(&va_priv->mclk_lock); + dev_set_drvdata(&pdev->dev, va_priv); + lpass_cdc_va_macro_init_ops(&ops, va_io_base, va_without_decimation); + ops.clk_id_req = va_priv->default_clk_id; + ops.default_clk_id = va_priv->default_clk_id; + ret = lpass_cdc_register_macro(&pdev->dev, VA_MACRO, &ops); + if (ret < 0) { + dev_err(&pdev->dev, "%s: register macro failed\n", __func__); + goto reg_macro_fail; + } + if (is_used_va_swr_gpio) + schedule_work(&va_priv->lpass_cdc_va_macro_add_child_devices_work); + pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_suspend_ignore_children(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); + return ret; + +reg_macro_fail: + mutex_destroy(&va_priv->mclk_lock); + if (is_used_va_swr_gpio) + mutex_destroy(&va_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_va_macro_remove(struct platform_device *pdev) +{ + struct lpass_cdc_va_macro_priv *va_priv; + int count = 0; + + va_priv = dev_get_drvdata(&pdev->dev); + + if (!va_priv) + return -EINVAL; + if (va_priv->is_used_va_swr_gpio) { + if (va_priv->swr_ctrl_data) + kfree(va_priv->swr_ctrl_data); + for (count = 0; count < va_priv->child_count && + count < LPASS_CDC_VA_MACRO_CHILD_DEVICES_MAX; count++) + platform_device_unregister( + va_priv->pdev_child_devices[count]); + } + + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + lpass_cdc_unregister_macro(&pdev->dev, VA_MACRO); + mutex_destroy(&va_priv->mclk_lock); + if (va_priv->is_used_va_swr_gpio) + mutex_destroy(&va_priv->swr_clk_lock); + return 0; +} + + +static const struct of_device_id lpass_cdc_va_macro_dt_match[] = { + {.compatible = "qcom,lpass-cdc-va-macro"}, + {} +}; + +static const struct dev_pm_ops lpass_cdc_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + pm_runtime_force_suspend, + pm_runtime_force_resume + ) + SET_RUNTIME_PM_OPS( + lpass_cdc_runtime_suspend, + lpass_cdc_runtime_resume, + NULL + ) +}; + +static struct platform_driver lpass_cdc_va_macro_driver = { + .driver = { + .name = "lpass_cdc_va_macro", + .owner = THIS_MODULE, + .pm = &lpass_cdc_dev_pm_ops, + .of_match_table = lpass_cdc_va_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_va_macro_probe, + .remove = lpass_cdc_va_macro_remove, +}; + +module_platform_driver(lpass_cdc_va_macro_driver); + +MODULE_DESCRIPTION("LPASS codec VA macro driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c new file mode 100644 index 0000000000..fb60d3dbca --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c @@ -0,0 +1,3323 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "lpass-cdc.h" +#include "lpass-cdc-registers.h" +#include "lpass-cdc-wsa-macro.h" +#include "lpass-cdc-clk-rsc.h" + +#define AUTO_SUSPEND_DELAY 50 /* delay in msec */ +#define LPASS_CDC_WSA_MACRO_MAX_OFFSET 0x1000 + +#define LPASS_CDC_WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define LPASS_CDC_WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define LPASS_CDC_WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define LPASS_CDC_WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_48000) +#define LPASS_CDC_WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define NUM_INTERPOLATORS 2 + +#define LPASS_CDC_WSA_MACRO_MUX_INP_SHFT 0x3 +#define LPASS_CDC_WSA_MACRO_MUX_INP_MASK1 0x07 +#define LPASS_CDC_WSA_MACRO_MUX_INP_MASK2 0x38 +#define LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET 0x8 +#define LPASS_CDC_WSA_MACRO_MUX_CFG1_OFFSET 0x4 +#define LPASS_CDC_WSA_MACRO_RX_COMP_OFFSET 0x40 +#define LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40 +#define LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET 0x80 +#define LPASS_CDC_WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10 +#define LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C +#define LPASS_CDC_WSA_MACRO_FS_RATE_MASK 0x0F +#define LPASS_CDC_WSA_MACRO_EC_MIX_TX0_MASK 0x03 +#define LPASS_CDC_WSA_MACRO_EC_MIX_TX1_MASK 0x18 + +#define LPASS_CDC_WSA_MACRO_MAX_DMA_CH_PER_PORT 0x2 + +enum { + LPASS_CDC_WSA_MACRO_RX0 = 0, + LPASS_CDC_WSA_MACRO_RX1, + LPASS_CDC_WSA_MACRO_RX_MIX, + LPASS_CDC_WSA_MACRO_RX_MIX0 = LPASS_CDC_WSA_MACRO_RX_MIX, + LPASS_CDC_WSA_MACRO_RX_MIX1, + LPASS_CDC_WSA_MACRO_RX_MAX, +}; + +enum { + LPASS_CDC_WSA_MACRO_TX0 = 0, + LPASS_CDC_WSA_MACRO_TX1, + LPASS_CDC_WSA_MACRO_TX_MAX, +}; + +enum { + LPASS_CDC_WSA_MACRO_EC0_MUX = 0, + LPASS_CDC_WSA_MACRO_EC1_MUX, + LPASS_CDC_WSA_MACRO_EC_MUX_MAX, +}; + +enum { + LPASS_CDC_WSA_MACRO_COMP1, /* SPK_L */ + LPASS_CDC_WSA_MACRO_COMP2, /* SPK_R */ + LPASS_CDC_WSA_MACRO_COMP_MAX +}; + +enum { + LPASS_CDC_WSA_MACRO_SOFTCLIP0, /* RX0 */ + LPASS_CDC_WSA_MACRO_SOFTCLIP1, /* RX1 */ + LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX +}; + +enum { + INTn_1_INP_SEL_ZERO = 0, + INTn_1_INP_SEL_RX0, + INTn_1_INP_SEL_RX1, + INTn_1_INP_SEL_RX2, + INTn_1_INP_SEL_RX3, + INTn_1_INP_SEL_DEC0, + INTn_1_INP_SEL_DEC1, +}; + +enum { + INTn_2_INP_SEL_ZERO = 0, + INTn_2_INP_SEL_RX0, + INTn_2_INP_SEL_RX1, + INTn_2_INP_SEL_RX2, + INTn_2_INP_SEL_RX3, +}; + +struct interp_sample_rate { + int sample_rate; + int rate_val; +}; + +/* + * Structure used to update codec + * register defaults after reset + */ +struct lpass_cdc_wsa_macro_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +static struct interp_sample_rate int_prim_sample_rate_val[] = { + {8000, 0x0}, /* 8K */ + {16000, 0x1}, /* 16K */ + {24000, -EINVAL},/* 24K */ + {32000, 0x3}, /* 32K */ + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ + {384000, 0x7}, /* 384K */ + {44100, 0x8}, /* 44.1K */ +}; + +static struct interp_sample_rate int_mix_sample_rate_val[] = { + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ +}; + +#define LPASS_CDC_WSA_MACRO_SWR_STRING_LEN 80 + +static int lpass_cdc_wsa_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); +static int lpass_cdc_wsa_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot); +static int lpass_cdc_wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute); +/* Hold instance to soundwire platform device */ +struct lpass_cdc_wsa_macro_swr_ctrl_data { + struct platform_device *wsa_swr_pdev; +}; + +struct lpass_cdc_wsa_macro_swr_ctrl_platform_data { + void *handle; /* holds codec private data */ + int (*read)(void *handle, int reg); + int (*write)(void *handle, int reg, int val); + int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len); + int (*clk)(void *handle, bool enable); + int (*core_vote)(void *handle, bool enable); + int (*handle_irq)(void *handle, + irqreturn_t (*swrm_irq_handler)(int irq, + void *data), + void *swrm_handle, + int action); +}; + +struct lpass_cdc_wsa_macro_bcl_pmic_params { + u8 id; + u8 sid; + u8 ppid; +}; + +enum { + LPASS_CDC_WSA_MACRO_AIF_INVALID = 0, + LPASS_CDC_WSA_MACRO_AIF1_PB, + LPASS_CDC_WSA_MACRO_AIF_MIX1_PB, + LPASS_CDC_WSA_MACRO_AIF_VI, + LPASS_CDC_WSA_MACRO_AIF_ECHO, + LPASS_CDC_WSA_MACRO_MAX_DAIS, +}; + +#define LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX 3 + +/* + * @dev: wsa macro device pointer + * @comp_enabled: compander enable mixer value set + * @ec_hq: echo HQ enable mixer value set + * @prim_int_users: Users of interpolator + * @wsa_mclk_users: WSA MCLK users count + * @swr_clk_users: SWR clk users count + * @vi_feed_value: VI sense mask + * @mclk_lock: to lock mclk operations + * @swr_clk_lock: to lock swr master clock operations + * @swr_ctrl_data: SoundWire data structure + * @swr_plat_data: Soundwire platform data + * @lpass_cdc_wsa_macro_add_child_devices_work: work for adding child devices + * @wsa_swr_gpio_p: used by pinctrl API + * @component: codec handle + * @rx_0_count: RX0 interpolation users + * @rx_1_count: RX1 interpolation users + * @active_ch_mask: channel mask for all AIF DAIs + * @active_ch_cnt: channel count of all AIF DAIs + * @rx_port_value: mixer ctl value of WSA RX MUXes + * @wsa_io_base: Base address of WSA macro addr space + */ +struct lpass_cdc_wsa_macro_priv { + struct device *dev; + int comp_enabled[LPASS_CDC_WSA_MACRO_COMP_MAX]; + int ec_hq[LPASS_CDC_WSA_MACRO_RX1 + 1]; + u16 prim_int_users[LPASS_CDC_WSA_MACRO_RX1 + 1]; + u16 wsa_mclk_users; + u16 swr_clk_users; + bool dapm_mclk_enable; + bool reset_swr; + unsigned int vi_feed_value; + struct mutex mclk_lock; + struct mutex swr_clk_lock; + struct lpass_cdc_wsa_macro_swr_ctrl_data *swr_ctrl_data; + struct lpass_cdc_wsa_macro_swr_ctrl_platform_data swr_plat_data; + struct work_struct lpass_cdc_wsa_macro_add_child_devices_work; + struct device_node *wsa_swr_gpio_p; + struct snd_soc_component *component; + int rx_0_count; + int rx_1_count; + unsigned long active_ch_mask[LPASS_CDC_WSA_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[LPASS_CDC_WSA_MACRO_MAX_DAIS]; + int rx_port_value[LPASS_CDC_WSA_MACRO_RX_MAX]; + char __iomem *wsa_io_base; + struct platform_device *pdev_child_devices + [LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX]; + int child_count; + int ear_spkr_gain; + int spkr_gain_offset; + int spkr_mode; + int is_softclip_on[LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX]; + int softclip_clk_users[LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX]; + struct lpass_cdc_wsa_macro_bcl_pmic_params bcl_pmic_params; + char __iomem *mclk_mode_muxsel; + u16 default_clk_id; + u32 pcm_rate_vi; + int wsa_digital_mute_status[LPASS_CDC_WSA_MACRO_RX_MAX]; +}; + +static int lpass_cdc_wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component, + struct lpass_cdc_wsa_macro_priv *wsa_priv, + int event, int gain_reg); +static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[]; +static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); + +static const char *const rx_text[] = { + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1" +}; + +static const char *const rx_mix_text[] = { + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1" +}; + +static const char *const rx_mix_ec_text[] = { + "ZERO", "RX_MIX_TX0", "RX_MIX_TX1" +}; + +static const char *const rx_mux_text[] = { + "ZERO", "AIF1_PB", "AIF_MIX1_PB" +}; + +static const char *const rx_sidetone_mix_text[] = { + "ZERO", "SRC0" +}; + +static const char * const lpass_cdc_wsa_macro_ear_spkr_pa_gain_text[] = { + "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB", + "G_4_DB", "G_5_DB", "G_6_DB" +}; + +static const char * const lpass_cdc_wsa_macro_speaker_boost_stage_text[] = { + "NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2" +}; + +static const char * const lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text[] = { + "OFF", "ON" +}; + +static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = { + SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0) +}; + +static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = { + SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0) +}; + +static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_ear_spkr_pa_gain_enum, + lpass_cdc_wsa_macro_ear_spkr_pa_gain_text); +static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_spkr_boost_stage_enum, + lpass_cdc_wsa_macro_speaker_boost_stage_text); +static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum, + lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text); + +/* RX INT0 */ +static const struct soc_enum rx0_prim_inp0_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, + 0, 7, rx_text); + +static const struct soc_enum rx0_prim_inp1_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, + 3, 7, rx_text); + +static const struct soc_enum rx0_prim_inp2_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, + 3, 7, rx_text); + +static const struct soc_enum rx0_mix_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, + 0, 5, rx_mix_text); + +static const struct soc_enum rx0_sidetone_mix_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text); + +static const struct snd_kcontrol_new rx0_prim_inp0_mux = + SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum); + +static const struct snd_kcontrol_new rx0_prim_inp1_mux = + SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum); + +static const struct snd_kcontrol_new rx0_prim_inp2_mux = + SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum); + +static const struct snd_kcontrol_new rx0_mix_mux = + SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum); + +static const struct snd_kcontrol_new rx0_sidetone_mix_mux = + SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum); + +/* RX INT1 */ +static const struct soc_enum rx1_prim_inp0_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, + 0, 7, rx_text); + +static const struct soc_enum rx1_prim_inp1_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, + 3, 7, rx_text); + +static const struct soc_enum rx1_prim_inp2_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, + 3, 7, rx_text); + +static const struct soc_enum rx1_mix_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, + 0, 5, rx_mix_text); + +static const struct snd_kcontrol_new rx1_prim_inp0_mux = + SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum); + +static const struct snd_kcontrol_new rx1_prim_inp1_mux = + SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum); + +static const struct snd_kcontrol_new rx1_prim_inp2_mux = + SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum); + +static const struct snd_kcontrol_new rx1_mix_mux = + SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum); + +static const struct soc_enum rx_mix_ec0_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, + 0, 3, rx_mix_ec_text); + +static const struct soc_enum rx_mix_ec1_enum = + SOC_ENUM_SINGLE(LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, + 3, 3, rx_mix_ec_text); + +static const struct snd_kcontrol_new rx_mix_ec0_mux = + SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum); + +static const struct snd_kcontrol_new rx_mix_ec1_mux = + SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum); + +static struct snd_soc_dai_ops lpass_cdc_wsa_macro_dai_ops = { + .hw_params = lpass_cdc_wsa_macro_hw_params, + .get_channel_map = lpass_cdc_wsa_macro_get_channel_map, + .digital_mute = lpass_cdc_wsa_macro_digital_mute, +}; + +static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[] = { + { + .name = "lpass_cdc_wsa_macro_rx1", + .id = LPASS_CDC_WSA_MACRO_AIF1_PB, + .playback = { + .stream_name = "WSA_AIF1 Playback", + .rates = LPASS_CDC_WSA_MACRO_RX_RATES, + .formats = LPASS_CDC_WSA_MACRO_RX_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_wsa_macro_dai_ops, + }, + { + .name = "lpass_cdc_wsa_macro_rx_mix", + .id = LPASS_CDC_WSA_MACRO_AIF_MIX1_PB, + .playback = { + .stream_name = "WSA_AIF_MIX1 Playback", + .rates = LPASS_CDC_WSA_MACRO_RX_MIX_RATES, + .formats = LPASS_CDC_WSA_MACRO_RX_FORMATS, + .rate_max = 192000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_wsa_macro_dai_ops, + }, + { + .name = "lpass_cdc_wsa_macro_vifeedback", + .id = LPASS_CDC_WSA_MACRO_AIF_VI, + .capture = { + .stream_name = "WSA_AIF_VI Capture", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, + .formats = LPASS_CDC_WSA_MACRO_RX_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &lpass_cdc_wsa_macro_dai_ops, + }, + { + .name = "lpass_cdc_wsa_macro_echo", + .id = LPASS_CDC_WSA_MACRO_AIF_ECHO, + .capture = { + .stream_name = "WSA_AIF_ECHO Capture", + .rates = LPASS_CDC_WSA_MACRO_ECHO_RATES, + .formats = LPASS_CDC_WSA_MACRO_ECHO_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &lpass_cdc_wsa_macro_dai_ops, + }, +}; + +static const struct lpass_cdc_wsa_macro_reg_mask_val + lpass_cdc_wsa_macro_spkr_default[] = { + {LPASS_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80}, + {LPASS_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80}, + {LPASS_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01}, + {LPASS_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01}, + {LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58}, + {LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58}, +}; + +static const struct lpass_cdc_wsa_macro_reg_mask_val + lpass_cdc_wsa_macro_spkr_mode1[] = { + {LPASS_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00}, + {LPASS_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00}, + {LPASS_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00}, + {LPASS_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00}, + {LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44}, + {LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44}, +}; + +static bool lpass_cdc_wsa_macro_get_data(struct snd_soc_component *component, + struct device **wsa_dev, + struct lpass_cdc_wsa_macro_priv **wsa_priv, + const char *func_name) +{ + *wsa_dev = lpass_cdc_get_device_ptr(component->dev, + WSA_MACRO); + if (!(*wsa_dev)) { + dev_err(component->dev, + "%s: null device for macro!\n", func_name); + return false; + } + *wsa_priv = dev_get_drvdata((*wsa_dev)); + if (!(*wsa_priv) || !(*wsa_priv)->component) { + dev_err(component->dev, + "%s: priv is null for macro!\n", func_name); + return false; + } + return true; +} + +static int lpass_cdc_wsa_macro_set_port_map(struct snd_soc_component *component, + u32 usecase, u32 size, void *data) +{ + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + struct swrm_port_config port_cfg; + int ret = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + memset(&port_cfg, 0, sizeof(port_cfg)); + port_cfg.uc = usecase; + port_cfg.size = size; + port_cfg.params = data; + + if (wsa_priv->swr_ctrl_data) + ret = swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_SET_PORT_MAP, &port_cfg); + + return ret; +} + +/** + * lpass_cdc_wsa_macro_set_spkr_gain_offset - offset the speaker path + * gain with the given offset value. + * + * @component: codec instance + * @offset: Indicates speaker path gain offset value. + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component, + int offset) +{ + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!component) { + pr_err("%s: NULL component pointer!\n", __func__); + return -EINVAL; + } + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv->spkr_gain_offset = offset; + return 0; +} +EXPORT_SYMBOL(lpass_cdc_wsa_macro_set_spkr_gain_offset); + +/** + * lpass_cdc_wsa_macro_set_spkr_mode - Configures speaker compander and smartboost + * settings based on speaker mode. + * + * @component: codec instance + * @mode: Indicates speaker configuration mode. + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode) +{ + int i; + const struct lpass_cdc_wsa_macro_reg_mask_val *regs; + int size; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!component) { + pr_err("%s: NULL codec pointer!\n", __func__); + return -EINVAL; + } + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + switch (mode) { + case LPASS_CDC_WSA_MACRO_SPKR_MODE_1: + regs = lpass_cdc_wsa_macro_spkr_mode1; + size = ARRAY_SIZE(lpass_cdc_wsa_macro_spkr_mode1); + break; + default: + regs = lpass_cdc_wsa_macro_spkr_default; + size = ARRAY_SIZE(lpass_cdc_wsa_macro_spkr_default); + break; + } + + wsa_priv->spkr_mode = mode; + for (i = 0; i < size; i++) + snd_soc_component_update_bits(component, regs[i].reg, + regs[i].mask, regs[i].val); + return 0; +} +EXPORT_SYMBOL(lpass_cdc_wsa_macro_set_spkr_mode); + +static int lpass_cdc_wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, + u8 int_prim_fs_rate_reg_val, + u32 sample_rate) +{ + u8 int_1_mix1_inp; + u32 j, port; + u16 int_mux_cfg0, int_mux_cfg1; + u16 int_fs_reg; + u8 int_mux_cfg0_val, int_mux_cfg1_val; + u8 inp0_sel, inp1_sel, inp2_sel; + struct snd_soc_component *component = dai->component; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id], + LPASS_CDC_WSA_MACRO_RX_MAX) { + int_1_mix1_inp = port; + if ((int_1_mix1_inp < LPASS_CDC_WSA_MACRO_RX0) || + (int_1_mix1_inp > LPASS_CDC_WSA_MACRO_RX_MIX1)) { + dev_err(wsa_dev, + "%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg0 = LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0; + + /* + * Loop through all interpolator MUX inputs and find out + * to which interpolator input, the cdc_dma rx port + * is connected + */ + for (j = 0; j < NUM_INTERPOLATORS; j++) { + int_mux_cfg1 = int_mux_cfg0 + LPASS_CDC_WSA_MACRO_MUX_CFG1_OFFSET; + + int_mux_cfg0_val = snd_soc_component_read32(component, + int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32(component, + int_mux_cfg1); + inp0_sel = int_mux_cfg0_val & LPASS_CDC_WSA_MACRO_MUX_INP_MASK1; + inp1_sel = (int_mux_cfg0_val >> + LPASS_CDC_WSA_MACRO_MUX_INP_SHFT) & + LPASS_CDC_WSA_MACRO_MUX_INP_MASK1; + inp2_sel = (int_mux_cfg1_val >> + LPASS_CDC_WSA_MACRO_MUX_INP_SHFT) & + LPASS_CDC_WSA_MACRO_MUX_INP_MASK1; + if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { + int_fs_reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL + + LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * j; + dev_dbg(wsa_dev, + "%s: AIF_PB DAI(%d) connected to INT%u_1\n", + __func__, dai->id, j); + dev_dbg(wsa_dev, + "%s: set INT%u_1 sample rate to %u\n", + __func__, j, sample_rate); + /* sample_rate is in Hz */ + snd_soc_component_update_bits(component, + int_fs_reg, + LPASS_CDC_WSA_MACRO_FS_RATE_MASK, + int_prim_fs_rate_reg_val); + } + int_mux_cfg0 += LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET; + } + } + + return 0; +} + +static int lpass_cdc_wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, + u8 int_mix_fs_rate_reg_val, + u32 sample_rate) +{ + u8 int_2_inp; + u32 j, port; + u16 int_mux_cfg1, int_fs_reg; + u8 int_mux_cfg1_val; + struct snd_soc_component *component = dai->component; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + + for_each_set_bit(port, &wsa_priv->active_ch_mask[dai->id], + LPASS_CDC_WSA_MACRO_RX_MAX) { + int_2_inp = port; + if ((int_2_inp < LPASS_CDC_WSA_MACRO_RX0) || + (int_2_inp > LPASS_CDC_WSA_MACRO_RX_MIX1)) { + dev_err(wsa_dev, + "%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg1 = LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1; + for (j = 0; j < NUM_INTERPOLATORS; j++) { + int_mux_cfg1_val = snd_soc_component_read32(component, + int_mux_cfg1) & + LPASS_CDC_WSA_MACRO_MUX_INP_MASK1; + if (int_mux_cfg1_val == int_2_inp + + INTn_2_INP_SEL_RX0) { + int_fs_reg = + LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL + + LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * j; + + dev_dbg(wsa_dev, + "%s: AIF_PB DAI(%d) connected to INT%u_2\n", + __func__, dai->id, j); + dev_dbg(wsa_dev, + "%s: set INT%u_2 sample rate to %u\n", + __func__, j, sample_rate); + snd_soc_component_update_bits(component, + int_fs_reg, + LPASS_CDC_WSA_MACRO_FS_RATE_MASK, + int_mix_fs_rate_reg_val); + } + int_mux_cfg1 += LPASS_CDC_WSA_MACRO_MUX_CFG_OFFSET; + } + } + return 0; +} + +static int lpass_cdc_wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai, + u32 sample_rate) +{ + int rate_val = 0; + int i, ret; + + /* set mixing path rate */ + for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) { + if (sample_rate == + int_mix_sample_rate_val[i].sample_rate) { + rate_val = + int_mix_sample_rate_val[i].rate_val; + break; + } + } + if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) || + (rate_val < 0)) + goto prim_rate; + ret = lpass_cdc_wsa_macro_set_mix_interpolator_rate(dai, + (u8) rate_val, sample_rate); +prim_rate: + /* set primary path sample rate */ + for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) { + if (sample_rate == + int_prim_sample_rate_val[i].sample_rate) { + rate_val = + int_prim_sample_rate_val[i].rate_val; + break; + } + } + if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) || + (rate_val < 0)) + return -EINVAL; + ret = lpass_cdc_wsa_macro_set_prim_interpolator_rate(dai, + (u8) rate_val, sample_rate); + return ret; +} + +static int lpass_cdc_wsa_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv = dev_get_drvdata(wsa_dev); + if (!wsa_priv) + return -EINVAL; + + dev_dbg(component->dev, + "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__, + dai->name, dai->id, params_rate(params), + params_channels(params)); + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = lpass_cdc_wsa_macro_set_interpolator_rate(dai, params_rate(params)); + if (ret) { + dev_err(component->dev, + "%s: cannot set sample rate: %u\n", + __func__, params_rate(params)); + return ret; + } + break; + case SNDRV_PCM_STREAM_CAPTURE: + if (dai->id == LPASS_CDC_WSA_MACRO_AIF_VI) + wsa_priv->pcm_rate_vi = params_rate(params); + default: + break; + } + return 0; +} + +static int lpass_cdc_wsa_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + u16 val = 0, mask = 0, cnt = 0, temp = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv = dev_get_drvdata(wsa_dev); + if (!wsa_priv) + return -EINVAL; + + switch (dai->id) { + case LPASS_CDC_WSA_MACRO_AIF_VI: + *tx_slot = wsa_priv->active_ch_mask[dai->id]; + *tx_num = wsa_priv->active_ch_cnt[dai->id]; + break; + case LPASS_CDC_WSA_MACRO_AIF1_PB: + case LPASS_CDC_WSA_MACRO_AIF_MIX1_PB: + for_each_set_bit(temp, &wsa_priv->active_ch_mask[dai->id], + LPASS_CDC_WSA_MACRO_RX_MAX) { + mask |= (1 << temp); + if (++cnt == LPASS_CDC_WSA_MACRO_MAX_DMA_CH_PER_PORT) + break; + } + if (mask & 0x0C) + mask = mask >> 0x2; + *rx_slot = mask; + *rx_num = cnt; + break; + case LPASS_CDC_WSA_MACRO_AIF_ECHO: + val = snd_soc_component_read32(component, + LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0); + if (val & LPASS_CDC_WSA_MACRO_EC_MIX_TX1_MASK) { + mask |= 0x2; + cnt++; + } + if (val & LPASS_CDC_WSA_MACRO_EC_MIX_TX0_MASK) { + mask |= 0x1; + cnt++; + } + *tx_slot = mask; + *tx_num = cnt; + break; + default: + dev_err(wsa_dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static int lpass_cdc_wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_component *component = dai->component; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0; + u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0; + u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0; + bool adie_lb = false; + + if (mute) + return 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + switch (dai->id) { + case LPASS_CDC_WSA_MACRO_AIF1_PB: + case LPASS_CDC_WSA_MACRO_AIF_MIX1_PB: + for (j = 0; j < NUM_INTERPOLATORS; j++) { + reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL + + (j * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET); + mix_reg = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL + + (j * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET); + dsm_reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL + + (j * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET) + + LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET; + int_mux_cfg0 = LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + j * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read32(component, + int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32(component, + int_mux_cfg1); + if (snd_soc_component_read32(component, dsm_reg) & 0x01) { + if (int_mux_cfg0_val || (int_mux_cfg1_val & 0x38)) + snd_soc_component_update_bits(component, reg, + 0x20, 0x20); + if (int_mux_cfg1_val & 0x07) { + snd_soc_component_update_bits(component, reg, + 0x20, 0x20); + snd_soc_component_update_bits(component, + mix_reg, 0x20, 0x20); + } + } + } + lpass_cdc_wsa_pa_on(wsa_dev, adie_lb); + break; + default: + break; + } + return 0; +} +static int lpass_cdc_wsa_macro_mclk_enable( + struct lpass_cdc_wsa_macro_priv *wsa_priv, + bool mclk_enable, bool dapm) +{ + struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n", + __func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users); + + mutex_lock(&wsa_priv->mclk_lock); + if (mclk_enable) { + if (wsa_priv->wsa_mclk_users == 0) { + ret = lpass_cdc_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + wsa_priv->default_clk_id, + true); + if (ret < 0) { + dev_err_ratelimited(wsa_priv->dev, + "%s: wsa request clock enable failed\n", + __func__); + goto exit; + } + lpass_cdc_clk_rsc_fs_gen_request(wsa_priv->dev, + true); + regcache_mark_dirty(regmap); + regcache_sync_region(regmap, + WSA_START_OFFSET, + WSA_MAX_OFFSET); + /* 9.6MHz MCLK, set value 0x00 if other frequency */ + regmap_update_bits(regmap, + LPASS_CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x01); + } + wsa_priv->wsa_mclk_users++; + } else { + if (wsa_priv->wsa_mclk_users <= 0) { + dev_err(wsa_priv->dev, "%s: clock already disabled\n", + __func__); + wsa_priv->wsa_mclk_users = 0; + goto exit; + } + wsa_priv->wsa_mclk_users--; + if (wsa_priv->wsa_mclk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x00); + lpass_cdc_clk_rsc_fs_gen_request(wsa_priv->dev, + false); + + lpass_cdc_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + wsa_priv->default_clk_id, + false); + } + } +exit: + mutex_unlock(&wsa_priv->mclk_lock); + return ret; +} + +static int lpass_cdc_wsa_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(wsa_dev, "%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 1, true); + if (ret) + wsa_priv->dapm_mclk_enable = false; + else + wsa_priv->dapm_mclk_enable = true; + break; + case SND_SOC_DAPM_POST_PMD: + if (wsa_priv->dapm_mclk_enable) + lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 0, true); + break; + default: + dev_err(wsa_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static int lpass_cdc_wsa_macro_event_handler(struct snd_soc_component *component, + u16 event, u32 data) +{ + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int ret = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + switch (event) { + case LPASS_CDC_MACRO_EVT_SSR_DOWN: + trace_printk("%s, enter SSR down\n", __func__); + if (wsa_priv->swr_ctrl_data) { + swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_DEVICE_SSR_DOWN, NULL); + } + if ((!pm_runtime_enabled(wsa_dev) || + !pm_runtime_suspended(wsa_dev))) { + ret = lpass_cdc_runtime_suspend(wsa_dev); + if (!ret) { + pm_runtime_disable(wsa_dev); + pm_runtime_set_suspended(wsa_dev); + pm_runtime_enable(wsa_dev); + } + } + break; + case LPASS_CDC_MACRO_EVT_PRE_SSR_UP: + /* enable&disable WSA_CORE_CLK to reset GFMUX reg */ + ret = lpass_cdc_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + WSA_CORE_CLK, true); + if (ret < 0) + dev_err_ratelimited(wsa_priv->dev, + "%s, failed to enable clk, ret:%d\n", + __func__, ret); + else + lpass_cdc_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + WSA_CORE_CLK, false); + break; + case LPASS_CDC_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + /* reset swr after ssr/pdr */ + wsa_priv->reset_swr = true; + if (wsa_priv->swr_ctrl_data) + swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_DEVICE_SSR_UP, NULL); + break; + case LPASS_CDC_MACRO_EVT_CLK_RESET: + lpass_cdc_rsc_clk_reset(wsa_dev, WSA_CORE_CLK); + break; + } + return 0; +} + +static int lpass_cdc_wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + u8 val = 0x0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + switch (wsa_priv->pcm_rate_vi) { + case 48000: + val = 0x04; + break; + case 24000: + val = 0x02; + break; + case 8000: + default: + val = 0x00; + break; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (test_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + dev_dbg(wsa_dev, "%s: spkr1 enabled\n", __func__); + /* Enable V&I sensing */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x0F, val); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x0F, val); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x10, 0x10); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x10, 0x10); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x20, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x20, 0x00); + } + if (test_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + dev_dbg(wsa_dev, "%s: spkr2 enabled\n", __func__); + /* Enable V&I sensing */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x0F, val); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x0F, val); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x10, 0x10); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x10, 0x10); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x20, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x20, 0x00); + } + break; + case SND_SOC_DAPM_POST_PMD: + if (test_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + /* Disable V&I sensing */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + dev_dbg(wsa_dev, "%s: spkr1 disabled\n", __func__); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + 0x10, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CTL, + 0x10, 0x00); + } + if (test_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + /* Disable V&I sensing */ + dev_dbg(wsa_dev, "%s: spkr2 disabled\n", __func__); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + 0x10, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CTL, + 0x10, 0x00); + } + break; + } + + return 0; +} + +static void lpass_cdc_wsa_macro_hd2_control(struct snd_soc_component *component, + u16 reg, int event) +{ + u16 hd2_scale_reg; + u16 hd2_enable_reg = 0; + + if (reg == LPASS_CDC_WSA_RX0_RX_PATH_CTL) { + hd2_scale_reg = LPASS_CDC_WSA_RX0_RX_PATH_SEC3; + hd2_enable_reg = LPASS_CDC_WSA_RX0_RX_PATH_CFG0; + } + if (reg == LPASS_CDC_WSA_RX1_RX_PATH_CTL) { + hd2_scale_reg = LPASS_CDC_WSA_RX1_RX_PATH_SEC3; + hd2_enable_reg = LPASS_CDC_WSA_RX1_RX_PATH_CFG0; + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x3C, 0x10); + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x03, 0x01); + snd_soc_component_update_bits(component, hd2_enable_reg, + 0x04, 0x04); + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, hd2_enable_reg, + 0x04, 0x00); + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x03, 0x00); + snd_soc_component_update_bits(component, hd2_scale_reg, + 0x3C, 0x00); + } +} + +static int lpass_cdc_wsa_macro_enable_swr(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ch_cnt; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) && + !wsa_priv->rx_0_count) + wsa_priv->rx_0_count++; + if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) && + !wsa_priv->rx_1_count) + wsa_priv->rx_1_count++; + ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count; + + if (wsa_priv->swr_ctrl_data) { + swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_DEVICE_UP, NULL); + swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_SET_NUM_RX_CH, &ch_cnt); + } + break; + case SND_SOC_DAPM_POST_PMD: + if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) && + wsa_priv->rx_0_count) + wsa_priv->rx_0_count--; + if (!(strnstr(w->name, "RX1", sizeof("WSA_RX1"))) && + wsa_priv->rx_1_count) + wsa_priv->rx_1_count--; + ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count; + + if (wsa_priv->swr_ctrl_data) + swrm_wcd_notify( + wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, + SWR_SET_NUM_RX_CH, &ch_cnt); + break; + } + dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n", + __func__, wsa_priv->rx_0_count + wsa_priv->rx_1_count); + + return 0; +} + +static int lpass_cdc_wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 gain_reg; + int offset_val = 0; + int val = 0; + + dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); + + if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) { + gain_reg = LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL; + } else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) { + gain_reg = LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL; + } else { + dev_err(component->dev, "%s: No gain register avail for %s\n", + __func__, w->name); + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + lpass_cdc_wsa_macro_enable_swr(w, kcontrol, event); + val = snd_soc_component_read32(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, + w->reg, 0x20, 0x00); + lpass_cdc_wsa_macro_enable_swr(w, kcontrol, event); + break; + } + + return 0; +} + +static int lpass_cdc_wsa_macro_config_compander(struct snd_soc_component *component, + int comp, int event) +{ + u16 comp_ctl0_reg, rx_path_cfg0_reg; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n", + __func__, event, comp + 1, wsa_priv->comp_enabled[comp]); + + if (!wsa_priv->comp_enabled[comp]) + return 0; + + comp_ctl0_reg = LPASS_CDC_WSA_COMPANDER0_CTL0 + + (comp * LPASS_CDC_WSA_MACRO_RX_COMP_OFFSET); + rx_path_cfg0_reg = LPASS_CDC_WSA_RX0_RX_PATH_CFG0 + + (comp * LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Compander Clock */ + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x01, 0x01); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x02); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x00); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + 0x02, 0x02); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x04, 0x04); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + 0x02, 0x00); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x02); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x02, 0x00); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x01, 0x00); + snd_soc_component_update_bits(component, comp_ctl0_reg, + 0x04, 0x00); + } + + return 0; +} + +static void lpass_cdc_wsa_macro_enable_softclip_clk(struct snd_soc_component *component, + struct lpass_cdc_wsa_macro_priv *wsa_priv, + int path, + bool enable) +{ + u16 softclip_clk_reg = LPASS_CDC_WSA_SOFTCLIP0_CRC + + (path * LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET); + u8 softclip_mux_mask = (1 << path); + u8 softclip_mux_value = (1 << path); + + dev_dbg(component->dev, "%s: path %d, enable %d\n", + __func__, path, enable); + if (enable) { + if (wsa_priv->softclip_clk_users[path] == 0) { + snd_soc_component_update_bits(component, + softclip_clk_reg, 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, + softclip_mux_mask, softclip_mux_value); + } + wsa_priv->softclip_clk_users[path]++; + } else { + wsa_priv->softclip_clk_users[path]--; + if (wsa_priv->softclip_clk_users[path] == 0) { + snd_soc_component_update_bits(component, + softclip_clk_reg, 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, + softclip_mux_mask, 0x00); + } + } +} + +static int lpass_cdc_wsa_macro_config_softclip(struct snd_soc_component *component, + int path, int event) +{ + u16 softclip_ctrl_reg = 0; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int softclip_path = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + if (path == LPASS_CDC_WSA_MACRO_COMP1) + softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP0; + else if (path == LPASS_CDC_WSA_MACRO_COMP2) + softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP1; + + dev_dbg(component->dev, "%s: event %d path %d, enabled %d\n", + __func__, event, softclip_path, + wsa_priv->is_softclip_on[softclip_path]); + + if (!wsa_priv->is_softclip_on[softclip_path]) + return 0; + + softclip_ctrl_reg = LPASS_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL + + (softclip_path * LPASS_CDC_WSA_MACRO_RX_SOFTCLIP_OFFSET); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Softclip clock and mux */ + lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv, + softclip_path, true); + /* Enable Softclip control */ + snd_soc_component_update_bits(component, softclip_ctrl_reg, + 0x01, 0x01); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, softclip_ctrl_reg, + 0x01, 0x00); + lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv, + softclip_path, false); + } + + return 0; +} + +static bool lpass_cdc_wsa_macro_adie_lb(struct snd_soc_component *component, + int interp_idx) +{ + u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0; + u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0; + u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0; + + int_mux_cfg0 = LPASS_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read32(component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read32(component, int_mux_cfg1); + + int_n_inp0 = int_mux_cfg0_val & 0x0F; + if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || + int_n_inp0 == INTn_1_INP_SEL_DEC1) + return true; + + int_n_inp1 = int_mux_cfg0_val >> 4; + if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || + int_n_inp1 == INTn_1_INP_SEL_DEC1) + return true; + + int_n_inp2 = int_mux_cfg1_val >> 4; + if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || + int_n_inp2 == INTn_1_INP_SEL_DEC1) + return true; + + return false; +} + +static int lpass_cdc_wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 reg = 0; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + bool adie_lb = false; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + + reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL + + LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift; + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (lpass_cdc_wsa_macro_adie_lb(component, w->shift)) { + adie_lb = true; + snd_soc_component_update_bits(component, + reg, 0x20, 0x20); + lpass_cdc_wsa_pa_on(wsa_dev, adie_lb); + } + break; + default: + break; + } + return 0; +} + +static int lpass_cdc_wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind) +{ + u16 prim_int_reg = 0; + + switch (reg) { + case LPASS_CDC_WSA_RX0_RX_PATH_CTL: + case LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL: + prim_int_reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL; + *ind = 0; + break; + case LPASS_CDC_WSA_RX1_RX_PATH_CTL: + case LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL: + prim_int_reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL; + *ind = 1; + break; + } + + return prim_int_reg; +} + +static int lpass_cdc_wsa_macro_enable_prim_interpolator( + struct snd_soc_component *component, + u16 reg, int event) +{ + u16 prim_int_reg; + u16 ind = 0; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + prim_int_reg = lpass_cdc_wsa_macro_interp_get_primary_reg(reg, &ind); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wsa_priv->prim_int_users[ind]++; + if (wsa_priv->prim_int_users[ind] == 1) { + snd_soc_component_update_bits(component, + prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_CFG3_OFFSET, + 0x03, 0x03); + snd_soc_component_update_bits(component, prim_int_reg, + 0x10, 0x10); + lpass_cdc_wsa_macro_hd2_control(component, prim_int_reg, event); + snd_soc_component_update_bits(component, + prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET, + 0x1, 0x1); + } + if ((reg != prim_int_reg) && + ((snd_soc_component_read32( + component, prim_int_reg)) & 0x10)) + snd_soc_component_update_bits(component, reg, + 0x10, 0x10); + break; + case SND_SOC_DAPM_POST_PMD: + wsa_priv->prim_int_users[ind]--; + if (wsa_priv->prim_int_users[ind] == 0) { + snd_soc_component_update_bits(component, prim_int_reg, + 1 << 0x5, 0 << 0x5); + snd_soc_component_update_bits(component, + prim_int_reg + LPASS_CDC_WSA_MACRO_RX_PATH_DSMDEM_OFFSET, + 0x1, 0x0); + snd_soc_component_update_bits(component, prim_int_reg, + 0x40, 0x40); + snd_soc_component_update_bits(component, prim_int_reg, + 0x40, 0x00); + lpass_cdc_wsa_macro_hd2_control(component, prim_int_reg, event); + } + break; + } + + dev_dbg(component->dev, "%s: primary interpolator: INT%d, users: %d\n", + __func__, ind, wsa_priv->prim_int_users[ind]); + return 0; +} + +static int lpass_cdc_wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 gain_reg; + u16 reg; + int val; + int offset_val = 0; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); + + if (!(strcmp(w->name, "WSA_RX INT0 INTERP"))) { + reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL; + gain_reg = LPASS_CDC_WSA_RX0_RX_VOL_CTL; + } else if (!(strcmp(w->name, "WSA_RX INT1 INTERP"))) { + reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL; + gain_reg = LPASS_CDC_WSA_RX1_RX_VOL_CTL; + } else { + dev_err(component->dev, "%s: Interpolator reg not found\n", + __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Reset if needed */ + lpass_cdc_wsa_macro_enable_prim_interpolator(component, reg, event); + break; + case SND_SOC_DAPM_POST_PMU: + lpass_cdc_wsa_macro_config_compander(component, w->shift, event); + lpass_cdc_wsa_macro_config_softclip(component, w->shift, event); + /* apply gain after int clk is enabled */ + if ((wsa_priv->spkr_gain_offset == + LPASS_CDC_WSA_MACRO_GAIN_OFFSET_M1P5_DB) && + (wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP1] || + wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP2]) && + (gain_reg == LPASS_CDC_WSA_RX0_RX_VOL_CTL || + gain_reg == LPASS_CDC_WSA_RX1_RX_VOL_CTL)) { + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_SEC1, + 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0, + 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_SEC1, + 0x01, 0x01); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0, + 0x01, 0x01); + offset_val = -2; + } + val = snd_soc_component_read32(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + lpass_cdc_wsa_macro_config_ear_spkr_gain(component, wsa_priv, + event, gain_reg); + break; + case SND_SOC_DAPM_POST_PMD: + lpass_cdc_wsa_macro_config_compander(component, w->shift, event); + lpass_cdc_wsa_macro_config_softclip(component, w->shift, event); + lpass_cdc_wsa_macro_enable_prim_interpolator(component, reg, event); + if ((wsa_priv->spkr_gain_offset == + LPASS_CDC_WSA_MACRO_GAIN_OFFSET_M1P5_DB) && + (wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP1] || + wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP2]) && + (gain_reg == LPASS_CDC_WSA_RX0_RX_VOL_CTL || + gain_reg == LPASS_CDC_WSA_RX1_RX_VOL_CTL)) { + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_SEC1, + 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_MIX_SEC0, + 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_SEC1, + 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_MIX_SEC0, + 0x01, 0x00); + offset_val = 2; + val = snd_soc_component_read32(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + } + lpass_cdc_wsa_macro_config_ear_spkr_gain(component, wsa_priv, + event, gain_reg); + break; + } + + return 0; +} + +static int lpass_cdc_wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component, + struct lpass_cdc_wsa_macro_priv *wsa_priv, + int event, int gain_reg) +{ + int comp_gain_offset, val; + + switch (wsa_priv->spkr_mode) { + /* Compander gain in LPASS_CDC_WSA_MACRO_SPKR_MODE1 case is 12 dB */ + case LPASS_CDC_WSA_MACRO_SPKR_MODE_1: + comp_gain_offset = -12; + break; + /* Default case compander gain is 15 dB */ + default: + comp_gain_offset = -15; + break; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Apply ear spkr gain only if compander is enabled */ + if (wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP1] && + (gain_reg == LPASS_CDC_WSA_RX0_RX_VOL_CTL) && + (wsa_priv->ear_spkr_gain != 0)) { + /* For example, val is -8(-12+5-1) for 4dB of gain */ + val = comp_gain_offset + wsa_priv->ear_spkr_gain - 1; + snd_soc_component_write(component, gain_reg, val); + + dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n", + __func__, val); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* + * Reset RX0 volume to 0 dB if compander is enabled and + * ear_spkr_gain is non-zero. + */ + if (wsa_priv->comp_enabled[LPASS_CDC_WSA_MACRO_COMP1] && + (gain_reg == LPASS_CDC_WSA_RX0_RX_VOL_CTL) && + (wsa_priv->ear_spkr_gain != 0)) { + snd_soc_component_write(component, gain_reg, 0x0); + + dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n", + __func__); + } + break; + } + + return 0; +} + +static int lpass_cdc_wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 boost_path_ctl, boost_path_cfg1; + u16 reg, reg_mix; + + dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event); + + if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) { + boost_path_ctl = LPASS_CDC_WSA_BOOST0_BOOST_PATH_CTL; + boost_path_cfg1 = LPASS_CDC_WSA_RX0_RX_PATH_CFG1; + reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL; + reg_mix = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL; + } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) { + boost_path_ctl = LPASS_CDC_WSA_BOOST1_BOOST_PATH_CTL; + boost_path_cfg1 = LPASS_CDC_WSA_RX1_RX_PATH_CFG1; + reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL; + reg_mix = LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL; + } else { + dev_err(component->dev, "%s: unknown widget: %s\n", + __func__, w->name); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, boost_path_cfg1, + 0x01, 0x01); + snd_soc_component_update_bits(component, boost_path_ctl, + 0x10, 0x10); + if ((snd_soc_component_read32(component, reg_mix)) & 0x10) + snd_soc_component_update_bits(component, reg_mix, + 0x10, 0x00); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_update_bits(component, reg, 0x10, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, boost_path_ctl, + 0x10, 0x00); + snd_soc_component_update_bits(component, boost_path_cfg1, + 0x01, 0x00); + break; + } + + return 0; +} + + +static int lpass_cdc_wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + u16 vbat_path_cfg = 0; + int softclip_path = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s %s %d\n", __func__, w->name, event); + if (!strcmp(w->name, "WSA_RX INT0 VBAT")) { + vbat_path_cfg = LPASS_CDC_WSA_RX0_RX_PATH_CFG1; + softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP0; + } else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) { + vbat_path_cfg = LPASS_CDC_WSA_RX1_RX_PATH_CFG1; + softclip_path = LPASS_CDC_WSA_MACRO_SOFTCLIP1; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable clock for VBAT block */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10); + /* Enable VBAT block */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01); + /* Update interpolator with 384K path */ + snd_soc_component_update_bits(component, vbat_path_cfg, + 0x80, 0x80); + /* Use attenuation mode */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x02, 0x00); + /* + * BCL block needs softclip clock and mux config to be enabled + */ + lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv, + softclip_path, true); + /* Enable VBAT at channel level */ + snd_soc_component_update_bits(component, vbat_path_cfg, + 0x02, 0x02); + /* Set the ATTK1 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3, + 0xFF, 0x00); + /* Set the ATTK2 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6, + 0xFF, 0x00); + /* Set the ATTK3 gain */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7, + 0xFF, 0xFF); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8, + 0xFF, 0x03); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9, + 0xFF, 0x00); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, vbat_path_cfg, + 0x80, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, + 0x02, 0x02); + snd_soc_component_update_bits(component, vbat_path_cfg, + 0x02, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8, + 0xFF, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9, + 0xFF, 0x00); + lpass_cdc_wsa_macro_enable_softclip_clk(component, wsa_priv, + softclip_path, false); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00); + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00); + break; + default: + dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event); + break; + } + return 0; +} + +static int lpass_cdc_wsa_macro_enable_echo(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + u16 val, ec_tx = 0, ec_hq_reg; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name); + + val = snd_soc_component_read32(component, + LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0); + if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX"))) + ec_tx = (val & 0x07) - 1; + else + ec_tx = ((val & 0x38) >> 0x3) - 1; + + if (ec_tx < 0 || ec_tx >= (LPASS_CDC_WSA_MACRO_RX1 + 1)) { + dev_err(wsa_dev, "%s: EC mix control not set correctly\n", + __func__); + return -EINVAL; + } + if (wsa_priv->ec_hq[ec_tx]) { + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, + 0x1 << ec_tx, 0x1 << ec_tx); + ec_hq_reg = LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL + + 0x40 * ec_tx; + snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01); + ec_hq_reg = LPASS_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 + + 0x40 * ec_tx; + /* default set to 48k */ + snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08); + } + + return 0; +} + +static int lpass_cdc_wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int ec_tx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx]; + return 0; +} + +static int lpass_cdc_wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int ec_tx = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(wsa_dev, "%s: enable current %d, new %d\n", + __func__, wsa_priv->ec_hq[ec_tx], value); + wsa_priv->ec_hq[ec_tx] = value; + + return 0; +} + +static int lpass_cdc_wsa_macro_get_rx_mute_status(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int wsa_rx_shift = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = + wsa_priv->wsa_digital_mute_status[wsa_rx_shift]; + return 0; +} + +static int lpass_cdc_wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int value = ucontrol->value.integer.value[0]; + int wsa_rx_shift = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int ret = 0; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + pm_runtime_get_sync(wsa_priv->dev); + switch (wsa_rx_shift) { + case 0: + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_CTL, + 0x10, value << 4); + break; + case 1: + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_CTL, + 0x10, value << 4); + break; + case 2: + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL, + 0x10, value << 4); + break; + case 3: + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL, + 0x10, value << 4); + break; + default: + pr_err("%s: invalid argument rx_shift = %d\n", __func__, + wsa_rx_shift); + ret = -EINVAL; + } + pm_runtime_mark_last_busy(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); + + dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n", + __func__, wsa_rx_shift, value); + wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value; + + return ret; +} + +static int lpass_cdc_wsa_macro_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa_priv->comp_enabled[comp]; + return 0; +} + +static int lpass_cdc_wsa_macro_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + dev_dbg(component->dev, "%s: Compander %d enable current %d, new %d\n", + __func__, comp + 1, wsa_priv->comp_enabled[comp], value); + wsa_priv->comp_enabled[comp] = value; + + return 0; +} + +static int lpass_cdc_wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa_priv->ear_spkr_gain; + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv->ear_spkr_gain = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: gain = %d\n", __func__, + wsa_priv->ear_spkr_gain); + + return 0; +} + +static int lpass_cdc_wsa_macro_spkr_left_boost_stage_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 bst_state_max = 0; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + bst_state_max = snd_soc_component_read32(component, + LPASS_CDC_WSA_BOOST0_BOOST_CTL); + bst_state_max = (bst_state_max & 0x0c) >> 2; + ucontrol->value.integer.value[0] = bst_state_max; + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_wsa_macro_spkr_left_boost_stage_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 bst_state_max; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + bst_state_max = ucontrol->value.integer.value[0] << 2; + /* lpass_cdc does not need to limit the boost levels */ + + return 0; +} + +static int lpass_cdc_wsa_macro_spkr_right_boost_stage_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 bst_state_max = 0; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + bst_state_max = snd_soc_component_read32(component, + LPASS_CDC_WSA_BOOST1_BOOST_CTL); + bst_state_max = (bst_state_max & 0x0c) >> 2; + ucontrol->value.integer.value[0] = bst_state_max; + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_wsa_macro_spkr_right_boost_stage_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 bst_state_max; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + bst_state_max = ucontrol->value.integer.value[0] << 2; + /* lpass_cdc does not need to limit the boost levels */ + + return 0; +} + +static int lpass_cdc_wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = + wsa_priv->rx_port_value[widget->shift]; + return 0; +} + +static int lpass_cdc_wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + u32 rx_port_value = ucontrol->value.integer.value[0]; + u32 bit_input = 0; + u32 aif_rst; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + aif_rst = wsa_priv->rx_port_value[widget->shift]; + if (!rx_port_value) { + if (aif_rst == 0) { + dev_err(wsa_dev, "%s: AIF reset already\n", __func__); + return 0; + } + if (aif_rst >= LPASS_CDC_WSA_MACRO_RX_MAX) { + dev_err(wsa_dev, "%s: Invalid AIF reset\n", __func__); + return 0; + } + } + wsa_priv->rx_port_value[widget->shift] = rx_port_value; + + bit_input = widget->shift; + + dev_dbg(wsa_dev, + "%s: mux input: %d, mux output: %d, bit: %d\n", + __func__, rx_port_value, widget->shift, bit_input); + + switch (rx_port_value) { + case 0: + if (wsa_priv->active_ch_cnt[aif_rst]) { + clear_bit(bit_input, + &wsa_priv->active_ch_mask[aif_rst]); + wsa_priv->active_ch_cnt[aif_rst]--; + } + break; + case 1: + case 2: + set_bit(bit_input, + &wsa_priv->active_ch_mask[rx_port_value]); + wsa_priv->active_ch_cnt[rx_port_value]++; + break; + default: + dev_err(wsa_dev, + "%s: Invalid AIF_ID for WSA RX MUX %d\n", + __func__, rx_port_value); + return -EINVAL; + } + + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + rx_port_value, e, update); + return 0; +} + +static int lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + ucontrol->value.integer.value[0] = + ((snd_soc_component_read32( + component, LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ? + 1 : 0); + + dev_dbg(component->dev, "%s: value: %lu\n", __func__, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + + dev_dbg(component->dev, "%s: value: %lu\n", __func__, + ucontrol->value.integer.value[0]); + + /* Set Vbat register configuration for GSM mode bit based on value */ + if (ucontrol->value.integer.value[0]) + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, + 0x04, 0x04); + else + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_CFG, + 0x04, 0x00); + + return 0; +} + +static int lpass_cdc_wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int path = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path]; + + dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + return 0; +} + +static int lpass_cdc_wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + int path = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: soft clip enable for %d: %d\n", __func__, + path, wsa_priv->is_softclip_on[path]); + + return 0; +} + +static const struct snd_kcontrol_new lpass_cdc_wsa_macro_snd_controls[] = { + SOC_ENUM_EXT("EAR SPKR PA Gain", lpass_cdc_wsa_macro_ear_spkr_pa_gain_enum, + lpass_cdc_wsa_macro_ear_spkr_pa_gain_get, + lpass_cdc_wsa_macro_ear_spkr_pa_gain_put), + SOC_ENUM_EXT("SPKR Left Boost Max State", + lpass_cdc_wsa_macro_spkr_boost_stage_enum, + lpass_cdc_wsa_macro_spkr_left_boost_stage_get, + lpass_cdc_wsa_macro_spkr_left_boost_stage_put), + SOC_ENUM_EXT("SPKR Right Boost Max State", + lpass_cdc_wsa_macro_spkr_boost_stage_enum, + lpass_cdc_wsa_macro_spkr_right_boost_stage_get, + lpass_cdc_wsa_macro_spkr_right_boost_stage_put), + SOC_ENUM_EXT("GSM mode Enable", lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum, + lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_get, + lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_put), + SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_SOFTCLIP0, 1, 0, + lpass_cdc_wsa_macro_soft_clip_enable_get, + lpass_cdc_wsa_macro_soft_clip_enable_put), + SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_SOFTCLIP1, 1, 0, + lpass_cdc_wsa_macro_soft_clip_enable_get, + lpass_cdc_wsa_macro_soft_clip_enable_put), + SOC_SINGLE_S8_TLV("WSA_RX0 Digital Volume", + LPASS_CDC_WSA_RX0_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("WSA_RX1 Digital Volume", + LPASS_CDC_WSA_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0, 1, + 0, lpass_cdc_wsa_macro_get_rx_mute_status, + lpass_cdc_wsa_macro_set_rx_mute_status), + SOC_SINGLE_EXT("WSA_RX1 Digital Mute", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1, 1, + 0, lpass_cdc_wsa_macro_get_rx_mute_status, + lpass_cdc_wsa_macro_set_rx_mute_status), + SOC_SINGLE_EXT("WSA_RX0_MIX Digital Mute", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_RX_MIX0, 1, 0, lpass_cdc_wsa_macro_get_rx_mute_status, + lpass_cdc_wsa_macro_set_rx_mute_status), + SOC_SINGLE_EXT("WSA_RX1_MIX Digital Mute", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_RX_MIX1, 1, 0, lpass_cdc_wsa_macro_get_rx_mute_status, + lpass_cdc_wsa_macro_set_rx_mute_status), + SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_COMP1, 1, 0, + lpass_cdc_wsa_macro_get_compander, lpass_cdc_wsa_macro_set_compander), + SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_COMP2, 1, 0, + lpass_cdc_wsa_macro_get_compander, lpass_cdc_wsa_macro_set_compander), + SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0, + 1, 0, lpass_cdc_wsa_macro_get_ec_hq, lpass_cdc_wsa_macro_set_ec_hq), + SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1, + 1, 0, lpass_cdc_wsa_macro_get_ec_hq, lpass_cdc_wsa_macro_set_ec_hq), +}; + +static const struct soc_enum rx_mux_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text); + +static const struct snd_kcontrol_new rx_mux[LPASS_CDC_WSA_MACRO_RX_MAX] = { + SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum, + lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum, + lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum, + lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum, + lpass_cdc_wsa_macro_rx_mux_get, lpass_cdc_wsa_macro_rx_mux_put), +}; + +static int lpass_cdc_wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 dai_id = widget->shift; + u32 spk_tx_id = mixer->shift; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int lpass_cdc_wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_multi_mixer_control *mixer = + ((struct soc_multi_mixer_control *)kcontrol->private_value); + u32 spk_tx_id = mixer->shift; + u32 enable = ucontrol->value.integer.value[0]; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv->vi_feed_value = ucontrol->value.integer.value[0]; + + if (enable) { + if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 && + !test_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + set_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]); + wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]++; + } + if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 && + !test_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + set_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]); + wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]++; + } + } else { + if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 && + test_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + clear_bit(LPASS_CDC_WSA_MACRO_TX0, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]); + wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]--; + } + if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 && + test_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI])) { + clear_bit(LPASS_CDC_WSA_MACRO_TX1, + &wsa_priv->active_ch_mask[LPASS_CDC_WSA_MACRO_AIF_VI]); + wsa_priv->active_ch_cnt[LPASS_CDC_WSA_MACRO_AIF_VI]--; + } + } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL); + + return 0; +} + +static const struct snd_kcontrol_new aif_vi_mixer[] = { + SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX0, 1, 0, + lpass_cdc_wsa_macro_vi_feed_mixer_get, + lpass_cdc_wsa_macro_vi_feed_mixer_put), + SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX1, 1, 0, + lpass_cdc_wsa_macro_vi_feed_mixer_get, + lpass_cdc_wsa_macro_vi_feed_mixer_put), +}; + +static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0, + SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_VI, 0, + lpass_cdc_wsa_macro_enable_vi_feedback, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_VI, + 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)), + SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_EC0_MUX, 0, + &rx_mix_ec0_mux, lpass_cdc_wsa_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_EC1_MUX, 0, + &rx_mix_ec1_mux, lpass_cdc_wsa_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX0, 0, + &rx_mux[LPASS_CDC_WSA_MACRO_RX0]), + SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX1, 0, + &rx_mux[LPASS_CDC_WSA_MACRO_RX1]), + SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX_MIX0, 0, + &rx_mux[LPASS_CDC_WSA_MACRO_RX_MIX0]), + SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_RX_MIX1, 0, + &rx_mux[LPASS_CDC_WSA_MACRO_RX_MIX1]), + + SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX_E("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, + &rx0_prim_inp0_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, + &rx0_prim_inp1_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, + &rx0_prim_inp2_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, + 0, 0, &rx0_mix_mux, lpass_cdc_wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, + &rx1_prim_inp0_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, + &rx1_prim_inp1_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, + &rx1_prim_inp2_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, + 0, 0, &rx1_mix_mux, lpass_cdc_wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("WSA_RX INT0 MIX", SND_SOC_NOPM, + 0, 0, NULL, 0, lpass_cdc_wsa_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_PGA_E("WSA_RX INT1 MIX", SND_SOC_NOPM, + 1, 0, NULL, 0, lpass_cdc_wsa_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX", + LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0, + &rx0_sidetone_mix_mux, lpass_cdc_wsa_macro_enable_swr, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_INPUT("WSA SRC0_INP"), + + SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"), + SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_COMP1, 0, NULL, 0, lpass_cdc_wsa_macro_enable_interpolator, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM, + LPASS_CDC_WSA_MACRO_COMP2, 0, NULL, 0, lpass_cdc_wsa_macro_enable_interpolator, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0, + NULL, 0, lpass_cdc_wsa_macro_spk_boost_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0, + NULL, 0, lpass_cdc_wsa_macro_spk_boost_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM, + 0, 0, wsa_int0_vbat_mix_switch, + ARRAY_SIZE(wsa_int0_vbat_mix_switch), + lpass_cdc_wsa_macro_enable_vbat, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM, + 0, 0, wsa_int1_vbat_mix_switch, + ARRAY_SIZE(wsa_int1_vbat_mix_switch), + lpass_cdc_wsa_macro_enable_vbat, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("VIINPUT_WSA"), + + SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"), + SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"), + + SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0, + lpass_cdc_wsa_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route wsa_audio_map[] = { + /* VI Feedback */ + {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"}, + {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"}, + {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"}, + {"WSA AIF_VI", NULL, "WSA_MCLK"}, + + {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"}, + {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"}, + {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"}, + {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"}, + {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"}, + {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"}, + {"WSA AIF_ECHO", NULL, "WSA_MCLK"}, + + {"WSA AIF1 PB", NULL, "WSA_MCLK"}, + {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"}, + + {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"}, + + {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + + {"WSA RX0", NULL, "WSA RX0 MUX"}, + {"WSA RX1", NULL, "WSA RX1 MUX"}, + {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"}, + {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"}, + + {"WSA_RX0 INP0", "RX0", "WSA RX0"}, + {"WSA_RX0 INP0", "RX1", "WSA RX1"}, + {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"}, + + {"WSA_RX0 INP1", "RX0", "WSA RX0"}, + {"WSA_RX0 INP1", "RX1", "WSA RX1"}, + {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"}, + + {"WSA_RX0 INP2", "RX0", "WSA RX0"}, + {"WSA_RX0 INP2", "RX1", "WSA RX1"}, + {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"}, + + {"WSA_RX0 MIX INP", "RX0", "WSA RX0"}, + {"WSA_RX0 MIX INP", "RX1", "WSA RX1"}, + {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"}, + + {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"}, + {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"}, + {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"}, + {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"}, + {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"}, + + {"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"}, + {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"}, + + {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"}, + {"WSA_SPK1 OUT", NULL, "WSA_MCLK"}, + + {"WSA_RX1 INP0", "RX0", "WSA RX0"}, + {"WSA_RX1 INP0", "RX1", "WSA RX1"}, + {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"}, + + {"WSA_RX1 INP1", "RX0", "WSA RX0"}, + {"WSA_RX1 INP1", "RX1", "WSA RX1"}, + {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"}, + + {"WSA_RX1 INP2", "RX0", "WSA RX0"}, + {"WSA_RX1 INP2", "RX1", "WSA RX1"}, + {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"}, + + {"WSA_RX1 MIX INP", "RX0", "WSA RX0"}, + {"WSA_RX1 MIX INP", "RX1", "WSA RX1"}, + {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"}, + + {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"}, + {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"}, + + {"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"}, + {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"}, + + {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"}, + {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"}, + {"WSA_SPK2 OUT", NULL, "WSA_MCLK"}, +}; + +static const struct lpass_cdc_wsa_macro_reg_mask_val + lpass_cdc_wsa_macro_reg_init[] = { + {LPASS_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12}, + {LPASS_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08}, + {LPASS_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x0C}, + {LPASS_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12}, + {LPASS_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08}, + {LPASS_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x0C}, + {LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58}, + {LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58}, + {LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08}, + {LPASS_CDC_WSA_RX1_RX_PATH_CFG1, 0x08, 0x08}, + {LPASS_CDC_WSA_TOP_TOP_CFG1, 0x02, 0x02}, + {LPASS_CDC_WSA_TOP_TOP_CFG1, 0x01, 0x01}, + {LPASS_CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01}, + {LPASS_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01}, + {LPASS_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_RX1_RX_PATH_CFG0, 0x01, 0x01}, + {LPASS_CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x01, 0x01}, + {LPASS_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01}, +}; + +static void lpass_cdc_wsa_macro_init_bcl_pmic_reg(struct snd_soc_component *component) +{ + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!component) { + pr_err("%s: NULL component pointer!\n", __func__); + return; + } + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return; + + switch (wsa_priv->bcl_pmic_params.id) { + case 0: + /* Enable ID0 to listen to respective PMIC group interrupts */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02); + /* Update MC_SID0 */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F, + wsa_priv->bcl_pmic_params.sid); + /* Update MC_PPID0 */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF, + wsa_priv->bcl_pmic_params.ppid); + break; + case 1: + /* Enable ID1 to listen to respective PMIC group interrupts */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01); + /* Update MC_SID1 */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F, + wsa_priv->bcl_pmic_params.sid); + /* Update MC_PPID1 */ + snd_soc_component_update_bits(component, + LPASS_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF, + wsa_priv->bcl_pmic_params.ppid); + break; + default: + dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n", + __func__, wsa_priv->bcl_pmic_params.id); + break; + } +} + +static void lpass_cdc_wsa_macro_init_reg(struct snd_soc_component *component) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lpass_cdc_wsa_macro_reg_init); i++) + snd_soc_component_update_bits(component, + lpass_cdc_wsa_macro_reg_init[i].reg, + lpass_cdc_wsa_macro_reg_init[i].mask, + lpass_cdc_wsa_macro_reg_init[i].val); + + lpass_cdc_wsa_macro_init_bcl_pmic_reg(component); +} + +static int lpass_cdc_wsa_macro_core_vote(void *handle, bool enable) +{ + struct lpass_cdc_wsa_macro_priv *wsa_priv = (struct lpass_cdc_wsa_macro_priv *) handle; + + if (wsa_priv == NULL) { + pr_err("%s: wsa priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) { + pm_runtime_get_sync(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); + pm_runtime_mark_last_busy(wsa_priv->dev); + } + + if (lpass_cdc_check_core_votes(wsa_priv->dev)) + return 0; + else + return -EINVAL; +} + +static int wsa_swrm_clock(void *handle, bool enable) +{ + struct lpass_cdc_wsa_macro_priv *wsa_priv = (struct lpass_cdc_wsa_macro_priv *) handle; + struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL); + int ret = 0; + + if (regmap == NULL) { + dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&wsa_priv->swr_clk_lock); + + trace_printk("%s: %s swrm clock %s\n", + dev_name(wsa_priv->dev), __func__, + (enable ? "enable" : "disable")); + dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n", + __func__, (enable ? "enable" : "disable")); + if (enable) { + pm_runtime_get_sync(wsa_priv->dev); + if (wsa_priv->swr_clk_users == 0) { + ret = msm_cdc_pinctrl_select_active_state( + wsa_priv->wsa_swr_gpio_p); + if (ret < 0) { + dev_err_ratelimited(wsa_priv->dev, + "%s: wsa swr pinctrl enable failed\n", + __func__); + pm_runtime_mark_last_busy(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); + goto exit; + } + ret = lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 1, true); + if (ret < 0) { + msm_cdc_pinctrl_select_sleep_state( + wsa_priv->wsa_swr_gpio_p); + dev_err_ratelimited(wsa_priv->dev, + "%s: wsa request clock enable failed\n", + __func__); + pm_runtime_mark_last_busy(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); + goto exit; + } + if (wsa_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x02); + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x01); + if (wsa_priv->reset_swr) + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + 0x02, 0x00); + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + 0x1C, 0x0C); + wsa_priv->reset_swr = false; + } + wsa_priv->swr_clk_users++; + pm_runtime_mark_last_busy(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); + } else { + if (wsa_priv->swr_clk_users <= 0) { + dev_err(wsa_priv->dev, "%s: clock already disabled\n", + __func__); + wsa_priv->swr_clk_users = 0; + goto exit; + } + wsa_priv->swr_clk_users--; + if (wsa_priv->swr_clk_users == 0) { + regmap_update_bits(regmap, + LPASS_CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + 0x01, 0x00); + lpass_cdc_wsa_macro_mclk_enable(wsa_priv, 0, true); + ret = msm_cdc_pinctrl_select_sleep_state( + wsa_priv->wsa_swr_gpio_p); + if (ret < 0) { + dev_err_ratelimited(wsa_priv->dev, + "%s: wsa swr pinctrl disable failed\n", + __func__); + goto exit; + } + } + } + trace_printk("%s: %s swrm clock users: %d\n", + dev_name(wsa_priv->dev), __func__, + wsa_priv->swr_clk_users); + dev_dbg(wsa_priv->dev, "%s: swrm clock users %d\n", + __func__, wsa_priv->swr_clk_users); +exit: + mutex_unlock(&wsa_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_wsa_macro_init(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + int ret; + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + wsa_dev = lpass_cdc_get_device_ptr(component->dev, WSA_MACRO); + if (!wsa_dev) { + dev_err(component->dev, + "%s: null device for macro!\n", __func__); + return -EINVAL; + } + wsa_priv = dev_get_drvdata(wsa_dev); + if (!wsa_priv) { + dev_err(component->dev, + "%s: priv is null for macro!\n", __func__); + return -EINVAL; + } + + ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa_macro_dapm_widgets, + ARRAY_SIZE(lpass_cdc_wsa_macro_dapm_widgets)); + if (ret < 0) { + dev_err(wsa_dev, "%s: Failed to add controls\n", __func__); + return ret; + } + + ret = snd_soc_dapm_add_routes(dapm, wsa_audio_map, + ARRAY_SIZE(wsa_audio_map)); + if (ret < 0) { + dev_err(wsa_dev, "%s: Failed to add routes\n", __func__); + return ret; + } + + ret = snd_soc_dapm_new_widgets(dapm->card); + if (ret < 0) { + dev_err(wsa_dev, "%s: Failed to add widgets\n", __func__); + return ret; + } + + ret = snd_soc_add_component_controls(component, lpass_cdc_wsa_macro_snd_controls, + ARRAY_SIZE(lpass_cdc_wsa_macro_snd_controls)); + if (ret < 0) { + dev_err(wsa_dev, "%s: Failed to add snd_ctls\n", __func__); + return ret; + } + snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF1 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA"); + snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP"); + snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP"); + snd_soc_dapm_sync(dapm); + + wsa_priv->component = component; + wsa_priv->spkr_gain_offset = LPASS_CDC_WSA_MACRO_GAIN_OFFSET_0_DB; + lpass_cdc_wsa_macro_init_reg(component); + + return 0; +} + +static int lpass_cdc_wsa_macro_deinit(struct snd_soc_component *component) +{ + struct device *wsa_dev = NULL; + struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL; + + if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) + return -EINVAL; + + wsa_priv->component = NULL; + + return 0; +} + +static void lpass_cdc_wsa_macro_add_child_devices(struct work_struct *work) +{ + struct lpass_cdc_wsa_macro_priv *wsa_priv; + struct platform_device *pdev; + struct device_node *node; + struct lpass_cdc_wsa_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp; + int ret; + u16 count = 0, ctrl_num = 0; + struct lpass_cdc_wsa_macro_swr_ctrl_platform_data *platdata; + char plat_dev_name[LPASS_CDC_WSA_MACRO_SWR_STRING_LEN]; + + wsa_priv = container_of(work, struct lpass_cdc_wsa_macro_priv, + lpass_cdc_wsa_macro_add_child_devices_work); + if (!wsa_priv) { + pr_err("%s: Memory for wsa_priv does not exist\n", + __func__); + return; + } + if (!wsa_priv->dev || !wsa_priv->dev->of_node) { + dev_err(wsa_priv->dev, + "%s: DT node for wsa_priv does not exist\n", __func__); + return; + } + + platdata = &wsa_priv->swr_plat_data; + wsa_priv->child_count = 0; + + for_each_available_child_of_node(wsa_priv->dev->of_node, node) { + if (strnstr(node->name, "wsa_swr_master", + strlen("wsa_swr_master")) != NULL) + strlcpy(plat_dev_name, "wsa_swr_ctrl", + (LPASS_CDC_WSA_MACRO_SWR_STRING_LEN - 1)); + else if (strnstr(node->name, "msm_cdc_pinctrl", + strlen("msm_cdc_pinctrl")) != NULL) + strlcpy(plat_dev_name, node->name, + (LPASS_CDC_WSA_MACRO_SWR_STRING_LEN - 1)); + else + continue; + + pdev = platform_device_alloc(plat_dev_name, -1); + if (!pdev) { + dev_err(wsa_priv->dev, "%s: pdev memory alloc failed\n", + __func__); + ret = -ENOMEM; + goto err; + } + pdev->dev.parent = wsa_priv->dev; + pdev->dev.of_node = node; + + if (strnstr(node->name, "wsa_swr_master", + strlen("wsa_swr_master")) != NULL) { + ret = platform_device_add_data(pdev, platdata, + sizeof(*platdata)); + if (ret) { + dev_err(&pdev->dev, + "%s: cannot add plat data ctrl:%d\n", + __func__, ctrl_num); + goto fail_pdev_add; + } + } + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, + "%s: Cannot add platform device\n", + __func__); + goto fail_pdev_add; + } + + if (!strcmp(node->name, "wsa_swr_master")) { + temp = krealloc(swr_ctrl_data, + (ctrl_num + 1) * sizeof( + struct lpass_cdc_wsa_macro_swr_ctrl_data), + GFP_KERNEL); + if (!temp) { + dev_err(&pdev->dev, "out of memory\n"); + ret = -ENOMEM; + goto err; + } + swr_ctrl_data = temp; + swr_ctrl_data[ctrl_num].wsa_swr_pdev = pdev; + ctrl_num++; + dev_dbg(&pdev->dev, + "%s: Added soundwire ctrl device(s)\n", + __func__); + wsa_priv->swr_ctrl_data = swr_ctrl_data; + } + if (wsa_priv->child_count < LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX) + wsa_priv->pdev_child_devices[ + wsa_priv->child_count++] = pdev; + else + goto err; + } + + return; +fail_pdev_add: + for (count = 0; count < wsa_priv->child_count; count++) + platform_device_put(wsa_priv->pdev_child_devices[count]); +err: + return; +} + +static void lpass_cdc_wsa_macro_init_ops(struct macro_ops *ops, + char __iomem *wsa_io_base) +{ + memset(ops, 0, sizeof(struct macro_ops)); + ops->init = lpass_cdc_wsa_macro_init; + ops->exit = lpass_cdc_wsa_macro_deinit; + ops->io_base = wsa_io_base; + ops->dai_ptr = lpass_cdc_wsa_macro_dai; + ops->num_dais = ARRAY_SIZE(lpass_cdc_wsa_macro_dai); + ops->event_handler = lpass_cdc_wsa_macro_event_handler; + ops->set_port_map = lpass_cdc_wsa_macro_set_port_map; +} + +static int lpass_cdc_wsa_macro_probe(struct platform_device *pdev) +{ + struct macro_ops ops; + struct lpass_cdc_wsa_macro_priv *wsa_priv; + u32 wsa_base_addr, default_clk_id; + char __iomem *wsa_io_base; + int ret = 0; + u8 bcl_pmic_params[3]; + u32 is_used_wsa_swr_gpio = 1; + const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio"; + + if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + + wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_wsa_macro_priv), + GFP_KERNEL); + if (!wsa_priv) + return -ENOMEM; + + wsa_priv->dev = &pdev->dev; + ret = of_property_read_u32(pdev->dev.of_node, "reg", + &wsa_base_addr); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "reg"); + return ret; + } + if (of_find_property(pdev->dev.of_node, is_used_wsa_swr_gpio_dt, + NULL)) { + ret = of_property_read_u32(pdev->dev.of_node, + is_used_wsa_swr_gpio_dt, + &is_used_wsa_swr_gpio); + if (ret) { + dev_err(&pdev->dev, "%s: error reading %s in dt\n", + __func__, is_used_wsa_swr_gpio_dt); + is_used_wsa_swr_gpio = 1; + } + } + wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,wsa-swr-gpios", 0); + if (!wsa_priv->wsa_swr_gpio_p && is_used_wsa_swr_gpio) { + dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n", + __func__); + return -EINVAL; + } + if (msm_cdc_pinctrl_get_state(wsa_priv->wsa_swr_gpio_p) < 0 && + is_used_wsa_swr_gpio) { + dev_err(&pdev->dev, "%s: failed to get swr pin state\n", + __func__); + return -EPROBE_DEFER; + } + msm_cdc_pinctrl_set_wakeup_capable( + wsa_priv->wsa_swr_gpio_p, false); + + wsa_io_base = devm_ioremap(&pdev->dev, + wsa_base_addr, LPASS_CDC_WSA_MACRO_MAX_OFFSET); + if (!wsa_io_base) { + dev_err(&pdev->dev, "%s: ioremap failed\n", __func__); + return -EINVAL; + } + wsa_priv->wsa_io_base = wsa_io_base; + wsa_priv->reset_swr = true; + INIT_WORK(&wsa_priv->lpass_cdc_wsa_macro_add_child_devices_work, + lpass_cdc_wsa_macro_add_child_devices); + wsa_priv->swr_plat_data.handle = (void *) wsa_priv; + wsa_priv->swr_plat_data.read = NULL; + wsa_priv->swr_plat_data.write = NULL; + wsa_priv->swr_plat_data.bulk_write = NULL; + wsa_priv->swr_plat_data.clk = wsa_swrm_clock; + wsa_priv->swr_plat_data.core_vote = lpass_cdc_wsa_macro_core_vote; + wsa_priv->swr_plat_data.handle_irq = NULL; + + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,mux0-clk-id"); + default_clk_id = WSA_CORE_CLK; + } + + ret = of_property_read_u8_array(pdev->dev.of_node, + "qcom,wsa-bcl-pmic-params", bcl_pmic_params, + sizeof(bcl_pmic_params)); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,wsa-bcl-pmic-params"); + } else { + wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0]; + wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1]; + wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2]; + } + wsa_priv->default_clk_id = default_clk_id; + + dev_set_drvdata(&pdev->dev, wsa_priv); + mutex_init(&wsa_priv->mclk_lock); + mutex_init(&wsa_priv->swr_clk_lock); + lpass_cdc_wsa_macro_init_ops(&ops, wsa_io_base); + ops.clk_id_req = wsa_priv->default_clk_id; + ops.default_clk_id = wsa_priv->default_clk_id; + + ret = lpass_cdc_register_macro(&pdev->dev, WSA_MACRO, &ops); + if (ret < 0) { + dev_err(&pdev->dev, "%s: register macro failed\n", __func__); + goto reg_macro_fail; + } + schedule_work(&wsa_priv->lpass_cdc_wsa_macro_add_child_devices_work); + pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_suspend_ignore_children(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); + + return ret; +reg_macro_fail: + mutex_destroy(&wsa_priv->mclk_lock); + mutex_destroy(&wsa_priv->swr_clk_lock); + return ret; +} + +static int lpass_cdc_wsa_macro_remove(struct platform_device *pdev) +{ + struct lpass_cdc_wsa_macro_priv *wsa_priv; + u16 count = 0; + + wsa_priv = dev_get_drvdata(&pdev->dev); + + if (!wsa_priv) + return -EINVAL; + + for (count = 0; count < wsa_priv->child_count && + count < LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX; count++) + platform_device_unregister(wsa_priv->pdev_child_devices[count]); + + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + lpass_cdc_unregister_macro(&pdev->dev, WSA_MACRO); + mutex_destroy(&wsa_priv->mclk_lock); + mutex_destroy(&wsa_priv->swr_clk_lock); + return 0; +} + +static const struct of_device_id lpass_cdc_wsa_macro_dt_match[] = { + {.compatible = "qcom,lpass-cdc-wsa-macro"}, + {} +}; + +static const struct dev_pm_ops lpass_cdc_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + pm_runtime_force_suspend, + pm_runtime_force_resume + ) + SET_RUNTIME_PM_OPS( + lpass_cdc_runtime_suspend, + lpass_cdc_runtime_resume, + NULL + ) +}; + +static struct platform_driver lpass_cdc_wsa_macro_driver = { + .driver = { + .name = "lpass_cdc_wsa_macro", + .owner = THIS_MODULE, + .pm = &lpass_cdc_dev_pm_ops, + .of_match_table = lpass_cdc_wsa_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_wsa_macro_probe, + .remove = lpass_cdc_wsa_macro_remove, +}; + +module_platform_driver(lpass_cdc_wsa_macro_driver); + +MODULE_DESCRIPTION("WSA macro driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.h b/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.h new file mode 100644 index 0000000000..17e65403e3 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ +#ifndef LPASS_CDC_WSA_MACRO_H +#define LPASS_CDC_WSA_MACRO_H + +/* + * Selects compander and smart boost settings + * for a given speaker mode + */ +enum { + LPASS_CDC_WSA_MACRO_SPKR_MODE_DEFAULT, + LPASS_CDC_WSA_MACRO_SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */ +}; + +/* Rx path gain offsets */ +enum { + LPASS_CDC_WSA_MACRO_GAIN_OFFSET_M1P5_DB, + LPASS_CDC_WSA_MACRO_GAIN_OFFSET_0_DB, +}; + + +#if IS_ENABLED(CONFIG_WSA_MACRO) +extern int lpass_cdc_wsa_macro_set_spkr_mode(struct snd_soc_component *component, + int mode); +extern int lpass_cdc_wsa_macro_set_spkr_gain_offset(struct snd_soc_component *component, + int offset); +#else /* CONFIG_WSA_MACRO */ +static inline int lpass_cdc_wsa_macro_set_spkr_mode(struct snd_soc_component *component, + int mode) +{ + return 0; +} +static inline int lpass_cdc_wsa_macro_set_spkr_gain_offset( + struct snd_soc_component *component, + int offset) +{ + return 0; +} +#endif /* CONFIG_WSA_MACRO */ +#endif diff --git a/asoc/codecs/lpass-cdc/lpass-cdc.c b/asoc/codecs/lpass-cdc/lpass-cdc.c new file mode 100644 index 0000000000..f7aafca182 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc.c @@ -0,0 +1,1546 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lpass-cdc.h" +#include "internal.h" +#include "lpass-cdc-clk-rsc.h" + +#define DRV_NAME "lpass_cdc" + +#define LPASS_CDC_VERSION_ENTRY_SIZE 32 +#define LPASS_CDC_STRING_LEN 80 + +static const struct snd_soc_component_driver lpass_cdc; + +/* pm runtime auto suspend timer in msecs */ +#define LPASS_CDC_AUTO_SUSPEND_DELAY 100 /* delay in msec */ + +/* MCLK_MUX table for all macros */ +static u16 lpass_cdc_mclk_mux_tbl[MAX_MACRO][MCLK_MUX_MAX] = { + {TX_MACRO, VA_MACRO}, + {TX_MACRO, RX_MACRO}, + {TX_MACRO, WSA_MACRO}, + {TX_MACRO, VA_MACRO}, +}; + +static bool lpass_cdc_is_valid_codec_dev(struct device *dev); + +int lpass_cdc_set_port_map(struct snd_soc_component *component, + u32 size, void *data) +{ + struct lpass_cdc_priv *priv = NULL; + struct swr_mstr_port_map *map = NULL; + u16 idx; + + if (!component || (size == 0) || !data) + return -EINVAL; + + priv = snd_soc_component_get_drvdata(component); + if (!priv) + return -EINVAL; + + if (!lpass_cdc_is_valid_codec_dev(priv->dev)) { + dev_err(priv->dev, "%s: invalid codec\n", __func__); + return -EINVAL; + } + map = (struct swr_mstr_port_map *)data; + + for (idx = 0; idx < size; idx++) { + if (priv->macro_params[map->id].set_port_map) + priv->macro_params[map->id].set_port_map(component, + map->uc, + SWR_MSTR_PORT_LEN, + map->swr_port_params); + map += 1; + } + + return 0; +} +EXPORT_SYMBOL(lpass_cdc_set_port_map); + +static void lpass_cdc_ahb_write_device(char __iomem *io_base, + u16 reg, u8 value) +{ + u32 temp = (u32)(value) & 0x000000FF; + + iowrite32(temp, io_base + reg); +} + +static void lpass_cdc_ahb_read_device(char __iomem *io_base, + u16 reg, u8 *value) +{ + u32 temp; + + temp = ioread32(io_base + reg); + *value = (u8)temp; +} + +static int __lpass_cdc_reg_read(struct lpass_cdc_priv *priv, + u16 macro_id, u16 reg, u8 *val) +{ + int ret = 0; + + mutex_lock(&priv->clk_lock); + if (!priv->dev_up) { + dev_dbg_ratelimited(priv->dev, + "%s: SSR in progress, exit\n", __func__); + ret = -EINVAL; + goto ssr_err; + } + + if (priv->macro_params[VA_MACRO].dev) { + pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev); + if (!lpass_cdc_check_core_votes(priv->macro_params[VA_MACRO].dev)) + goto ssr_err; + } + + if (priv->version < LPASS_CDC_VERSION_2_0) { + /* Request Clk before register access */ + ret = lpass_cdc_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + true); + if (ret < 0) { + dev_err_ratelimited(priv->dev, + "%s: Failed to enable clock, ret:%d\n", + __func__, ret); + goto err; + } + } + + lpass_cdc_ahb_read_device( + priv->macro_params[macro_id].io_base, reg, val); + + if (priv->version < LPASS_CDC_VERSION_2_0) + lpass_cdc_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + false); + +err: + if (priv->macro_params[VA_MACRO].dev) { + pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev); + pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev); + } +ssr_err: + mutex_unlock(&priv->clk_lock); + return ret; +} + +static int __lpass_cdc_reg_write(struct lpass_cdc_priv *priv, + u16 macro_id, u16 reg, u8 val) +{ + int ret = 0; + + mutex_lock(&priv->clk_lock); + if (!priv->dev_up) { + dev_dbg_ratelimited(priv->dev, + "%s: SSR in progress, exit\n", __func__); + ret = -EINVAL; + goto ssr_err; + } + if (priv->macro_params[VA_MACRO].dev) { + pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev); + if (!lpass_cdc_check_core_votes(priv->macro_params[VA_MACRO].dev)) + goto ssr_err; + } + + if (priv->version < LPASS_CDC_VERSION_2_0) { + /* Request Clk before register access */ + ret = lpass_cdc_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + true); + if (ret < 0) { + dev_err_ratelimited(priv->dev, + "%s: Failed to enable clock, ret:%d\n", + __func__, ret); + goto err; + } + } + + lpass_cdc_ahb_write_device( + priv->macro_params[macro_id].io_base, reg, val); + + if (priv->version < LPASS_CDC_VERSION_2_0) + lpass_cdc_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + false); + +err: + if (priv->macro_params[VA_MACRO].dev) { + pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev); + pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev); + } +ssr_err: + mutex_unlock(&priv->clk_lock); + return ret; +} + +static int lpass_cdc_update_wcd_event(void *handle, u16 event, u32 data) +{ + struct lpass_cdc_priv *priv = (struct lpass_cdc_priv *)handle; + + if (!priv) { + pr_err("%s:Invalid lpass_cdc priv handle\n", __func__); + return -EINVAL; + } + + switch (event) { + case WCD_LPASS_CDC_EVT_RX_MUTE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_RX_MUTE, data); + break; + case WCD_LPASS_CDC_EVT_IMPED_TRUE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_IMPED_TRUE, data); + break; + case WCD_LPASS_CDC_EVT_IMPED_FALSE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_IMPED_FALSE, data); + break; + case WCD_LPASS_CDC_EVT_RX_COMPANDER_SOFT_RST: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST, data); + break; + case WCD_LPASS_CDC_EVT_BCS_CLK_OFF: + if (priv->macro_params[TX_MACRO].event_handler) + priv->macro_params[TX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_BCS_CLK_OFF, data); + break; + case WCD_LPASS_CDC_EVT_RX_PA_GAIN_UPDATE: + /* Update PA Gain only for lpass_cdc version 2.1 */ + if (priv->version == LPASS_CDC_VERSION_2_1) + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE, + data); + break; + case WCD_LPASS_CDC_EVT_HPHL_HD2_ENABLE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE, data); + break; + case WCD_LPASS_CDC_EVT_HPHR_HD2_ENABLE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE, data); + break; + default: + dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n", + __func__, event); + return -EINVAL; + } + return 0; +} + +static int lpass_cdc_register_notifier(void *handle, + struct notifier_block *nblock, + bool enable) +{ + struct lpass_cdc_priv *priv = (struct lpass_cdc_priv *)handle; + + if (!priv) { + pr_err("%s: lpass_cdc priv is null\n", __func__); + return -EINVAL; + } + if (enable) + return blocking_notifier_chain_register(&priv->notifier, + nblock); + + return blocking_notifier_chain_unregister(&priv->notifier, + nblock); +} + +static void lpass_cdc_notifier_call(struct lpass_cdc_priv *priv, + u32 data) +{ + dev_dbg(priv->dev, "%s: notifier call, data:%d\n", __func__, data); + blocking_notifier_call_chain(&priv->notifier, + data, (void *)priv->wcd_dev); +} + +static bool lpass_cdc_is_valid_child_dev(struct device *dev) +{ + if (of_device_is_compatible(dev->parent->of_node, "qcom,lpass-cdc")) + return true; + + return false; +} + +static bool lpass_cdc_is_valid_codec_dev(struct device *dev) +{ + if (of_device_is_compatible(dev->of_node, "qcom,lpass-cdc")) + return true; + + return false; +} + +/** + * lpass_cdc_clear_amic_tx_hold - clears AMIC register on analog codec + * + * @dev: lpass_cdc device ptr. + * + */ +void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n) +{ + struct lpass_cdc_priv *priv; + u16 event; + u16 amic = 0; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return; + } + + if (!lpass_cdc_is_valid_codec_dev(dev)) { + pr_err("%s: invalid codec\n", __func__); + return; + } + priv = dev_get_drvdata(dev); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return; + } + event = LPASS_CDC_WCD_EVT_TX_CH_HOLD_CLEAR; + if (adc_n == LPASS_CDC_ADC0) + amic = 0x1; + else if (adc_n == LPASS_CDC_ADC1) + amic = 0x2; + else if (adc_n == LPASS_CDC_ADC2) + amic = 0x2; + else if (adc_n == LPASS_CDC_ADC3) + amic = 0x3; + else + return; + + lpass_cdc_notifier_call(priv, (amic << 0x10 | event)); +} +EXPORT_SYMBOL(lpass_cdc_clear_amic_tx_hold); + +/** + * lpass_cdc_get_device_ptr - Get child or macro device ptr + * + * @dev: lpass_cdc device ptr. + * @macro_id: ID of macro calling this API. + * + * Returns dev ptr on success or NULL on error. + */ +struct device *lpass_cdc_get_device_ptr(struct device *dev, u16 macro_id) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return NULL; + } + + if (!lpass_cdc_is_valid_codec_dev(dev)) { + pr_err("%s: invalid codec\n", __func__); + return NULL; + } + priv = dev_get_drvdata(dev); + if (!priv || (macro_id >= MAX_MACRO)) { + dev_err(dev, "%s: priv is null or invalid macro\n", __func__); + return NULL; + } + + return priv->macro_params[macro_id].dev; +} +EXPORT_SYMBOL(lpass_cdc_get_device_ptr); + +/** + * lpass_cdc_get_rsc_clk_device_ptr - Get rsc clk device ptr + * + * @dev: lpass_cdc device ptr. + * + * Returns dev ptr on success or NULL on error. + */ +struct device *lpass_cdc_get_rsc_clk_device_ptr(struct device *dev) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return NULL; + } + + if (!lpass_cdc_is_valid_codec_dev(dev)) { + pr_err("%s: invalid codec\n", __func__); + return NULL; + } + priv = dev_get_drvdata(dev); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return NULL; + } + + return priv->clk_dev; +} +EXPORT_SYMBOL(lpass_cdc_get_rsc_clk_device_ptr); + +static int lpass_cdc_copy_dais_from_macro(struct lpass_cdc_priv *priv) +{ + struct snd_soc_dai_driver *dai_ptr; + u16 macro_idx; + + /* memcpy into lpass_cdc_dais all macro dais */ + if (!priv->lpass_cdc_dais) + priv->lpass_cdc_dais = devm_kzalloc(priv->dev, + priv->num_dais * + sizeof( + struct snd_soc_dai_driver), + GFP_KERNEL); + if (!priv->lpass_cdc_dais) + return -ENOMEM; + + dai_ptr = priv->lpass_cdc_dais; + + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (priv->macro_params[macro_idx].dai_ptr) { + memcpy(dai_ptr, + priv->macro_params[macro_idx].dai_ptr, + priv->macro_params[macro_idx].num_dais * + sizeof(struct snd_soc_dai_driver)); + dai_ptr += priv->macro_params[macro_idx].num_dais; + } + } + return 0; +} + +/** + * lpass_cdc_register_res_clk - Registers rsc clk driver to lpass_cdc + * + * @dev: rsc clk device ptr. + * @rsc_clk_cb: event handler callback for notifications like SSR + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t rsc_clk_cb) +{ + struct lpass_cdc_priv *priv; + + if (!dev || !rsc_clk_cb) { + pr_err("%s: dev or rsc_clk_cb is null\n", __func__); + return -EINVAL; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device :%pK not added yet\n", + __func__, dev); + return -EINVAL; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return -EINVAL; + } + + priv->clk_dev = dev; + priv->rsc_clk_cb = rsc_clk_cb; + + return 0; +} +EXPORT_SYMBOL(lpass_cdc_register_res_clk); + +/** + * lpass_cdc_unregister_res_clk - Unregisters rsc clk driver from lpass_cdc + * + * @dev: resource clk device ptr. + */ +void lpass_cdc_unregister_res_clk(struct device *dev) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device :%pK not added\n", + __func__, dev); + return; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return; + } + + priv->clk_dev = NULL; + priv->rsc_clk_cb = NULL; +} +EXPORT_SYMBOL(lpass_cdc_unregister_res_clk); + +static u8 lpass_cdc_dmic_clk_div_get(struct snd_soc_component *component, + int mode) +{ + struct lpass_cdc_priv* priv = snd_soc_component_get_drvdata(component); + int macro = (mode ? VA_MACRO : TX_MACRO); + int ret = 0; + + if (priv->macro_params[macro].clk_div_get) { + ret = priv->macro_params[macro].clk_div_get(component); + if (ret > 0) + return ret; + } + + return 1; +} + +int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component, + u32 dmic, u32 tx_mode, bool enable) +{ + struct lpass_cdc_priv* priv = snd_soc_component_get_drvdata(component); + u8 dmic_clk_en = 0x01; + u16 dmic_clk_reg = 0; + s32 *dmic_clk_cnt = NULL; + u8 *dmic_clk_div = NULL; + u8 freq_change_mask = 0; + u8 clk_div = 0; + + dev_dbg(component->dev, "%s: enable: %d, tx_mode:%d, dmic: %d\n", + __func__, enable, tx_mode, dmic); + + switch (dmic) { + case 0: + case 1: + dmic_clk_cnt = &(priv->dmic_0_1_clk_cnt); + dmic_clk_div = &(priv->dmic_0_1_clk_div); + dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC0_CTL; + freq_change_mask = 0x01; + break; + case 2: + case 3: + dmic_clk_cnt = &(priv->dmic_2_3_clk_cnt); + dmic_clk_div = &(priv->dmic_2_3_clk_div); + dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC1_CTL; + freq_change_mask = 0x02; + break; + case 4: + case 5: + dmic_clk_cnt = &(priv->dmic_4_5_clk_cnt); + dmic_clk_div = &(priv->dmic_4_5_clk_div); + dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC2_CTL; + freq_change_mask = 0x04; + break; + case 6: + case 7: + dmic_clk_cnt = &(priv->dmic_6_7_clk_cnt); + dmic_clk_div = &(priv->dmic_6_7_clk_div); + dmic_clk_reg = LPASS_CDC_VA_TOP_CSR_DMIC3_CTL; + freq_change_mask = 0x08; + break; + default: + dev_err(component->dev, "%s: Invalid DMIC Selection\n", + __func__); + return -EINVAL; + } + dev_dbg(component->dev, "%s: DMIC%d dmic_clk_cnt %d\n", + __func__, dmic, *dmic_clk_cnt); + if (enable) { + clk_div = lpass_cdc_dmic_clk_div_get(component, tx_mode); + (*dmic_clk_cnt)++; + if (*dmic_clk_cnt == 1) { + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + 0x80, 0x00); + snd_soc_component_update_bits(component, dmic_clk_reg, + 0x0E, clk_div << 0x1); + snd_soc_component_update_bits(component, dmic_clk_reg, + dmic_clk_en, dmic_clk_en); + } else { + if (*dmic_clk_div > clk_div) { + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, freq_change_mask); + snd_soc_component_update_bits(component, dmic_clk_reg, + 0x0E, clk_div << 0x1); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, 0x00); + } else { + clk_div = *dmic_clk_div; + } + } + *dmic_clk_div = clk_div; + } else { + (*dmic_clk_cnt)--; + if (*dmic_clk_cnt == 0) { + snd_soc_component_update_bits(component, dmic_clk_reg, + dmic_clk_en, 0); + clk_div = 0; + snd_soc_component_update_bits(component, dmic_clk_reg, + 0x0E, clk_div << 0x1); + } else { + clk_div = lpass_cdc_dmic_clk_div_get(component, tx_mode); + if (*dmic_clk_div > clk_div) { + clk_div = lpass_cdc_dmic_clk_div_get(component, !tx_mode); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, freq_change_mask); + snd_soc_component_update_bits(component, dmic_clk_reg, + 0x0E, clk_div << 0x1); + snd_soc_component_update_bits(component, + LPASS_CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, 0x00); + } else { + clk_div = *dmic_clk_div; + } + } + *dmic_clk_div = clk_div; + } + + return 0; +} +EXPORT_SYMBOL(lpass_cdc_dmic_clk_enable); + +bool lpass_cdc_is_va_macro_registered(struct device *dev) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return false; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device calling is not added yet\n", + __func__); + return false; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return false; + } + return priv->macros_supported[VA_MACRO]; +} +EXPORT_SYMBOL(lpass_cdc_is_va_macro_registered); + +/** + * lpass_cdc_register_macro - Registers macro to lpass_cdc + * + * @dev: macro device ptr. + * @macro_id: ID of macro calling this API. + * @ops: macro params to register. + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_register_macro(struct device *dev, u16 macro_id, + struct macro_ops *ops) +{ + struct lpass_cdc_priv *priv; + int ret = -EINVAL; + + if (!dev || !ops) { + pr_err("%s: dev or ops is null\n", __func__); + return -EINVAL; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device for macro:%d not added yet\n", + __func__, macro_id); + return -EINVAL; + } + priv = dev_get_drvdata(dev->parent); + if (!priv || (macro_id >= MAX_MACRO)) { + dev_err(dev, "%s: priv is null or invalid macro\n", __func__); + return -EINVAL; + } + + priv->macro_params[macro_id].clk_id_req = ops->clk_id_req; + priv->macro_params[macro_id].default_clk_id = ops->default_clk_id; + priv->macro_params[macro_id].init = ops->init; + priv->macro_params[macro_id].exit = ops->exit; + priv->macro_params[macro_id].io_base = ops->io_base; + priv->macro_params[macro_id].num_dais = ops->num_dais; + priv->macro_params[macro_id].dai_ptr = ops->dai_ptr; + priv->macro_params[macro_id].event_handler = ops->event_handler; + priv->macro_params[macro_id].set_port_map = ops->set_port_map; + priv->macro_params[macro_id].dev = dev; + priv->current_mclk_mux_macro[macro_id] = + lpass_cdc_mclk_mux_tbl[macro_id][MCLK_MUX0]; + if (macro_id == TX_MACRO) { + priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq; + priv->macro_params[macro_id].reg_evt_listener = + ops->reg_evt_listener; + priv->macro_params[macro_id].clk_enable = ops->clk_enable; + } + if (macro_id == TX_MACRO || macro_id == VA_MACRO) + priv->macro_params[macro_id].clk_div_get = ops->clk_div_get; + + if (priv->version == LPASS_CDC_VERSION_2_1) { + if (macro_id == VA_MACRO) + priv->macro_params[macro_id].reg_wake_irq = + ops->reg_wake_irq; + } + priv->num_dais += ops->num_dais; + priv->num_macros_registered++; + priv->macros_supported[macro_id] = true; + + dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id); + + if (priv->num_macros_registered == priv->num_macros) { + ret = lpass_cdc_copy_dais_from_macro(priv); + if (ret < 0) { + dev_err(dev, "%s: copy_dais failed\n", __func__); + return ret; + } + if (priv->macros_supported[TX_MACRO] == false) { + lpass_cdc_mclk_mux_tbl[WSA_MACRO][MCLK_MUX0] = WSA_MACRO; + priv->current_mclk_mux_macro[WSA_MACRO] = WSA_MACRO; + lpass_cdc_mclk_mux_tbl[VA_MACRO][MCLK_MUX0] = VA_MACRO; + priv->current_mclk_mux_macro[VA_MACRO] = VA_MACRO; + } + ret = snd_soc_register_component(dev->parent, &lpass_cdc, + priv->lpass_cdc_dais, priv->num_dais); + if (ret < 0) { + dev_err(dev, "%s: register codec failed\n", __func__); + return ret; + } + } + return 0; +} +EXPORT_SYMBOL(lpass_cdc_register_macro); + +/** + * lpass_cdc_unregister_macro - De-Register macro from lpass_cdc + * + * @dev: macro device ptr. + * @macro_id: ID of macro calling this API. + * + */ +void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: macro:%d not in valid registered macro-list\n", + __func__, macro_id); + return; + } + priv = dev_get_drvdata(dev->parent); + if (!priv || (macro_id >= MAX_MACRO)) { + dev_err(dev, "%s: priv is null or invalid macro\n", __func__); + return; + } + + priv->macro_params[macro_id].init = NULL; + priv->macro_params[macro_id].num_dais = 0; + priv->macro_params[macro_id].dai_ptr = NULL; + priv->macro_params[macro_id].event_handler = NULL; + priv->macro_params[macro_id].dev = NULL; + if (macro_id == TX_MACRO) { + priv->macro_params[macro_id].reg_wake_irq = NULL; + priv->macro_params[macro_id].reg_evt_listener = NULL; + priv->macro_params[macro_id].clk_enable = NULL; + } + if (macro_id == TX_MACRO || macro_id == VA_MACRO) + priv->macro_params[macro_id].clk_div_get = NULL; + + priv->num_dais -= priv->macro_params[macro_id].num_dais; + priv->num_macros_registered--; + + /* UNREGISTER CODEC HERE */ + if (priv->num_macros - 1 == priv->num_macros_registered) + snd_soc_unregister_component(dev->parent); +} +EXPORT_SYMBOL(lpass_cdc_unregister_macro); + +void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: not a valid child dev\n", + __func__); + return; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return; + } + if (adie_lb) + lpass_cdc_notifier_call(priv, + LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB); + else + lpass_cdc_notifier_call(priv, + LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK); +} +EXPORT_SYMBOL(lpass_cdc_wsa_pa_on); + +int lpass_cdc_get_version(struct device *dev) +{ + struct lpass_cdc_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return -EINVAL; + } + if (!lpass_cdc_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device for macro not added yet\n", + __func__); + return -EINVAL; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return -EINVAL; + } + return priv->version; +} +EXPORT_SYMBOL(lpass_cdc_get_version); + +static ssize_t lpass_cdc_version_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + char __user *buf, size_t count, + loff_t pos) +{ + struct lpass_cdc_priv *priv; + char buffer[LPASS_CDC_VERSION_ENTRY_SIZE]; + int len = 0; + + priv = (struct lpass_cdc_priv *) entry->private_data; + if (!priv) { + pr_err("%s: lpass_cdc priv is null\n", __func__); + return -EINVAL; + } + + switch (priv->version) { + case LPASS_CDC_VERSION_1_0: + len = snprintf(buffer, sizeof(buffer), "LPASS_CDC_1_0\n"); + break; + case LPASS_CDC_VERSION_1_1: + len = snprintf(buffer, sizeof(buffer), "LPASS_CDC_1_1\n"); + break; + case LPASS_CDC_VERSION_1_2: + len = snprintf(buffer, sizeof(buffer), "LPASS_CDC_1_2\n"); + break; + case LPASS_CDC_VERSION_2_1: + len = snprintf(buffer, sizeof(buffer), "LPASS_CDC_2_1\n"); + break; + default: + len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n"); + } + + return simple_read_from_buffer(buf, count, &pos, buffer, len); +} + +static int lpass_cdc_ssr_enable(struct device *dev, void *data) +{ + struct lpass_cdc_priv *priv = data; + int macro_idx; + + if (priv->initial_boot) { + priv->initial_boot = false; + return 0; + } + + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_UP); + + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (priv->macro_params[macro_idx].event_handler) + priv->macro_params[macro_idx].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_CLK_RESET, 0x0); + } + trace_printk("%s: clk count reset\n", __func__); + + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP); + + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (!priv->macro_params[macro_idx].event_handler) + continue; + priv->macro_params[macro_idx].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_PRE_SSR_UP, 0x0); + } + + regcache_cache_only(priv->regmap, false); + mutex_lock(&priv->clk_lock); + priv->dev_up = true; + mutex_unlock(&priv->clk_lock); + regcache_mark_dirty(priv->regmap); + lpass_cdc_clk_rsc_enable_all_clocks(priv->clk_dev, true); + regcache_sync(priv->regmap); + /* Add a 100usec sleep to ensure last register write is done */ + usleep_range(100,110); + lpass_cdc_clk_rsc_enable_all_clocks(priv->clk_dev, false); + trace_printk("%s: regcache_sync done\n", __func__); + /* call ssr event for supported macros */ + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (!priv->macro_params[macro_idx].event_handler) + continue; + priv->macro_params[macro_idx].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_SSR_UP, 0x0); + } + trace_printk("%s: SSR up events processed by all macros\n", __func__); + lpass_cdc_notifier_call(priv, LPASS_CDC_WCD_EVT_SSR_UP); + return 0; +} + +static void lpass_cdc_ssr_disable(struct device *dev, void *data) +{ + struct lpass_cdc_priv *priv = data; + int macro_idx; + + if (!priv->dev_up) { + dev_err_ratelimited(priv->dev, + "%s: already disabled\n", __func__); + return; + } + + lpass_cdc_notifier_call(priv, LPASS_CDC_WCD_EVT_PA_OFF_PRE_SSR); + regcache_cache_only(priv->regmap, true); + + mutex_lock(&priv->clk_lock); + priv->dev_up = false; + mutex_unlock(&priv->clk_lock); + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, LPASS_CDC_MACRO_EVT_SSR_DOWN); + /* call ssr event for supported macros */ + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (!priv->macro_params[macro_idx].event_handler) + continue; + priv->macro_params[macro_idx].event_handler( + priv->component, + LPASS_CDC_MACRO_EVT_SSR_DOWN, 0x0); + } + lpass_cdc_notifier_call(priv, LPASS_CDC_WCD_EVT_SSR_DOWN); +} + +static struct snd_info_entry_ops lpass_cdc_info_ops = { + .read = lpass_cdc_version_read, +}; + +static const struct snd_event_ops lpass_cdc_ssr_ops = { + .enable = lpass_cdc_ssr_enable, + .disable = lpass_cdc_ssr_disable, +}; + +/* + * lpass_cdc_info_create_codec_entry - creates lpass_cdc module + * @codec_root: The parent directory + * @component: Codec component instance + * + * Creates lpass_cdc module and version entry under the given + * parent directory. + * + * Return: 0 on success or negative error code on failure. + */ +int lpass_cdc_info_create_codec_entry(struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + struct snd_info_entry *version_entry; + struct lpass_cdc_priv *priv; + struct snd_soc_card *card; + + if (!codec_root || !component) + return -EINVAL; + + priv = snd_soc_component_get_drvdata(component); + if (priv->entry) { + dev_dbg(priv->dev, + "%s:lpass_cdc module already created\n", __func__); + return 0; + } + card = component->card; + priv->entry = snd_info_create_module_entry(codec_root->module, + "lpass_cdc", codec_root); + if (!priv->entry) { + dev_dbg(component->dev, "%s: failed to create lpass_cdc entry\n", + __func__); + return -ENOMEM; + } + priv->entry->mode = S_IFDIR | 0555; + if (snd_info_register(priv->entry) < 0) { + snd_info_free_entry(priv->entry); + return -ENOMEM; + } + + version_entry = snd_info_create_card_entry(card->snd_card, + "version", + priv->entry); + if (!version_entry) { + dev_err(component->dev, "%s: failed to create lpass_cdc version entry\n", + __func__); + snd_info_free_entry(priv->entry); + return -ENOMEM; + } + + version_entry->private_data = priv; + version_entry->size = LPASS_CDC_VERSION_ENTRY_SIZE; + version_entry->content = SNDRV_INFO_CONTENT_DATA; + version_entry->c.ops = &lpass_cdc_info_ops; + + if (snd_info_register(version_entry) < 0) { + snd_info_free_entry(version_entry); + snd_info_free_entry(priv->entry); + return -ENOMEM; + } + priv->version_entry = version_entry; + + return 0; +} +EXPORT_SYMBOL(lpass_cdc_info_create_codec_entry); + +/** + * lpass_cdc_register_wake_irq - Register wake irq of Tx macro + * + * @component: codec component ptr. + * @ipc_wakeup: bool to identify ipc_wakeup to be used or HW interrupt line. + * + * Return: 0 on success or negative error code on failure. + */ +int lpass_cdc_register_wake_irq(struct snd_soc_component *component, + u32 ipc_wakeup) +{ + struct lpass_cdc_priv *priv = NULL; + + if (!component) + return -EINVAL; + + priv = snd_soc_component_get_drvdata(component); + if (!priv) + return -EINVAL; + + if (!lpass_cdc_is_valid_codec_dev(priv->dev)) { + dev_err(component->dev, "%s: invalid codec\n", __func__); + return -EINVAL; + } + + if (priv->version == LPASS_CDC_VERSION_2_1) { + if (priv->macro_params[VA_MACRO].reg_wake_irq) + priv->macro_params[VA_MACRO].reg_wake_irq( + component, ipc_wakeup); + } else { + if (priv->macro_params[TX_MACRO].reg_wake_irq) + priv->macro_params[TX_MACRO].reg_wake_irq( + component, ipc_wakeup); + } + + return 0; +} +EXPORT_SYMBOL(lpass_cdc_register_wake_irq); + +/** + * lpass_cdc_tx_mclk_enable - Enable/Disable TX Macro mclk + * + * @component: pointer to codec component instance. + * @enable: set true to enable, otherwise false. + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_tx_mclk_enable(struct snd_soc_component *component, + bool enable) +{ + struct lpass_cdc_priv *priv = NULL; + int ret = 0; + + if (!component) + return -EINVAL; + + priv = snd_soc_component_get_drvdata(component); + if (!priv) + return -EINVAL; + + if (!lpass_cdc_is_valid_codec_dev(priv->dev)) { + dev_err(component->dev, "%s: invalid codec\n", __func__); + return -EINVAL; + } + + if (priv->macro_params[TX_MACRO].clk_enable) + ret = priv->macro_params[TX_MACRO].clk_enable(component, + enable); + + return ret; +} +EXPORT_SYMBOL(lpass_cdc_tx_mclk_enable); + +/** + * lpass_cdc_register_event_listener - Register/Deregister to event listener + * + * @component: pointer to codec component instance. + * @enable: when set to 1 registers to event listener otherwise, derigisters + * from the event listener + * + * Returns 0 on success or -EINVAL on error. + */ +int lpass_cdc_register_event_listener(struct snd_soc_component *component, + bool enable) +{ + struct lpass_cdc_priv *priv = NULL; + int ret = 0; + + if (!component) + return -EINVAL; + + priv = snd_soc_component_get_drvdata(component); + if (!priv) + return -EINVAL; + + if (!lpass_cdc_is_valid_codec_dev(priv->dev)) { + dev_err(component->dev, "%s: invalid codec\n", __func__); + return -EINVAL; + } + + if (priv->macro_params[TX_MACRO].reg_evt_listener) + ret = priv->macro_params[TX_MACRO].reg_evt_listener(component, + enable); + + return ret; +} +EXPORT_SYMBOL(lpass_cdc_register_event_listener); + +static int lpass_cdc_soc_codec_probe(struct snd_soc_component *component) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(component->dev); + int macro_idx, ret = 0; + u8 core_id_0 = 0, core_id_1 = 0; + + snd_soc_component_init_regmap(component, priv->regmap); + + if (!priv->version) { + /* + * In order for the ADIE RTC to differentiate between targets + * version info is used. + * Assign 1.0 for target with only one macro + * Assign 1.1 for target with two macros + * Assign 1.2 for target with more than two macros + */ + if (priv->num_macros_registered == 1) + priv->version = LPASS_CDC_VERSION_1_0; + else if (priv->num_macros_registered == 2) + priv->version = LPASS_CDC_VERSION_1_1; + else if (priv->num_macros_registered > 2) + priv->version = LPASS_CDC_VERSION_1_2; + } + + /* Assign lpass_cdc version */ + core_id_0 = snd_soc_component_read32(component, + LPASS_CDC_VA_TOP_CSR_CORE_ID_0); + core_id_1 = snd_soc_component_read32(component, + LPASS_CDC_VA_TOP_CSR_CORE_ID_1); + if ((core_id_0 == 0x01) && (core_id_1 == 0x0F)) + priv->version = LPASS_CDC_VERSION_2_0; + if ((core_id_0 == 0x02) && (core_id_1 == 0x0E)) + priv->version = LPASS_CDC_VERSION_2_1; + + /* call init for supported macros */ + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (priv->macro_params[macro_idx].init) { + ret = priv->macro_params[macro_idx].init(component); + if (ret < 0) { + dev_err(component->dev, + "%s: init for macro %d failed\n", + __func__, macro_idx); + goto err; + } + } + } + priv->component = component; + + ret = snd_event_client_register(priv->dev, &lpass_cdc_ssr_ops, priv); + if (!ret) { + snd_event_notify(priv->dev, SND_EVENT_UP); + } else { + dev_err(component->dev, + "%s: Registration with SND event FWK failed ret = %d\n", + __func__, ret); + goto err; + } + + dev_dbg(component->dev, "%s: lpass_cdc soc codec probe success\n", + __func__); +err: + return ret; +} + +static void lpass_cdc_soc_codec_remove(struct snd_soc_component *component) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(component->dev); + int macro_idx; + + snd_event_client_deregister(priv->dev); + /* call exit for supported macros */ + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) + if (priv->macro_params[macro_idx].exit) + priv->macro_params[macro_idx].exit(component); + + return; +} + +static const struct snd_soc_component_driver lpass_cdc = { + .name = DRV_NAME, + .probe = lpass_cdc_soc_codec_probe, + .remove = lpass_cdc_soc_codec_remove, +}; + +static void lpass_cdc_add_child_devices(struct work_struct *work) +{ + struct lpass_cdc_priv *priv; + bool split_codec = false; + struct platform_device *pdev; + struct device_node *node; + int ret = 0, count = 0; + struct wcd_ctrl_platform_data *platdata = NULL; + char plat_dev_name[LPASS_CDC_STRING_LEN] = ""; + + priv = container_of(work, struct lpass_cdc_priv, + lpass_cdc_add_child_devices_work); + if (!priv) { + pr_err("%s: Memory for lpass_cdc priv does not exist\n", + __func__); + return; + } + if (!priv->dev || !priv->dev->of_node) { + dev_err(priv->dev, "%s: DT node for lpass_cdc does not exist\n", + __func__); + return; + } + + platdata = &priv->plat_data; + priv->child_count = 0; + + for_each_available_child_of_node(priv->dev->of_node, node) { + split_codec = false; + if (of_find_property(node, "qcom,split-codec", NULL)) { + split_codec = true; + dev_dbg(priv->dev, "%s: split codec slave exists\n", + __func__); + } + + strlcpy(plat_dev_name, node->name, + (LPASS_CDC_STRING_LEN - 1)); + + pdev = platform_device_alloc(plat_dev_name, -1); + if (!pdev) { + dev_err(priv->dev, "%s: pdev memory alloc failed\n", + __func__); + ret = -ENOMEM; + goto err; + } + pdev->dev.parent = priv->dev; + pdev->dev.of_node = node; + + priv->dev->platform_data = platdata; + if (split_codec) + priv->wcd_dev = &pdev->dev; + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, + "%s: Cannot add platform device\n", + __func__); + platform_device_put(pdev); + goto fail_pdev_add; + } + + if (priv->child_count < LPASS_CDC_CHILD_DEVICES_MAX) + priv->pdev_child_devices[priv->child_count++] = pdev; + else + goto err; + } + return; +fail_pdev_add: + for (count = 0; count < priv->child_count; count++) + platform_device_put(priv->pdev_child_devices[count]); +err: + return; +} + +static int lpass_cdc_probe(struct platform_device *pdev) +{ + struct lpass_cdc_priv *priv; + u32 num_macros = 0; + int ret; + struct clk *lpass_core_hw_vote = NULL; + struct clk *lpass_audio_hw_vote = NULL; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-macros", + &num_macros); + if (ret) { + dev_err(&pdev->dev, + "%s:num-macros property not found\n", + __func__); + return ret; + } + priv->num_macros = num_macros; + if (priv->num_macros > MAX_MACRO) { + dev_err(&pdev->dev, + "%s:num_macros(%d) > MAX_MACRO(%d) than supported\n", + __func__, priv->num_macros, MAX_MACRO); + return -EINVAL; + } + priv->va_without_decimation = of_property_read_bool(pdev->dev.of_node, + "qcom,va-without-decimation"); + if (priv->va_without_decimation) + lpass_cdc_reg_access[VA_MACRO] = lpass_cdc_va_top_reg_access; + + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,lpass-cdc-version", &priv->version); + if (ret) { + dev_dbg(&pdev->dev, "%s:lpass_cdc version not specified\n", + __func__); + ret = 0; + } + if (priv->version == LPASS_CDC_VERSION_2_1) { + lpass_cdc_reg_access[TX_MACRO] = lpass_cdc_tx_reg_access_v2; + lpass_cdc_reg_access[VA_MACRO] = lpass_cdc_va_reg_access_v2; + } else if (priv->version == LPASS_CDC_VERSION_2_0) { + lpass_cdc_reg_access[VA_MACRO] = lpass_cdc_va_reg_access_v3; + } + + priv->dev = &pdev->dev; + priv->dev_up = true; + priv->initial_boot = true; + priv->regmap = lpass_cdc_regmap_init(priv->dev, + &lpass_cdc_regmap_config); + if (IS_ERR_OR_NULL((void *)(priv->regmap))) { + dev_err(&pdev->dev, "%s:regmap init failed\n", __func__); + return -EINVAL; + } + priv->read_dev = __lpass_cdc_reg_read; + priv->write_dev = __lpass_cdc_reg_write; + + priv->plat_data.handle = (void *) priv; + priv->plat_data.update_wcd_event = lpass_cdc_update_wcd_event; + priv->plat_data.register_notifier = lpass_cdc_register_notifier; + + priv->core_hw_vote_count = 0; + priv->core_audio_vote_count = 0; + + dev_set_drvdata(&pdev->dev, priv); + mutex_init(&priv->io_lock); + mutex_init(&priv->clk_lock); + mutex_init(&priv->vote_lock); + INIT_WORK(&priv->lpass_cdc_add_child_devices_work, + lpass_cdc_add_child_devices); + schedule_work(&priv->lpass_cdc_add_child_devices_work); + + /* Register LPASS core hw vote */ + lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote"); + if (IS_ERR(lpass_core_hw_vote)) { + ret = PTR_ERR(lpass_core_hw_vote); + dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n", + __func__, "lpass_core_hw_vote", ret); + lpass_core_hw_vote = NULL; + ret = 0; + } + priv->lpass_core_hw_vote = lpass_core_hw_vote; + + /* Register LPASS audio hw vote */ + lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote"); + if (IS_ERR(lpass_audio_hw_vote)) { + ret = PTR_ERR(lpass_audio_hw_vote); + dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n", + __func__, "lpass_audio_hw_vote", ret); + lpass_audio_hw_vote = NULL; + ret = 0; + } + priv->lpass_audio_hw_vote = lpass_audio_hw_vote; + + return 0; +} + +static int lpass_cdc_remove(struct platform_device *pdev) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(&pdev->dev); + + if (!priv) + return -EINVAL; + + of_platform_depopulate(&pdev->dev); + mutex_destroy(&priv->io_lock); + mutex_destroy(&priv->clk_lock); + mutex_destroy(&priv->vote_lock); + return 0; +} + +#ifdef CONFIG_PM +int lpass_cdc_runtime_resume(struct device *dev) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent); + int ret = 0; + + mutex_lock(&priv->vote_lock); + if (priv->lpass_core_hw_vote == NULL) { + dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__); + goto audio_vote; + } + + if (priv->core_hw_vote_count == 0) { + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote); + if (ret < 0) { + dev_err(dev, "%s:lpass core hw enable failed\n", + __func__); + goto audio_vote; + } + } + priv->core_hw_vote_count++; + trace_printk("%s: hw vote count %d\n", + __func__, priv->core_hw_vote_count); + +audio_vote: + if (priv->lpass_audio_hw_vote == NULL) { + dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__); + goto done; + } + + if (priv->core_audio_vote_count == 0) { + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote); + if (ret < 0) { + dev_err(dev, "%s:lpass audio hw enable failed\n", + __func__); + goto done; + } + } + priv->core_audio_vote_count++; + trace_printk("%s: audio vote count %d\n", + __func__, priv->core_audio_vote_count); + +done: + mutex_unlock(&priv->vote_lock); + pm_runtime_set_autosuspend_delay(priv->dev, LPASS_CDC_AUTO_SUSPEND_DELAY); + return 0; +} +EXPORT_SYMBOL(lpass_cdc_runtime_resume); + +int lpass_cdc_runtime_suspend(struct device *dev) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent); + + mutex_lock(&priv->vote_lock); + if (priv->lpass_core_hw_vote != NULL) { + if (--priv->core_hw_vote_count == 0) + digital_cdc_rsc_mgr_hw_vote_disable( + priv->lpass_core_hw_vote); + if (priv->core_hw_vote_count < 0) + priv->core_hw_vote_count = 0; + } else { + dev_dbg(dev, "%s: Invalid lpass core hw node\n", + __func__); + } + trace_printk("%s: hw vote count %d\n", + __func__, priv->core_hw_vote_count); + + if (priv->lpass_audio_hw_vote != NULL) { + if (--priv->core_audio_vote_count == 0) + digital_cdc_rsc_mgr_hw_vote_disable( + priv->lpass_audio_hw_vote); + if (priv->core_audio_vote_count < 0) + priv->core_audio_vote_count = 0; + } else { + dev_dbg(dev, "%s: Invalid lpass audio hw node\n", + __func__); + } + trace_printk("%s: audio vote count %d\n", + __func__, priv->core_audio_vote_count); + + mutex_unlock(&priv->vote_lock); + return 0; +} +EXPORT_SYMBOL(lpass_cdc_runtime_suspend); +#endif /* CONFIG_PM */ + +bool lpass_cdc_check_core_votes(struct device *dev) +{ + struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent); + bool ret = true; + + mutex_lock(&priv->vote_lock); + if ((priv->lpass_core_hw_vote && !priv->core_hw_vote_count) || + (priv->lpass_audio_hw_vote && !priv->core_audio_vote_count)) + ret = false; + mutex_unlock(&priv->vote_lock); + + return ret; +} +EXPORT_SYMBOL(lpass_cdc_check_core_votes); + +static const struct of_device_id lpass_cdc_dt_match[] = { + {.compatible = "qcom,lpass-cdc"}, + {} +}; +MODULE_DEVICE_TABLE(of, lpass_cdc_dt_match); + +static struct platform_driver lpass_cdc_drv = { + .driver = { + .name = "lpass-cdc", + .owner = THIS_MODULE, + .of_match_table = lpass_cdc_dt_match, + .suppress_bind_attrs = true, + }, + .probe = lpass_cdc_probe, + .remove = lpass_cdc_remove, +}; + +static int lpass_cdc_drv_init(void) +{ + return platform_driver_register(&lpass_cdc_drv); +} + +static void lpass_cdc_drv_exit(void) +{ + platform_driver_unregister(&lpass_cdc_drv); +} + +static int __init lpass_cdc_init(void) +{ + lpass_cdc_drv_init(); + lpass_cdc_clk_rsc_mgr_init(); + return 0; +} +module_init(lpass_cdc_init); + +static void __exit lpass_cdc_exit(void) +{ + lpass_cdc_clk_rsc_mgr_exit(); + lpass_cdc_drv_exit(); +} +module_exit(lpass_cdc_exit); + +MODULE_DESCRIPTION("LPASS Codec driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/lpass-cdc/lpass-cdc.h b/asoc/codecs/lpass-cdc/lpass-cdc.h new file mode 100644 index 0000000000..c57b9d52c9 --- /dev/null +++ b/asoc/codecs/lpass-cdc/lpass-cdc.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef LPASS_CDC_H +#define LPASS_CDC_H + +#include +#include + +#define LPASS_CDC_VERSION_1_0 0x0001 +#define LPASS_CDC_VERSION_1_1 0x0002 +#define LPASS_CDC_VERSION_1_2 0x0003 +#define LPASS_CDC_VERSION_2_0 0x0004 +#define LPASS_CDC_VERSION_2_1 0x0005 + +enum { + START_MACRO, + TX_MACRO = START_MACRO, + RX_MACRO, + WSA_MACRO, + VA_MACRO, + MAX_MACRO +}; + +enum mclk_mux { + MCLK_MUX0, + MCLK_MUX1, + MCLK_MUX_MAX +}; + +enum { + LPASS_CDC_ADC0 = 1, + LPASS_CDC_ADC1, + LPASS_CDC_ADC2, + LPASS_CDC_ADC3, + LPASS_CDC_ADC_MAX +}; + +enum { + LPASS_CDC_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */ + LPASS_CDC_MACRO_EVT_IMPED_TRUE, /* for imped true */ + LPASS_CDC_MACRO_EVT_IMPED_FALSE, /* for imped false */ + LPASS_CDC_MACRO_EVT_SSR_DOWN, + LPASS_CDC_MACRO_EVT_SSR_UP, + LPASS_CDC_MACRO_EVT_WAIT_VA_CLK_RESET, + LPASS_CDC_MACRO_EVT_CLK_RESET, + LPASS_CDC_MACRO_EVT_REG_WAKE_IRQ, + LPASS_CDC_MACRO_EVT_RX_COMPANDER_SOFT_RST, + LPASS_CDC_MACRO_EVT_BCS_CLK_OFF, + LPASS_CDC_MACRO_EVT_SSR_GFMUX_UP, + LPASS_CDC_MACRO_EVT_PRE_SSR_UP, + LPASS_CDC_MACRO_EVT_RX_PA_GAIN_UPDATE, + LPASS_CDC_MACRO_EVT_HPHL_HD2_ENABLE, /* Enable HD2 cfg for HPHL */ + LPASS_CDC_MACRO_EVT_HPHR_HD2_ENABLE, /* Enable HD2 cfg for HPHR */ +}; + +enum { + DMIC_TX = 0, + DMIC_VA = 1, + +}; + +struct macro_ops { + int (*init)(struct snd_soc_component *component); + int (*exit)(struct snd_soc_component *component); + u16 num_dais; + struct device *dev; + struct snd_soc_dai_driver *dai_ptr; + int (*mclk_fn)(struct device *dev, bool enable); + int (*event_handler)(struct snd_soc_component *component, u16 event, + u32 data); + int (*reg_wake_irq)(struct snd_soc_component *component, u32 data); + int (*set_port_map)(struct snd_soc_component *component, u32 uc, + u32 size, void *data); + int (*clk_div_get)(struct snd_soc_component *component); + int (*reg_evt_listener)(struct snd_soc_component *component, bool en); + int (*clk_enable)(struct snd_soc_component *c, bool en); + char __iomem *io_base; + u16 clk_id_req; + u16 default_clk_id; +}; + +typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event); + +#if IS_ENABLED(CONFIG_SND_SOC_LPASS_CDC) +int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t cb); +void lpass_cdc_unregister_res_clk(struct device *dev); +bool lpass_cdc_is_va_macro_registered(struct device *dev); +int lpass_cdc_register_macro(struct device *dev, u16 macro_id, + struct macro_ops *ops); +void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id); +struct device *lpass_cdc_get_device_ptr(struct device *dev, u16 macro_id); +struct device *lpass_cdc_get_rsc_clk_device_ptr(struct device *dev); +int lpass_cdc_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component); +int lpass_cdc_register_wake_irq(struct snd_soc_component *component, u32 data); +void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n); +int lpass_cdc_runtime_resume(struct device *dev); +int lpass_cdc_runtime_suspend(struct device *dev); +int lpass_cdc_set_port_map(struct snd_soc_component *component, u32 size, void *data); +int lpass_cdc_register_event_listener(struct snd_soc_component *component, + bool enable); +void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb); +bool lpass_cdc_check_core_votes(struct device *dev); +int lpass_cdc_tx_mclk_enable(struct snd_soc_component *c, bool enable); +int lpass_cdc_get_version(struct device *dev); +int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component, + u32 dmic, u32 tx_mode, bool enable); +#else +static inline int lpass_cdc_register_res_clk(struct device *dev, rsc_clk_cb_t cb) +{ + return 0; +} +static inline void lpass_cdc_unregister_res_clk(struct device *dev) +{ +} + +static bool lpass_cdc_is_va_macro_registered(struct device *dev) +{ + return false; +} + +static inline int lpass_cdc_register_macro(struct device *dev, + u16 macro_id, + struct macro_ops *ops) +{ + return 0; +} + +static inline void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id) +{ +} + +static inline struct device *lpass_cdc_get_device_ptr(struct device *dev, + u16 macro_id) +{ + return NULL; +} + +static int lpass_cdc_info_create_codec_entry( + struct snd_info_entry *codec_root, + struct snd_soc_component *component) +{ + return 0; +} + +static inline void lpass_cdc_clear_amic_tx_hold(struct device *dev, u16 adc_n) +{ +} + +static inline int lpass_cdc_register_wake_irq(struct snd_soc_component *component, + u32 data) +{ + return 0; +} + +static inline int lpass_cdc_runtime_resume(struct device *dev) +{ + return 0; +} + +static int lpass_cdc_runtime_suspend(struct device *dev) +{ + return 0; +} + +static inline int lpass_cdc_set_port_map(struct snd_soc_component *component, + u32 size, void *data) +{ + return 0; +} + +static inline int lpass_cdc_register_event_listener( + struct snd_soc_component *component, + bool enable) +{ + return 0; +} + +static void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb) +{ +} + +static inline bool lpass_cdc_check_core_votes(struct device *dev) +{ + return false; +} + +static int lpass_cdc_get_version(struct device *dev) +{ + return 0; +} + +static int lpass_cdc_dmic_clk_enable(struct snd_soc_component *component, + u32 dmic, u32 tx_mode, bool enable) +{ + return 0; +} +static int lpass_cdc_tx_mclk_enable(struct snd_soc_component *c, bool enable) +{ + return 0; +} +#endif /* CONFIG_SND_SOC_LPASS_CDC */ +#endif /* LPASS_CDC_H */