diff options
author | Lucas Wei <lucaswei@google.com> | 2021-07-26 21:22:01 +0800 |
---|---|---|
committer | Lucas Wei <lucaswei@google.com> | 2021-07-26 21:22:01 +0800 |
commit | b91d7d909e4e0724235ae5a549aabc59ced1c263 (patch) | |
tree | 06a1db673415392eb52dc0d3a44ad57b033b493f | |
parent | 7c6cfed3e7ea8bb6371872aa8700d8d1f01456f4 (diff) | |
parent | 45edbf733479053bb97caf86cbf982df96173351 (diff) | |
download | msm-extra-b91d7d909e4e0724235ae5a549aabc59ced1c263.tar.gz |
Merge 'android-msm-barbet-4.19' into android-msm-pixel-4.19
Bug: 194667419
Signed-off-by: Lucas Wei <lucaswei@google.com>
Change-Id: I6ce5a4180292b85b304d1efe6440e4f52c37e93f
36 files changed, 13670 insertions, 2 deletions
diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index 6dc44429..91149d22 100644 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -233,6 +233,7 @@ ifeq ($(KERNEL_BUILD), 1) obj-y += bolero/ obj-y += rouleur/ obj-y += wsa883x/ + obj-y += tas256x/ obj-y += sdm660_cdc/ endif # Module information used by KBuild framework diff --git a/asoc/codecs/tas256x/Kbuild b/asoc/codecs/tas256x/Kbuild new file mode 100644 index 00000000..fb320607 --- /dev/null +++ b/asoc/codecs/tas256x/Kbuild @@ -0,0 +1,144 @@ +# We can build either as part of a standalone Kernel build or as +# an external module. Determine which mechanism is being used +ifeq ($(MODNAME),) + KERNEL_BUILD := 1 +else + KERNEL_BUILD := 0 +endif + +ifeq ($(KERNEL_BUILD), 1) + # These are configurable via Kconfig for kernel-based builds + # Need to explicitly configure for Android-based builds + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-4.19 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio +endif + +ifeq ($(KERNEL_BUILD), 0) + ifeq ($(CONFIG_ARCH_KONA), y) + include $(AUDIO_ROOT)/config/konaauto.conf + 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 + +endif + +# As per target team, build is done as follows: +# Defconfig : build with default flags +# Slub : defconfig + CONFIG_SLUB_DEBUG := y + +# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y +# Perf : Using appropriate msmXXXX-perf_defconfig +# +# Shipment builds (user variants) should not have any debug feature +# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds +# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since +# there is no other way to identify defconfig builds, QTI internal +# representation of perf builds (identified using the string 'perf'), +# is used to identify if the build is a slub or defconfig one. This +# way no critical debug feature will be enabled for perf and shipment +# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT +# config. + +############ UAPI ############ +UAPI_DIR := uapi +UAPI_INC := -I$(AUDIO_ROOT)/include/$(UAPI_DIR) + +############ COMMON ############ +COMMON_DIR := include +COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR) + +############ TAS256X ############ + +ifdef CONFIG_SND_SOC_TAS256X + TAS256X_OBJS += os_layer/src/tas256x-codec.o + TAS256X_OBJS += os_layer/src/tas256x-regmap.o + TAS256X_OBJS += physical_layer/src/tas256x.o + TAS256X_OBJS += logical_layer/src/tas256x-logic.o +endif + +ifdef CONFIG_TAS25XX_ALGO + TAS256X_OBJS += algo/src/tas25xx-algo-intf.o + TAS256X_OBJS += algo/src/tas25xx-algo-common.o + TAS256X_OBJS += algo/src/tas25xx-calib.o +endif + +ifdef CONFIG_PLATFORM_QCOM + TAS256X_OBJS += algo/platform/qcom/tas25xx-algo-qdsp-intf.o +endif + +ifdef CONFIG_TAS25XX_CALIB_VAL_BIG + TAS256X_OBJS += algo/src/tas25xx-calib-validation.o +endif + +ifdef CONFIG_TAS256X_MISC + TAS256X_OBJS += misc/tas256x-misc.o +endif + +ifdef CONFIG_TISA_DEBUGFS_INTF + TAS256X_OBJS += algo/src/tas25xx-algo-debugfs.o + TAS256X_OBJS += logical_layer/smartpa-debug-common.o +endif + +ifdef CONFIG_TISA_BIN_INTF + TAS256X_OBJS += algo/src/tas25xx-algo-bin-intf.o +endif + +ifdef CONFIG_PLATFORM_MTK + TAS256X_OBJS += algo/src/tas256x-mtk-wrapper.o +endif + +ifdef CONFIG_TISA_KBIN_INTF + TAS256X_OBJS += algo/src/tas25xx-algo-kbin-intf.o + TAS256X_OBJS += algo/src/tas25xx-algo-bin-utils.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_TAS256X) += tas256x_dlkm.o +tas256x_dlkm-y := $(TAS256X_OBJS) + +# inject some build related information +DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/asoc/codecs/tas256x/Makefile b/asoc/codecs/tas256x/Makefile new file mode 100644 index 00000000..ed75ee05 --- /dev/null +++ b/asoc/codecs/tas256x/Makefile @@ -0,0 +1,23 @@ +EXTRA_CFLAGS= -I$(shell pwd) +obj-y += snd-soc-tas256x.o + +snd-soc-tas256x-y := os_layer/src/tas256x-codec.o \ + os_layer/src/tas256x-regmap.o \ + physical_layer/src/tas256x.o \ + logical_layer/src/tas256x-logic.o + +snd-soc-tas256x-$(CONFIG_TAS256X_MISC) += misc/tas256x-misc.o +snd-soc-tas256x-$(CONFIG_TAS25XX_ALGO) += algo/src/tas25xx-algo-intf.o \ + algo/src/tas25xx-calib.o \ + algo/src/tas25xx-algo-common.o + +snd-soc-tas256x-$(CONFIG_PLATFORM_QCOM) += algo/platform/qcom/tas25xx-algo-qdsp-intf.o +snd-soc-tas256x-$(CONFIG_TISA_KBIN_INTF) += algo/src/tas25xx-algo-kbin-intf.o \ + algo/src/tas25xx-algo-bin-utils.o + + +snd-soc-tas256x-$(CONFIG_TAS25XX_CALIB_VAL_BIG) += algo/src/tas25xx-calib-validation.o +snd-soc-tas256x-$(CONFIG_TISA_DEBUGFS_INTF) += algo/src/tas25xx-algo-debugfs.o \ + logical_layer/src/smartpa-debug-common.o +snd-soc-tas256x-$(CONFIG_TISA_BIN_INTF) += algo/src/tas25xx-algo-bin-intf.o +snd-soc-tas256x-$(CONFIG_PLATFORM_MTK) += algo/platform/mtk/tas256x-mtk-wrapper.o11 diff --git a/asoc/codecs/tas256x/algo/inc/tas25xx-calib.h b/asoc/codecs/tas256x/algo/inc/tas25xx-calib.h new file mode 100644 index 00000000..1a264a3a --- /dev/null +++ b/asoc/codecs/tas256x/algo/inc/tas25xx-calib.h @@ -0,0 +1,29 @@ +/* + ** =========================================================================== + ** Copyright (c) 2016 Texas Instruments Inc. + ** + ** This program is free software; you can redistribute it and/or modify it + ** under the terms of the GNU General Public License as published by the Free + ** Software Foundation; version 2. + ** + ** This program is distributed in the hope that it will be useful, but + ** WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + ** or FITNESSFOR A PARTICULAR PURPOSE. See the GNU General Public License + ** for more details. + ** + ** File: + ** tas25xx-calib.h + ** + ** Description: + ** header file for tas25xx-calib.c + ** + ** =========================================================================== + */ + +#ifndef _TAS25XX_CALIB_H_ +#define _TAS25XX_CALIB_H_ + +int tas_calib_init(void); +void tas_calib_exit(void); + +#endif /* _TAS25XX_CALIB_H */ diff --git a/asoc/codecs/tas256x/algo/inc/tas_smart_amp_v2.h b/asoc/codecs/tas256x/algo/inc/tas_smart_amp_v2.h new file mode 100644 index 00000000..b85f1c1b --- /dev/null +++ b/asoc/codecs/tas256x/algo/inc/tas_smart_amp_v2.h @@ -0,0 +1,157 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-algo-bin-utils.c +** +** Description: +** Common algo related header. +** +** ============================================================================= +*/ +#ifndef __TAS_SMART_AMP__ +#define __TAS_SMART_AMP__ + +#include <linux/types.h> +#include <sound/soc.h> +#include <linux/version.h> +#include <linux/delay.h> +#include <linux/device.h> + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +struct snd_soc_component; +#else +struct snd_soc_codec; +#endif + +typedef enum { + TISA_MOD_RX = 0, + TISA_MOD_TX = 1, + TISA_MOD_END = 2 +} module_id_t; + +#define CAPI_V2_TAS_TX_ENABLE 0x10012D14 +#define CAPI_V2_TAS_TX_CFG 0x10012D16 +#define CAPI_V2_TAS_RX_ENABLE 0x10012D13 +#define CAPI_V2_TAS_RX_CFG 0x10012D15 + +#define TI_SMARTPA_VENDOR_ID 1234 + +/* FIXME */ +/* update this value at OEM/ODM */ +/* #pragma message("########### FIXME ################") */ +/* #define SMARTAMP_SPEAKER_CALIBDATA_FILE "/mnt/vendor/persist/audio/tas25xx_calib.bin" */ +#define SMARTAMP_SPEAKER_CALIBDATA_FILE "/persist/audio/smartamp_calib.bin" + +#define MAX_DSP_PARAM_INDEX 2048 +#define MAX_CHANNELS 2 + +#define TAS_SET_PARAM 0 +#define TAS_GET_PARAM 1 + +#define CHANNEL0 1 +#define CHANNEL1 2 + +#define TRUE 1 +#define FALSE 0 + +#define TAS_DSP_SWAP_IDX 3 + +#define TAS_SA_GET_F0 3810 +#define TAS_SA_GET_Q 3811 +#define TAS_SA_GET_TV 3812 +#define TAS_SA_GET_RE 3813 +#define TAS_SA_CALIB_INIT 3814 +#define TAS_SA_CALIB_DEINIT 3815 +#define TAS_SA_SET_RE 3816 +#define TAS_SA_F0_TEST_INIT 3817 +#define TAS_SA_F0_TEST_DEINIT 3818 +#define TAS_SA_SET_PROFILE 3819 +#define TAS_SA_GET_STATUS 3821 +#define TAS_SA_SET_SPKID 3822 +#define TAS_SA_SET_TCAL 3823 +#define TAS_SA_EXC_TEMP_STAT 3824 + +#define TAS_SA_IV_VBAT_FMT 3825 + +#define TAS_SA_VALID_INIT 3831 +#define TAS_SA_VALID_DEINIT 3832 +#define TAS_SA_GET_VALID_STATUS 3833 +#define TAS_SA_SET_BYPASS_MODE 3834 +#define TAS_SA_GET_OP_MODE 3835 +#define TAS_SA_SET_INTERFACE_MODE 3836 +#define TAS_PCM_CHANNEL_MAPPING 3837 +#define TAS_SA_GET_RE_RANGE 3838 + +/*Added for DC Detection*/ +#define CAPI_V2_TAS_SA_DC_DETECT 0x40404040 + +#define CALIB_START 1 +#define CALIB_STOP 2 +#define TEST_START 3 +#define TEST_STOP 4 + +#define SLAVE1 0x98 +#define SLAVE2 0x9A +#define SLAVE3 0x9C +#define SLAVE4 0x9E + +#define TAS_SA_IS_SPL_IDX(X) ((((X) >= 3810) && ((X) < 3899)) ? 1 : 0) +#define TAS_CALC_PARAM_IDX(I, LEN, CH) ((I) | ((LEN) << 16) | ((CH) << 28)) +#define AFE_SA_IS_SPL_IDX(X) TAS_SA_IS_SPL_IDX(X) + + +typedef enum { + IV_SENSE_FORMAT_NO_VBAT = 0, + IV_SENSE_FORMAT_12_BIT_WITH_8BIT_VBAT = 1, + IV_SENSE_FORMAT_8_BIT_WITH_8BIT_VBAT = 2, + IV_SENSE_FORMAT_16_BIT_WITH_8BIT_VBAT = 3, +} ti_smartamp_iv_vbat_format_t; + +/* + * List all the other profiles other than none and calibration. + */ +#define TAS_ALGO_PROFILE_LIST "MUSIC", "VOICE", "VOIP", "RINGTONE" + +void tas25xx_parse_algo_dt(struct device_node *np); +typedef int (*dsp_set_get_f)(u8 *user_data, uint32_t param_id, + uint8_t get_set, uint32_t length, module_id_t module_id); + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +void tas_smartamp_add_algo_controls(struct snd_soc_component *codec, + struct device *dev, int number_of_channels); +void tas_smartamp_remove_algo_controls(struct snd_soc_component *codec); +void tas_smartamp_add_codec_mixer_controls(struct snd_soc_component *codec); +#else +void tas_smartamp_add_algo_controls(struct snd_soc_codec *codec, + struct device *dev, int number_of_channels); +void tas_smartamp_remove_algo_controls(struct snd_soc_codec *codec); +void tas_smartamp_add_codec_mixer_controls(struct snd_soc_codec *codec); +#endif +bool tas25xx_set_iv_bit_fomat(int iv_data_with, int vbat, int update_now); + +int get_iv_vbat_format(void); + +void tas25xx_send_channel_mapping(void); + +#if IS_ENABLED(CONFIG_TISA_KBIN_INTF) +void tas25xx_algo_set_active (void); +void tas25xx_algo_set_inactive (void); +void tas_smartamp_kbin_deinitalize (void); +#endif /* CONFIG_TISA_KBIN_INTF */ + +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) +void tas25xx_send_algo_calibration(void); +void tas25xx_update_big_data(void); +#endif + +#endif /*__TAS_SMART_AMP__*/ diff --git a/asoc/codecs/tas256x/algo/platform/qcom/tas25xx-algo-qdsp-intf.c b/asoc/codecs/tas256x/algo/platform/qcom/tas25xx-algo-qdsp-intf.c new file mode 100644 index 00000000..37388cb7 --- /dev/null +++ b/asoc/codecs/tas256x/algo/platform/qcom/tas25xx-algo-qdsp-intf.c @@ -0,0 +1,114 @@ +/* +** ============================================================================= +** Copyright (c) 2017 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details +** +** File: +** tas25xx-algo-qdsp-intf.c +** +** Description: +** Qcom interface wrapper. +** +** ============================================================================= +*/ +#include <linux/types.h> +#include <linux/of.h> +#include <dsp/tas_qualcomm.h> +#include "../../inc/tas_smart_amp_v2.h" + +#define AFE_SMARTAMP_MODULE_RX 0x11111112 +#define AFE_SMARTAMP_MODULE_TX 0x11111111 +#define AFE_SMARTAMP_DFAULT_PORT 0x9000 + +static uint16_t g_afe_port_id_rx = 0xFFFF; +static int g_afe_initalized; +static uint32_t s_tisa_module_id[] = { + AFE_SMARTAMP_MODULE_RX, + AFE_SMARTAMP_MODULE_TX +}; + +static void set_port_id_rx(uint16_t port_id) +{ + g_afe_port_id_rx = port_id; +} + +static inline uint16_t get_rx_port_id(void) +{ + return g_afe_port_id_rx; +} + +static void tas25xx_afe_init(void) +{ + if (g_afe_initalized) + return; + + afe_tas_smartamp_init(s_tisa_module_id[0], s_tisa_module_id[1]); + g_afe_initalized = 1; +} + +void tas25xx_parse_algo_dt_qdsp_intf(struct device_node *np) +{ + uint32_t port_id = 0; + uint32_t module_id = 0; + int32_t ret = 0; + + ret = of_property_read_u32(np, "ti,port_id", &port_id); + if (!ret) { + set_port_id_rx ((uint16_t)port_id); + pr_info("[TI-SmartPA:%s] ti,port_id=0x%x", __func__, port_id); + } + + ret = of_property_read_u32(np, "ti,module_id_rx", &module_id); + if (!ret) { + pr_info("[TI-SmartPA:%s] ti,module_id_rx=0x%x", __func__, module_id); + s_tisa_module_id[TISA_MOD_RX] = module_id; + } + + ret = of_property_read_u32(np, "ti,module_id_tx", &module_id); + if (!ret) { + pr_info("[TI-SmartPA:%s] ti,module_id_tx=0x%x", __func__, module_id); + s_tisa_module_id[TISA_MOD_TX] = module_id; + } + + return; +} +EXPORT_SYMBOL(tas25xx_parse_algo_dt_qdsp_intf); + +int tas25xx_smartamp_get_set(u8 *user_data, uint32_t param_id, + uint8_t get_set, uint32_t length, module_id_t mod_id_i) +{ + int ret = 0; + uint32_t module_id; + + if (mod_id_i > 2) + return -EINVAL; + + module_id = s_tisa_module_id[mod_id_i]; + + tas25xx_afe_init(); + + switch (get_set) { + case TAS_SET_PARAM: + ret = afe_tas_smartamp_set_calib_data(module_id, param_id, + length, user_data, get_rx_port_id()); + break; + + case TAS_GET_PARAM: + memset(user_data, 0, length); + ret = afe_tas_smartamp_get_calib_data(module_id, + param_id, length, user_data, get_rx_port_id()); + break; + + default: + break; + } + return ret; +} +EXPORT_SYMBOL(tas25xx_smartamp_get_set); diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.c b/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.c new file mode 100644 index 00000000..36cba8cd --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.c @@ -0,0 +1,286 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-algo-bin-utils.c +** +** Description: +** Algorithm parameter's binary file utility wrapper. +** +** ============================================================================= +*/ +#include <linux/types.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include <linux/slab.h> + +#include "tas25xx-algo-bin-utils.h" + +const char *binfilenames[NUM_SPK_TYPES] = { + "tas25xx_TI_0.bin", + "tas25xx_TI_1.bin", + "tas25xx_TI_2.bin", + "tas25xx_TI_3.bin" +}; + +static struct bin_file_data_t s_bin = { + .uses_bin_file = 0, + .parse_done = 0, + .profile_id = 0, + .spk_id = 0, + .bytes_per_prof_per_channel = 0, + .number_of_profiles = 0, + .no_of_channels = 0, + .single_profile_size = 0, + .profile_data = NULL, +}; + +static struct device *s_dev; + +void bin_file_set_device(struct device *dev) +{ + s_dev = dev; +} + +static inline struct device *bin_file_get_device(void) +{ + return s_dev; +} + +/* + * returns 0 on success, -ve errorcode otherwise + */ +int bin_file_parse_init(void) +{ + int ret = 0; + char metadata[SA_BIN_MDATA_SZ] = { 0 }; + char header[SA_BIN_HDR_SIZE] = { 0 }; + uint32_t *header_ptr = (uint32_t *)header; + const struct firmware *fw_entry = NULL; + struct device *dev; + int32_t i = 0; + int bin_data_size; + + int32_t *data; + int32_t version; + int32_t time; + char *ddc; + char ddcl[64] = { 0 }; + + s_bin.uses_bin_file = 1; + + if (s_bin.profile_data) + return 0; + + dev = bin_file_get_device(); + if (!dev) { + pr_err("TI-SmartPA BIN: struct device is null\n"); + return -EINVAL; + } + + if ((s_bin.spk_id >= 0) && (s_bin.spk_id < NUM_SPK_TYPES)) { + printk(KERN_INFO "TI-SmartPA BIN : Speaker ID:%d,Bin file : %s\n", s_bin.spk_id, binfilenames[s_bin.spk_id]); + ret = request_firmware(&fw_entry, binfilenames[s_bin.spk_id], dev); + if (ret || !fw_entry || !fw_entry->data || (fw_entry->size < (SA_BIN_MDATA_SZ+SA_BIN_HDR_SIZE))) { + printk(KERN_ERR "TI-SmartPA BIN : request_firmware failed with error=%d, fw_entry=%p, size=%d\n", ret, fw_entry, + fw_entry ? (int)fw_entry->size : 0); + return ret; + } + + memcpy(metadata, fw_entry->data, SA_BIN_MDATA_SZ); + + data = (int32_t *)metadata; + version = data[0]; + time = data[1]; + + ddc = (char *)data; + while (((71 - i) > 8) && ddc[71 - i]) { + ddcl[i] = ddc[71 - i]; + i++; + } + + printk(KERN_INFO "TI-SmartPA BIN: Version = 0x%x\n", version); + printk(KERN_INFO "TI-SmartPA BIN: Time = %d seconds from epoch time\n", time); + printk(KERN_INFO "TI-SmartPA BIN: DDC Name = %s\n", ddcl); + printk(KERN_INFO "TI-SmartPA BIN: metadata read !!\n"); + + memcpy(header, (char *)(fw_entry->data) + SA_BIN_MDATA_SZ, SA_BIN_HDR_SIZE); + s_bin.number_of_profiles = header_ptr[0]; + s_bin.no_of_channels = (header_ptr[1] >> 24) & 0xFF; + s_bin.single_profile_size = header_ptr[1] & 0xFFFF; + s_bin.bytes_per_prof_per_channel = s_bin.single_profile_size / s_bin.no_of_channels; + + printk(KERN_INFO"TI-SmartPA BIN: [BIN]: num of prof=%d, num of ch=%d, single profile sz=%d\n", + s_bin.number_of_profiles, + s_bin.no_of_channels, + s_bin.single_profile_size); + + bin_data_size = s_bin.number_of_profiles * s_bin.single_profile_size; + if (bin_data_size == (fw_entry->size - SA_BIN_MDATA_SZ - SA_BIN_HDR_SIZE)) { + s_bin.profile_data = kmalloc(bin_data_size, GFP_KERNEL); + } else { + printk(KERN_ERR "TI-SmartPA BIN : size mismatch bin vs firmware\n"); + s_bin.profile_data = NULL; + } + + if (!s_bin.profile_data) { + printk(KERN_ERR "TI-SmartPA BIN : kmalloc failed\n"); + bin_file_parse_deinit(); + ret = -ENOMEM; + } else { + char *data_start = ((char *)(fw_entry->data)) + SA_BIN_MDATA_SZ + SA_BIN_HDR_SIZE; + memcpy (s_bin.profile_data, data_start, bin_data_size); + s_bin.parse_done = 1; + printk(KERN_INFO "TI-SmartPA BIN: [BIN]: Read %d bytes successfully !!!\n", bin_data_size); + } + + release_firmware(fw_entry); + } else { + printk(KERN_ERR "TI-SmartPA BIN : Invalid speaker ID : %d\n", s_bin.spk_id); + return -EINVAL; + } + + return ret; +} + +/* + * 1 is success, 0 is false + */ +bool bin_file_parse_status(void) +{ + if (s_bin.uses_bin_file && s_bin.parse_done) + return true; + + return false; +} + +/* parse profile apr */ +bool bin_file_get_profile_data(char **buf, int *size) +{ + bool success = false; + int profile_id; + + if (s_bin.profile_id < 0) { + s_bin.profile_id = 0; + } + + profile_id = s_bin.profile_id; + + printk(KERN_INFO "TI-SmartPA BIN: [BIN] load_profile %d", s_bin.profile_id); + + /* + * profile_id [0- g_number_of_profiles) + */ + if (!bin_file_parse_init() && (profile_id < s_bin.number_of_profiles) && buf && size) { + + int sz = s_bin.bytes_per_prof_per_channel; + uint8_t *ptr = (uint8_t *)s_bin.profile_data; + ptr += (profile_id * s_bin.single_profile_size); + *buf = ptr; + + if (s_bin.no_of_channels == 2) { + sz += s_bin.bytes_per_prof_per_channel; + } + + *size = sz; + success = true; + } else { + printk(KERN_INFO "TI-SmartPA BIN:[BIN] error parsing bin file!!!"); + } + + return success; +} + +void bin_file_parse_deinit(void) +{ + + bool temp = s_bin.uses_bin_file; + int old_spk_id = s_bin.spk_id; + int old_profile_id = s_bin.profile_id; + if (s_bin.profile_data) + kfree(s_bin.profile_data); + + memset(&s_bin, 0, sizeof(s_bin)); + + s_bin.profile_id = old_profile_id; + s_bin.spk_id = old_spk_id; + s_bin.uses_bin_file = temp; +} + +void bin_file_set_profile_id(int profile_id) +{ + s_bin.profile_id = profile_id; +} + +void bin_file_set_spk_id(int spk_id) +{ + + bin_file_parse_deinit(); + s_bin.spk_id = spk_id; +} + +/*read only functions*/ +int bin_file_get_profile_id(void) +{ + return s_bin.profile_id; +} + +int bin_file_get_spk_id(void) +{ + return s_bin.spk_id; +} + +int bin_file_get_number_of_channels(void) +{ + return s_bin.no_of_channels; +} + +bool uses_bin_file(void) +{ + return s_bin.uses_bin_file; +} + +int bin_file_get_per_profile_per_channel_param_count(void) +{ + return s_bin.bytes_per_prof_per_channel / sizeof(int); +} + +int32_t *bin_file_get_profile_0_data_pointer(void) +{ + if (s_bin.uses_bin_file && s_bin.parse_done) + return (int32_t *)s_bin.profile_data; + + return NULL; +} + +/** + * custom value start - size + * custom value 1 + * custom value 2 + */ +int32_t bin_file_get_custom_value_by_idx(int index_request, int *value) +{ + int custom_index_start; + int ret = -EINVAL; + + int32_t *data = bin_file_get_profile_0_data_pointer(); + if (data && value) { + custom_index_start = data[CUSTOM_VALUE_INDEX_PTR]; + if (custom_index_start && (index_request < data[custom_index_start])) { + custom_index_start += 1; /* points to data - index 0 */ + *value = data[custom_index_start + index_request]; + ret = 0; + } + } + + return ret; +} diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.h b/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.h new file mode 100644 index 00000000..d04a3e0a --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-bin-utils.h @@ -0,0 +1,67 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-algo-bin-utils.c +** +** Description: +** Algorithm parameter's binary file utility header file. +** +** ============================================================================= +*/ +#ifndef __BIN_IN_KERNEL_H__ +#define __BIN_IN_KERNEL_H__ + +#include <linux/types.h> + +#define SA_BIN_HDR_SIZE 16 /*Bin file header size*/ +#define SA_BIN_MDATA_SZ 72 +#define DEFAULT_SMARTAMP_PROFILE 0 +#define NUM_SPK_TYPES 4 +#define CUSTOM_VALUE_INDEX_PTR 19 + +struct bin_file_data_t { + int uses_bin_file; + int parse_done; + int profile_id; + int spk_id; + int bytes_per_prof_per_channel; + int number_of_profiles; + int no_of_channels; + int single_profile_size; + int *profile_data; +}; + +int bin_file_parse_init(void); +bool bin_file_parse_status(void); +bool bin_file_get_profile_data(char **buf, int *size); +void bin_file_parse_deinit(void); + +void bin_file_set_profile_id(int profile_id); + +void bin_file_set_spk_id(int spk_id); + +int bin_file_get_profile_id(void); +int bin_file_get_spk_id(void); +bool uses_bin_file(void); +int bin_file_get_per_profile_per_channel_param_count(void); +int *bin_file_get_profile_0_data_pointer(void); + +int bin_file_get_number_of_channels(void); + +void bin_file_set_device(struct device *dev); + +/* Custom index access*/ +/* index starts from 0 */ +int32_t bin_file_get_custom_value_by_idx(int index_request, int *value); + +#endif /*__BIN_IN_KERNEL_H__*/ diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-common.c b/asoc/codecs/tas256x/algo/src/tas25xx-algo-common.c new file mode 100644 index 00000000..dc479478 --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-common.c @@ -0,0 +1,278 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-algo-common.c +** +** Description: +** Basic common interface required for the algorithm. +** +** ============================================================================= +*/ +#include <sound/soc.h> +#include <linux/types.h> +#include <linux/device.h> +#include "algo/inc/tas25xx-calib.h" +#include "algo/inc/tas_smart_amp_v2.h" +#include "tas25xx-algo-bin-utils.h" +#include "tas25xx-algo-intf.h" + +#define TDM_MAX_CHANNELS 4 + +#if IS_ENABLED(CONFIG_PLATFORM_QCOM) +#include <dsp/tas_qualcomm.h> +void tas25xx_parse_algo_dt_qdsp_intf(struct device_node *np); +#endif /*CONFIG_PLATFORM_XXX*/ + +#if IS_ENABLED(CONFIG_TISA_DEBUGFS_INTF) +void tas25xx_parse_algo_dt_debugfs(struct device_node *np); +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +int tas_smartamp_add_algo_controls_debugfs(struct snd_soc_component *codec, + int number_of_channels); +void tas_smartamp_remove_algo_controls_debugfs(struct snd_soc_component *codec); +#else +int tas_smartamp_add_algo_controls_debugfs(struct snd_soc_codec *codec, + int number_of_channels); +void tas_smartamp_remove_algo_controls_debugfs(struct snd_soc_codec *codec); +#endif +#endif + +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) +#include "tas25xx-calib-validation.h" +#endif + +static int32_t g_fmt; +static struct device *s_device; +static char s_channel_map[TDM_MAX_CHANNELS] = {0, 1, 2, 3}; + +struct soc_multi_control_ch_map { + int min, max, platform_max, count; + unsigned int reg, rreg, shift, rshift, invert; +}; + +int get_iv_vbat_format(void) +{ + return g_fmt; +} + +void tas25xx_algo_set_device (struct device *dev) +{ + s_device = dev; +} + +struct device *tas25xx_algo_get_device(void) +{ + return s_device; +} + +bool tas25xx_set_iv_bit_fomat(int iv_data_with, int vbat, int update_now) +{ + int32_t param_id; + int32_t ret; + bool success; + + if ((vbat == 1) && (iv_data_with == 12)) + g_fmt = IV_SENSE_FORMAT_12_BIT_WITH_8BIT_VBAT; + else if ((vbat == 1) && (iv_data_with == 8)) + g_fmt = IV_SENSE_FORMAT_8_BIT_WITH_8BIT_VBAT; + else if ((vbat == 1) && (iv_data_with == 16)) + g_fmt = IV_SENSE_FORMAT_16_BIT_WITH_8BIT_VBAT; + else + g_fmt = IV_SENSE_FORMAT_NO_VBAT; + + success = true; + + if (update_now) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_IV_VBAT_FMT, 1, CHANNEL0); + pr_info("TI-SmartPA: %s: Sending IV,Vbat format %d\n", + __func__, g_fmt); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&g_fmt, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set config\n", + __func__); + success = false; + } + + } + + return success; +} +EXPORT_SYMBOL(tas25xx_set_iv_bit_fomat); + +void tas25xx_send_channel_mapping(void) +{ + int ret; + int32_t param_id; + + param_id = TAS_CALC_PARAM_IDX(TAS_PCM_CHANNEL_MAPPING, + TDM_MAX_CHANNELS/sizeof(int32_t), CHANNEL0); + ret = tas25xx_smartamp_algo_ctrl((u8 *)s_channel_map, param_id, + TAS_SET_PARAM, TDM_MAX_CHANNELS, TISA_MOD_RX); + if (ret) + pr_err("TI-SmartPA: %s, Error sending, ret=%d\n", __func__, ret); +} + +/** + Common Mixer Controls required for all interfaces +**/ +/* get api shall return the cached values from set api. Default mapping if not set*/ +static int tas25xx_algo_get_channel_map(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i; + for (i = 0; i < TDM_MAX_CHANNELS; i++) { + pr_debug("TI-SmartPA: %s idx=%d, value=%d\n", __func__, i, (int)s_channel_map[i]); + ucontrol->value.integer.value[i] = (unsigned int) s_channel_map[i]; + } + + return 0; +} + +static int tas25xx_algo_put_channel_map(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i; + char channel_map[TDM_MAX_CHANNELS]; + + for (i = 0; i < TDM_MAX_CHANNELS; i++) { + channel_map[i] = (char)(ucontrol->value.integer.value[i]); + pr_debug("TI-SmartPA: %s mapping - index %d = channel %d\n", + __func__, i, channel_map[i]); + } + + memcpy(s_channel_map, channel_map, sizeof(channel_map)); + return 0; +} + +int tas25xx_algo_channel_map_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_multi_control_ch_map *mc = + (struct soc_multi_control_ch_map *)kcontrol->private_value; + + pr_debug("TI-SmartPA: %s count=%d, platform_max=%d\n", __func__, mc->count, + mc->platform_max); + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = mc->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = mc->platform_max; + + return 0; +} + +static const struct snd_kcontrol_new tas25xx_algo_common_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "TAS25XX_ALGO_RX_CH_MAP", + .info = tas25xx_algo_channel_map_info, + .get = tas25xx_algo_get_channel_map, + .put = tas25xx_algo_put_channel_map, + .private_value = (unsigned long) &(struct soc_multi_control_ch_map) { + .reg = SND_SOC_NOPM, + .shift = 0, + .rshift = 0, + .max = TDM_MAX_CHANNELS, + .count = TDM_MAX_CHANNELS, + .platform_max = 16, + .invert = 0, + } + } +}; + +void tas25xx_parse_algo_dt(struct device_node *np) +{ +#if IS_ENABLED(CONFIG_PLATFORM_QCOM) + tas25xx_parse_algo_dt_qdsp_intf (np); +#endif + +#if IS_ENABLED(CONFIG_TISA_DEBUGFS_INTF) + tas25xx_parse_algo_dt_debugfs(np); +#endif +} +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +void tas_smartamp_add_algo_controls(struct snd_soc_component *codec, + struct device *dev, int number_of_channels) +#else +void tas_smartamp_add_algo_controls(struct snd_soc_codec *codec, + struct device *dev, int number_of_channels) +#endif +{ + pr_info("TI-SmartPA: %s: Adding smartamp controls\n", __func__); + + g_fmt = 0; + + tas25xx_smartamp_alg_intf_init(); + +#if IS_ENABLED(CONFIG_TISA_DEBUGFS_INTF) + pr_err("TI-SmartPA: %s: Adding debugfs controls\n", __func__); + tas_smartamp_add_algo_controls_debugfs(codec, number_of_channels); +#endif + +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) + tas25xx_algo_add_calib_valid_bigdata(number_of_channels); +#endif + + /* Some common interfaces used*/ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + snd_soc_add_component_controls(codec, tas25xx_algo_common_controls, + ARRAY_SIZE(tas25xx_algo_common_controls)); +#else + snd_soc_add_codec_controls(codec, tas25xx_algo_common_controls, + ARRAY_SIZE(tas25xx_algo_common_controls)); +#endif + +#if IS_ENABLED(CONFIG_TISA_BIN_INTF) + pr_err("TI-SmartPA: %s: Adding bin intf controls\n", __func__); + tas_smartamp_add_codec_mixer_controls(codec); +#endif + +#if IS_ENABLED(CONFIG_TISA_KBIN_INTF) + tas_smartamp_add_codec_mixer_controls (codec); + tas25xx_algo_set_device (dev); + bin_file_set_device (dev); + bin_file_parse_init(); + + pr_info("TI-SmartPA: %s: Initialising kbin file done\n", __func__); +#endif + + tas_calib_init(); +} +EXPORT_SYMBOL(tas_smartamp_add_algo_controls); + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +void tas_smartamp_remove_algo_controls(struct snd_soc_component *codec) +#else +void tas_smartamp_remove_algo_controls(struct snd_soc_codec *codec) +#endif +{ +#if IS_ENABLED(CONFIG_TISA_DEBUGFS_INTF) + tas_smartamp_remove_algo_controls_debugfs(codec); +#endif + +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) + tas25xx_algo_remove_calib_valid_bigdata(); +#endif + +#if IS_ENABLED(CONFIG_TISA_KBIN_INTF) + tas_smartamp_kbin_deinitalize (); + tas25xx_algo_set_device(NULL); + bin_file_set_device(NULL); + bin_file_parse_deinit(); +#endif + + tas25xx_smartamp_alg_intf_deinit(); + tas_calib_exit(); +} +EXPORT_SYMBOL(tas_smartamp_remove_algo_controls); diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.c b/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.c new file mode 100644 index 00000000..c583d570 --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.c @@ -0,0 +1,80 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * File: + * tas25xx-algo-intf.c + * + * Description: + * Wrapper on Interface to algorithm. + * + * ============================================================================= + */ +#include <sound/soc.h> +#include <linux/types.h> +#include <linux/device.h> +#include "algo/inc/tas25xx-calib.h" +#include "algo/inc/tas_smart_amp_v2.h" +#include "tas25xx-algo-bin-utils.h" +#include "tas25xx-algo-intf.h" + +static int s_tas_smartamp_bypass; +static int init_once; +static struct mutex smartpa_algo_lock; + +void tas25xx_set_algo_bypass(int bypass) +{ + s_tas_smartamp_bypass = bypass; +} + +int tas25xx_get_algo_bypass(void) +{ + return s_tas_smartamp_bypass; +} + +void tas25xx_smartamp_alg_intf_init(void) +{ + if (!init_once) { + mutex_init(&smartpa_algo_lock); + pr_info("tas mutex init"); + init_once = 1; + } +} + +void tas25xx_smartamp_alg_intf_deinit(void) +{ + if (init_once) { + mutex_destroy(&smartpa_algo_lock); + pr_info("tas mutex destroy"); + init_once = 0; + } +} + +/*Wrapper arround set/get parameter, + *all set/get commands pass through this wrapper + */ +int tas25xx_smartamp_algo_ctrl(u8 *user_data, uint32_t param_id, + uint8_t get_set, uint32_t length, module_id_t module_id) +{ + int ret = 0; + + if (!s_tas_smartamp_bypass) { + mutex_lock(&smartpa_algo_lock); + ret = tas25xx_smartamp_get_set(user_data, param_id, get_set, + length, module_id); + mutex_unlock(&smartpa_algo_lock); + } else { + pr_info("TI-SmartPA: %s: algo set/get is bypassed\n", __func__); + } + + return ret; +} +EXPORT_SYMBOL(tas25xx_smartamp_algo_ctrl); diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.h b/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.h new file mode 100644 index 00000000..1b4ba055 --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-intf.h @@ -0,0 +1,36 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * File: + * tas25xx-algo-intf.h + * + * Description: + * Header file for Wrapper on interface to algorithm. + * + * ============================================================================= + */ +#ifndef __TAS25XX_ALGO_INTF__ +#define __TAS25XX_ALGO_INTF__ + +void tas25xx_smartamp_alg_intf_init(void); +void tas25xx_smartamp_alg_intf_deinit(void); +int tas25xx_smartamp_algo_ctrl(u8 *user_data, uint32_t param_id, + uint8_t get_set, uint32_t length, module_id_t module_id); + +/* bypass set and get */ +int tas25xx_get_algo_bypass(void); +void tas25xx_set_algo_bypass(int bypass); + +int tas25xx_smartamp_get_set(u8 *user_data, uint32_t param_id, + uint8_t get_set, uint32_t length, module_id_t mod_id_i); + +#endif /* __TAS25XX_ALGO_INTF__ */ diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-algo-kbin-intf.c b/asoc/codecs/tas256x/algo/src/tas25xx-algo-kbin-intf.c new file mode 100644 index 00000000..171dee93 --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-algo-kbin-intf.c @@ -0,0 +1,1015 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-algo-kbin-intf.c +** +** Description: +** Algorithm interface wrapper to open the parameter bin file in kernel +** using "request_firmware" API +** +** ============================================================================= +*/ +#include <sound/soc.h> +#include <linux/delay.h> /* usleep_range */ +#include <linux/kernel.h> +#include <linux/types.h> /* atomic_t */ +#include <linux/workqueue.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include "algo/inc/tas_smart_amp_v2.h" +#include "algo/inc/tas25xx-calib.h" +#include "tas25xx-algo-bin-utils.h" +#include "tas25xx-algo-intf.h" + +#if IS_ENABLED(CONFIG_SND_SOC_CODEC_DETECT) +#include <linux/codec-misc.h> +#endif + +#define POISON_VAL 0xDEADDEAD +#define MAX_STRING (300) +#define QFORMAT19 19 +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +static struct delayed_work query_tisa_algo_wrk; +static atomic_t algo_active = ATOMIC_INIT(0); + +/*Master Control to Bypass the Smartamp TI CAPIv2 module*/ +static int s_tas_smartamp_enable; +static int s_allow_dsp_query; +static int s_calib_test_flag; + +/* fwd declaration */ +static int tas25xx_get_re_common(int channel); +struct device *tas25xx_algo_get_device(void); + +/*Max value supported is 2^8*/ +static int trans_val_to_user_m(int val, int qformat, int scale) +{ + int ret = (int)(((long long)val * scale) >> qformat) % scale; + return ret; +} + +/*Max value supported is 2^8*/ +static int trans_val_to_user_i(int val, int qformat) +{ + return ((val * 100) >> qformat) / 100; +} + +#if IS_ENABLED(CONFIG_SND_SOC_CODEC_DETECT) +static int trans_val_to_int(int val, int scale, int qformat) +{ + return trans_val_to_user_i(val, qformat) * scale + + trans_val_to_user_m(val, qformat, scale); +} +#endif + +#ifdef CONFIG_SET_RE_IN_KERNEL +static int get_calibrated_re_tcalib(uint32_t *rdc_fix, uint32_t *tv_fix, int channel_count) +{ + int ret = 0; + int calib_re_sz; + uint32_t *calib_data; + struct device *dev; + const struct firmware *fw_entry; + + static uint32_t s_rdc_fix[2] = { POISON_VAL, POISON_VAL }; + static uint32_t s_tv_fix = POISON_VAL; + + if ((s_rdc_fix[0] == POISON_VAL) && + (s_rdc_fix[1] == POISON_VAL)) { + ret = -EINVAL; + dev = tas25xx_algo_get_device(); + if (dev) + ret = request_firmware(&fw_entry, "smartamp_calib.bin", dev); + + if (ret) { + pr_err("[TI-SmartPA: %s] request_firmware failed, err=%d!\n", __func__, ret); + return ret; + } + + calib_re_sz = (channel_count * sizeof(uint32_t)); + calib_data = (int32_t *) fw_entry->data; + /*calib re + temp*/ + if (fw_entry->size < (calib_re_sz + 1)) { + memcpy(s_rdc_fix, calib_data, calib_re_sz); + memcpy(&s_tv_fix, calib_data + calib_re_sz, sizeof(uint32_t)); + } + + release_firmware(fw_entry); + } + + if (ret == 0) { + if (rdc_fix) { + rdc_fix[0] = (uint32_t)s_rdc_fix[0]; + if (channel_count == 2) + rdc_fix[1] = (uint32_t)s_rdc_fix[1]; + } + if (tv_fix) + *tv_fix = (uint32_t)s_tv_fix; + } + return ret; +} +#endif /*CONFIG_SET_RE_IN_KERNEL*/ + +void tas25xx_algo_set_inactive(void) +{ + atomic_set(&algo_active, 0); + s_tas_smartamp_enable = 0; + + pr_info("[TI-SmartPA:%s] algo disabled..", __func__); + + bin_file_set_profile_id(0); + s_calib_test_flag = 0; +} + +void tas25xx_algo_set_active(void) +{ + atomic_set(&algo_active, 1); + schedule_delayed_work(&query_tisa_algo_wrk, msecs_to_jiffies(1000)); +} + +static void query_tisa_algo(struct work_struct *wrk) +{ + int sleep_ms; + int sleep_us; + int sleep_us_max; + int ret; + int temp; + int re_l = 0, re_r = 0; +#if IS_ENABLED(CONFIG_SND_SOC_CODEC_DETECT) + int scale = 100000; +#endif + + ret = bin_file_get_custom_value_by_idx(0, &sleep_ms); + if (ret) { + sleep_ms = 1000; + } + + sleep_us = sleep_ms * 1000; + sleep_us_max = sleep_us + 1000; + + pr_info("TI-SmartPA: Re query interval is set to %d(ms)\n", sleep_ms); + + while (atomic_read(&algo_active)) { + + temp = s_allow_dsp_query; + s_allow_dsp_query = 1; + re_l = tas25xx_get_re_common(CHANNEL0); + re_r = tas25xx_get_re_common(CHANNEL1); + s_allow_dsp_query = temp; + +#if IS_ENABLED(CONFIG_SND_SOC_CODEC_DETECT) + codec_misc_amp_put(0, (long)trans_val_to_int(re_l, scale, QFORMAT19)); + codec_misc_amp_put(1, (long)trans_val_to_int(re_r, scale, QFORMAT19)); +#endif + pr_debug("[TI-SmartPA:%s] Re value is %02d.%02d (%d), %02d.%02d (%d) \n", + __func__, + (int32_t)trans_val_to_user_i(re_l, QFORMAT19), + (int32_t)trans_val_to_user_m(re_l, QFORMAT19, 100), + re_l, + (int32_t)trans_val_to_user_i(re_r, QFORMAT19), + (int32_t)trans_val_to_user_m(re_r, QFORMAT19, 100), + re_r); + + usleep_range(sleep_us, sleep_us_max); + } +} + +static int tas25xx_send_kbin_params(void) +{ + int ret = -EINVAL; + int profile_size_bytes = 0; + int param_id = 0; + int sent = 0; + int ch = CHANNEL0; + int param_sz_rem; + int current_idx = 0; + u16 size; + int i; + + char *profile_data = NULL; + int *data; + + int per_ch_param_sz = bin_file_get_per_profile_per_channel_param_count(); + int number_of_ch = bin_file_get_number_of_channels(); + bool success = bin_file_get_profile_data(&profile_data, &profile_size_bytes); + + if (success && profile_data && profile_size_bytes) { + data = (int *)profile_data; + ret = 0; + + for (i = 0; i < number_of_ch; i++) { + ch = i + 1; + sent = 0; + param_sz_rem = per_ch_param_sz; + for (current_idx = 0; current_idx < per_ch_param_sz; ) { + /*size = MIN(1000, param_sz_rem);*/ + size = MIN(100, param_sz_rem); + param_id = TAS_CALC_PARAM_IDX(current_idx, size, ch); + ret = tas25xx_smartamp_algo_ctrl((u8 *)data, param_id, + TAS_SET_PARAM, size * sizeof(int), TISA_MOD_RX); + if (ret) { + pr_err("TI-SmartPA: %s data send error = %d\n", __func__, ret); + } + data += size; + sent += size; + param_sz_rem -= size; + current_idx += size; + + pr_debug("TI-SmartPA: %s send=%d, param_sz_rem=%d(total=%d), last sent sz=%d\n", + __func__, sent, param_sz_rem, per_ch_param_sz, size); + } + } + } + + /*send swap index*/ + if (ret == 0) { + int user_data = 1; + param_id = TAS_CALC_PARAM_IDX(TAS_DSP_SWAP_IDX, 1, CHANNEL0); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + + if (ch == CHANNEL1) { + param_id = TAS_CALC_PARAM_IDX(TAS_DSP_SWAP_IDX, 1, CHANNEL1); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + } + } + + return ret; + +} + +/*Control-1: Set Profile*/ +static const char *profile_index_text[] = { + "NONE", TAS_ALGO_PROFILE_LIST, "CALIB" }; +static const struct soc_enum profile_index_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(profile_index_text), + profile_index_text), +}; + +static int tas25xx_set_profile_kbin(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int profile_id = pUcontrol->value.integer.value[0]; + int max_number_of_profiles = + sizeof(profile_index_text) / sizeof(profile_index_text[0]); + + if ((profile_id >= max_number_of_profiles) || (profile_id < 0)) + return -EINVAL; + + pr_info("TI-SmartPA: %s: Setting profile %s \n", + __func__, profile_index_text[profile_id]); + if (profile_id) + profile_id -= 1; + else + return 0; + + bin_file_set_profile_id(profile_id); + + /*playback started*/ + if (s_tas_smartamp_enable) { + tas25xx_send_kbin_params (); + } + + return ret; +} + +static int tas25xx_get_profile_kbin(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int profile_id = bin_file_get_profile_id(); + int max_number_of_profiles = + sizeof(profile_index_text) / sizeof(profile_index_text[0]); + + pUcontrol->value.integer.value[0] = profile_id; + if ((profile_id < max_number_of_profiles) && (profile_id > -1)) + pr_info("TI-SmartPA: %s: getting profile %s\n", + __func__, profile_index_text[profile_id]); + + return 0; +} + +/*Control-2: Set Calibrated Rdc*/ +static int tas25xx_set_Re_common(int re_value_in, int channel) +{ + int ret; + int param_id = 0; + int re_value = re_value_in; + + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, channel); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&re_value, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + + return ret; +} + +static int tas25xx_set_Re_left(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int re_value = pUcontrol->value.integer.value[0]; + + pr_info("TI-SmartPA: %s: Setting Re %d", __func__, re_value); + return tas25xx_set_Re_common(re_value, CHANNEL0); +} + +static int tas25xx_dummy_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + + pUcontrol->value.integer.value[0] = 0; + return ret; +} + +static int tas25xx_dummy_set(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + return 0; +} + +/*Control-3: Calibration and Test(F0,Q,Tv) Controls*/ +static const char *tas25xx_calib_test_text[] = { + "NONE", + "CALIB_START", + "CALIB_STOP", + "TEST_START", + "TEST_STOP" +}; + +static const struct soc_enum tas25xx_calib_test_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_calib_test_text), + tas25xx_calib_test_text), +}; + +static int tas25xx_calib_test_set_common(int calib_command, int channel) +{ + int ret = 0; + int param_id = 0; + int data = 1; + + switch (calib_command) { + case CALIB_START: + pr_info("TI-SmartPA: %s: CALIB_START", __func__); + s_calib_test_flag = 1; + param_id = TAS_CALC_PARAM_IDX(TAS_SA_CALIB_INIT, 1, channel); + break; + + case CALIB_STOP: + pr_info("TI-SmartPA: %s: CALIB_STOP", __func__); + s_calib_test_flag = 0; + param_id = TAS_CALC_PARAM_IDX(TAS_SA_CALIB_DEINIT, 1, channel); + break; + + case TEST_START: + s_calib_test_flag = 1; + break; + + case TEST_STOP: + s_calib_test_flag = 0; + break; + + default: + pr_info("TI-SmartPA: %s: no impl calib_command %d\n", + __func__, calib_command); + ret = -EINVAL; + break; + } + + if (param_id) { + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + s_calib_test_flag = 0; + pr_err("TI-SmartPA: %s: Failed to set calib/test, ret=%d\n", + __func__, ret); + } + } + + return ret; +} + +static int tas25xx_calib_test_set(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int user_data = pUcontrol->value.integer.value[0]; + + ret = tas25xx_calib_test_set_common(user_data, CHANNEL0); + + if (ret == 0) { +#ifdef CONFIG_TAS25XX_ALGO_STEREO + ret = tas25xx_calib_test_set_common(user_data, CHANNEL1); +#endif + } + + return ret; +} + +/*Control-4: Get Re*/ +/*returns -ve error or +ve re value, 0 if not called*/ +static int tas25xx_get_re_common(int channel) +{ + int ret = 0; + int re_value = 0; + int param_id = 0; + + pr_debug("TI-SmartPA: %s, channel=%d\n", __func__, channel); + + if (s_tas_smartamp_enable && (s_calib_test_flag || s_allow_dsp_query)) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_RE, 1, channel); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&re_value, param_id, + TAS_GET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) + pr_err("TI-SmartPA: %s: Failed to get Re\n", __func__); + else + ret = re_value; + } + + return ret; +} + +static int tas25xx_get_re_left(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_re_common(CHANNEL0); + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + ret = 0; + pr_info("TI-SmartPA: %s: Getting Re %d\n", __func__, ret); + } + + return ret; +} + +/*Control-5: Get F0*/ +static int tas25xx_get_f0_common(int channel) +{ + int f0_value = 0; + int param_id = 0; + int ret = 0; + + pr_info("TI-SmartPA: %s, channel=%d\n", __func__, channel); + + if (s_tas_smartamp_enable && (s_calib_test_flag || s_allow_dsp_query)) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_F0, 1, channel); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&f0_value, param_id, + TAS_GET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) + pr_err("TI-SmartPA: %s: Failed to get F0\n", __func__); + else + ret = f0_value; + } + + return ret; +} + +static int tas25xx_get_f0_left(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_f0_common(CHANNEL0); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting F0 val=%d\n", __func__, ret); + ret = 0; + } + + return ret; +} + +/*Control-6: Get Q*/ +static int tas25xx_get_q_common(int channel) +{ + int ret = 0; + int q_value = 0; + int param_id = 0; + + pr_info("TI-SmartPA: %s, channel=%d", __func__, channel); + + if (s_tas_smartamp_enable && (s_calib_test_flag || s_allow_dsp_query)) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_Q, 1, channel); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&q_value, param_id, + TAS_GET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) + pr_err("TI-SmartPA: %s: Failed to get F0\n", __func__); + else + ret = q_value; + } + + return ret; +} + +static int tas25xx_get_q_left(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_q_common(CHANNEL0); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting Q %d\n", __func__, ret); + ret = 0; + } + + return ret; +} + +/*Control-7: Get Tv*/ +static int tas25xx_get_tv_common(int channel) +{ + int ret = 0; + int tv_value = 0; + int param_id = 0; + + pr_info("TI-SmartPA: %s, channel=%d", __func__, channel); + + if (s_tas_smartamp_enable && (s_calib_test_flag || s_allow_dsp_query)) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_TV, 1, channel); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&tv_value, param_id, + TAS_GET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) + pr_err("TI-SmartPA: %s: Failed to get Tv\n", __func__); + else + ret = tv_value; + } + + return ret; +} + +static int tas25xx_get_tv_left(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + + int ret = tas25xx_get_tv_common(CHANNEL0); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting Tv %d\n", __func__, ret); + ret = 0; + } + + return ret; +} + +/*Control-8: Smartamp Enable*/ +static const char *tas25xx_smartamp_enable_text[] = { + "DISABLE", + "ENABLE" +}; + +static const struct soc_enum tas25xx_smartamp_enable_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_smartamp_enable_text), + tas25xx_smartamp_enable_text), +}; + +static int tas25xx_smartamp_enable_set_kbin(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int param_id = 0; + int user_data = pUcontrol->value.integer.value[0]; +#ifdef CONFIG_SET_RE_IN_KERNEL + uint32_t calibration_data[3]; +#endif + +#ifdef CONFIG_TAS25XX_ALGO_STEREO + int number_of_ch = 2; +#else + int number_of_ch = 1; +#endif + + if (tas25xx_get_algo_bypass()) { + pr_info("TI-SmartPA: bypass enabled, not enabling\n"); + return 0; + } + + pr_info("TI-SmartPA: %s: case %d, number_of_ch=%d\n", + __func__, user_data, number_of_ch); + + s_tas_smartamp_enable = user_data; + if (s_tas_smartamp_enable == 0) { + pr_info("TI-SmartPA: %s: Disable called\n", __func__); + return 0; + } + + pr_info("TI-SmartPA: %s: Sending TX Enable\n", __func__); + param_id = CAPI_V2_TAS_TX_ENABLE; + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_TX); + if (ret) { + pr_err("TI-SmartPA: %s: TX Enable Failed ret = 0x%x\n", + __func__, ret); + goto fail_cmd; + } + + user_data = 1; + pr_info("TI-SmartPA: %s: Sending RX Enable\n", __func__); + param_id = CAPI_V2_TAS_RX_ENABLE; + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret) { + pr_err("TI-SmartPA: %s: RX Enable Failed ret = 0x%x\n", + __func__, ret); + goto fail_cmd; + } + + tas25xx_send_kbin_params(); + + user_data = 0xCCCCB1B1; + pr_info("TI-SmartPA: %s: Sending TX Config\n", __func__); + param_id = CAPI_V2_TAS_TX_CFG; + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_TX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set config\n", __func__); + goto fail_cmd; + } + + user_data = 0xCCCCB1B1; + pr_info("TI-SmartPA: %s: Sending RX Config\n", __func__); + param_id = CAPI_V2_TAS_RX_CFG; + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set config\n", __func__); + goto fail_cmd; + } + + tas25xx_send_channel_mapping(); + + user_data = get_iv_vbat_format(); + param_id = TAS_CALC_PARAM_IDX(TAS_SA_IV_VBAT_FMT, 1, CHANNEL0); + pr_info("TI-SmartPA: %s: Sending IV,Vbat format %d\n", + __func__, user_data); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set config\n", __func__); + goto fail_cmd; + } + + s_tas_smartamp_enable = true; + +#ifdef CONFIG_SET_RE_IN_KERNEL + if (number_of_ch == 2) + ret = get_calibrated_re_tcalib(calibration_data, + &calibration_data[2], number_of_ch); + else + ret = get_calibrated_re_tcalib(calibration_data, + &calibration_data[1], number_of_ch); + + if (ret) { + pr_err("[Smartamp:%s] unable to get the calibration data = 0x%x\n", + __func__, ret); + /* TODO: Ignore the calibration read error */ + ret = 0; + } else { + int32_t t_cal; + if (number_of_ch == 2) { + t_cal = calibration_data[2]; + pr_info("[Smartamp:%s] setting re %d,%d and tcal %d\n", + __func__, calibration_data[0], + calibration_data[1], + calibration_data[2]); + } else { + t_cal = calibration_data[1]; + pr_info("[Smartamp:%s] setting re %d and tcal %d\n", + __func__, calibration_data[0], + calibration_data[1]); + } + + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_TCAL, 1, CHANNEL0); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&t_cal, + param_id, TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + pr_err("[Smartamp:%s] Failed to set Tcal\n", __func__); + goto fail_cmd; + } + + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, CHANNEL0); + ret = tas25xx_smartamp_algo_ctrl( + (u8 *)(&(calibration_data[0])), + param_id, TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set Re\n", __func__); + goto fail_cmd; + } + + if (number_of_ch == 2) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, CHANNEL1); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&(calibration_data[1]), + param_id, TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + if (ret < 0) { + pr_err("TI-SmartPA: %s: Failed to set Re\n", + __func__); + goto fail_cmd; + } + } + } +#endif /* CONFIG_SET_RE_IN_KERNEL */ + + tas25xx_algo_set_active(); + +fail_cmd: + return ret; +} + +static int tas25xx_smartamp_enable_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int user_data = s_tas_smartamp_enable; + + pUcontrol->value.integer.value[0] = user_data; + pr_info("TI-SmartPA: %s: case %d(0=DISABLE, 1=ENABLE)\n", + __func__, user_data); + return ret; +} + +/*Control-9: Smartamp Bypass */ +static const char *tas25xx_smartamp_bypass_text[] = { + "FALSE", + "TRUE" +}; + +static const struct soc_enum tas25xx_smartamp_bypass_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_smartamp_bypass_text), tas25xx_smartamp_bypass_text), +}; + +static int tas25xx_smartamp_bypass_set(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int user_data = pUcontrol->value.integer.value[0]; + + if (s_tas_smartamp_enable) { + pr_debug("TI-SmartPA: %s: cannot update while smartamp enabled\n", + __func__); + return -EINVAL; + } + + tas25xx_set_algo_bypass (user_data); + pr_info("TI-SmartPA: %s: case %d(FALSE=0,TRUE=1)\n", + __func__, user_data); + return ret; +} + +static int tas25xx_smartamp_bypass_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + + pUcontrol->value.integer.value[0] = tas25xx_get_algo_bypass(); + pr_info("TI-SmartPA: %s: case %d\n", __func__, (int)pUcontrol->value.integer.value[0]); + return ret; +} + +/*Control-9: Smartamp Bypass */ +static const char *tas25xx_smartamp_debug_enable_text[] = { + "FALSE", + "TRUE" +}; + +static const struct soc_enum tas25xx_smartamp_debug_enable_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_smartamp_debug_enable_text), + tas25xx_smartamp_debug_enable_text), +}; + +static int tas25xx_smartamp_debug_enable_set(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int user_data = pUcontrol->value.integer.value[0]; + + s_allow_dsp_query = user_data; + pr_info("TI-SmartPA: %s: case %d(FALSE=0,TRUE=1)\n", + __func__, user_data); + return ret; +} + +static int tas25xx_smartamp_debug_enable_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + + pUcontrol->value.integer.value[0] = s_allow_dsp_query; + pr_info("TI-SmartPA: %s: case %d\n", __func__, s_allow_dsp_query); + return ret; +} + +static int tas25xx_set_spk_id_kbin(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int spk_id = pUcontrol->value.integer.value[0]; + bin_file_set_spk_id(spk_id); + pr_info("TI-SmartPA: %s: spk-id set %d\n", __func__, spk_id); + return ret; +} + +static int tas25xx_set_t_calib(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = 0; + int calib_temp = pUcontrol->value.integer.value[0]; + int param_id = 0; + + pr_info("TI-SmartPA: %s: tcalib set %d\n", __func__, calib_temp); + if (s_tas_smartamp_enable) { + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_TCAL, 1, CHANNEL0); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&calib_temp, param_id, + TAS_SET_PARAM, sizeof(uint32_t), + TISA_MOD_RX); + if (ret < 0) + pr_err("TI-SmartPA: %s: Failed to set spk id\n", + __func__); + } + + return ret; +} + +#ifdef CONFIG_TAS25XX_ALGO_STEREO +static int tas25xx_set_Re_right(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int re_value = pUcontrol->value.integer.value[0]; + + pr_info("TI-SmartPA: %s: Setting Re %d\n", __func__, re_value); + return tas25xx_set_Re_common(re_value, CHANNEL1); +} + +static int tas25xx_get_re_right(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret; + + ret = tas25xx_get_re_common(CHANNEL1); + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + ret = 0; + pr_info("TI-SmartPA: %s: Getting Re value=%d\n", + __func__, ret); + } + + return ret; +} + +static int tas25xx_get_f0_right(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_f0_common(CHANNEL1); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting F0 valu=%d\n", __func__, ret); + ret = 0; + } + + return ret; +} + +static int tas25xx_get_q_right(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_q_common(CHANNEL1); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting Q val=%d\n", __func__, ret); + ret = 0; + } + + return ret; +} + +static int tas25xx_get_tv_right(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int ret = tas25xx_get_tv_common(CHANNEL1); + + if (ret >= 0) { + pUcontrol->value.integer.value[0] = ret; + pr_info("TI-SmartPA: %s: Getting Tv %d\n", __func__, ret); + ret = 0; + } + + return ret; +} +#endif + +static int tas25xx_smartamp_set_bin_updated(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pUcontrol) +{ + int update = pUcontrol->value.integer.value[0]; + if (update) { + bin_file_parse_deinit(); + bin_file_parse_init(); + } + + return 0; +} + +static const struct snd_kcontrol_new smartamp_tas25xx_mixer_controls[] = { + SOC_ENUM_EXT("TAS25XX_DEBUG_ENABLE", tas25xx_smartamp_debug_enable_enum[0], + tas25xx_smartamp_debug_enable_get, + tas25xx_smartamp_debug_enable_set), + SOC_ENUM_EXT("TAS25XX_ALGO_PROFILE", profile_index_enum[0], + tas25xx_get_profile_kbin, tas25xx_set_profile_kbin), + SOC_ENUM_EXT("TAS25XX_ALGO_CALIB_TEST", tas25xx_calib_test_enum[0], + tas25xx_dummy_get, tas25xx_calib_test_set), + SOC_SINGLE_EXT("TAS25XX_SET_SPK_ID", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_dummy_get, tas25xx_set_spk_id_kbin), + SOC_SINGLE_EXT("TAS25XX_SET_T_CALIB", SND_SOC_NOPM, 0, 100, 0, + tas25xx_dummy_get, tas25xx_set_t_calib), + + /*left*/ + SOC_SINGLE_EXT("TAS25XX_SET_RE_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_dummy_get, tas25xx_set_Re_left), + SOC_SINGLE_EXT("TAS25XX_GET_RE_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_re_left, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_F0_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_f0_left, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_Q_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_q_left, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_TV_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_tv_left, tas25xx_dummy_set), + + SOC_SINGLE_EXT("TAS25XX_PARAMS_UPDATED", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_dummy_get, tas25xx_smartamp_set_bin_updated), + + /*Right*/ +#ifdef CONFIG_TAS25XX_ALGO_STEREO + SOC_SINGLE_EXT("TAS25XX_SET_RE_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_dummy_get, tas25xx_set_Re_right), + SOC_SINGLE_EXT("TAS25XX_GET_RE_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_re_right, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_F0_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_f0_right, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_Q_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_q_right, tas25xx_dummy_set), + SOC_SINGLE_EXT("TAS25XX_GET_TV_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0, + tas25xx_get_tv_right, tas25xx_dummy_set), +#endif + SOC_ENUM_EXT("TAS25XX_SMARTPA_ENABLE", tas25xx_smartamp_enable_enum[0], + tas25xx_smartamp_enable_get, + tas25xx_smartamp_enable_set_kbin), + + SOC_ENUM_EXT("TAS25XX_ALGO_BYPASS", tas25xx_smartamp_bypass_enum[0], + tas25xx_smartamp_bypass_get, + tas25xx_smartamp_bypass_set), +}; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +void tas_smartamp_add_codec_mixer_controls(struct snd_soc_component *codec) +#else +void tas_smartamp_add_codec_mixer_controls(struct snd_soc_codec *codec) +#endif +{ + pr_debug("TI-SmartPA: %s: Adding smartamp controls\n", __func__); + + /*Initialize all to global variables to 0s*/ + s_tas_smartamp_enable = 0; + s_allow_dsp_query = 0; + s_calib_test_flag = 0; + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + + snd_soc_add_component_controls(codec, smartamp_tas25xx_mixer_controls, + ARRAY_SIZE(smartamp_tas25xx_mixer_controls)); + +#else + snd_soc_add_codec_controls(codec, smartamp_tas25xx_mixer_controls, + ARRAY_SIZE(smartamp_tas25xx_mixer_controls)); +#endif + INIT_DELAYED_WORK(&query_tisa_algo_wrk, query_tisa_algo); + +} +EXPORT_SYMBOL(tas_smartamp_add_codec_mixer_controls); + +void tas_smartamp_kbin_deinitalize (void) +{ + tas25xx_algo_set_inactive(); + cancel_delayed_work_sync(&query_tisa_algo_wrk); +} diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.c b/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.c new file mode 100644 index 00000000..b9749ead --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.c @@ -0,0 +1,1061 @@ +#ifdef CONFIG_TAS25XX_ALGO + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/debugfs.h> +#include <linux/kthread.h> +#include <linux/uaccess.h> +#include <linux/wait.h> +#include <linux/jiffies.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/syscalls.h> +#include <linux/file.h> +#include <asm/uaccess.h> +#include <linux/fs.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/power_supply.h> +#include "algo/inc/tas_smart_amp_v2.h" +#include "tas25xx-calib-validation.h" + +static uint8_t calibration_result[MAX_CHANNELS] = {STATUS_NONE}; +static uint8_t validation_result[MAX_CHANNELS] = {STATUS_NONE}; +static bool calibration_status; +static bool validation_running_status; +static uint32_t calib_re_hold[MAX_CHANNELS] = {0}; +static uint32_t amb_temp_hold[MAX_CHANNELS] = {0}; +static int32_t re_low[MAX_CHANNELS] = {0}; +static int32_t re_high[MAX_CHANNELS] = {0}; + +static struct tas25xx_algo *p_tas25xx_algo; + +struct tas25xx_algo *smartamp_get_sysfs_ptr(void) +{ + if (!p_tas25xx_algo) + p_tas25xx_algo = kzalloc(sizeof(struct tas25xx_algo), GFP_KERNEL); + + if (!p_tas25xx_algo) + return ERR_PTR(-ENOMEM); + + return p_tas25xx_algo; +} + +/*Max value supported is 2^8*/ +static uint8_t trans_val_to_user_m(uint32_t val, uint8_t qformat) +{ + uint32_t ret = (uint32_t)(((long long)val * 1000) >> qformat) % 1000; + return (uint8_t)(ret / 10); +} + +/*Max value supported is 2^8*/ +static uint8_t trans_val_to_user_i(uint32_t val, uint8_t qformat) +{ + return ((val * 100) >> qformat) / 100; +} + +static uint8_t tas25xx_get_amb_temp(void) +{ + struct power_supply *psy; + union power_supply_propval value = {0}; + + psy = power_supply_get_by_name("battery"); + if (!psy || !psy->desc || !psy->desc->get_property) { + pr_err("[TI-SmartPA:%s] getting ambient temp failed, using default value %d\n", + __func__, DEFAULT_AMBIENT_TEMP); + return DEFAULT_AMBIENT_TEMP; + } + psy->desc->get_property(psy, POWER_SUPPLY_PROP_TEMP, &value); + + return DIV_ROUND_CLOSEST(value.intval, 10); +} + +static int tas25xx_get_efs_data(uint32_t *data, uint8_t rdc_temp_l_r) +{ + struct file *pf = NULL; + char fname[MAX_STRING] = {0}; + loff_t pos = 0; + char calib_data[MAX_STRING] = {0}; + uint32_t data_flt[2]; + mm_segment_t fs; + int ret = 0; + + fs = get_fs(); + set_fs(get_ds()); + + if (rdc_temp_l_r == TEMP_L) + memcpy(fname, TAS25XX_EFS_TEMP_DATA_L, sizeof(TAS25XX_EFS_TEMP_DATA_L)); + else if (rdc_temp_l_r == RDC_L) + memcpy(fname, TAS25XX_EFS_CALIB_DATA_L, sizeof(TAS25XX_EFS_CALIB_DATA_L)); + else if (rdc_temp_l_r == TEMP_R) + memcpy(fname, TAS25XX_EFS_TEMP_DATA_R, sizeof(TAS25XX_EFS_TEMP_DATA_R)); + else if (rdc_temp_l_r == RDC_R) + memcpy(fname, TAS25XX_EFS_CALIB_DATA_R, sizeof(TAS25XX_EFS_CALIB_DATA_R)); + + pf = filp_open(fname, O_RDONLY, 0666); + + if (!IS_ERR(pf)) { + vfs_read(pf, calib_data, MAX_STRING-1, &pos); + if ((rdc_temp_l_r == TEMP_L) || (rdc_temp_l_r == TEMP_R)) { + ret = sscanf(calib_data, "%d", data); + if (ret != 1) { + pr_err("[TI-SmartPA:%s] file %s read error\n", __func__, fname); + ret = -1; + } + } else { + ret = sscanf(calib_data, "%d.%d", &(data_flt[0]), &(data_flt[1])); + if (ret != 2) { + pr_err("[TI-SmartPA:%s] file %s read error\n", __func__, fname); + ret = -1; + } + *data = TRANSF_USER_TO_IMPED(data_flt[0], data_flt[1]); + } + filp_close(pf, NULL); + } else { + pr_err("[TI-SmartPA:%s] file %s open failed\n", __func__, fname); + ret = -1; + } + set_fs(fs); + return ret; +} + +void tas25xx_update_big_data(void) +{ + uint8_t iter = 0; + uint32_t data[8] = {0}; + uint32_t param_id = 0; + int32_t ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] BigData update skipping memory not allocated yet!!\n", __func__); + return; + } + + for (iter = 0; iter < algo->spk_count; iter++) { + /*Reset data*/ + memset(data, 0, 8*sizeof(uint32_t)); + //param_id = (TAS_SA_EXC_TEMP_STAT)|((uint32_t)(iter+1)<<24)|((uint32_t)(sizeof(data)/sizeof(uint32_t))<<16); + param_id = TAS_CALC_PARAM_IDX(TAS_SA_EXC_TEMP_STAT, sizeof(data) / sizeof(data[0]), (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)(&(data[0])), param_id + , TAS_GET_PARAM, sizeof(data), TISA_MOD_RX); + if (ret < 0) { + pr_err("[TI-SmartPA:%s] Failed to get Excursion and Temperature Stats\n", __func__); + } else { + pr_info("[TI-SmartPA:%s] Emax[%d] %d(%02d.%02d), Tmax[%d] %d, EOcount[%d] %d, TOcount[%d] %d \n", + __func__, iter, data[0], (int32_t)trans_val_to_user_i(data[0], QFORMAT31), + (int32_t)trans_val_to_user_m(data[0], QFORMAT31), + iter, data[1], iter, data[2], iter, data[3]); + + /*Update Excursion Data*/ + algo->b_data[iter].exc_max = + (data[0] > algo->b_data[iter].exc_max) ? data[0] : algo->b_data[iter].exc_max; + algo->b_data[iter].exc_max_persist = + (data[0] > algo->b_data[iter].exc_max_persist) ? data[0] : algo->b_data[iter].exc_max_persist; + algo->b_data[iter].exc_over_count += data[2]; + + /*Update Temperature Data*/ + algo->b_data[iter].temp_max = + (data[1] > algo->b_data[iter].temp_max) ? data[1] : algo->b_data[iter].temp_max; + algo->b_data[iter].temp_max_persist = + (data[1] > algo->b_data[iter].temp_max_persist) ? data[1] : algo->b_data[iter].temp_max_persist; + algo->b_data[iter].temp_over_count += data[3]; + } + } +} + +int tas25xx_update_calibration_limits(void) +{ + uint8_t iter = 0; + uint32_t param_id = 0; + int32_t ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + ret = PTR_ERR(algo); + return ret; + } + + /*Reset Calibration Result*/ + memset(calibration_result, STATUS_NONE, sizeof(uint8_t)*MAX_CHANNELS); + + for (iter = 0; iter < algo->spk_count; iter++) { + int32_t re_range[2] = {0}; + + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_RE_RANGE, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)re_range, param_id, + TAS_GET_PARAM, sizeof(re_range), TISA_MOD_RX); + if (ret < 0) { + pr_err("[TI-SmartPA:%s]get re low fail channel no %d Exiting ..\n", __func__, iter); + return ret; + } + + re_low[iter] = re_range[0] >> 8; /* Qformat 27 -> 19*/ + re_high[iter] = re_range[1] >> 8; /* Qformat 27 -> 19*/ + + pr_info("[TI-SmartPA:%s] Channel No:%d, Rdc Limits(%02d.%02d ~ %02d.%02d) \n", __func__, iter, + (int32_t)trans_val_to_user_i(re_low[iter], QFORMAT19), (int32_t)trans_val_to_user_m(re_low[iter], QFORMAT19), + (int32_t)trans_val_to_user_i(re_high[iter], QFORMAT19), (int32_t)trans_val_to_user_m(re_high[iter], QFORMAT19)); + } + return 0; +} + +int tas25xx_check_limits(uint8_t channel, int32_t rdc) +{ + if ((rdc >= re_low[channel]) && (rdc <= re_high[channel])) { + calibration_result[channel] = STATUS_SUCCESS; + return 1; + } + calibration_result[channel] = STATUS_FAIL; + return 0; +} + +void tas25xx_send_algo_calibration(void) +{ + uint32_t calib_re = 0; + uint32_t amb_temp = 0; + uint32_t data = 0; + uint32_t param_id = 0; + uint8_t iter; + int32_t ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return; + } + + for (iter = 0; iter < algo->spk_count; iter++) { + if (!(algo->calib_update[iter])) { + algo->calib_update[iter] = true; + + ret = tas25xx_get_efs_data(&calib_re, RDC_L + iter*2); + if (ret < 0) { + algo->calib_update[iter] = false; + } + + ret = tas25xx_get_efs_data(&amb_temp, TEMP_L + iter*2); + if (ret < 0) { + algo->calib_update[iter] = false; + } + + if (algo->calib_update[iter]) { + algo->calib_re[iter] = calib_re; + algo->amb_temp[iter] = amb_temp; + } + } + + if (algo->calib_update[iter]) { + /*Set ambient temperature*/ + data = algo->amb_temp[iter]; + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_TCAL, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + + /*Set Re*/ + data = algo->calib_re[iter]; + param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + } + } +} + +static int tas25xx_save_calib_data(uint32_t *calib_rdc) +{ + uint8_t iter = 0; + int ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + ret = PTR_ERR(algo); + return ret; + } + + if (!calib_rdc) { + pr_err("[TI-SmartPA:%s] argument is Null\n", __func__); + ret = -EINVAL; + return ret; + } + + for (iter = 0; iter < algo->spk_count; iter++) { + calib_re_hold[iter] = calib_rdc[iter]; + amb_temp_hold[iter] = tas25xx_get_amb_temp(); + } + return 0; +} + +/*******************************Calibration Related Codes Start*************************************/ +/* Forward declerations */ +static ssize_t tas25xx_calib_calibration_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size); + +static ssize_t tas25xx_calib_calibration_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_calib_status_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_calib_rdc_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_amb_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static void calib_work_routine(struct work_struct *work) +{ + uint8_t iter = 0, iter2 = 0; + uint32_t data = 0; + uint32_t param_id = 0; + uint32_t calib_re[MAX_CHANNELS] = {0}; + int32_t ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + return; + } + + if (tas25xx_update_calibration_limits()) + return; + + /*Get Re*/ + for (iter2 = 0; iter2 < CALIB_RETRY_COUNT; iter2++) { + for (iter = 0; iter < algo->spk_count; iter++) { + if (calibration_result[iter] == STATUS_SUCCESS) + continue; + + /*Calinration Init*/ + data = 1;/*Value is ignored*/ + param_id = TAS_CALC_PARAM_IDX(TAS_SA_CALIB_INIT, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + if (ret < 0) { + pr_err("[TI-SmartPA:%s] Init error. Exiting ..\n", __func__); + return; + } + + msleep(CALIB_TIME*1000); + + data = 0;//Reset data to 0 + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_RE, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_GET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + if (ret < 0) { + calibration_result[iter] = STATUS_FAIL; + pr_info("[TI-SmartPA:%s]get re fail. Exiting ..\n", __func__); + } else { + calib_re[iter] = data; + pr_info("[TI-SmartPA:%s]calib_re is %02d.%02d (%d) \n", __func__, + (int32_t)trans_val_to_user_i(calib_re[iter], QFORMAT19), (int32_t)trans_val_to_user_m(calib_re[iter], QFORMAT19), + (int32_t)calib_re[iter]); + if (tas25xx_check_limits(iter, calib_re[iter])) + pr_info("[TI-SmartPA:%s] Calibration Pass Channel No:%d\n", __func__, iter); + } + + /*Calibration De-Init*/ + data = 1;//Value is ignored + param_id = TAS_CALC_PARAM_IDX(TAS_SA_CALIB_DEINIT, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id + , TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + /*Wait some time*/ + msleep(200); + } + } + tas25xx_save_calib_data(calib_re); + + calibration_status = 0; + return; +} + +static DEVICE_ATTR(calibration, 0664, tas25xx_calib_calibration_show, + tas25xx_calib_calibration_store); + +static DEVICE_ATTR(cstatus, 0664, tas25xx_calib_status_show, + NULL); + +static DEVICE_ATTR(rdc, 0664, tas25xx_calib_rdc_show, + NULL); + +static DEVICE_ATTR(temp, 0664, tas25xx_amb_temp_show, + NULL); + +static DEVICE_ATTR(cstatus_r, 0664, tas25xx_calib_status_show, + NULL); + +static DEVICE_ATTR(rdc_r, 0664, tas25xx_calib_rdc_show, + NULL); + +static DEVICE_ATTR(temp_r, 0664, tas25xx_amb_temp_show, + NULL); + +static ssize_t tas25xx_calib_calibration_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int32_t ret = 0; + int32_t start; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + ret = PTR_ERR(algo); + goto end; + } + + ret = kstrtos32(buf, 10, &start); + if (ret) { + pr_err("[TI-SmartPA:%s] Invalid input\n", __func__); + goto end; + } + + if (start) { + calibration_status = 1; + /*Give time for algorithm to converge rdc*/ + schedule_delayed_work(&algo->calib_work, + msecs_to_jiffies(200)); + } +end: + return size; +} + +static ssize_t tas25xx_calib_calibration_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /*Enough to check for only one channel*/ + return snprintf(buf, MAX_STRING, "%s\n", + (calibration_status) ? "Enabled" : "Disabled"); +} + +static ssize_t tas25xx_calib_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret = 0; + + if (attr == &dev_attr_cstatus_r) + ret = snprintf(buf, MAX_STRING, "%d", calibration_result[1]); + else + ret = snprintf(buf, MAX_STRING, "%d", calibration_result[0]); + + return ret; +} + +static ssize_t tas25xx_calib_rdc_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + uint32_t calib_re = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + ret = PTR_ERR(algo); + return ret; + } + + if (attr == &dev_attr_rdc_r) { + if (calibration_result[1] == STATUS_NONE) { + if (algo->calib_update[1]) + calib_re = algo->calib_re[1]; + else + tas25xx_get_efs_data(&calib_re, RDC_R); + } else + calib_re = calib_re_hold[1]; + + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(calib_re, QFORMAT19), (int32_t)trans_val_to_user_m(calib_re, QFORMAT19)); + } else { + if (calibration_result[0] == STATUS_NONE) { + if (algo->calib_update[0]) + calib_re = algo->calib_re[0]; + else + tas25xx_get_efs_data(&calib_re, RDC_L); + } else + calib_re = calib_re_hold[0]; + + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(calib_re, QFORMAT19), (int32_t)trans_val_to_user_m(calib_re, QFORMAT19)); + } + + return ret; +} + +static ssize_t tas25xx_amb_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + uint32_t amb_temp = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + ret = PTR_ERR(algo); + return ret; + } + + if (attr == &dev_attr_temp_r) { + if (calibration_result[1] == STATUS_NONE) { + if (algo->calib_update[1]) + amb_temp = algo->amb_temp[1]; + else + tas25xx_get_efs_data(&amb_temp, TEMP_R); + } else + amb_temp = amb_temp_hold[1]; + + ret = snprintf(buf, MAX_STRING, "%d", amb_temp); + } else { + if (calibration_result[0] == STATUS_NONE) { + if (algo->calib_update[0]) + amb_temp = algo->amb_temp[0]; + else + tas25xx_get_efs_data(&amb_temp, TEMP_L); + } else + amb_temp = amb_temp_hold[0]; + + ret = snprintf(buf, MAX_STRING, "%d", amb_temp); + } + + return ret; +} + +static struct attribute *tas25xx_calib_attr[] = { + &dev_attr_calibration.attr, + &dev_attr_cstatus.attr, + &dev_attr_rdc.attr, + &dev_attr_temp.attr, +}; + +static struct attribute *tas25xx_calib_attr_r[] = { + &dev_attr_cstatus_r.attr, + &dev_attr_rdc_r.attr, + &dev_attr_temp_r.attr, +}; + +static struct attribute *tas25xx_calib_attr_m[ + ARRAY_SIZE(tas25xx_calib_attr) + + ARRAY_SIZE(tas25xx_calib_attr_r) + 1] = {NULL}; + +static struct attribute_group tas25xx_calib_attr_grp = { + .attrs = tas25xx_calib_attr_m, +}; + +/*******************************Calibration Related Codes End*************************************/ +/*******************************Validation Related Codes Start*************************************/ +/* Forward Declarations */ +static ssize_t tas25xx_valid_validation_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size); + +static ssize_t tas25xx_valid_validation_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_valid_status_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static void valid_work_routine(struct work_struct *work) +{ + uint8_t iter = 0; + uint32_t data = 0; + uint32_t param_id = 0; + int32_t ret = 0; + + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! memory not allocated yet!!\n", __func__); + return; + } + + //Get Validation Status + for (iter = 0; iter < algo->spk_count; iter++) { + data = 0;//Reset data to 0 + param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_VALID_STATUS, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_GET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + if (ret < 0) { + validation_result[iter] = STATUS_FAIL; + pr_info("[TI-SmartPA:%s]status read failed \n", __func__); + } else { + if (data == VALIDATION_SUCCESS) { + validation_result[iter] = STATUS_SUCCESS; + } else { + validation_result[iter] = STATUS_FAIL; + } + } + pr_info("[TI-SmartPA:%s] Channel-%d\n", __func__, iter); + pr_info("[TI-SmartPA:%s] validation_result %s(0x%x)\n", __func__, + validation_result[iter] == STATUS_SUCCESS ? "Success" : "Fail\n", (int32_t)data); + + /*De-Init the validation process*/ + data = 0; //Value is ignored + param_id = TAS_CALC_PARAM_IDX(TAS_SA_VALID_DEINIT, 1, (iter+1)); + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id, + TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + } + validation_running_status = 0; +} + +static DEVICE_ATTR(validation, 0644, tas25xx_valid_validation_show, + tas25xx_valid_validation_store); + +static DEVICE_ATTR(status, 0644, tas25xx_valid_status_show, + NULL); + +static DEVICE_ATTR(status_r, 0644, tas25xx_valid_status_show, + NULL); + +static ssize_t tas25xx_valid_validation_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + uint8_t iter = 0; + uint32_t data = 0; + uint32_t param_id = 0; + int32_t start = 0; + int32_t ret = 0; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! Error memory allocation\n", __func__); + ret = PTR_ERR(algo); + goto end; + } + + ret = kstrtos32(buf, 10, &start); + if (ret) { + pr_err("[TI-SmartPA:%s] Invalid input\n", __func__); + goto end; + } + + if (start) { + //Init + for (iter = 0; iter < algo->spk_count; iter++) { + data = 1;/*Value is ignored*/ + param_id = TAS_CALC_PARAM_IDX(TAS_SA_VALID_INIT, 1, (iter+1)); + + ret = tas25xx_smartamp_algo_ctrl((u8 *)&data, param_id + , TAS_SET_PARAM, sizeof(uint32_t), TISA_MOD_RX); + if (ret < 0) { + pr_err("[TI-SmartPA:%s] Init error. Exiting ..", __func__); + goto end; + } + } + + //Give time for algorithm to converge V-sns level + validation_running_status = 1; + schedule_delayed_work(&algo->valid_work, + msecs_to_jiffies(VALIDATION_TIME * 1000)); + } +end: + return size; +} + +static ssize_t tas25xx_valid_validation_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, MAX_STRING, "%s\n", + (validation_running_status) ? "Enabled" : "Disabled"); +} + +static ssize_t tas25xx_valid_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + + if (attr == &dev_attr_status_r) { + ret = snprintf(buf, MAX_STRING, "%d", validation_result[1]); + } else { + ret = snprintf(buf, MAX_STRING, "%d", validation_result[0]); + } + return ret; +} + +static struct attribute *tas25xx_valid_attr[] = { + &dev_attr_validation.attr, + &dev_attr_status.attr, +}; + +static struct attribute *tas25xx_valid_attr_r[] = { + &dev_attr_status_r.attr, +}; + +static struct attribute *tas25xx_valid_attr_m[ + ARRAY_SIZE(tas25xx_valid_attr) + + ARRAY_SIZE(tas25xx_valid_attr_r) + 1] = {NULL}; + +static struct attribute_group tas25xx_valid_attr_grp = { + .attrs = tas25xx_valid_attr_m, +}; +/*******************************Validation Related Codes End*************************************/ +/*******************************BigData Related Codes Start*************************************/ +/* Forward Declarations */ +static ssize_t tas25xx_bd_exc_max_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_bd_exc_max_persist_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_bd_exc_over_count_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_bd_temp_max_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_bd_temp_max_persist_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t tas25xx_bd_temp_over_count_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static DEVICE_ATTR(exc_max, 0664, tas25xx_bd_exc_max_show, + NULL); + +static DEVICE_ATTR(exc_max_persist, 0664, tas25xx_bd_exc_max_persist_show, + NULL); + +static DEVICE_ATTR(exc_over_count, 0664, tas25xx_bd_exc_over_count_show, + NULL); + +static DEVICE_ATTR(temp_max, 0664, tas25xx_bd_temp_max_show, + NULL); + +static DEVICE_ATTR(temp_max_persist, 0664, tas25xx_bd_temp_max_persist_show, + NULL); + +static DEVICE_ATTR(temp_over_count, 0664, tas25xx_bd_temp_over_count_show, + NULL); + +static DEVICE_ATTR(exc_max_r, 0664, tas25xx_bd_exc_max_show, + NULL); + +static DEVICE_ATTR(exc_max_persist_r, 0664, tas25xx_bd_exc_max_persist_show, + NULL); + +static DEVICE_ATTR(exc_over_count_r, 0664, tas25xx_bd_exc_over_count_show, + NULL); + +static DEVICE_ATTR(temp_max_r, 0664, tas25xx_bd_temp_max_show, + NULL); + +static DEVICE_ATTR(temp_max_persist_r, 0664, tas25xx_bd_temp_max_persist_show, + NULL); + +static DEVICE_ATTR(temp_over_count_r, 0664, tas25xx_bd_temp_over_count_show, + NULL); + +static ssize_t tas25xx_bd_exc_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] failed !! Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_exc_max_r) { + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(algo->b_data[1].exc_max, QFORMAT31), + (int32_t)trans_val_to_user_m(algo->b_data[1].exc_max, QFORMAT31)); + algo->b_data[1].exc_max = 0; + } else { + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(algo->b_data[0].exc_max, QFORMAT31), + (int32_t)trans_val_to_user_m(algo->b_data[0].exc_max, QFORMAT31)); + algo->b_data[0].exc_max = 0; + } + + return ret; +} + +static ssize_t tas25xx_bd_exc_max_persist_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_exc_max_persist_r) { + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(algo->b_data[1].exc_max_persist, QFORMAT31), + (int32_t)trans_val_to_user_m(algo->b_data[1].exc_max_persist, QFORMAT31)); + } else { + ret = snprintf(buf, MAX_STRING, "%02d.%02d", + (int32_t)trans_val_to_user_i(algo->b_data[0].exc_max_persist, QFORMAT31), + (int32_t)trans_val_to_user_m(algo->b_data[0].exc_max_persist, QFORMAT31)); + } + + return ret; +} + +static ssize_t tas25xx_bd_exc_over_count_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_exc_over_count_r) { + ret = snprintf(buf, MAX_STRING, "%d", + algo->b_data[1].exc_over_count); + } else { + ret = snprintf(buf, MAX_STRING, "%d", + algo->b_data[0].exc_over_count); + } + + return ret; +} + +static ssize_t tas25xx_bd_temp_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_temp_max_r) { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[1].temp_max); + algo->b_data[1].temp_max = 0; + } else { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[0].temp_max); + algo->b_data[0].temp_max = 0; + } + + return ret; +} + +static ssize_t tas25xx_bd_temp_max_persist_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_temp_max_persist_r) { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[1].temp_max_persist); + } else { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[0].temp_max_persist); + } + + return ret; +} + +static ssize_t tas25xx_bd_temp_over_count_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + return PTR_ERR(algo); + } + + if (attr == &dev_attr_temp_over_count_r) { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[1].temp_over_count); + } else { + ret = snprintf(buf, MAX_STRING, "%d", algo->b_data[0].temp_over_count); + } + + return ret; +} + +static struct attribute *tas25xx_bd_attr[] = { + &dev_attr_exc_max.attr, + &dev_attr_exc_max_persist.attr, + &dev_attr_exc_over_count.attr, + &dev_attr_temp_max.attr, + &dev_attr_temp_max_persist.attr, + &dev_attr_temp_over_count.attr, +}; + +static struct attribute *tas25xx_bd_attr_r[] = { + &dev_attr_exc_max_r.attr, + &dev_attr_exc_max_persist_r.attr, + &dev_attr_exc_over_count_r.attr, + &dev_attr_temp_max_r.attr, + &dev_attr_temp_max_persist_r.attr, + &dev_attr_temp_over_count_r.attr, +}; + +static struct attribute *tas25xx_bd_attr_m[ + ARRAY_SIZE(tas25xx_bd_attr) + + ARRAY_SIZE(tas25xx_bd_attr_r) + 1] = {NULL}; + +static struct attribute_group tas25xx_bd_attr_grp = { + .attrs = tas25xx_bd_attr_m, +}; + +/*******************************BigData Related Codes End*************************************/ + +static void clean_up_tas_sysfs (void) +{ + if (p_tas25xx_algo) { + struct tas25xx_algo *algo = p_tas25xx_algo; + if (algo->calib_dev) { + sysfs_remove_group (&algo->calib_dev->kobj, &tas25xx_calib_attr_grp); + device_destroy (algo->algo_class, 1); + } + + if (algo->valid_dev) { + sysfs_remove_group (&algo->valid_dev->kobj, &tas25xx_valid_attr_grp); + device_destroy (algo->algo_class, 1); + } + + if (algo->bd_dev) { + sysfs_remove_group (&algo->bd_dev->kobj, &tas25xx_bd_attr_grp); + device_destroy (algo->algo_class, 1); + } + + if (algo->algo_class) { + class_destroy (algo->algo_class); + } + + kfree (p_tas25xx_algo); + p_tas25xx_algo = NULL; + } +} + +void tas25xx_algo_add_calib_valid_bigdata(uint8_t channels) +{ + int32_t ret = 0; + struct tas25xx_algo *algo = smartamp_get_sysfs_ptr(); + + if (IS_ERR(algo)) { + pr_err("[TI-SmartPA:%s] Error memory allocation\n", __func__); + ret = PTR_ERR(algo); + goto err_dev; + } + + pr_info("[TI-SmartPA:%s] Adding Smartamp algo functions, spk_count=%d\n", + __func__, channels); + algo->spk_count = channels; + + memcpy(tas25xx_calib_attr_m, tas25xx_calib_attr, sizeof(tas25xx_calib_attr)); + memcpy(tas25xx_valid_attr_m, tas25xx_valid_attr, sizeof(tas25xx_valid_attr)); + memcpy(tas25xx_bd_attr_m, tas25xx_bd_attr, sizeof(tas25xx_bd_attr)); + if (channels == 2) { + memcpy(tas25xx_calib_attr_m + ARRAY_SIZE(tas25xx_calib_attr), + tas25xx_calib_attr_r, sizeof(tas25xx_calib_attr_r)); + memcpy(tas25xx_valid_attr_m + ARRAY_SIZE(tas25xx_valid_attr), + tas25xx_valid_attr_r, sizeof(tas25xx_valid_attr_r)); + memcpy(tas25xx_bd_attr_m + ARRAY_SIZE(tas25xx_bd_attr), + tas25xx_bd_attr_r, sizeof(tas25xx_bd_attr_r)); + } + + algo->algo_class = class_create(THIS_MODULE, TAS25XX_SYSFS_CLASS_NAME); + if (IS_ERR(algo->algo_class)) { + ret = PTR_ERR(algo->algo_class); + pr_err("[TI-SmartPA:%s] err class create\n", __func__); + algo->algo_class = NULL; + goto err_dev; + } + + algo->calib_dev = device_create(algo->algo_class, NULL, 1, NULL, TAS25XX_CALIB_DIR_NAME); + if (IS_ERR(algo->calib_dev)) { + pr_err("[TI-SmartPA:%s]Failed to create calib_dev\n", __func__); + ret = PTR_ERR(algo->calib_dev); + algo->calib_dev = NULL; + goto err_dev; + } + + ret = sysfs_create_group(&algo->calib_dev->kobj, &tas25xx_calib_attr_grp); + if (ret) { + pr_err("[TI-SmartPA:%s]Failed to create sysfs group\n", __func__); + goto err_dev; + } + + INIT_DELAYED_WORK(&algo->calib_work, calib_work_routine); + + algo->valid_dev = device_create(algo->algo_class, NULL, 1, NULL, + TAS25XX_VALID_DIR_NAME); + if (IS_ERR(algo->valid_dev)) { + pr_err("[TI-SmartPA:%s]Failed to create valid_dev\n", __func__); + ret = PTR_ERR(algo->valid_dev); + algo->valid_dev = NULL; + goto err_dev; + } + + ret = sysfs_create_group(&algo->valid_dev->kobj, &tas25xx_valid_attr_grp); + if (ret) { + pr_err("[TI-SmartPA:%s]Failed to create sysfs group\n", __func__); + algo->valid_dev = NULL; + goto err_dev; + } + + INIT_DELAYED_WORK(&algo->valid_work, valid_work_routine); + + algo->bd_dev = device_create(algo->algo_class, NULL, 1, NULL, + TAS25XX_BD_DIR_NAME); + if (IS_ERR(algo->bd_dev)) { + pr_err("[TI-SmartPA:%s]Failed to create bd_dev\n", __func__); + ret = PTR_ERR(algo->bd_dev); + algo->bd_dev = NULL; + goto err_dev; + } + + ret = sysfs_create_group(&algo->bd_dev->kobj, &tas25xx_bd_attr_grp); + if (ret) { + pr_err("[TI-SmartPA:%s]Failed to create sysfs group\n", __func__); + algo->bd_dev = NULL; + goto err_dev; + } + + pr_info ("[TI-SmartPA:%s] ret=%d\n", __func__, ret); + return; + +err_dev: + clean_up_tas_sysfs(); + pr_err("[TI-SmartPA:%s] Error %d\n", __func__, ret); +} + +void tas25xx_algo_remove_calib_valid_bigdata(void) +{ + pr_info("[TI-SmartPA:%s] Removing Smartamp Algorithm functions\n", __func__); + clean_up_tas_sysfs(); +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS25XX Algorithm"); +MODULE_LICENSE("GPL v2"); + +#endif /*CONFIG_TAS25XX_ALGO*/ diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.h b/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.h new file mode 100644 index 00000000..d7534e1f --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-calib-validation.h @@ -0,0 +1,85 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas25xx-calib-validataion.h +** +** Description: +** header file for calibration and validataion interface to SmartPA +** +** ============================================================================= +*/ + +#ifndef _TAS25XX_ALGO_H +#define _TAS25XX_ALGO_H + +#define MAX_STRING 200 +#define CALIB_RETRY_COUNT 5 +#define RDC_L 0 +#define TEMP_L 1 +#define RDC_R 2 +#define TEMP_R 3 +#define DEFAULT_AMBIENT_TEMP 25 +#define CALIB_TIME 2 +#define VALIDATION_TIME 3 +#define STATUS_NONE 0x00 +#define STATUS_SUCCESS 0x01 +#define STATUS_FAIL 0xcc + +#define TAS_SA_GET_RE_LOW 398 +#define TAS_SA_GET_RE_HIGH 399 +#define VALIDATION_SUCCESS 0xC00DC00D + +#define TRANSF_USER_TO_IMPED(X, Y) \ + ((X << 19) + ((Y << 19) / 100)) +#define QFORMAT19 19 +#define QFORMAT31 31 + +#define TAS25XX_SYSFS_CLASS_NAME "tas25xx" +#define TAS25XX_CALIB_DIR_NAME "calib" +#define TAS25XX_VALID_DIR_NAME "valid" +#define TAS25XX_BD_DIR_NAME "bigdata" + +#define TAS25XX_EFS_CALIB_DATA_L "/efs/tas25xx/calib_re" +#define TAS25XX_EFS_TEMP_DATA_L "/efs/tas25xx/amb_temp" +#define TAS25XX_EFS_CALIB_DATA_R "/efs/tas25xx/calib_re_r" +#define TAS25XX_EFS_TEMP_DATA_R "/efs/tas25xx/amb_temp_r" + +struct big_data { + uint32_t exc_max; + uint32_t exc_max_persist; + uint32_t exc_over_count; + uint32_t temp_max; + uint32_t temp_max_persist; + uint32_t temp_over_count; +}; + +struct tas25xx_algo { + struct class *algo_class; + struct device *calib_dev; + struct device *valid_dev; + struct device *bd_dev; + struct big_data b_data[MAX_CHANNELS]; + struct delayed_work calib_work; + struct delayed_work valid_work; + uint8_t spk_count; + uint32_t port; + uint32_t calib_re[MAX_CHANNELS]; + uint32_t amb_temp[MAX_CHANNELS]; + bool calib_update[MAX_CHANNELS]; +}; + +void tas25xx_algo_add_calib_valid_bigdata(uint8_t channels); +void tas25xx_algo_remove_calib_valid_bigdata(void); +struct tas25xx_algo *smartamp_get_sysfs_ptr(void); + +#endif /* _TAS25XX_ALGO_H */
\ No newline at end of file diff --git a/asoc/codecs/tas256x/algo/src/tas25xx-calib.c b/asoc/codecs/tas256x/algo/src/tas25xx-calib.c new file mode 100644 index 00000000..3af138d3 --- /dev/null +++ b/asoc/codecs/tas256x/algo/src/tas25xx-calib.c @@ -0,0 +1,196 @@ +/* +** ============================================================================= +** Copyright (c) 2017 Texas Instruments Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details +** +** File: +** tas25xx-calib.c +** +** Description: +** misc driver for interfacing for Texas Instruments TAS25xx algorithm +** +** ============================================================================= +*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/device.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/miscdevice.h> +#include "algo/inc/tas_smart_amp_v2.h" +#include "tas25xx-algo-intf.h" + +#define TAS_PAYLOAD_SIZE 14 + +/* Holds the Packet data required for processing */ +struct tas_dsp_pkt { + u8 slave_id; + u8 book; + u8 page; + u8 offset; + u8 data[TAS_PAYLOAD_SIZE * 4]; +}; + +static int smartamp_params_ctrl(uint8_t *input, u8 dir, u8 count) +{ + u32 length = count / 4; + u32 paramid = 0; + u32 index; + int ret = 0; + int special_index = 0; + struct tas_dsp_pkt *ppacket; + + if (length >= TAS_PAYLOAD_SIZE) { + pr_err("TI-SmartPA: %s: Unsupported length!", __func__); + return -EINVAL; + } + + ppacket = (struct tas_dsp_pkt *)kmalloc(sizeof(struct tas_dsp_pkt), + GFP_KERNEL); + if (!ppacket) { + pr_err("TI-SmartPA: %s: kmalloc failed!", __func__); + return -ENOMEM; + } + + memset(ppacket, 0, sizeof(struct tas_dsp_pkt)); + ret = copy_from_user(ppacket, input, sizeof(struct tas_dsp_pkt)); + if (ret) { + pr_err("TI-SmartPA: %s: Error copying from user\n", __func__); + kfree(ppacket); + return -EFAULT; + } + + index = (ppacket->page - 1) * 30 + (ppacket->offset - 8) / 4; + special_index = TAS_SA_IS_SPL_IDX(index); + pr_info("TI-SmartPA: %s: index = %d", __func__, index); + if (special_index == 0) { + if ((index < 0 || index > MAX_DSP_PARAM_INDEX)) { + pr_err("TI-SmartPA: %s: invalid index !\n", __func__); + kfree(ppacket); + return -EINVAL; + } + } + pr_info("TI-SmartPA: %s: Valid Index. special = %s\n", + __func__, special_index ? "Yes" : "No"); + + /* speakers are differentiated by slave ids */ + if (ppacket->slave_id == SLAVE1) { + paramid = TAS_CALC_PARAM_IDX(index, length, CHANNEL0); + pr_err("TI-SmartPA: %s: Rcvd Slave id for slave 1, %x\n", __func__, ppacket->slave_id); + } else if (ppacket->slave_id == SLAVE2) { + paramid = TAS_CALC_PARAM_IDX(index, length, CHANNEL1); + pr_err("TI-SmartPA: %s: Rcvd Slave id for slave 2, %x\n", __func__, ppacket->slave_id); + } else { + pr_err("TI-SmartPA: %s: Wrong slaveid = %x\n", + __func__, ppacket->slave_id); + } + + ret = tas25xx_smartamp_algo_ctrl(ppacket->data, paramid, + dir, length * 4, 0/*Default to Rx*/); + if (ret) + pr_err("TI-SmartPA: %s: %s Slave 0x%x params failed from afe, ret=%x\n", + __func__, + dir == TAS_GET_PARAM ? "get" : "set", + ppacket->slave_id, ret); + else + pr_info("TI-SmartPA: %s: Algo control returned %d\n", + __func__, ret); + + if (dir == TAS_GET_PARAM) { + ret = copy_to_user(input, ppacket, sizeof(struct tas_dsp_pkt)); + if (ret) { + pr_err("TI-SmartPA: %s: Error copying to user after DSP", + __func__); + ret = -EFAULT; + } + } + + kfree(ppacket); + return ret; +} + +static int tas_calib_open(struct inode *inode, struct file *fd) +{ + return 0; +} + +static ssize_t tas_calib_write(struct file *file, + const char __user *buffer, size_t count, loff_t *offp) +{ + int rc = 0; + + rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_SET_PARAM, count); + return rc; +} + +static ssize_t tas_calib_read(struct file *file, char __user *buffer, + size_t count, loff_t *ptr) +{ + int rc; + + rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_GET_PARAM, count); + if (rc < 0) + count = rc; + return count; +} + +static long tas_calib_ioctl(struct file *filp, uint cmd, ulong arg) +{ + return 0; +} + +static int tas_calib_release(struct inode *inode, struct file *fd) +{ + return 0; +} + +const struct file_operations tas_calib_fops = { + .owner = THIS_MODULE, + .open = tas_calib_open, + .write = tas_calib_write, + .read = tas_calib_read, + .release = tas_calib_release, + .unlocked_ioctl = tas_calib_ioctl, +}; + +static struct miscdevice tas_calib_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "tas_calib", + .fops = &tas_calib_fops, +}; + +int tas_calib_init(void) +{ + int rc; + + pr_info("TI-SmartPA: %s", __func__); + rc = misc_register(&tas_calib_misc); + if (rc) + pr_err("TI-SmartPA: %s: register calib misc failed\n", + __func__); + return rc; +} + +void tas_calib_exit(void) +{ + misc_deregister(&tas_calib_misc); +} + +/* +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("tas2560 Misc driver"); +MODULE_LICENSE("GPL v2"); +*/ diff --git a/asoc/codecs/tas256x/logical_layer/inc/smartpa-debug-common.h b/asoc/codecs/tas256x/logical_layer/inc/smartpa-debug-common.h new file mode 100644 index 00000000..14bde3d2 --- /dev/null +++ b/asoc/codecs/tas256x/logical_layer/inc/smartpa-debug-common.h @@ -0,0 +1,7 @@ +#ifndef __SMARTPA_DEGUG_COMMON_H__ +#define __SMARTPA_DEGUG_COMMON_H__ +#include <linux/i2c.h> + +int smartpa_debug_probe(struct i2c_client *client); + +#endif diff --git a/asoc/codecs/tas256x/logical_layer/inc/tas256x-logic.h b/asoc/codecs/tas256x/logical_layer/inc/tas256x-logic.h new file mode 100644 index 00000000..695e088d --- /dev/null +++ b/asoc/codecs/tas256x/logical_layer/inc/tas256x-logic.h @@ -0,0 +1,29 @@ +#ifndef __TAS256X_LOGIC_ +#define __TAS256X_LOGIC_ + +#include "physical_layer/inc/tas256x.h" + +#define TAS256X_STREAM_PLAYBACK 0 +#define TAS256X_STREAM_CAPTURE 1 + +int tas256x_register_device(struct tas256x_priv *p_tas256x); +int tas256x_probe(struct tas256x_priv *p_tas256x); +void tas256x_remove(struct tas256x_priv *p_tas256x); +int tas256x_load_init(struct tas256x_priv *p_tas256x); +int tas256x_irq_work_func(struct tas256x_priv *p_tas256x); +void tas256x_load_config(struct tas256x_priv *p_tas256x); +int tas256x_init_work_func(struct tas256x_priv *p_tas256x); +int tas256x_dc_work_func(struct tas256x_priv *p_tas256x, int ch); +void tas_reload(struct tas256x_priv *p_tas256x, int chn); +int tas256x_set_power_state(struct tas256x_priv *p_tas256x, + int state); +int tas256x_iv_vbat_slot_config(struct tas256x_priv *p_tas256x, + int mn_slot_width); +int tas256x_set_bitwidth(struct tas256x_priv *p_tas256x, + int bitwidth, int stream); +int tas256x_set_tdm_rx_slot(struct tas256x_priv *p_tas256x, + int slots, int slot_width); +int tas256x_set_tdm_tx_slot(struct tas256x_priv *p_tas256x, + int slots, int slot_width); + +#endif /*__TAS256X_LOGIC_*/
\ No newline at end of file diff --git a/asoc/codecs/tas256x/logical_layer/src/smartpa-debug-common.c b/asoc/codecs/tas256x/logical_layer/src/smartpa-debug-common.c new file mode 100644 index 00000000..753318a9 --- /dev/null +++ b/asoc/codecs/tas256x/logical_layer/src/smartpa-debug-common.c @@ -0,0 +1,214 @@ +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/serial_core.h> +#include <linux/dma-mapping.h> +#include <linux/device.h> +#include <linux/miscdevice.h> + +#include "logical_layer/inc/smartpa-debug-common.h" + +#define AM_DEV_NAME "smartpa" +#define MSGS_SIZE 256 +#define RESERVED_SIZE 252 + +struct smartpa_msg { + char msgs[MSGS_SIZE]; + char reserved[RESERVED_SIZE]; + int msg_result; +}; + +struct smartpa_prars { + int fRes_max; + int fRes_min; + int Qt; + int impedance_max; + int impedance_min; +}; + +#define TFA_CTL_IOC_MAGIC 'T' +#define TFA_IOCTL_SPK_REST _IOW(TFA_CTL_IOC_MAGIC, 0x01, int) +#define TFA_IOCTL_SPK_INTS _IOR(TFA_CTL_IOC_MAGIC, 0x02, struct smartpa_msg) +#define TFA_IOCTL_SPK_INTT _IOW(TFA_CTL_IOC_MAGIC, 0x03, int) +#define TFA_IOCTL_SPK_RFDES _IOR(TFA_CTL_IOC_MAGIC, 0x04, struct smartpa_msg) +#define TFA_IOCTL_SPK_CHCK _IOR(TFA_CTL_IOC_MAGIC, 0x05, int) +#define TFA_IOCTL_SPK_PRARS _IOR(TFA_CTL_IOC_MAGIC, 0x06, struct smartpa_prars) +#define TFA_IOCTL_SPK_ADDR _IOW(TFA_CTL_IOC_MAGIC, 0x07, unsigned char) +#define TFA_IOCTL_SPK_MTP_BACKUP _IOR(TFA_CTL_IOC_MAGIC, 0x08, int) + +extern int smartpa_check_calib_dbg(void); +extern int smartpa_init_dbg(char *buffer, int size); +extern int smartpa_read_freq_dbg(char *buffer, int size); +extern void smartpa_read_prars_dbg(int temp[5], unsigned char addr); +extern void smartpa_get_client(struct i2c_client **client, unsigned char addr); + +static struct i2c_client *smartpa_debug_client; +static unsigned char last_addr; + +static ssize_t smartpa_debug_read(struct file *file, + char __user *buf, size_t count, loff_t *offset) +{ + char *tmp; + int ret; + + smartpa_get_client(&smartpa_debug_client, last_addr); + tmp = kmalloc(count, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; + + ret = i2c_master_recv(smartpa_debug_client, tmp, count); + if (ret >= 0) + ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; + else + printk("[SmartPA]%s: transfer error %d\n", __func__, ret); + kfree(tmp); + return ret; +} + +static ssize_t smartpa_debug_write(struct file *file, + const char __user *buf, size_t count, loff_t *offset) +{ + char *tmp; + int ret; + + smartpa_get_client(&smartpa_debug_client, last_addr); + tmp = memdup_user(buf, count); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + ret = i2c_master_send(smartpa_debug_client, tmp, count); + if (ret < 0) + printk("[SmartPA]%s: transfer error %d\n", __func__, ret); + kfree(tmp); + return ret; +} + +static long smartpa_debug_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = 0, check = 0; + int temp[5] = {0}; + struct smartpa_msg msg = {0}; + struct smartpa_prars prars = {0}; + + memset(&prars, 0, sizeof(struct smartpa_prars)); + memset(&msg, 0, sizeof(struct smartpa_msg)); + switch (cmd) { + /* Reset MTP */ + case TFA_IOCTL_SPK_REST: + printk("smartpa_ioctl SPK_REST\n"); + break; + /* calibrate */ + case TFA_IOCTL_SPK_INTS: + printk("smartpa_ioctl SPK_INTS\n"); + check = smartpa_init_dbg(msg.msgs, MSGS_SIZE); + msg.msg_result = check; + ret = copy_to_user((void *)arg, &msg, + sizeof(struct smartpa_msg)); + break; + case TFA_IOCTL_SPK_INTT: + + printk("smartpa_ioctl SPK_INT\n"); + break; + case TFA_IOCTL_SPK_RFDES: + usleep_range(10*1000, 10*1000); + printk("smartpa_ioctl SPK_ReadFDes\n"); + ret = smartpa_read_freq_dbg(msg.msgs, MSGS_SIZE); + ret = copy_to_user((void *)arg, &msg, + sizeof(struct smartpa_msg)); + break; + /* checkmtp */ + case TFA_IOCTL_SPK_CHCK: + printk("smartpa_ioctl SPK Check MtpEx\n"); + check = smartpa_check_calib_dbg(); + pr_info("%s check %d.\n", __func__, check); + ret = copy_to_user((__user int *)arg, &check, sizeof(int)); + break; + case TFA_IOCTL_SPK_PRARS: + printk("smartpa_ioctl SPK Read f0 and Qt\n"); + smartpa_read_prars_dbg(temp, last_addr); + prars.fRes_max = temp[0]; + prars.fRes_min = temp[1]; + prars.Qt = temp[2]; + prars.impedance_max = temp[3]; + prars.impedance_min = temp[4]; + ret = copy_to_user((void *)arg, &prars, + sizeof(struct smartpa_prars)); + pr_info("smartpa_ioctl %d %d %d\n", temp[0], temp[1], temp[2]); + break; + case TFA_IOCTL_SPK_ADDR: + ret = copy_from_user(&last_addr, (void __user *)arg, + sizeof(unsigned char)); + printk("smartpa_ioctl addr %x\n", last_addr); + break; + case TFA_IOCTL_SPK_MTP_BACKUP: + pr_info("%s mtp backup %d.\n", __func__, check); + default: + printk("smartpa Fail IOCTL command no such ioctl cmd = %x\n", + cmd); + ret = -1; + break; + } + + return ret; +} + +static int smartpa_debug_open( + struct inode *inode, struct file *file) +{ + printk("[SmartPA]%s\n", __func__); + return 0; +} + +int smartpa_debug_release( + struct inode *inode, struct file *file) +{ + printk("[SmartPA]%s\n", __func__); + return 0; +} + +static const struct file_operations smartpa_debug_fileops = { + .owner = THIS_MODULE, + .open = smartpa_debug_open, + .read = smartpa_debug_read, + .write = smartpa_debug_write, + .unlocked_ioctl = smartpa_debug_ioctl, + .release = smartpa_debug_release, +}; + +static struct miscdevice smartpa_debug_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = AM_DEV_NAME, + .fops = &smartpa_debug_fileops, +}; + +int smartpa_debug_probe(struct i2c_client *client) +{ + int err = 0; + + printk("%s\n", __func__); + + if (smartpa_debug_client) + return 0; + + err = misc_register(&smartpa_debug_device); + if (err) { + printk("%s: smartpa_device register failed\n", __func__); + return err; + } + + smartpa_debug_client = client; + + return 0; +} + +MODULE_DESCRIPTION("smartpa debug driver"); +MODULE_AUTHOR("chenjinquan <chenjinquan@vivo.com>"); +MODULE_LICENSE("GPL"); diff --git a/asoc/codecs/tas256x/logical_layer/src/tas256x-logic.c b/asoc/codecs/tas256x/logical_layer/src/tas256x-logic.c new file mode 100644 index 00000000..125d0a45 --- /dev/null +++ b/asoc/codecs/tas256x/logical_layer/src/tas256x-logic.c @@ -0,0 +1,1428 @@ +#include "logical_layer/inc/tas256x-logic.h" +#include "physical_layer/inc/tas256x-device.h" +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#include "algo/inc/tas_smart_amp_v2.h" +#include "algo/inc/tas25xx-calib.h" +#include "os_layer/inc/tas256x-regmap.h" +#endif /*CONFIG_TAS25XX_ALGO*/ + +static int tas256x_change_book_page(struct tas256x_priv *p_tas256x, + enum channel chn, + int book, int page) +{ + int n_result = 0, rc = 0; + int i = 0; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (((chn&channel_left) && (i == 0)) + || ((chn&channel_right) && (i == 1))) { + if (p_tas256x->devs[i]->mn_current_book != book) { + n_result = p_tas256x->plat_write(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_BOOKCTL_PAGE, 0); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%d, E=%d\n", + __func__, __LINE__, n_result); + rc |= n_result; + continue; + } + p_tas256x->devs[i]->mn_current_page = 0; + n_result = p_tas256x->plat_write(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_BOOKCTL_REG, book); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%d, E=%d\n", + __func__, __LINE__, n_result); + rc |= n_result; + continue; + } + p_tas256x->devs[i]->mn_current_book = book; + } + + if (p_tas256x->devs[i]->mn_current_page != page) { + n_result = p_tas256x->plat_write(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_BOOKCTL_PAGE, page); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%d, E=%d\n", + __func__, __LINE__, n_result); + rc |= n_result; + continue; + } + p_tas256x->devs[i]->mn_current_page = page; + } + } + } + + if (rc < 0) { + if (chn&channel_left) + p_tas256x->mn_err_code |= ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code |= ERROR_DEVB_I2C_COMM; + } else { + if (chn&channel_left) + p_tas256x->mn_err_code &= ~ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code &= ~ERROR_DEVB_I2C_COMM; + } + return rc; +} + +static int tas256x_dev_read(struct tas256x_priv *p_tas256x, + enum channel chn, + unsigned int reg, unsigned int *pValue) +{ + int n_result = 0; + int i = 0, chnTemp = 0; + + mutex_lock(&p_tas256x->dev_lock); + + if (chn == channel_both) { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + } + + n_result = tas256x_change_book_page(p_tas256x, chn, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg)); + if (n_result < 0) + goto end; + + /*Force left incase of mono*/ + if ((chn == channel_right) && (p_tas256x->mn_channels == 1)) + chn = channel_left; + + n_result = p_tas256x->plat_read(p_tas256x->platform_data, + p_tas256x->devs[chn >> 1]->mn_addr, + TAS256X_PAGE_REG(reg), pValue); + if (n_result < 0) { + pr_err("%s, ERROR, L=%d, E=%d\n", + __func__, __LINE__, n_result); + if (chn&channel_left) + p_tas256x->mn_err_code |= ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code |= ERROR_DEVB_I2C_COMM; + } else { + pr_debug( + "%s: chn:%x:BOOK:PAGE:REG 0x%02x:0x%02x:0x%02x,0x%02x\n", + __func__, + p_tas256x->devs[chn >> 1]->mn_addr, TAS256X_BOOK_ID(reg), + TAS256X_PAGE_ID(reg), + TAS256X_PAGE_REG(reg), *pValue); + if (chn&channel_left) + p_tas256x->mn_err_code &= ~ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code &= ~ERROR_DEVB_I2C_COMM; + } +end: + mutex_unlock(&p_tas256x->dev_lock); + return n_result; +} + +static int tas256x_dev_write(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned int value) +{ + int n_result = 0, rc = 0; + int i = 0, chnTemp = 0; + + mutex_lock(&p_tas256x->dev_lock); + + if (chn == channel_both) { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + } + + n_result = tas256x_change_book_page(p_tas256x, chn, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg)); + if (n_result < 0) + goto end; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (((chn&channel_left) && (i == 0)) + || ((chn&channel_right) && (i == 1))) { + n_result = p_tas256x->plat_write(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_PAGE_REG(reg), value); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%u, chn=0x%02x, E=%d\n", + __func__, __LINE__, + p_tas256x->devs[i]->mn_addr, n_result); + rc |= n_result; + if (chn&channel_left) + p_tas256x->mn_err_code |= ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code |= ERROR_DEVB_I2C_COMM; + } else { + pr_debug( + "%s: %u: chn:0x%02x:BOOK:PAGE:REG 0x%02x:0x%02x:0x%02x, VAL: 0x%02x\n", + __func__, __LINE__, + p_tas256x->devs[i]->mn_addr, + TAS256X_BOOK_ID(reg), + TAS256X_PAGE_ID(reg), + TAS256X_PAGE_REG(reg), value); + if (chn&channel_left) + p_tas256x->mn_err_code &= ~ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code &= ~ERROR_DEVB_I2C_COMM; + } + } + } +end: + mutex_unlock(&p_tas256x->dev_lock); + return rc; +} + +static int tas256x_dev_bulk_write(struct tas256x_priv *p_tas256x, + enum channel chn, + unsigned int reg, unsigned char *p_data, unsigned int n_length) +{ + int n_result = 0, rc = 0; + int i = 0, chnTemp = 0; + + mutex_lock(&p_tas256x->dev_lock); + + if (chn == channel_both) { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + } + + n_result = tas256x_change_book_page(p_tas256x, chn, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg)); + if (n_result < 0) + goto end; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (((chn&channel_left) && (i == 0)) + || ((chn&channel_right) && (i == 1))) { + n_result = p_tas256x->plat_bulk_write(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_PAGE_REG(reg), + p_data, n_length); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%u, chn=0x%02x: E=%d\n", + __func__, __LINE__, + p_tas256x->devs[i]->mn_addr, n_result); + rc |= n_result; + if (chn&channel_left) + p_tas256x->mn_err_code |= ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code |= ERROR_DEVB_I2C_COMM; + } else { + pr_debug( + "%s: chn%x:BOOK:PAGE:REG 0x%02x:0x%02x:0x%02x, len: %u\n", + __func__, p_tas256x->devs[i]->mn_addr, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg), + TAS256X_PAGE_REG(reg), n_length); + if (chn&channel_left) + p_tas256x->mn_err_code &= ~ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code &= ~ERROR_DEVB_I2C_COMM; + } + } + } + +end: + mutex_unlock(&p_tas256x->dev_lock); + return rc; +} + +static int tas256x_dev_bulk_read(struct tas256x_priv *p_tas256x, + enum channel chn, + unsigned int reg, unsigned char *p_data, unsigned int n_length) +{ + int n_result = 0; + int i = 0, chnTemp = 0; + + mutex_lock(&p_tas256x->dev_lock); + + if (chn == channel_both) { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + } + + n_result = tas256x_change_book_page(p_tas256x, chn, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg)); + if (n_result < 0) + goto end; + + n_result = p_tas256x->plat_bulk_read(p_tas256x->platform_data, + p_tas256x->devs[chn >> 1]->mn_addr, TAS256X_PAGE_REG(reg), + p_data, n_length); + if (n_result < 0) { + pr_err("%s, ERROR, L=%d, E=%d\n", + __func__, __LINE__, n_result); + if (chn&channel_left) + p_tas256x->mn_err_code |= ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code |= ERROR_DEVB_I2C_COMM; + } else { + pr_debug( + "%s: chn%x:BOOK:PAGE:REG %u:%u:%u, len: 0x%02x\n", + __func__, p_tas256x->devs[chn >> 1]->mn_addr, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg), + TAS256X_PAGE_REG(reg), n_length); + if (chn&channel_left) + p_tas256x->mn_err_code &= ~ERROR_DEVA_I2C_COMM; + if (chn&channel_right) + p_tas256x->mn_err_code &= ~ERROR_DEVB_I2C_COMM; + } +end: + mutex_unlock(&p_tas256x->dev_lock); + return n_result; +} + +static int tas256x_dev_update_bits(struct tas256x_priv *p_tas256x, + enum channel chn, + unsigned int reg, unsigned int mask, unsigned int value) +{ + int n_result = 0, rc = 0; + int i = 0, chnTemp = 0; + + mutex_lock(&p_tas256x->dev_lock); + + if (chn == channel_both) { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + } + + n_result = tas256x_change_book_page(p_tas256x, chn, + TAS256X_BOOK_ID(reg), TAS256X_PAGE_ID(reg)); + if (n_result < 0) { + rc = n_result; + goto end; + } + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (((chn&channel_left) && (i == 0)) + || ((chn&channel_right) && (i == 1))) { + n_result = p_tas256x->plat_update_bits(p_tas256x->platform_data, + p_tas256x->devs[i]->mn_addr, + TAS256X_PAGE_REG(reg), + mask, value); + if (n_result < 0) { + pr_err( + "%s, ERROR, L=%u, chn=0x%02x: E=%d\n", + __func__, __LINE__, + p_tas256x->devs[i]->mn_addr, n_result); + rc |= n_result; + p_tas256x->mn_err_code |= + (chn == channel_left) ? ERROR_DEVA_I2C_COMM : ERROR_DEVB_I2C_COMM; + } else { + pr_debug( + "%s: chn%x:BOOK:PAGE:REG 0x%02x:0x%02x:0x%02x, mask: 0x%02x, val: 0x%02x\n", + __func__, p_tas256x->devs[i]->mn_addr, + TAS256X_BOOK_ID(reg), + TAS256X_PAGE_ID(reg), + TAS256X_PAGE_REG(reg), mask, value); + p_tas256x->mn_err_code &= + (chn == channel_left) ? ~ERROR_DEVA_I2C_COMM : ~ERROR_DEVB_I2C_COMM; + } + } + } + +end: + mutex_unlock(&p_tas256x->dev_lock); + return rc; +} + +static void tas256x_hard_reset(struct tas256x_priv *p_tas256x) +{ + int i = 0; + + p_tas256x->hw_reset(p_tas256x); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + p_tas256x->devs[i]->mn_current_book = -1; + p_tas256x->devs[i]->mn_current_page = -1; + } + + if (p_tas256x->mn_err_code) + pr_err("%s: before reset, ErrCode=0x%x\n", __func__, + p_tas256x->mn_err_code); + p_tas256x->mn_err_code = 0; +} + +void tas256x_failsafe(struct tas256x_priv *p_tas256x) +{ + int n_result; + + pr_err("%s\n", __func__); + p_tas256x->mn_err_code |= ERROR_FAILSAFE; + + if (p_tas256x->mn_restart < RESTART_MAX) { + p_tas256x->mn_restart++; + msleep(100); + pr_err("I2C COMM error, restart SmartAmp.\n"); + tas256x_set_power_state(p_tas256x, p_tas256x->mn_power_state); + return; + } + + n_result = tas256x_set_power_shutdown(p_tas256x, channel_both); + p_tas256x->mb_power_up = false; + p_tas256x->mn_power_state = TAS256X_POWER_SHUTDOWN; + msleep(20); + /*Mask interrupt for TDM*/ + n_result = tas256x_interrupt_enable(p_tas256x, 0/*Disable*/, + channel_both); + p_tas256x->enable_irq(p_tas256x, false); + tas256x_hard_reset(p_tas256x); + p_tas256x->write(p_tas256x, channel_both, TAS256X_SOFTWARERESET, + TAS256X_SOFTWARERESET_SOFTWARERESET_RESET); + udelay(1000); + /*pTAS256x->write(pTAS256x, channel_both, TAS256X_SPK_CTRL_REG, 0x04);*/ +} + +int tas256x_load_i2s_tdm_interface_settings(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + /*Frame_Start Settings*/ + n_result |= tas256x_rx_set_frame_start(p_tas256x, + p_tas256x->mn_frame_start, ch); + /*RX Edge Settings*/ + n_result |= tas256x_rx_set_edge(p_tas256x, + p_tas256x->mn_rx_edge, ch); + /*RX Offset Settings*/ + n_result |= tas256x_rx_set_start_slot(p_tas256x, + p_tas256x->mn_rx_offset, ch); + /*TX Edge Settings*/ + n_result |= tas256x_tx_set_edge(p_tas256x, + p_tas256x->mn_tx_edge, ch); + /*TX Offset Settings*/ + n_result |= tas256x_tx_set_start_slot(p_tas256x, + p_tas256x->mn_tx_offset, ch); + + return n_result; +} + +int tas256x_load_init(struct tas256x_priv *p_tas256x) +{ + int ret = 0, i; + + pr_info("%s:\n", __func__); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->dev_ops.tas_init) + ret |= (p_tas256x->devs[i]->dev_ops.tas_init)(p_tas256x, i+1); + } + + ret |= tas256x_set_misc_config(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; + ret |= tas256x_set_tx_config(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; + ret |= tas256x_load_i2s_tdm_interface_settings(p_tas256x, channel_both); + if (ret < 0) + goto end; + ret |= tas256x_set_clock_config(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; + + /*ICN Improve Performance*/ + ret |= tas256x_icn_config(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; +#if IS_ENABLED(HPF_BYPASS) + /*Disable the HPF in Forward Path*/ + ret |= tas256x_HPF_FF_Bypass(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; + /*Disable the HPF in Reverse Path*/ + ret |= tas256x_HPF_FB_Bypass(p_tas256x, 0/*Ignored*/, channel_both); + if (ret < 0) + goto end; +#endif + ret |= tas256x_set_classH_config(p_tas256x, 0/*Ignored*/, channel_both); + +end: + if (ret < 0) { + if (p_tas256x->mn_err_code & + (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM)) + tas256x_failsafe(p_tas256x); + } + return ret; +} + +int tas256x_load_ctrl_values(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + n_result |= tas256x_update_playback_volume(p_tas256x, + p_tas256x->devs[ch-1]->dvc_pcm, ch); + + n_result |= tas256x_update_lim_max_attenuation(p_tas256x, + p_tas256x->devs[ch-1]->lim_max_attn, ch); + + n_result |= tas256x_update_lim_max_thr(p_tas256x, + p_tas256x->devs[ch-1]->lim_thr_max, ch); + + n_result |= tas256x_update_lim_min_thr(p_tas256x, + p_tas256x->devs[ch-1]->lim_thr_min, ch); + + n_result |= tas256x_update_lim_inflection_point(p_tas256x, + p_tas256x->devs[ch-1]->lim_infl_pt, ch); + + n_result |= tas256x_update_lim_slope(p_tas256x, + p_tas256x->devs[ch-1]->lim_trk_slp, ch); + + n_result |= tas256x_update_bop_thr(p_tas256x, + p_tas256x->devs[ch-1]->bop_thd, ch); + + n_result |= tas256x_update_bosd_thr(p_tas256x, + p_tas256x->devs[ch-1]->bosd_thd, ch); + + n_result |= tas256x_update_boost_voltage(p_tas256x, + p_tas256x->devs[ch-1]->bst_vltg, ch); + + n_result |= tas256x_update_current_limit(p_tas256x, + p_tas256x->devs[ch-1]->bst_ilm, ch); + + n_result |= tas256x_update_ampoutput_level(p_tas256x, + p_tas256x->devs[ch-1]->ampoutput_lvl, ch); + + n_result |= tas256x_update_limiter_enable(p_tas256x, + p_tas256x->devs[ch-1]->lim_switch, ch); + + n_result |= tas256x_update_limiter_attack_rate(p_tas256x, + p_tas256x->devs[ch-1]->lim_att_rate, ch); + + n_result |= tas256x_update_limiter_attack_step_size(p_tas256x, + p_tas256x->devs[ch-1]->lim_att_stp_size, ch); + + n_result |= tas256x_update_limiter_release_rate(p_tas256x, + p_tas256x->devs[ch-1]->lim_rel_rate, ch); + + n_result |= tas256x_update_limiter_release_step_size(p_tas256x, + p_tas256x->devs[ch-1]->lim_rel_stp_size, ch); + + n_result |= tas256x_update_bop_enable(p_tas256x, + p_tas256x->devs[ch-1]->bop_enable, ch); + + n_result |= tas256x_update_bop_mute(p_tas256x, + p_tas256x->devs[ch-1]->bop_mute, ch); + + n_result |= tas256x_update_bop_shutdown_enable(p_tas256x, + p_tas256x->devs[ch-1]->bosd_enable, ch); + + n_result |= tas256x_update_bop_attack_rate(p_tas256x, + p_tas256x->devs[ch-1]->bop_att_rate, ch); + + n_result |= tas256x_update_bop_attack_step_size(p_tas256x, + p_tas256x->devs[ch-1]->bop_att_stp_size, ch); + + n_result |= tas256x_update_bop_hold_time(p_tas256x, + p_tas256x->devs[ch-1]->bop_hld_time, ch); + + n_result |= tas256x_update_vbat_lpf(p_tas256x, + p_tas256x->devs[ch-1]->vbat_lpf, ch); + + n_result |= tas256x_update_rx_cfg(p_tas256x, + p_tas256x->devs[ch-1]->rx_cfg, ch); + + n_result |= tas256x_update_classh_timer(p_tas256x, + p_tas256x->devs[ch-1]->classh_timer, ch); + + n_result |= tas256x_enable_reciever_mode(p_tas256x, + p_tas256x->devs[ch-1]->reciever_enable, ch); + + n_result |= tas256x_icn_disable(p_tas256x, + p_tas256x->icn_sw, ch); + + n_result |= tas256x_rx_set_slot(p_tas256x, + p_tas256x->mn_rx_slot_map[ch-1], ch); + + return n_result; +} + +void tas256x_irq_reload(struct tas256x_priv *p_tas256x) +{ + int ret = 0; + + pr_info("%s:\n", __func__); + ret |= tas256x_set_power_state(p_tas256x, p_tas256x->mn_power_state); + /* power up failed, restart later */ + if (ret < 0) { + if (p_tas256x->mn_err_code & + (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM)) + tas256x_failsafe(p_tas256x); + } + +} + +void tas256x_load_config(struct tas256x_priv *p_tas256x) +{ + int ret = 0; + + pr_info("%s:\n", __func__); + tas256x_hard_reset(p_tas256x); + msleep(20); + + ret |= tas56x_software_reset(p_tas256x, channel_both); + if (ret < 0) + goto end; + ret |= tas256x_load_ctrl_values(p_tas256x, channel_left); + if (ret < 0) + goto end; + if (p_tas256x->mn_channels == 2) { + ret |= tas256x_load_ctrl_values(p_tas256x, channel_right); + if (ret < 0) + goto end; + } + ret |= tas256x_load_init(p_tas256x); + if (ret < 0) + goto end; + ret |= tas256x_update_rx_cfg(p_tas256x, p_tas256x->devs[0]->rx_cfg, + channel_left); + if (ret < 0) + goto end; + if (p_tas256x->mn_channels == 2) { + ret |= tas256x_update_rx_cfg(p_tas256x, p_tas256x->devs[1]->rx_cfg, + channel_right); + if (ret < 0) + goto end; + } + ret |= tas256x_iv_sense_enable_set(p_tas256x, 1, + channel_both); + if (ret < 0) + goto end; + if (p_tas256x->mn_fmt_mode == 2) { + ret |= tas256x_set_tdm_rx_slot(p_tas256x, p_tas256x->mn_slots, + p_tas256x->mn_rx_slot_width); + if (ret < 0) + goto end; + ret |= tas256x_set_tdm_tx_slot(p_tas256x, p_tas256x->mn_slots, + p_tas256x->mn_tx_slot_width); + if (ret < 0) + goto end; + } else { /*I2S Mode*/ + ret |= tas256x_set_bitwidth(p_tas256x, + p_tas256x->mn_rx_width, TAS256X_STREAM_PLAYBACK); + if (ret < 0) + goto end; + ret |= tas256x_set_bitwidth(p_tas256x, + p_tas256x->mn_rx_width, TAS256X_STREAM_CAPTURE); + if (ret < 0) + goto end; + } + + ret |= tas256x_set_samplerate(p_tas256x, p_tas256x->mn_sampling_rate, + channel_both); + if (ret < 0) + goto end; + ret |= tas256x_set_power_state(p_tas256x, p_tas256x->mn_power_state); + if (ret < 0) + goto end; +end: +/* power up failed, restart later */ + if (ret < 0) { + if (p_tas256x->mn_err_code & + (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM)) + tas256x_failsafe(p_tas256x); + } +} + +void tas256x_reload(struct tas256x_priv *p_tas256x, int chn) +{ + int ret = 0; + /*To be used later*/ + (void)chn; + + pr_info("%s: chn %d\n", __func__, chn); + p_tas256x->enable_irq(p_tas256x, false); + + ret |= tas56x_software_reset(p_tas256x, channel_both); + if (ret < 0) + goto end; + ret |= tas256x_load_init(p_tas256x); + if (ret < 0) + goto end; + ret |= tas256x_load_ctrl_values(p_tas256x, channel_left); + if (ret < 0) + goto end; + if (p_tas256x->mn_channels == 2) { + ret |= tas256x_load_ctrl_values(p_tas256x, channel_right); + if (ret < 0) + goto end; + } + ret |= tas256x_iv_sense_enable_set(p_tas256x, 1, + channel_both); + if (ret < 0) + goto end; + ret |= tas256x_set_bitwidth(p_tas256x, + p_tas256x->mn_rx_width, TAS256X_STREAM_PLAYBACK); + if (ret < 0) + goto end; + ret |= tas256x_set_bitwidth(p_tas256x, + p_tas256x->mn_rx_width, TAS256X_STREAM_CAPTURE); + if (ret < 0) + goto end; + ret |= tas256x_set_samplerate(p_tas256x, p_tas256x->mn_sampling_rate, + channel_both); + if (ret < 0) + goto end; + ret |= tas256x_set_power_state(p_tas256x, p_tas256x->mn_power_state); + if (ret < 0) + goto end; +end: + p_tas256x->enable_irq(p_tas256x, true); +/* power up failed, restart later */ + if (ret < 0) { + if (p_tas256x->mn_err_code & + (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM)) + tas256x_failsafe(p_tas256x); + } +} + +static int tas2558_specific(struct tas256x_priv *p_tas256x, int chn) +{ + int ret = 0; + + pr_info("%s: chn %d\n", __func__, chn); + ret = tas256x_boost_volt_update(p_tas256x, DEVICE_TAS2558, chn); + + return ret; +} + +static int tas2564_specific(struct tas256x_priv *p_tas256x, int chn) +{ + int ret = 0; + + pr_info("%s: chn %d\n", __func__, chn); + ret = tas256x_boost_volt_update(p_tas256x, DEVICE_TAS2564, chn); + + return ret; +} + +int tas256x_irq_work_func(struct tas256x_priv *p_tas256x) +{ + unsigned int nDevInt1Status = 0, nDevInt2Status = 0, + nDevInt3Status = 0, nDevInt4Status = 0; + int n_counter = 2; + int n_result = 0; + int irqreg, irqreg2, i, chnTemp = 0; + enum channel chn = channel_left; + + pr_info("%s:\n", __func__); + + p_tas256x->enable_irq(p_tas256x, false); + + if (p_tas256x->mn_err_code & ERROR_FAILSAFE) + goto reload; + + if (p_tas256x->mn_power_state == TAS256X_POWER_SHUTDOWN) { + pr_err("%s: device not powered\n", __func__); + goto end; + } + + n_result = tas256x_interrupt_enable(p_tas256x, 0/*Disable*/, + channel_both); + if (n_result < 0) + goto reload; + + /*Reset error codes*/ + p_tas256x->mn_err_code = 0; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + + if (chn & channel_left) { + n_result = tas256x_interrupt_read(p_tas256x, + &nDevInt1Status, &nDevInt2Status, channel_left); + if (n_result < 0) + goto reload; + p_tas256x->mn_err_code = + tas256x_interrupt_determine(p_tas256x, channel_left, + nDevInt1Status, nDevInt2Status); + } + + if (chn & channel_right) { + n_result = tas256x_interrupt_read(p_tas256x, + &nDevInt3Status, &nDevInt4Status, channel_right); + if (n_result < 0) + goto reload; + p_tas256x->mn_err_code |= + tas256x_interrupt_determine(p_tas256x, channel_right, + nDevInt3Status, nDevInt4Status); + } + + pr_err("%s: IRQ status : 0x%x, 0x%x, 0x%x, 0x%x mn_err_code %d\n", + __func__, + nDevInt1Status, nDevInt2Status, + nDevInt3Status, nDevInt4Status, + p_tas256x->mn_err_code); + + if (p_tas256x->mn_err_code) { + tas256x_irq_reload(p_tas256x); + goto end; + } else { + pr_err("%s: Power Up\n", __func__); + n_counter = 2; + while (n_counter > 0) { + if (chn & channel_left) + n_result = tas256x_power_check(p_tas256x, + &nDevInt1Status, + channel_left); + if (n_result < 0) + goto reload; + if (chn & channel_right) + n_result = tas256x_power_check(p_tas256x, + &nDevInt3Status, + channel_right); + if (n_result < 0) + goto reload; + + if (nDevInt1Status) { + /* If only left should be power on */ + if (chn == channel_left) + break; + /* If both should be power on */ + if (nDevInt3Status) + break; + } else if (chn == channel_right) { + /*If only right should be power on */ + if (nDevInt3Status) + break; + } + + tas256x_interrupt_read(p_tas256x, + &irqreg, &irqreg2, channel_both); + n_counter--; + if (n_counter > 0) { + /* in case check pow status + *just after power on TAS256x + */ + if (chn & channel_left) + pr_err("%s: PowSts A: 0x%x, check again after 10ms\n", + __func__, + nDevInt1Status); + + if (chn & channel_right) + pr_err("%s: PowSts B: 0x%x, check again after 10ms\n", + __func__, + nDevInt3Status); + + msleep(20); + } + } + + if (((!nDevInt1Status) && (chn & channel_left)) + || ((!nDevInt3Status) && (chn & channel_right))) { + if (chn & channel_left) + pr_err("%s, Critical ERROR A REG[POWERCONTROL] = 0x%x\n", + __func__, + nDevInt1Status); + + if (chn & channel_right) + pr_err("%s, Critical ERROR B REG[POWERCONTROL] = 0x%x\n", + __func__, + nDevInt3Status); + goto reload; + } + } + + n_result = tas256x_interrupt_enable(p_tas256x, 1/*Enable*/, + channel_both); + if (n_result < 0) + goto reload; + + goto end; + +reload: + /* hardware reset and reload */ + tas256x_load_config(p_tas256x); + +end: + p_tas256x->enable_irq(p_tas256x, true); + + return n_result; +} + +int tas256x_init_work_func(struct tas256x_priv *p_tas256x) +{ + int n_result = 0; + + pr_info("%s:\n", __func__); + + /* Clear latched IRQ before power on */ + n_result = tas256x_interrupt_clear(p_tas256x, channel_both); + + /*Un-Mask interrupt for TDM*/ + n_result = tas256x_interrupt_enable(p_tas256x, 1/*Enable*/, + channel_both); + + p_tas256x->enable_irq(p_tas256x, true); + + return n_result; +} + +int tas256x_dc_work_func(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + pr_info("%s: ch %d\n", __func__, ch); + tas256x_reload(p_tas256x, ch); + + return n_result; +} + +int tas256x_register_device(struct tas256x_priv *p_tas256x) +{ + int n_result; + int i; + + pr_info("%s:\n", __func__); + p_tas256x->read = tas256x_dev_read; + p_tas256x->write = tas256x_dev_write; + p_tas256x->bulk_read = tas256x_dev_bulk_read; + p_tas256x->bulk_write = tas256x_dev_bulk_write; + p_tas256x->update_bits = tas256x_dev_update_bits; + + tas256x_hard_reset(p_tas256x); + + pr_info("Before SW reset\n"); + /* Reset the chip */ + n_result = tas56x_software_reset(p_tas256x, channel_both); + if (n_result < 0) { + pr_err("I2c fail, %d\n", n_result); + goto err; + } + + pr_info("After SW reset\n"); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + n_result = tas56x_get_chipid(p_tas256x, + &(p_tas256x->devs[i]->mn_chip_id), + (i == 0) ? channel_left : channel_right); + if (n_result < 0) + goto err; + switch (p_tas256x->devs[i]->mn_chip_id) { + case 0x10: + case 0x20: + p_tas256x->devs[i]->device_id = DEVICE_TAS2562; + p_tas256x->devs[i]->dev_ops.tas_init = NULL; + break; + case 0x00: + p_tas256x->devs[i]->device_id = DEVICE_TAS2564; + p_tas256x->devs[i]->dev_ops.tas_init = + tas2564_specific; + break; + default: + p_tas256x->devs[i]->device_id = DEVICE_TAS2558; + p_tas256x->devs[i]->dev_ops.tas_init = + tas2558_specific; + break; + } + pr_info("TAS%x chip, chip_id = 0x%x", + p_tas256x->devs[i]->device_id, + p_tas256x->devs[i]->mn_chip_id); + n_result |= tas256x_set_misc_config(p_tas256x, 0, + (i == 0) ? channel_left : channel_right); + } +err: + return n_result; +} + +int tas256x_probe(struct tas256x_priv *p_tas256x) +{ + int ret = 0; +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; +#endif + + pr_info("%s:\n", __func__); + ret = tas256x_load_init(p_tas256x); + if (ret < 0) + goto end; + ret = tas256x_iv_sense_enable_set(p_tas256x, 1, channel_both); +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + if (plat_data) { + tas_smartamp_add_algo_controls(plat_data->codec, plat_data->dev, + p_tas256x->mn_channels); + /*Send IV Vbat format but don't update to algo yet*/ + tas25xx_set_iv_bit_fomat(p_tas256x->mn_iv_width, + p_tas256x->mn_vbat, 0); + } +#endif +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + ret = tas256x_load_container(p_tas256x); + pr_info("%s Bin file loading requested: %d\n", __func__, ret); +#endif +end: + return ret; +} + +void tas256x_remove(struct tas256x_priv *p_tas256x) +{ +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + if (plat_data) { + tas_smartamp_remove_algo_controls(plat_data->codec); + } +#else + /*Ignore argument*/ + (void)p_tas256x; +#endif +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + tas256x_config_info_remove(p_tas256x); +#endif +} + +int tas256x_set_power_state(struct tas256x_priv *p_tas256x, + int state) +{ + int n_result = 0, i = 0, chnTemp = 0; + enum channel chn = channel_left; + + pr_info("%s: state %d\n", __func__, state); + + if ((p_tas256x->mb_mute) && (state == TAS256X_POWER_ACTIVE)) + state = TAS256X_POWER_MUTE; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + + switch (state) { + case TAS256X_POWER_ACTIVE: + n_result = tas256x_iv_sense_enable_set(p_tas256x, 1, chn); +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) + tas25xx_send_channel_mapping(); + tas25xx_send_algo_calibration(); + tas25xx_set_iv_bit_fomat(p_tas256x->mn_iv_width, + p_tas256x->mn_vbat, 1); +#endif + /* Clear latched IRQ before power on */ + tas256x_interrupt_clear(p_tas256x, chn); + + /*Mask interrupt for TDM*/ + n_result = tas256x_interrupt_enable(p_tas256x, 0/*Disable*/, + channel_both); + +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, + p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_PRE_POWER_UP); +#endif + n_result = tas256x_set_power_up(p_tas256x, chn); + + pr_info("%s: set ICN to -80dB\n", __func__); + n_result = tas256x_icn_data(p_tas256x, chn); +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, + p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_POST_POWER_UP); +#endif + p_tas256x->mb_power_up = true; + p_tas256x->mn_power_state = TAS256X_POWER_ACTIVE; + p_tas256x->schedule_init_work(p_tas256x); + break; + + case TAS256X_POWER_MUTE: + n_result = tas256x_set_power_mute(p_tas256x, chn); + p_tas256x->mb_power_up = true; + p_tas256x->mn_power_state = TAS256X_POWER_MUTE; + + /*Mask interrupt for TDM*/ + n_result = tas256x_interrupt_enable(p_tas256x, 0/*Disable*/, + chn); + break; + + case TAS256X_POWER_SHUTDOWN: +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_PRE_SHUTDOWN); +#endif + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->device_id == DEVICE_TAS2564) { + if (chn & (i+1)) { + /*Mask interrupt for TDM*/ + n_result = + tas256x_interrupt_enable(p_tas256x, + 0/*Disable*/, i+1); + n_result = + tas256x_set_power_mute(p_tas256x, + i+1); + n_result = + tas256x_iv_sense_enable_set(p_tas256x, + 0, i+1); + p_tas256x->mb_power_up = false; + p_tas256x->mn_power_state = + TAS256X_POWER_SHUTDOWN; + } + } else { + if (chn & (i+1)) { + n_result = + tas256x_set_power_shutdown(p_tas256x, i+1); + n_result = + tas256x_iv_sense_enable_set(p_tas256x, 0, + i+1); + p_tas256x->mb_power_up = false; + p_tas256x->mn_power_state = + TAS256X_POWER_SHUTDOWN; + /*Mask interrupt for TDM*/ + n_result = tas256x_interrupt_enable(p_tas256x, + 0/*Disable*/, + i+1); + } + } + } + p_tas256x->enable_irq(p_tas256x, false); + /*Device Shutdown need 16ms after shutdown writes are made*/ + usleep_range(16000, 16100); + +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_POST_SHUTDOWN); +#endif +#if IS_ENABLED(CONFIG_TAS25XX_CALIB_VAL_BIG) + tas25xx_update_big_data(); +#endif +#if IS_ENABLED(CONFIG_TISA_KBIN_INTF) + tas25xx_algo_set_inactive(); +#endif + break; + default: + pr_err("wrong power state setting %d\n", + state); + } + + return n_result; +} + +int tas256x_iv_vbat_slot_config(struct tas256x_priv *p_tas256x, + int mn_slot_width) +{ + int n_result = 0; + + pr_debug("%s: mn_slot_width %d\n", __func__, mn_slot_width); + + if (p_tas256x->mn_fmt_mode == 2) { /*TDM Mode*/ + if (p_tas256x->mn_channels == 2) { + if (mn_slot_width == 16) { + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, + TX_SLOT0); + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT5, + TX_SLOT4); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT3); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_right, + TX_SLOT7); + } else { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT2, + TX_SLOT0); + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT6, + TX_SLOT4); + } + + } else if (mn_slot_width == 24) { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT3, + TX_SLOT0); + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT9, + TX_SLOT6); + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT5); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_right, + TX_SLOTa); + } + } else { /*Assumed 32bit*/ + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT4, + TX_SLOT0); + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOTc, + TX_SLOT8); + + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT6); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_right, + TX_SLOTe); + } + } + } else { /*Assumed Mono Channels*/ + if (mn_slot_width == 16) { + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, + TX_SLOT0); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT3); + } else { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT2, + TX_SLOT0); + } + } else if (mn_slot_width == 24) { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT3, + TX_SLOT0); + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT5); + } + } else { /*Assumed 32bit*/ + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT4, + TX_SLOT0); + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT6); + } + } + } + } else { /*I2S Mode*/ + if (p_tas256x->mn_channels == 2) { + if (mn_slot_width == 16) { + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, TX_SLOT0); + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT3, TX_SLOT2); + } else { /*16 or 32 bit*/ + if (p_tas256x->mn_iv_width == 8) { + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, + TX_SLOT0); + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT5, + TX_SLOT4); + if (p_tas256x->mn_vbat == 1) { + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT2); + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_right, TX_SLOT6); + } + } else { /*p_tas256x->mn_iv_width == 16 & VBat + *cannot exist in this combination + */ + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT2, + TX_SLOT0); + n_result |= + tas256x_set_iv_slot(p_tas256x, + channel_right, TX_SLOT6, + TX_SLOT4); + } + } + } else if ((p_tas256x->mn_channels == 1) + && (mn_slot_width == 32)) { + if (p_tas256x->mn_iv_width == 16) { + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT4, TX_SLOT0); + } else if (p_tas256x->mn_iv_width == 12) { + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, TX_SLOT0); + if (p_tas256x->mn_vbat == 1) + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT4); + } + } else if ((p_tas256x->mn_channels == 1) + && (mn_slot_width == 16)) { + if (p_tas256x->mn_iv_width == 16) { + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT2, TX_SLOT0); + } else if (p_tas256x->mn_iv_width == 12) { + n_result |= tas256x_set_iv_slot(p_tas256x, + channel_left, TX_SLOT1, TX_SLOT0); + if (p_tas256x->mn_vbat == 1) + n_result |= + tas256x_set_vbat_slot(p_tas256x, + channel_left, TX_SLOT3); + } + } else { + n_result = -1; + } + } + + if (n_result == 0) + p_tas256x->mn_tx_slot_width = mn_slot_width; + + return n_result; +} + +int tas256x_set_bitwidth(struct tas256x_priv *p_tas256x, + int bitwidth, int stream) +{ + int n_result = 0; + int slot_width_tmp = 16; + + if (bitwidth == 24) + slot_width_tmp = 32; + + pr_info("%s: bitwidth %d stream %d\n", __func__, bitwidth, stream); + + if (stream == TAS256X_STREAM_PLAYBACK) { + n_result |= tas256x_rx_set_bitwidth(p_tas256x, bitwidth, + channel_both); + n_result |= tas256x_rx_set_slot_len(p_tas256x, slot_width_tmp, + channel_both); + } else { /*stream == TAS256X_STREAM_CAPTURE*/ + n_result |= tas256x_iv_bitwidth_config(p_tas256x, + p_tas256x->mn_iv_width, channel_both); + n_result |= tas256x_iv_vbat_slot_config(p_tas256x, + slot_width_tmp); + } + + if (n_result < 0) { + if (p_tas256x->mn_err_code & + (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM)) + tas256x_failsafe(p_tas256x); + } + + return n_result; +} + +int tas256x_set_tdm_rx_slot(struct tas256x_priv *p_tas256x, + int slots, int slot_width) +{ + int ret = -1; + int bitwidth = slot_width; + + if (((p_tas256x->mn_channels == 1) && (slots < 1)) || + ((p_tas256x->mn_channels == 2) && (slots < 2))) { + pr_err("Invalid Slots %d\n", slots); + return ret; + } + p_tas256x->mn_slots = slots; + + if ((slot_width != 16) && + (slot_width != 24) && + (slot_width != 32)) { + pr_err("Unsupported slot width %d\n", slot_width); + return ret; + } + + ret = tas256x_rx_set_slot_len(p_tas256x, slot_width, channel_both); + + switch (bitwidth) { + case 16: + ret = tas256x_rx_set_bitwidth(p_tas256x, + 16, channel_both); + break; + case 24: + case 32: + ret = tas256x_rx_set_bitwidth(p_tas256x, + 24, channel_both); + break; + default: + pr_err("Not supported params format\n"); + } + + /*Enable Auto Detect of Sample Rate */ + ret = tas256x_set_auto_detect_clock(p_tas256x, + 1, channel_both); + + /*Enable Clock Config*/ + ret = tas256x_set_clock_config(p_tas256x, 0/*Ignored*/, + channel_both); + + return ret; +} + +int tas256x_set_tdm_tx_slot(struct tas256x_priv *p_tas256x, + int slots, int slot_width) +{ + int ret = -1; + + if ((slot_width != 16) && + (slot_width != 24) && + (slot_width != 32)) { + pr_err("Unsupported slot width %d\n", slot_width); + return ret; + } + + if (((p_tas256x->mn_channels == 1) && (slots < 2)) || + ((p_tas256x->mn_channels == 2) && (slots < 4))) { + pr_err("Invalid Slots %d\n", slots); + return ret; + } + p_tas256x->mn_slots = slots; + + if (slot_width == 24) + slot_width = 32; + + ret = tas256x_iv_vbat_slot_config(p_tas256x, slot_width); + + if ((p_tas256x->mn_channels == 2) && + (p_tas256x->mn_tx_slot_width == 16)) { + if (p_tas256x->mn_vbat == 1) { + ret |= tas256x_iv_bitwidth_config(p_tas256x, 12, + channel_both); + } else { + ret |= tas256x_iv_bitwidth_config(p_tas256x, 16, + channel_both); + } + } else { + ret |= tas256x_iv_bitwidth_config(p_tas256x, 16, + channel_both); + } + + return ret; +} diff --git a/asoc/codecs/tas256x/misc/tas256x-misc.c b/asoc/codecs/tas256x/misc/tas256x-misc.c new file mode 100644 index 00000000..2561efc4 --- /dev/null +++ b/asoc/codecs/tas256x/misc/tas256x-misc.c @@ -0,0 +1,240 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * File: + * tas256x-misc.c + * + * Description: + * misc driver for Texas Instruments + * TAS256X High Performance 4W Smart Amplifier + * + * ============================================================================= + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/firmware.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <linux/syscalls.h> +#include <linux/fcntl.h> +#include <linux/miscdevice.h> +#include <linux/uaccess.h> + +#include "physical_layer/inc/tas256x.h" +#include "tas256x-misc.h" +#include <linux/dma-mapping.h> + +static struct tas256x_priv *g_tas256x; + +static int tas256x_file_open(struct inode *inode, struct file *file) +{ + struct tas256x_priv *p_tas256x = g_tas256x; + + file->private_data = (void *)p_tas256x; + + pr_info("TAS256X %s\n", __func__); + return 0; +} + +static int tas256x_file_release(struct inode *inode, struct file *file) +{ + pr_info("TAS256X %s\n", __func__); + + file->private_data = (void *)NULL; + + return 0; +} + +static ssize_t tas256x_file_read(struct file *file, + char *buf, size_t count, loff_t *ppos) +{ + struct tas256x_priv *p_tas256x = + (struct tas256x_priv *)file->private_data; + int ret = 0; + unsigned char *p_kbuf = NULL; + unsigned int reg = 0; + unsigned int len = 0; + unsigned int channel = channel_left; + + mutex_lock(&p_tas256x->file_lock); + + p_kbuf = kzalloc(count, GFP_KERNEL); + if (p_kbuf == NULL) { + pr_err("TAS256X write no mem\n"); + goto err; + } + + ret = copy_from_user(p_kbuf, buf, count); + if (ret != 0) { + pr_err("TAS256X copy_from_user failed.\n"); + goto err; + } + + if ((p_kbuf[1] >= 0) && ((p_kbuf[1] <= 1))) + channel = p_kbuf[1]+1; + + switch (p_kbuf[0]) { + case TIAUDIO_CMD_REG_READ: + { + reg = ((unsigned int)p_kbuf[2] << 24) + + ((unsigned int)p_kbuf[3] << 16) + + ((unsigned int)p_kbuf[4] << 8) + + (unsigned int)p_kbuf[5]; + + pr_info("TAS256X TIAUDIO_CMD_REG_READ: current_reg = 0x%x, count=%d\n", + reg, (int)count-6); + len = count-6; + if (len == 1) { + unsigned int value = 0; + ret = p_tas256x->read(p_tas256x, channel, + reg, &value); + if (ret < 0) { + pr_err("TAS256X dev read fail %d\n", ret); + break; + } + p_kbuf[6] = value; + ret = copy_to_user(buf, p_kbuf, count); + /* Failed to copy all the data, exit */ + if (ret != 0) + pr_err("TAS256X copy to user fail %d\n", ret); + } else if (len > 1) { + ret = p_tas256x->bulk_read(p_tas256x, channel, + reg, (unsigned char *)&p_kbuf[6], len); + if (ret < 0) { + pr_err("TAS256X dev bulk read fail %d\n", ret); + } else { + ret = copy_to_user(buf, p_kbuf, count); + /* Failed to copy all the data, exit */ + if (ret != 0) + pr_err("TAS256X copy to user fail %d\n", ret); + } + } + } + break; + } +err: + if (p_kbuf != NULL) + kfree(p_kbuf); + mutex_unlock(&p_tas256x->file_lock); + return count; +} + +static ssize_t tas256x_file_write(struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + struct tas256x_priv *p_tas256x = + (struct tas256x_priv *)file->private_data; + int ret = 0; + unsigned char *p_kbuf = NULL; + unsigned int reg = 0; + unsigned int len = 0; + unsigned int channel = channel_left; + + mutex_lock(&p_tas256x->file_lock); + + p_kbuf = kzalloc(count, GFP_KERNEL); + if (p_kbuf == NULL) { + pr_err("TAS256X write no mem\n"); + goto err; + } + + ret = copy_from_user(p_kbuf, buf, count); + if (ret != 0) { + pr_err("TAS256X copy_from_user failed.\n"); + goto err; + } + + if ((p_kbuf[1] >= 0) && ((p_kbuf[1] <= 1))) + channel = p_kbuf[1]+1; + switch (p_kbuf[0]) { + case TIAUDIO_CMD_REG_WITE: + if (count > 5) { + reg = ((unsigned int)p_kbuf[2] << 24) + + ((unsigned int)p_kbuf[3] << 16) + + ((unsigned int)p_kbuf[4] << 8) + + (unsigned int)p_kbuf[5]; + len = count - 6; + pr_info("TAS256X TIAUDIO_CMD_REG_WITE, Reg=0x%x, Val=0x%x\n", + reg, p_kbuf[6]); + if (len == 1) { + unsigned int value = 0; + value = p_kbuf[6]; + ret = p_tas256x->write(p_tas256x, channel, reg, value); + } else if (len > 1) { + ret = p_tas256x->bulk_write(p_tas256x, channel, + reg, &p_kbuf[6], len); + } + } else { + pr_err("TAS256X %s, write len fail, count=%d.\n", + __func__, (int)count); + } + break; + } +err: + if (p_kbuf != NULL) + kfree(p_kbuf); + + mutex_unlock(&p_tas256x->file_lock); + + return count; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .read = tas256x_file_read, + .write = tas256x_file_write, + .unlocked_ioctl = NULL, + .open = tas256x_file_open, + .release = tas256x_file_release, +}; + +#define MODULE_NAME "tas256x" +static struct miscdevice tas256x_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = MODULE_NAME, + .fops = &fops, +}; + +int tas256x_register_misc(struct tas256x_priv *p_tas256x) +{ + int ret = 0; + + g_tas256x = p_tas256x; + ret = misc_register(&tas256x_misc); + if (ret) + pr_err("TAS256X TAS256X misc fail: %d\n", ret); + + pr_info("TAS256X %s, leave\n", __func__); + + return ret; +} +EXPORT_SYMBOL(tas256x_register_misc); + +int tas256x_deregister_misc(struct tas256x_priv *p_tas256x) +{ + misc_deregister(&tas256x_misc); + return 0; +} +EXPORT_SYMBOL(tas256x_deregister_misc); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS256X Misc Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/tas256x/misc/tas256x-misc.h b/asoc/codecs/tas256x/misc/tas256x-misc.h new file mode 100644 index 00000000..03a29680 --- /dev/null +++ b/asoc/codecs/tas256x/misc/tas256x-misc.h @@ -0,0 +1,38 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * File: + * tas2562-misc.h + * + * Description: + * header file for tas2562-misc.c + * + * ============================================================================= + */ + +#ifndef _TAS256X_MISC_H +#define _TAS256X_MISC_H + +#define TIAUDIO_CMD_REG_WITE 1 +#define TIAUDIO_CMD_REG_READ 2 +#define TIAUDIO_CMD_DEBUG_ON 3 +#define TIAUDIO_CMD_CALIBRATION 7 +#define TIAUDIO_CMD_SAMPLERATE 8 +#define TIAUDIO_CMD_BITRATE 9 +#define TIAUDIO_CMD_DACVOLUME 10 +#define TIAUDIO_CMD_SPEAKER 11 + +int tas256x_register_misc(struct tas256x_priv *p_tas256x); +int tas256x_deregister_misc(struct tas256x_priv *p_tas256x); + +#endif /* _TAS256X_MISC_H */ diff --git a/asoc/codecs/tas256x/os_layer/inc/tas256x-codec.h b/asoc/codecs/tas256x/os_layer/inc/tas256x-codec.h new file mode 100644 index 00000000..e8116b96 --- /dev/null +++ b/asoc/codecs/tas256x/os_layer/inc/tas256x-codec.h @@ -0,0 +1,30 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details. + * + * File: + * tas256x-codec.h + * + * Description: + * header file for tas256x-codec.c + * + * ============================================================================= + */ + +#ifndef _TAS256X_CODEC_H +#define _TAS256X_CODEC_H + +#include "physical_layer/inc/tas256x.h" + +int tas256x_register_codec(struct tas256x_priv *p_tas256x); +int tas256x_deregister_codec(struct tas256x_priv *p_tas256x); + +#endif /* _TAS256X_CODEC_H */ diff --git a/asoc/codecs/tas256x/os_layer/inc/tas256x-regmap.h b/asoc/codecs/tas256x/os_layer/inc/tas256x-regmap.h new file mode 100644 index 00000000..36779d67 --- /dev/null +++ b/asoc/codecs/tas256x/os_layer/inc/tas256x-regmap.h @@ -0,0 +1,22 @@ +#ifndef __TAS256X_REGMAP__ +#define __TAS256X_REGMAP__ +#include <linux/version.h> + +struct linux_platform { + struct device *dev; + struct i2c_client *client; + struct regmap *regmap; + struct hrtimer mtimer; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec; +#else + struct snd_soc_codec *codec; +#endif + /* device is working, but system is suspended */ + int (*runtime_suspend)(struct tas256x_priv *p_tas256x); + int (*runtime_resume)(struct tas256x_priv *p_tas256x); + bool mb_runtime_suspend; + bool i2c_suspend; +}; + +#endif /*__TAS256X_REGMAP__*/
\ No newline at end of file diff --git a/asoc/codecs/tas256x/os_layer/src/tas256x-codec.c b/asoc/codecs/tas256x/os_layer/src/tas256x-codec.c new file mode 100644 index 00000000..b228ead4 --- /dev/null +++ b/asoc/codecs/tas256x/os_layer/src/tas256x-codec.c @@ -0,0 +1,1880 @@ +/* + * ============================================================================= + * Copyright (c) 2016 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details. + * + * File: + * tas256x-codec.c + * + * Description: + * ALSA SoC driver for Texas Instruments TAS256X High Performance 4W Smart + * Amplifier + * + * ============================================================================= + */ + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/firmware.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/initval.h> +#include <sound/tlv.h> +#include <linux/version.h> + +#include "physical_layer/inc/tas256x.h" +#include "physical_layer/inc/tas256x-device.h" +#include "logical_layer/inc/tas256x-logic.h" +#include "os_layer/inc/tas256x-regmap.h" +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#include "algo/inc/tas_smart_amp_v2.h" +#include "algo/inc/tas25xx-calib.h" +#endif /*CONFIG_TAS25XX_ALGO*/ + +#define TAS256X_MDELAY 0xFFFFFFFE +#define TAS256X_MSLEEP 0xFFFFFFFD +#define TAS256X_IVSENSER_ENABLE 1 +#define TAS256X_IVSENSER_DISABLE 0 +/* #define TAS2558_CODEC */ + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static unsigned int tas256x_codec_read(struct snd_soc_component *codec, + unsigned int reg) +{ + unsigned int value = 0; + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + int ret = 0; + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + switch (reg) { + case TAS256X_LEFT_SWITCH: + value = p_tas256x->devs[0]->spk_control; + break; + case TAS256X_RIGHT_SWITCH: + value = p_tas256x->devs[1]->spk_control; + break; + case RX_SCFG_LEFT: + value = p_tas256x->devs[0]->rx_cfg; + break; + case RX_SCFG_RIGHT: + value = p_tas256x->devs[1]->rx_cfg; + break; + default: + ret = p_tas256x->read(p_tas256x, channel_left, reg, + &value); + break; + } + + dev_dbg(plat_data->dev, "%s, reg=%d, value=%d", __func__, reg, value); + + if (ret == 0) + return value; + else + return ret; +} +#else +static unsigned int tas256x_codec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int value = 0; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + switch (reg) { + case TAS256X_LEFT_SWITCH: + value = p_tas256x->devs[0]->spk_control; + break; + case TAS256X_RIGHT_SWITCH: + value = p_tas256x->devs[1]->spk_control; + break; + case RX_SCFG_LEFT: + value = p_tas256x->devs[0]->rx_cfg; + break; + case RX_SCFG_RIGHT: + value = p_tas256x->devs[1]->rx_cfg; + break; + default: + ret = p_tas256x->read(p_tas256x, channel_left, reg, + &value); + break; + } + + dev_dbg(plat_data->dev, "%s, reg=%d, value=%d", __func__, reg, value); + + if (ret == 0) + return value; + else + return ret; +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static int tas256x_codec_write(struct snd_soc_component *codec, + unsigned int reg, unsigned int value) +{ + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + dev_dbg(plat_data->dev, "%s: %d, %d", __func__, reg, value); + + switch (reg) { + case TAS256X_LEFT_SWITCH: + p_tas256x->devs[0]->spk_control = value; + break; + case TAS256X_RIGHT_SWITCH: + p_tas256x->devs[1]->spk_control = value; + break; + case RX_SCFG_LEFT: + ret = tas256x_update_rx_cfg(p_tas256x, value, + channel_left); + break; + case RX_SCFG_RIGHT: + ret = tas256x_update_rx_cfg(p_tas256x, value, + channel_right); + break; + default: + ret = p_tas256x->write(p_tas256x, channel_both, + reg, value); + break; + } + + return ret; +} +#else +static int tas256x_codec_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + dev_dbg(plat_data->dev, "%s: %d, %d", __func__, reg, value); + + switch (reg) { + case TAS256X_LEFT_SWITCH: + p_tas256x->devs[0]->spk_control = value; + break; + case TAS256X_RIGHT_SWITCH: + p_tas256x->devs[1]->spk_control = value; + break; + case RX_SCFG_LEFT: + ret = tas256x_update_rx_cfg(p_tas256x, value, + channel_left); + break; + case RX_SCFG_RIGHT: + ret = tas256x_update_rx_cfg(p_tas256x, value, + channel_right); + break; + default: + ret = p_tas256x->write(p_tas256x, channel_both, + reg, value); + break; + } + + return ret; +} +#endif + +#if IS_ENABLED(CODEC_PM) +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static int tas256x_codec_suspend(struct snd_soc_component *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + mutex_lock(&p_tas256x->codec_lock); + + dev_dbg(plat_data->dev, "%s\n", __func__); + plat_data->runtime_suspend(p_tas256x); + + mutex_unlock(&p_tas256x->codec_lock); + return ret; +} + +static int tas256x_codec_resume(struct snd_soc_component *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + mutex_lock(&p_tas256x->codec_lock); + + dev_dbg(plat_data->dev, "%s\n", __func__); + plat_data->runtime_resume(p_tas256x); + + mutex_unlock(&p_tas256x->codec_lock); + return ret; +} +#else +static int tas256x_codec_suspend(struct snd_soc_codec *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + mutex_lock(&p_tas256x->codec_lock); + + dev_dbg(plat_data->dev, "%s\n", __func__); + plat_data->runtime_suspend(p_tas256x); + + mutex_unlock(&p_tas256x->codec_lock); + return ret; +} + +static int tas256x_codec_resume(struct snd_soc_codec *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + + mutex_lock(&p_tas256x->codec_lock); + + dev_dbg(plat_data->dev, "%s\n", __func__); + plat_data->runtime_resume(p_tas256x); + + mutex_unlock(&p_tas256x->codec_lock); + return ret; +} +#endif +#endif + +static int tas256x_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + dev_info(plat_data->dev, "SND_SOC_DAPM_POST_PMU\n"); + if (p_tas256x->mb_power_up == false) + tas256x_set_power_state(p_tas256x, + TAS256X_POWER_ACTIVE); + break; + case SND_SOC_DAPM_PRE_PMD: + dev_info(plat_data->dev, "SND_SOC_DAPM_PRE_PMD\n"); + if (p_tas256x->mb_power_up == true) + tas256x_set_power_state(p_tas256x, + TAS256X_POWER_SHUTDOWN); + break; + } + + return 0; +} + +static const char * const tas256x_ASI1_src[] = { + "I2C offset", "Left", "Right", "LeftRightDiv2", +}; + +static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_left_enum, RX_SCFG_LEFT, 0, + tas256x_ASI1_src); +static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_right_enum, RX_SCFG_RIGHT, 0, + tas256x_ASI1_src); + +static const struct snd_kcontrol_new dapm_switch_left = + SOC_DAPM_SINGLE("Switch", TAS256X_LEFT_SWITCH, 0, 1, 0); +static const struct snd_kcontrol_new dapm_switch_right = + SOC_DAPM_SINGLE("Switch", TAS256X_RIGHT_SWITCH, 0, 1, 0); +static const struct snd_kcontrol_new tas256x_asi1_left_mux = + SOC_DAPM_ENUM("Mux", tas2562_ASI1_src_left_enum); +static const struct snd_kcontrol_new tas256x_asi1_right_mux = + SOC_DAPM_ENUM("Mux", tas2562_ASI1_src_right_enum); + +static const struct snd_soc_dapm_widget tas256x_dapm_widgets_stereo[] = { + SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SWITCH("TAS256X ASI Left", SND_SOC_NOPM, 0, 0, + &dapm_switch_left), + SND_SOC_DAPM_SWITCH("TAS256X ASI Right", SND_SOC_NOPM, 0, 0, + &dapm_switch_right), + SND_SOC_DAPM_MUX("TAS256X ASI1 SEL LEFT", SND_SOC_NOPM, 0, 0, + &tas256x_asi1_left_mux), + SND_SOC_DAPM_MUX("TAS256X ASI1 SEL RIGHT", SND_SOC_NOPM, 0, 0, + &tas256x_asi1_right_mux), + SND_SOC_DAPM_AIF_OUT("Voltage Sense", "ASI1 Capture", 1, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("Current Sense", "ASI1 Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC_E("DAC1", NULL, SND_SOC_NOPM, 0, 0, tas256x_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("DAC2", NULL, SND_SOC_NOPM, 0, 0, tas256x_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUTPUT("OUT1"), + SND_SOC_DAPM_OUTPUT("OUT2"), + SND_SOC_DAPM_SIGGEN("VMON"), + SND_SOC_DAPM_SIGGEN("IMON") +}; + +static const struct snd_soc_dapm_route tas256x_audio_map_stereo[] = { + {"TAS256X ASI1 SEL LEFT", "Left", "ASI1"}, + {"TAS256X ASI1 SEL LEFT", "Right", "ASI1"}, + {"TAS256X ASI1 SEL LEFT", "LeftRightDiv2", "ASI1"}, + {"TAS256X ASI1 SEL LEFT", "I2C offset", "ASI1"}, + {"TAS256X ASI1 SEL RIGHT", "Left", "ASI1"}, + {"TAS256X ASI1 SEL RIGHT", "Right", "ASI1"}, + {"TAS256X ASI1 SEL RIGHT", "LeftRightDiv2", "ASI1"}, + {"TAS256X ASI1 SEL RIGHT", "I2C offset", "ASI1"}, + {"DAC1", NULL, "TAS256X ASI1 SEL LEFT"}, + {"DAC2", NULL, "TAS256X ASI1 SEL RIGHT"}, + {"TAS256X ASI Left", "Switch", "DAC1"}, + {"TAS256X ASI Right", "Switch", "DAC2"}, + {"OUT1", NULL, "TAS256X ASI Left"}, + {"OUT2", NULL, "TAS256X ASI Right"}, + {"Voltage Sense", NULL, "VMON"}, + {"Current Sense", NULL, "IMON"} +}; + +static const struct snd_soc_dapm_widget tas256x_dapm_widgets_mono[] = { + SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SWITCH("TAS256X ASI", SND_SOC_NOPM, 0, 0, + &dapm_switch_left), + SND_SOC_DAPM_MUX("TAS256X ASI1 SEL", SND_SOC_NOPM, 0, 0, + &tas256x_asi1_left_mux), + SND_SOC_DAPM_AIF_OUT("Voltage Sense", "ASI1 Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("Current Sense", "ASI1 Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas256x_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUTPUT("OUT"), + SND_SOC_DAPM_SIGGEN("VMON"), + SND_SOC_DAPM_SIGGEN("IMON") +}; + +static const struct snd_soc_dapm_route tas256x_audio_map_mono[] = { + {"TAS256X ASI1 SEL", "Left", "ASI1"}, + {"TAS256X ASI1 SEL", "Right", "ASI1"}, + {"TAS256X ASI1 SEL", "LeftRightDiv2", "ASI1"}, + {"TAS256X ASI1 SEL", "I2C offset", "ASI1"}, + {"DAC", NULL, "TAS256X ASI1 SEL"}, + {"TAS256X ASI", "Switch", "DAC"}, + {"OUT", NULL, "TAS256X ASI"}, + {"Voltage Sense", NULL, "VMON"}, + {"Current Sense", NULL, "IMON"} +}; + +static int tas256x_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = dai->component; + struct tas256x_priv *p_tas256x + = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = dai->codec; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + int bitwidth = 16; + int n_result = 0; + unsigned int channels = params_channels(params); + + dev_dbg(plat_data->dev, "%s, stream %s format: %d\n", __func__, + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"), + params_format(params)); + + mutex_lock(&p_tas256x->codec_lock); +#ifndef TDM_MACHINE + /*Assumed TDM*/ + if (channels > 2) { + p_tas256x->mn_fmt_mode = 2; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bitwidth = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + bitwidth = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + bitwidth = 32; + break; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + n_result = tas256x_set_tdm_rx_slot(p_tas256x, channels, bitwidth); + else /*Assumed Capture*/ + n_result = tas256x_set_tdm_tx_slot(p_tas256x, channels, bitwidth); + } else { /*Assumed I2S Mode*/ + p_tas256x->mn_fmt_mode = 1; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bitwidth = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + bitwidth = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + bitwidth = 32; + break; + } + + n_result = tas256x_set_bitwidth(p_tas256x, + bitwidth, substream->stream); + if (n_result < 0) { + dev_err(plat_data->dev, "set bitwidth failed, %d\n", + n_result); + goto ret; + } + } +#else + if (p_tas256x->mn_fmt_mode != 2) { + p_tas256x->mn_fmt_mode = 1; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bitwidth = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + bitwidth = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + bitwidth = 32; + break; + } + + n_result = tas256x_set_bitwidth(p_tas256x, + bitwidth, substream->stream); + if (n_result < 0) { + dev_err(plat_data->dev, "set bitwidth failed, %d\n", + n_result); + goto ret; + } + } +#endif + + dev_info(plat_data->dev, "%s, stream %s sample rate: %d\n", __func__, + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"), + params_rate(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + n_result = tas256x_set_samplerate(p_tas256x, + params_rate(params), channel_both); + +ret: + mutex_unlock(&p_tas256x->codec_lock); + return n_result; +} + +static int tas256x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = dai->component; + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = dai->codec; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + int ret = 0; + u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0, asi_cfg_2 = 0; + + dev_dbg(plat_data->dev, "%s, format=0x%x\n", __func__, fmt); + + p_tas256x->mn_fmt = 1; + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + asi_cfg_1 = 0x00; + asi_cfg_2 = 0x00; + break; + default: + dev_err(plat_data->dev, "ASI format master is not found\n"); + ret = -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + dev_dbg(plat_data->dev, "INV format: NBNF\n"); + asi_cfg_1 |= 0; + asi_cfg_2 |= 0; + break; + case SND_SOC_DAIFMT_IB_NF: + dev_dbg(plat_data->dev, "INV format: IBNF\n"); + asi_cfg_1 |= 1; + asi_cfg_2 |= 0; + break; + case SND_SOC_DAIFMT_NB_IF: + dev_dbg(plat_data->dev, "INV format: NBIF\n"); + asi_cfg_1 |= 0; + asi_cfg_2 |= 1; + break; + case SND_SOC_DAIFMT_IB_IF: + dev_dbg(plat_data->dev, "INV format: IBIF\n"); + asi_cfg_1 |= 1; + asi_cfg_2 |= 1; + break; + default: + dev_err(plat_data->dev, "ASI format Inverse is not found\n"); + ret = -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case (SND_SOC_DAIFMT_I2S): + tdm_rx_start_slot = 1; + dev_dbg(plat_data->dev, " SND_SOC_DAIFMT_I2S tdm_rx_start_slot = 1\n"); + break; + case (SND_SOC_DAIFMT_DSP_A): + tdm_rx_start_slot = 1; + dev_dbg(plat_data->dev, "SND_SOC_DAIFMT_DSP_A tdm_rx_start_slot =1\n"); + break; + case (SND_SOC_DAIFMT_DSP_B): + tdm_rx_start_slot = 0; + dev_dbg(plat_data->dev, "SND_SOC_DAIFMT_DSP_B tdm_rx_start_slot = 0\n"); + break; + case (SND_SOC_DAIFMT_LEFT_J): + tdm_rx_start_slot = 0; + dev_dbg(plat_data->dev, "SND_SOC_DAIFMT_LEFT_J tdm_rx_start_slot = 0\n"); + break; + default: + dev_err(plat_data->dev, "DAI Format is not found, fmt=0x%x\n", fmt); + ret = -EINVAL; + break; + } + + ret = tas256x_rx_set_start_slot(p_tas256x, + tdm_rx_start_slot, channel_both); + if (ret) + goto end; + + /*TX Offset is same as RX Offset*/ + ret = tas256x_tx_set_start_slot(p_tas256x, + tdm_rx_start_slot, channel_both); + if (ret) + goto end; + + ret = tas256x_rx_set_edge(p_tas256x, + asi_cfg_1, channel_both); + if (ret) + goto end; + + /*TX Edge is reverse of RX Edge*/ + ret = tas256x_tx_set_edge(p_tas256x, + !asi_cfg_1, channel_both); + if (ret) + goto end; + + ret = tas256x_rx_set_frame_start(p_tas256x, + asi_cfg_2, channel_both); + if (ret) + goto end; + +end: + return ret; +} + +static int tas256x_set_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + int ret = 0; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = dai->component; + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = dai->codec; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + + dev_dbg(plat_data->dev, "%s, tx_mask:%d, rx_mask:%d", + __func__, tx_mask, rx_mask); + dev_dbg(plat_data->dev, "%s, slots:%d,slot_width:%d", + __func__, slots, slot_width); + + if (rx_mask) { + p_tas256x->mn_fmt_mode = 2; /*TDM Mode*/ + ret = tas256x_set_tdm_rx_slot(p_tas256x, slots, slot_width); + } else if (tx_mask) { + p_tas256x->mn_fmt_mode = 2; + ret = tas256x_set_tdm_tx_slot(p_tas256x, slots, slot_width); + } else { + dev_err(plat_data->dev, "%s, Invalid Mask", + __func__); + p_tas256x->mn_fmt_mode = 0; + } + + return ret; +} + +static int tas256x_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = dai->component; + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = dai->codec; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + dev_dbg(plat_data->dev, "%s, stream %s mute %d\n", __func__, + (stream == SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"), + mute); + + return 0; +} + +static struct snd_soc_dai_ops tas256x_dai_ops = { + .hw_params = tas256x_hw_params, + .set_fmt = tas256x_set_dai_fmt, + .set_tdm_slot = tas256x_set_dai_tdm_slot, + .mute_stream = tas256x_mute_stream, +}; + +#define TAS256X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver tas256x_dai_driver[] = { + { + .name = "tas256x ASI1", + .id = 0, + .playback = { + .stream_name = "ASI1 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS256X_FORMATS, + }, + .capture = { + .stream_name = "ASI1 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS256X_FORMATS, + }, + .ops = &tas256x_dai_ops, + .symmetric_rates = 1, + }, +}; + +/*Generic Control-1: IV Sense enable*/ +static char const *iv_enable_text[] = {"Off", "On"}; +static const struct soc_enum tas256x_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(iv_enable_text), iv_enable_text), +}; + +static int tas256xiv_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct tas256x_priv *p_tas256x = NULL; + int iv_enable = 0, n_result = 0; + struct linux_platform *plat_data = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return 0; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return 0; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + iv_enable = ucontrol->value.integer.value[0]; + + n_result = tas256x_iv_sense_enable_set(p_tas256x, iv_enable, + channel_both); + + pr_debug("%s: tas256x->iv_enable = %d\n", __func__, + p_tas256x->iv_enable); + + return n_result; +} + +static int tas256xiv_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return 0; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return 0; + } + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + ucontrol->value.integer.value[0] = + tas256x_iv_sense_enable_get(p_tas256x, channel_left); + p_tas256x->iv_enable = ucontrol->value.integer.value[0]; + + dev_info(plat_data->dev, "p_tas256x->iv_enable %d\n", + p_tas256x->iv_enable); + + return 0; +} + +static const struct snd_kcontrol_new tas256x_controls[] = { +SOC_ENUM_EXT("TAS256X IVSENSE ENABLE", tas256x_enum[0], + tas256xiv_get, tas256xiv_put), +}; + +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) +/* max. length of a alsa mixer control name */ +#define MAX_CONTROL_NAME 48 + +static char *fw_name = "tas256x_reg.bin"; + +const char *blocktype[5] = { + "COEFF", + "POST_POWER_UP", + "PRE_SHUTDOWN", + "PRE_POWER_UP", + "POST_SHUTDOWN" +}; + +static int tas256x_process_block(void *pContext, unsigned char *data, + unsigned char dev_idx, int sublocksize) +{ + struct tas256x_priv *pTAS256x = (struct tas256x_priv *)pContext; + unsigned char subblk_typ = data[1]; + int subblk_offset = 2; + enum channel chn = (0 == dev_idx) ? channel_both : (enum channel)dev_idx; + + switch (subblk_typ) { + case TAS256X_CMD_SING_W: { +/* + dev_idx : one byte + subblk_type : one byte + payload_len : two bytes + { + book : one byte + page : one byte + reg : one byte + val : one byte + }[payload_len/4] +*/ + int i = 0; + unsigned short len = SMS_HTONS(data[2], data[3]); + subblk_offset += 2; + if (subblk_offset + 4 * len > sublocksize) { + pr_err("Out of memory %s: %u\n", __func__, __LINE__); + break; + } + + for (i = 0; i < len; i++) { + pTAS256x->write(pTAS256x, chn, + TAS256X_REG(data[subblk_offset], data[subblk_offset + 1], data[subblk_offset + 2]), + data[subblk_offset + 3]); + subblk_offset += 4; + } + } + break; + case TAS256X_CMD_BURST: { +/* + dev_idx : one byte + subblk_type : one byte + payload_len : two bytes + book : one byte + page : one byte + reg : one byte + reserve : one byte + payload : payload_len bytes +*/ + unsigned short len = SMS_HTONS(data[2], data[3]); + subblk_offset += 2; + if (subblk_offset + 4 + len > sublocksize) { + pr_err("Out of memory %s: %u\n", __func__, __LINE__); + break; + } + if (len % 4) { + pr_err("Burst len is wrong %s: %u\n", __func__, __LINE__); + break; + } + + pTAS256x->bulk_write(pTAS256x, chn, + TAS256X_REG(data[subblk_offset], data[subblk_offset + 1], + data[subblk_offset + 2]), &(data[subblk_offset + 4]), len); + subblk_offset += (len + 4); + } + break; + case TAS256X_CMD_DELAY: { +/* + dev_idx : one byte + subblk_type : one byte + delay_time : two bytes +*/ + unsigned short delay_time = 0; + if (subblk_offset + 2 > sublocksize) { + pr_err("Out of memory %s: %u\n", __func__, __LINE__); + break; + } + delay_time = SMS_HTONS(data[2], data[3]); + usleep_range(delay_time * 1000, delay_time * 1000); + subblk_offset += 2; + } + break; + case TAS256X_CMD_FIELD_W: +/* + dev_idx : one byte + subblk_type : one byte + reserve : one byte + mask : one byte + book : one byte + page : one byte + reg : one byte + reserve : one byte + payload : payload_len bytes +*/ + if (subblk_offset + 6 > sublocksize) { + pr_err("Out of memory %s: %u\n", __func__, __LINE__); + break; + } + pTAS256x->update_bits(pTAS256x, chn, + TAS256X_REG(data[subblk_offset + 2], data[subblk_offset + 3], data[subblk_offset + 4]), + data[subblk_offset + 1], data[subblk_offset + 5]); + subblk_offset += 6; + break; + default: + break; + }; + + return subblk_offset; + +} + +void tas256x_select_cfg_blk(void *pContext, int conf_no, unsigned char block_type) +{ + struct tas256x_priv *pTAS256x = (struct tas256x_priv *) pContext; + struct tas256x_config_info **cfg_info = pTAS256x->cfg_info; + int i = 0, j = 0, k = 0; + + if (conf_no > pTAS256x->ncfgs || conf_no < 0 || NULL == cfg_info) { + pr_err("conf_no shoud be in range from 0 to %u\n", pTAS256x->ncfgs - 1); + goto EXIT; + } else { + pr_info("%s:%u:profile_conf_id = %d\n", __func__, __LINE__, conf_no); + } + for (i = 0; i < pTAS256x->ncfgs; i++) { + if (conf_no == i) { + for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) { + unsigned int length = 0, rc = 0; + if (block_type > 5 || block_type < 2) { + pr_err("ERROR!!!block_type shoud be in range from 2 to 5\n"); + goto EXIT; + } + if (block_type != cfg_info[i]->blk_data[j]->block_type) + continue; + pr_info("%s:%u:conf %d\n", __func__, __LINE__, i); + pr_info("%s:%u:block type:%s\t device idx = 0x%02x\n", + __func__, __LINE__, blocktype[cfg_info[i]->blk_data[j]->block_type - 1], + cfg_info[i]->blk_data[j]->dev_idx); + for (k = 0; k < (int)cfg_info[i]->blk_data[j]->nSublocks; k++) { + rc = tas256x_process_block(pTAS256x, cfg_info[i]->blk_data[j]->regdata + length, + cfg_info[i]->blk_data[j]->dev_idx, cfg_info[i]->blk_data[j]->block_size - length); + length += rc; + if (cfg_info[i]->blk_data[j]->block_size < length) { + pr_err("%s:%u:ERROR:%u %u out of memory\n", __func__, __LINE__, + length, cfg_info[i]->blk_data[j]->block_size); + break; + } + } + if (length != cfg_info[i]->blk_data[j]->block_size) { + pr_err("%s:%u:ERROR: %u %u size is not same\n", __func__, + __LINE__, length, cfg_info[i]->blk_data[j]->block_size); + } + } + } else { + continue; + } + } +EXIT: + return; +} + +static struct tas256x_config_info *tas256x_add_config(unsigned char *config_data, unsigned int config_size) +{ + struct tas256x_config_info *cfg_info = NULL; + int config_offset = 0, i = 0; + cfg_info = (struct tas256x_config_info *)kzalloc(sizeof(struct tas256x_config_info), GFP_KERNEL); + if (!cfg_info) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + goto EXIT; + } + if (config_offset + 4 > (int)config_size) { + pr_err("%s:%u:Out of memory\n", __func__, __LINE__); + goto EXIT; + } + cfg_info->nblocks = SMS_HTONL(config_data[config_offset], config_data[config_offset + 1], + config_data[config_offset + 2], config_data[config_offset + 3]); + config_offset += 4; + pr_info("cfg_info->num_blocks = %u\n", cfg_info->nblocks); + cfg_info->blk_data = (struct tas256x_block_data **)kzalloc( + cfg_info->nblocks*sizeof(struct tas256x_block_data *), + GFP_KERNEL); + if (!cfg_info->blk_data) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + goto EXIT; + } + cfg_info->real_nblocks = 0; + for (i = 0; i < (int)cfg_info->nblocks; i++) { + if (config_offset + 12 > config_size) { + pr_err("%s:%u:Out of memory: i = %d nblocks = %u!\n", + __func__, __LINE__, i, cfg_info->nblocks); + break; + } + cfg_info->blk_data[i] = (struct tas256x_block_data *)kzalloc( + sizeof(struct tas256x_block_data), GFP_KERNEL); + if (!cfg_info->blk_data[i]) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + break; + } + cfg_info->blk_data[i]->dev_idx = config_data[config_offset]; + config_offset++; + pr_info("blk_data(%d).dev_idx = 0x%02x\n", i, + cfg_info->blk_data[i]->dev_idx); + cfg_info->blk_data[i]->block_type = config_data[config_offset]; + config_offset++; + pr_info("blk_data(%d).block_type = 0x%02x\n", i, + cfg_info->blk_data[i]->block_type); + cfg_info->blk_data[i]->yram_checksum = SMS_HTONS(config_data[config_offset], + config_data[config_offset + 1]); + config_offset += 2; + cfg_info->blk_data[i]->block_size = SMS_HTONL(config_data[config_offset], + config_data[config_offset + 1], config_data[config_offset + 2], + config_data[config_offset + 3]); + config_offset += 4; + pr_info("blk_data(%d).block_size = %u\n", i, + cfg_info->blk_data[i]->block_size); + cfg_info->blk_data[i]->nSublocks = SMS_HTONL(config_data[config_offset], + config_data[config_offset + 1], config_data[config_offset + 2], + config_data[config_offset + 3]); + pr_info("blk_data(%d).num_subblocks = %u\n", i, + cfg_info->blk_data[i]->nSublocks); + config_offset += 4; + pr_info("config_offset = %d\n", config_offset); + cfg_info->blk_data[i]->regdata = (unsigned char *)kzalloc( + cfg_info->blk_data[i]->block_size, GFP_KERNEL); + if (!cfg_info->blk_data[i]->regdata) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + goto EXIT; + } + if (config_offset + cfg_info->blk_data[i]->block_size > config_size) { + pr_err("%s:%u:Out of memory: i = %d nblocks = %u!\n", + __func__, __LINE__, i, cfg_info->nblocks); + break; + } + memcpy(cfg_info->blk_data[i]->regdata, &config_data[config_offset], + cfg_info->blk_data[i]->block_size); + config_offset += cfg_info->blk_data[i]->block_size; + cfg_info->real_nblocks += 1; + } +EXIT: + return cfg_info; +} + +static int tas256x_info_profile(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + uinfo->count = 1; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif + uinfo->value.integer.min = -1; + uinfo->value.integer.max = max(-1, p_tas256x->ncfgs - 1); + pr_info("%s: max profile = %d\n", __func__, (int)uinfo->value.integer.max); + + return 0; +} + +static int tas256x_get_profile_id(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + ucontrol->value.integer.value[0] = p_tas256x->profile_cfg_id; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif + return 0; +} + +static int tas256x_set_profile_id(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + p_tas256x->profile_cfg_id = ucontrol->value.integer.value[0]; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif + + return 0; +} + +static int tas256x_create_controls(struct tas256x_priv *pTAS256x) +{ + int nr_controls = 1, ret = 0, mix_index = 0; + char *name = NULL; + struct linux_platform *platform_data = + (struct linux_platform *)pTAS256x->platform_data; + + struct snd_kcontrol_new *tas256x_profile_controls = NULL; + tas256x_profile_controls = devm_kzalloc(platform_data->dev, + nr_controls * sizeof(tas256x_profile_controls[0]), GFP_KERNEL); + if (NULL == tas256x_profile_controls) { + ret = -ENOMEM; + goto EXIT; + } + + /* Create a mixer item for selecting the active profile */ + name = devm_kzalloc(platform_data->dev, MAX_CONTROL_NAME, GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto EXIT; + } + scnprintf(name, MAX_CONTROL_NAME, "TAS256x Profile id"); + tas256x_profile_controls[mix_index].name = name; + tas256x_profile_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + tas256x_profile_controls[mix_index].info = tas256x_info_profile; + tas256x_profile_controls[mix_index].get = tas256x_get_profile_id; + tas256x_profile_controls[mix_index].put = tas256x_set_profile_id; + mix_index++; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + ret = snd_soc_add_component_controls(platform_data->codec, + tas256x_profile_controls, nr_controls < mix_index ? nr_controls : mix_index); +#else + ret = snd_soc_add_codec_controls(platform_data->codec, + tas256x_profile_controls, nr_controls < mix_index ? nr_controls : mix_index); +#endif +EXIT: + return ret; +} + +static void tas256x_fw_ready(const struct firmware *pFW, void *pContext) +{ + struct tas256x_priv *pTAS256x = (struct tas256x_priv *) pContext; + struct tas256x_fw_hdr *fw_hdr = &(pTAS256x->fw_hdr); + struct tas256x_config_info **cfg_info = NULL; + unsigned char *buf = NULL; + int offset = 0, i = 0; + unsigned int total_config_sz = 0; + + pTAS256x->fw_state = TAS256X_DSP_FW_FAIL; + + if (unlikely(!pFW) || unlikely(!pFW->data)) { + pr_err("Failed to read %s, no side-effect on driver running\n", fw_name); + return; + } + buf = (unsigned char *)pFW->data; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&pTAS256x->codec_lock); +#endif +#if IS_ENABLED(CONFIG_TAS256X_MISC) + mutex_lock(&pTAS256x->file_lock); +#endif + pr_info("%s: start\n", __func__); + fw_hdr->img_sz = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + if (fw_hdr->img_sz != pFW->size) { + pr_err("File size not match, %d %u", (int)pFW->size, fw_hdr->img_sz); + goto EXIT; + } + + fw_hdr->checksum = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + fw_hdr->binnary_version_num = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + fw_hdr->drv_fw_version = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + fw_hdr->timestamp = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + fw_hdr->plat_type = buf[offset]; + offset += 1; + fw_hdr->dev_family = buf[offset]; + offset += 1; + fw_hdr->reserve = buf[offset]; + offset += 1; + fw_hdr->ndev = buf[offset]; + offset += 1; + + pr_info("ndev = %u\n", fw_hdr->ndev); + + if (offset + TAS256X_DEVICE_SUM > fw_hdr->img_sz) { + pr_err("%s:%u:Out of Memory!\n", __func__, __LINE__); + goto EXIT; + } + + for (i = 0; i < TAS256X_DEVICE_SUM; i++) { + fw_hdr->devs[i] = buf[offset]; + offset += 1; + pr_info("devs[%d] = %u\n", i, fw_hdr->devs[i]); + } + fw_hdr->nconfig = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + pr_info("nconfig = %u\n", fw_hdr->nconfig); + for (i = 0; i < TAS256X_CONFIG_SIZE; i++) { + fw_hdr->config_size[i] = SMS_HTONL(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]); + offset += 4; + pr_info("config_size[%d] = %u\n", i, fw_hdr->config_size[i]); + total_config_sz += fw_hdr->config_size[i]; + } + pr_info("img_sz = %u total_config_sz = %u offset = %d\n", + fw_hdr->img_sz, total_config_sz, offset); + if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) { + pr_err("Bin file error!\n"); + goto EXIT; + } + cfg_info = (struct tas256x_config_info **)kzalloc( + fw_hdr->nconfig*sizeof(struct tas256x_config_info *), + GFP_KERNEL); + if (!cfg_info) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + goto EXIT; + } + pTAS256x->cfg_info = cfg_info; + pTAS256x->ncfgs = 0; + for (i = 0; i < (int)fw_hdr->nconfig; i++) { + cfg_info[i] = tas256x_add_config(&buf[offset], fw_hdr->config_size[i]); + if (!cfg_info[i]) { + pr_err("%s:%u:Memory alloc failed!\n", __func__, __LINE__); + break; + } + offset += (int)fw_hdr->config_size[i]; + pTAS256x->ncfgs += 1; + } + + pTAS256x->fw_state = TAS256X_DSP_FW_OK; + tas256x_create_controls(pTAS256x); +EXIT: +#if IS_ENABLED(CONFIG_TAS256X_MISC) + mutex_unlock(&pTAS256x->file_lock); +#endif +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&pTAS256x->codec_lock); +#endif + release_firmware(pFW); + pr_info("%s: Firmware init complete\n", __func__); + return; +} + +int tas256x_load_container(struct tas256x_priv *pTAS256x) +{ + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) pTAS256x->platform_data; + pTAS256x->fw_state = TAS256X_DSP_FW_PENDING; + return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + fw_name, plat_data->dev, GFP_KERNEL, pTAS256x, tas256x_fw_ready); +} + +void tas256x_config_info_remove(void *pContext) +{ + struct tas256x_priv *pTAS256x = (struct tas256x_priv *) pContext; + struct tas256x_config_info **cfg_info = pTAS256x->cfg_info; + int i = 0, j = 0; + + if (cfg_info) { + for (i = 0; i < pTAS256x->ncfgs; i++) { + if (cfg_info[i]) { + for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) { + if (cfg_info[i]->blk_data[j]->regdata) + kfree(cfg_info[i]->blk_data[j]->regdata); + if (cfg_info[i]->blk_data[j]) + kfree(cfg_info[i]->blk_data[j]); + } + if (cfg_info[i]->blk_data) + kfree(cfg_info[i]->blk_data); + kfree(cfg_info[i]); + } + } + kfree(cfg_info); + } +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static int tas256x_codec_probe(struct snd_soc_component *codec) +{ + int ret, i; + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(codec); + + if (plat_data) + plat_data->codec = codec; + + ret = snd_soc_add_component_controls(codec, tas256x_controls, + ARRAY_SIZE(tas256x_controls)); + if (ret < 0) { + pr_err("%s: add_codec_controls failed, err %d\n", + __func__, ret); + return ret; + } + + snd_soc_dapm_ignore_suspend(dapm, "ASI1 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "ASI1 Capture"); + if (p_tas256x->mn_channels == 2) { + snd_soc_dapm_ignore_suspend(dapm, "OUT1"); + snd_soc_dapm_ignore_suspend(dapm, "OUT2"); + snd_soc_dapm_ignore_suspend(dapm, "VMON"); + snd_soc_dapm_ignore_suspend(dapm, "IMON"); + } else { + snd_soc_dapm_ignore_suspend(dapm, "OUT"); + snd_soc_dapm_ignore_suspend(dapm, "VMON"); + snd_soc_dapm_ignore_suspend(dapm, "IMON"); + } + + snd_soc_dapm_sync(dapm); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->dev_ops.tas_probe) + ret |= (p_tas256x->devs[i]->dev_ops.tas_probe)(p_tas256x, codec, i + 1); + } + + /* Generic Probe */ + ret = tas256x_probe(p_tas256x); + dev_dbg(plat_data->dev, "%s\n", __func__); + + return 0; +} +#else +static int tas256x_codec_probe(struct snd_soc_codec *codec) +{ + int ret, i; + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + + if (plat_data) + plat_data->codec = codec; + + dev_info(plat_data->dev, "Driver Tag: %s\n", TAS256X_DRIVER_TAG); + ret = snd_soc_add_codec_controls(codec, tas256x_controls, + ARRAY_SIZE(tas256x_controls)); + if (ret < 0) { + pr_err("%s: add_codec_controls failed, err %d\n", + __func__, ret); + return ret; + } + + snd_soc_dapm_ignore_suspend(dapm, "ASI1 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "ASI1 Capture"); + if (p_tas256x->mn_channels == 2) { + snd_soc_dapm_ignore_suspend(dapm, "OUT1"); + snd_soc_dapm_ignore_suspend(dapm, "OUT2"); + snd_soc_dapm_ignore_suspend(dapm, "VMON"); + snd_soc_dapm_ignore_suspend(dapm, "IMON"); + } else { + snd_soc_dapm_ignore_suspend(dapm, "OUT"); + snd_soc_dapm_ignore_suspend(dapm, "VMON"); + snd_soc_dapm_ignore_suspend(dapm, "IMON"); + } + + snd_soc_dapm_sync(dapm); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->dev_ops.tas_probe) + ret |= (p_tas256x->devs[i]->dev_ops.tas_probe)(p_tas256x, codec, i + 1); + } + /* Generic Probe */ + ret = tas256x_probe(p_tas256x); + dev_dbg(plat_data->dev, "%s\n", __func__); + + return ret; +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static void tas256x_codec_remove(struct snd_soc_component *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); + + tas256x_remove(p_tas256x); +} +#else +static int tas256x_codec_remove(struct snd_soc_codec *codec) +{ + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); + + tas256x_remove(p_tas256x); + return 0; +} +#endif + +/*snd control-1: SmartPA System Mute(Master) Control*/ +static int tas256x_system_mute_ctrl_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec + = snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + pValue->value.integer.value[0] = p_tas256x->mb_mute; + dev_dbg(plat_data->dev, "%s = %d\n", + __func__, p_tas256x->mb_mute); + + return 0; +} + +static int tas256x_system_mute_ctrl_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int mb_mute = pValue->value.integer.value[0]; + + dev_dbg(plat_data->dev, "%s = %d\n", __func__, mb_mute); + + p_tas256x->mb_mute = !!mb_mute; + + return 0; +} + +/*snd control-2: SmartPA Mute Control*/ +static int tas256x_mute_ctrl_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + pValue->value.integer.value[0] = p_tas256x->mb_mute; + + if ((p_tas256x->mb_power_up == true) && + (p_tas256x->mn_power_state == TAS256X_POWER_ACTIVE)) + pValue->value.integer.value[0] = 0; + else + pValue->value.integer.value[0] = 1; + + dev_dbg(plat_data->dev, "%s = %ld\n", + __func__, pValue->value.integer.value[0]); + + return 0; +} + +static int tas256x_mute_ctrl_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int mute = pValue->value.integer.value[0]; + + dev_dbg(plat_data->dev, "%s, %d\n", __func__, mute); + mutex_lock(&p_tas256x->codec_lock); + + if (mute) + tas256x_set_power_state(p_tas256x, TAS256X_POWER_MUTE); + else + tas256x_set_power_state(p_tas256x, TAS256X_POWER_ACTIVE); + + mutex_unlock(&p_tas256x->codec_lock); + return 0; +} + +/*snd control-3: DAC Mute Control*/ +static int tas256x_dac_mute_ctrl_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + pValue->value.integer.value[0] = p_tas256x->dac_mute; + + dev_dbg(plat_data->dev, "%s = %ld\n", + __func__, pValue->value.integer.value[0]); + + return 0; +} + +static int tas256x_dac_mute_ctrl_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ + int n_result = 0; + enum channel chn = channel_left; + int mute = pValue->value.integer.value[0]; + int i = 0, chnTemp = 0; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + + dev_dbg(plat_data->dev, "%s, %d\n", __func__, mute); + mutex_lock(&p_tas256x->codec_lock); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (p_tas256x->devs[i]->spk_control == 1) + chnTemp |= 1 << i; + } + chn = (chnTemp == 0) ? chn : (enum channel)chnTemp; + + if (mute) { + n_result = tas256x_set_power_mute(p_tas256x, chn); + } else { + msleep(50); +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_PRE_POWER_UP); +#endif + n_result = tas256x_set_power_up(p_tas256x, chn); +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + /*set p_tas256x->profile_cfg_id by tinymix*/ + tas256x_select_cfg_blk(p_tas256x, p_tas256x->profile_cfg_id, + TAS256X_BIN_BLK_POST_POWER_UP); +#endif + } + + p_tas256x->dac_mute = mute; + mutex_unlock(&p_tas256x->codec_lock); + + return n_result; +} + +/*ICN Disable*/ +static const char * const icn_sw_text[] = {"Enable", "Disable"}; +static const struct soc_enum icn_sw_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(icn_sw_text), + icn_sw_text), +}; +static int tas256x_get_icn_switch(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *p_u_control) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + + dev_info(plat_data->dev, "%s, icn_sw = %ld\n", + __func__, p_u_control->value.integer.value[0]); + p_u_control->value.integer.value[0] = p_tas256x->icn_sw; + return 0; +} +static int tas256x_set_icn_switch(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *p_u_control) +{ + int ret = 0; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + + p_tas256x->icn_sw = p_u_control->value.integer.value[0]; + ret = tas256x_icn_disable(p_tas256x, p_tas256x->icn_sw, channel_both); + + return ret; +} + +/*Rx Slot*/ +static int tas256x_set_rx_slot_map_single(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ + int ret = 0; + int value = 0; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + value = pValue->value.integer.value[0]; + + ret = tas256x_rx_set_slot(p_tas256x, value, channel_left); + dev_dbg(plat_data->dev, "%s = %ld\n", + __func__, pValue->value.integer.value[0]); + + return ret; +} + +static int tas256x_get_rx_slot_map_single(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = (struct linux_platform *) p_tas256x->platform_data; + + pValue->value.integer.value[0] = p_tas256x->mn_rx_slot_map[0]; + dev_dbg(plat_data->dev, "%s = %ld\n", + __func__, pValue->value.integer.value[0]); + return 0; +} + +static const struct snd_kcontrol_new tas256x_snd_controls_mono[] = { + SOC_SINGLE_EXT("SmartPA System Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_system_mute_ctrl_get, tas256x_system_mute_ctrl_put), + SOC_SINGLE_EXT("SmartPA Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_mute_ctrl_get, tas256x_mute_ctrl_put), + SOC_SINGLE_EXT("TAS256X DAC Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_dac_mute_ctrl_get, tas256x_dac_mute_ctrl_put), + SOC_ENUM_EXT("TAS256X ICN Switch", icn_sw_enum[0], + tas256x_get_icn_switch, + tas256x_set_icn_switch), + SOC_SINGLE_EXT("TAS256X_RX_SLOT_MAP", SND_SOC_NOPM, 0, 7, 0, + tas256x_get_rx_slot_map_single, + tas256x_set_rx_slot_map_single), +}; + +struct soc_multi_control_ch_map { + int min, max, platform_max, count; + unsigned int reg, rreg, shift, rshift, invert; +}; + +int tas256x_rx_slot_map_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_multi_control_ch_map *mc = + (struct soc_multi_control_ch_map *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = mc->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = mc->platform_max; + + return 0; +} + +static int tas256x_get_rx_slot_map_multi(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int i; + for (i = 0; i < 2; i++) { + dev_info(plat_data->dev, "%s idx=%d, value=%d\n", + __func__, i, (int)p_tas256x->mn_rx_slot_map[i]); + ucontrol->value.integer.value[i] = + (unsigned int) p_tas256x->mn_rx_slot_map[i]; + } + + return 0; +} + +static int tas256x_set_rx_slot_map_multi(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = + snd_soc_kcontrol_component(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_component_get_drvdata(codec); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas256x_priv *p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + int i, ret = 0; + char slot_map[2]; + + for (i = 0; i < 2; i++) { + slot_map[i] = (char)(ucontrol->value.integer.value[i]); + ret = tas256x_rx_set_slot(p_tas256x, slot_map[i], i+1); + dev_info(plat_data->dev, "%s mapping - index %d = channel %d\n", + __func__, i, slot_map[i]); + } + + return ret; +} + +static const struct snd_kcontrol_new tas256x_snd_controls_stereo[] = { + SOC_SINGLE_EXT("SmartPA System Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_system_mute_ctrl_get, tas256x_system_mute_ctrl_put), + SOC_SINGLE_EXT("SmartPA Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_mute_ctrl_get, tas256x_mute_ctrl_put), + SOC_SINGLE_EXT("TAS256X DAC Mute", SND_SOC_NOPM, 0, 0x0001, 0, + tas256x_dac_mute_ctrl_get, tas256x_dac_mute_ctrl_put), + SOC_ENUM_EXT("TAS256X ICN Switch", icn_sw_enum[0], + tas256x_get_icn_switch, + tas256x_set_icn_switch), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "TAS256X_RX_SLOT_MAP", + .info = tas256x_rx_slot_map_info, + .get = tas256x_get_rx_slot_map_multi, + .put = tas256x_set_rx_slot_map_multi, + .private_value = (unsigned long) &(struct soc_multi_control_ch_map) { + .reg = SND_SOC_NOPM, + .shift = 0, + .rshift = 0, + .max = 7, + .count = 2, + .platform_max = 7, + .invert = 0, + } + }, +}; + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static struct snd_soc_component_driver soc_codec_driver_tas256x = { + .probe = tas256x_codec_probe, + .remove = tas256x_codec_remove, + .read = tas256x_codec_read, + .write = tas256x_codec_write, +#if IS_ENABLED(CODEC_PM) + .suspend = tas256x_codec_suspend, + .resume = tas256x_codec_resume, +#endif + .controls = tas256x_snd_controls_mono, + .num_controls = ARRAY_SIZE(tas256x_snd_controls_mono), + .dapm_widgets = tas256x_dapm_widgets_mono, + .num_dapm_widgets = ARRAY_SIZE(tas256x_dapm_widgets_mono), + .dapm_routes = tas256x_audio_map_mono, + .num_dapm_routes = ARRAY_SIZE(tas256x_audio_map_mono), +}; +#else +static struct snd_soc_codec_driver soc_codec_driver_tas256x = { + .probe = tas256x_codec_probe, + .remove = tas256x_codec_remove, + .read = tas256x_codec_read, + .write = tas256x_codec_write, +#if IS_ENABLED(CODEC_PM) + .suspend = tas256x_codec_suspend, + .resume = tas256x_codec_resume, +#endif + .component_driver = { + .controls = tas256x_snd_controls_mono, + .num_controls = ARRAY_SIZE(tas256x_snd_controls_mono), + .dapm_widgets = tas256x_dapm_widgets_mono, + .num_dapm_widgets = ARRAY_SIZE(tas256x_dapm_widgets_mono), + .dapm_routes = tas256x_audio_map_mono, + .num_dapm_routes = ARRAY_SIZE(tas256x_audio_map_mono), + }, +}; +#endif + +int tas256x_register_codec(struct tas256x_priv *p_tas256x) +{ + int n_result = 0; + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; + + dev_info(plat_data->dev, "%s, enter\n", __func__); + + if (p_tas256x->mn_channels == 2) { +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + soc_codec_driver_tas256x.controls = + tas256x_snd_controls_stereo; + soc_codec_driver_tas256x.num_controls = + ARRAY_SIZE(tas256x_snd_controls_stereo); + soc_codec_driver_tas256x.dapm_widgets = + tas256x_dapm_widgets_stereo; + soc_codec_driver_tas256x.num_dapm_widgets = + ARRAY_SIZE(tas256x_dapm_widgets_stereo); + soc_codec_driver_tas256x.dapm_routes = + tas256x_audio_map_stereo; + soc_codec_driver_tas256x.num_dapm_routes = + ARRAY_SIZE(tas256x_audio_map_stereo); + n_result = devm_snd_soc_register_component(plat_data->dev, + &soc_codec_driver_tas256x, + tas256x_dai_driver, ARRAY_SIZE(tas256x_dai_driver)); +#else + soc_codec_driver_tas256x.component_driver.controls = + tas256x_snd_controls_stereo; + soc_codec_driver_tas256x.component_driver.num_controls = + ARRAY_SIZE(tas256x_snd_controls_stereo); + soc_codec_driver_tas256x.component_driver.dapm_widgets = + tas256x_dapm_widgets_stereo; + soc_codec_driver_tas256x.component_driver.num_dapm_widgets = + ARRAY_SIZE(tas256x_dapm_widgets_stereo); + soc_codec_driver_tas256x.component_driver.dapm_routes = + tas256x_audio_map_stereo; + soc_codec_driver_tas256x.component_driver.num_dapm_routes = + ARRAY_SIZE(tas256x_audio_map_stereo); + n_result = snd_soc_register_codec(plat_data->dev, + &soc_codec_driver_tas256x, + tas256x_dai_driver, ARRAY_SIZE(tas256x_dai_driver)); +#endif + } else { +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + n_result = devm_snd_soc_register_component(plat_data->dev, + &soc_codec_driver_tas256x, + tas256x_dai_driver, ARRAY_SIZE(tas256x_dai_driver)); +#else + n_result = snd_soc_register_codec(plat_data->dev, + &soc_codec_driver_tas256x, + tas256x_dai_driver, ARRAY_SIZE(tas256x_dai_driver)); +#endif + } + return n_result; +} + +int tas256x_deregister_codec(struct tas256x_priv *p_tas256x) +{ + struct linux_platform *plat_data = + (struct linux_platform *) p_tas256x->platform_data; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + snd_soc_unregister_component(plat_data->dev); +#else + snd_soc_unregister_codec(plat_data->dev); +#endif + return 0; +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS256X ALSA SOC Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); +#endif /* CONFIG_TAS256X_CODEC */ diff --git a/asoc/codecs/tas256x/os_layer/src/tas256x-regmap.c b/asoc/codecs/tas256x/os_layer/src/tas256x-regmap.c new file mode 100644 index 00000000..de5d3ee0 --- /dev/null +++ b/asoc/codecs/tas256x/os_layer/src/tas256x-regmap.c @@ -0,0 +1,1676 @@ +/* + * ALSA SoC Texas Instruments TAS256X High Performance 4W Smart Amplifier + * + * Copyright (C) 2016 Texas Instruments, Inc. + * + * Author: saiprasad + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#if IS_ENABLED(CONFIG_TAS256X_REGMAP) +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/firmware.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/pm.h> +#include <linux/version.h> +#include "physical_layer/inc/tas256x.h" +#include "logical_layer/inc/tas256x-logic.h" +#include "physical_layer/inc/tas256x-device.h" +#include "os_layer/inc/tas256x-codec.h" +#include "os_layer/inc/tas256x-regmap.h" +#include "misc/tas256x-misc.h" + +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#include "algo/inc/tas_smart_amp_v2.h" + +#if IS_ENABLED(CONFIG_PLATFORM_QCOM) +#include <dsp/tas_qualcomm.h> +static dc_detection_data_t s_dc_detect; +#endif /*CONFIG_PLATFORM_QCOM*/ +#endif /*CONFIG_TAS25XX_ALGO*/ +/*For mixer_control implementation*/ +#define MAX_STRING 200 + +static const char *dts_tag[][3] = { + { + "ti,left-channel", + "ti,reset-gpio", + "ti,irq-gpio" + }, + { + "ti,right-channel", + "ti,reset-gpio2", + "ti,irq-gpio2" + } +}; + +static const char *reset_gpio_label[2] = { + "TAS256X_RESET", "TAS256X_RESET2" +}; + +static const char *irq_gpio_label[2] = { + "TAS256X-IRQ", "TAS256X-IRQ2" +}; + +static int tas256x_regmap_write(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned int value) +{ + int nResult = 0; + int retry_count = TAS256X_I2C_RETRY_COUNT; + struct linux_platform *platform_data = + (struct linux_platform *)plat_data; + + if (platform_data->i2c_suspend) + return ERROR_I2C_SUSPEND; + + platform_data->client->addr = i2c_addr; + while (retry_count--) { + nResult = regmap_write(platform_data->regmap, reg, + value); + if (nResult >= 0) + break; + msleep(20); + } + if (retry_count == -1) + return ERROR_I2C_FAILED; + else + return 0; +} + +static int tas256x_regmap_bulk_write(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned char *pData, + unsigned int nLength) +{ + int nResult = 0; + int retry_count = TAS256X_I2C_RETRY_COUNT; + struct linux_platform *platform_data = + (struct linux_platform *)plat_data; + + if (platform_data->i2c_suspend) + return ERROR_I2C_SUSPEND; + + platform_data->client->addr = i2c_addr; + while (retry_count--) { + nResult = regmap_bulk_write(platform_data->regmap, reg, + pData, nLength); + if (nResult >= 0) + break; + msleep(20); + } + if (retry_count == -1) + return ERROR_I2C_FAILED; + else + return 0; +} + +static int tas256x_regmap_read(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned int *value) +{ + int nResult = 0; + int retry_count = TAS256X_I2C_RETRY_COUNT; + struct linux_platform *platform_data = + (struct linux_platform *)plat_data; + + if (platform_data->i2c_suspend) + return ERROR_I2C_SUSPEND; + + platform_data->client->addr = i2c_addr; + while (retry_count--) { + nResult = regmap_read(platform_data->regmap, reg, + value); + if (nResult >= 0) + break; + msleep(20); + } + if (retry_count == -1) + return ERROR_I2C_FAILED; + else + return 0; +} + +static int tas256x_regmap_bulk_read(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned char *pData, + unsigned int nLength) +{ + int nResult = 0; + int retry_count = TAS256X_I2C_RETRY_COUNT; + struct linux_platform *platform_data = + (struct linux_platform *)plat_data; + + if (platform_data->i2c_suspend) + return ERROR_I2C_SUSPEND; + + platform_data->client->addr = i2c_addr; + while (retry_count--) { + nResult = regmap_bulk_read(platform_data->regmap, reg, + pData, nLength); + if (nResult >= 0) + break; + msleep(20); + } + if (retry_count == -1) + return ERROR_I2C_FAILED; + else + return 0; +} + +static int tas256x_regmap_update_bits(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned int mask, + unsigned int value) +{ + int nResult = 0; + int retry_count = TAS256X_I2C_RETRY_COUNT; + struct linux_platform *platform_data = + (struct linux_platform *)plat_data; + + if (platform_data->i2c_suspend) + return ERROR_I2C_SUSPEND; + + platform_data->client->addr = i2c_addr; + while (retry_count--) { + nResult = regmap_update_bits(platform_data->regmap, reg, + mask, value); + if (nResult >= 0) + break; + msleep(20); + } + if (retry_count == -1) + return ERROR_I2C_FAILED; + else + return 0; +} + +static char const *tas2564_rx_mode_text[] = {"Speaker", "Receiver"}; + +static const struct soc_enum tas2564_rx_mode_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas2564_rx_mode_text), + tas2564_rx_mode_text), +}; + +static int tas2564_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + int ret = -1; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + if (strnstr(ucontrol->id.name, "LEFT", MAX_STRING)) + ret = tas2564_rx_mode_update(p_tas256x, + ucontrol->value.integer.value[0], channel_left); + else if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) + ret = tas2564_rx_mode_update(p_tas256x, + ucontrol->value.integer.value[0], channel_right); + else + dev_err(plat_data->dev, "Invalid Channel %s\n", + ucontrol->id.name); + + return ret; +} + +static int tas2564_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = -1; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct linux_platform *plat_data = NULL; + struct tas256x_priv *p_tas256x = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + if (strnstr(ucontrol->id.name, "LEFT", MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->rx_mode; + else if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->rx_mode; + else + dev_err(plat_data->dev, "Invalid Channel %s\n", + ucontrol->id.name); + + return 0; +} + +static int tas256x_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + int ret = -1; + + if ((codec == NULL) || (mc == NULL)) { + pr_err("%s:codec or control is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + if (ucontrol->value.integer.value[0] > mc->max) + return ret; + + switch (mc->reg) { + case DVC_PCM: + ret = tas256x_update_playback_volume(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIM_MAX_ATN: + ret = tas256x_update_lim_max_attenuation(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_INF_PT: + ret = tas256x_update_lim_inflection_point(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_SLOPE: + ret = tas256x_update_lim_slope(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_ATK_RT: + ret = tas256x_update_limiter_attack_rate(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_RLS_RT: + ret = tas256x_update_limiter_release_rate(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_RLS_ST: + ret = tas256x_update_limiter_release_step_size(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_ATK_ST: + ret = tas256x_update_limiter_attack_step_size(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BOP_ATK_RT: + ret = tas256x_update_bop_attack_rate(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BOP_ATK_ST: + ret = tas256x_update_bop_attack_step_size(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BOP_HLD_TM: + ret = tas256x_update_bop_hold_time(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BST_VREG: + ret = tas256x_update_boost_voltage(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BST_ILIM: + ret = tas256x_update_current_limit(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_TH_MAX: + ret = tas256x_update_lim_max_thr(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case LIMB_TH_MIN: + ret = tas256x_update_lim_min_thr(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BOP_TH: + ret = tas256x_update_bop_thr(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case BOSD_TH: + ret = tas256x_update_bosd_thr(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case CLASSH_TIMER: + ret = tas256x_update_classh_timer(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + case AMPOUTPUT_LVL: + ret = tas256x_update_ampoutput_level(p_tas256x, + ucontrol->value.integer.value[0], mc->shift); + break; + } + return ret; +} + +static int tas256x_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + int ret = -1; + + if ((codec == NULL) || (mc == NULL)) { + pr_err("%s:codec or control is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + switch (mc->reg) { + case DVC_PCM: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->dvc_pcm; + break; + case LIM_MAX_ATN: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_max_attn; + break; + case LIMB_INF_PT: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_infl_pt; + break; + case LIMB_SLOPE: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_trk_slp; + break; + case LIMB_ATK_RT: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_att_rate; + break; + case LIMB_RLS_RT: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_rel_rate; + break; + case LIMB_RLS_ST: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_rel_stp_size; + break; + case LIMB_ATK_ST: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_att_stp_size; + break; + case BOP_ATK_RT: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bop_att_rate; + break; + case BOP_ATK_ST: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bop_att_stp_size; + break; + case BOP_HLD_TM: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bop_hld_time; + break; + case BST_VREG: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bst_vltg; + break; + case BST_ILIM: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bst_ilm; + break; + case LIMB_TH_MAX: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_thr_max; + break; + case LIMB_TH_MIN: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->lim_thr_min; + break; + case BOP_TH: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bop_thd; + break; + case BOSD_TH: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->bosd_thd; + break; + case CLASSH_TIMER: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->classh_timer; + break; + case AMPOUTPUT_LVL: + ucontrol->value.integer.value[0] = + p_tas256x->devs[mc->shift-1]->ampoutput_lvl; + break; + } + return 0; +} + +static int tas256x_enum_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = -1; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return ret; + } + + if (ucontrol == NULL) { + pr_err("%s:ucontrol is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + if (strnstr(ucontrol->id.name, "Version", MAX_STRING)) { + ucontrol->value.integer.value[0] = 0; + } else if (strnstr(ucontrol->id.name, "LEFT", MAX_STRING)) { + if (strnstr(ucontrol->id.name, "LIMITER SWITCH", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->lim_switch; + else if (strnstr(ucontrol->id.name, "BOP ENABLE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->bop_enable; + else if (strnstr(ucontrol->id.name, "BOP MUTE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->bop_mute; + else if (strnstr(ucontrol->id.name, "BROWNOUT SHUTDOWN", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->bosd_enable; + else if (strnstr(ucontrol->id.name, "VBAT LPF", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->vbat_lpf; + else if (strnstr(ucontrol->id.name, "RECIEVER ENABLE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[0]->reciever_enable; + else + dev_err(plat_data->dev, "Invalid controll %s\n", + ucontrol->id.name); + } else if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) { + if (strnstr(ucontrol->id.name, "LIMITER SWITCH", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->lim_switch; + else if (strnstr(ucontrol->id.name, "BOP ENABLE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->bop_enable; + else if (strnstr(ucontrol->id.name, "BOP MUTE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->bop_mute; + else if (strnstr(ucontrol->id.name, "BROWNOUT SHUTDOWN", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->bosd_enable; + else if (strnstr(ucontrol->id.name, "VBAT LPF", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->vbat_lpf; + else if (strnstr(ucontrol->id.name, "RECIEVER ENABLE", + MAX_STRING)) + ucontrol->value.integer.value[0] = + p_tas256x->devs[1]->reciever_enable; + else + dev_err(plat_data->dev, "Invalid controll %s\n", + ucontrol->id.name); + } else { + dev_err(plat_data->dev, "Invalid Channel %s\n", + ucontrol->id.name); + } + return 0; +} + +static int tas256x_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); +#else + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +#endif + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct tas256x_priv *p_tas256x = NULL; + struct linux_platform *plat_data = NULL; + int ret = -1; + + if ((codec == NULL) || (mc == NULL)) { + pr_err("%s:codec or control is NULL\n", __func__); + return ret; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + p_tas256x = snd_soc_component_get_drvdata(codec); +#else + p_tas256x = snd_soc_codec_get_drvdata(codec); +#endif + if (p_tas256x == NULL) { + pr_err("%s:p_tas256x is NULL\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + if (strnstr(ucontrol->id.name, "LEFT", MAX_STRING)) { + if (strnstr(ucontrol->id.name, "LIMITER SWITCH", + MAX_STRING)) + ret = tas256x_update_limiter_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else if (strnstr(ucontrol->id.name, "BOP ENABLE", + MAX_STRING)) + ret = tas256x_update_bop_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else if (strnstr(ucontrol->id.name, "BOP MUTE", + MAX_STRING)) + ret = tas256x_update_bop_mute(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else if (strnstr(ucontrol->id.name, "BROWNOUT SHUTDOWN", + MAX_STRING)) + ret = tas256x_update_bop_shutdown_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else if (strnstr(ucontrol->id.name, "VBAT LPF", + MAX_STRING)) + ret = tas256x_update_vbat_lpf(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else if (strnstr(ucontrol->id.name, "RECIEVER ENABLE", + MAX_STRING)) + ret = tas256x_enable_reciever_mode(p_tas256x, + ucontrol->value.integer.value[0], + channel_left); + else + dev_err(plat_data->dev, "Invalid Control %s\n", + ucontrol->id.name); + } else if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) { + if (strnstr(ucontrol->id.name, "LIMITER SWITCH", + MAX_STRING)) + ret = tas256x_update_limiter_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else if (strnstr(ucontrol->id.name, "BOP ENABLE", + MAX_STRING)) + ret = tas256x_update_bop_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else if (strnstr(ucontrol->id.name, "BOP MUTE", + MAX_STRING)) + ret = tas256x_update_bop_mute(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else if (strnstr(ucontrol->id.name, "BROWNOUT SHUTDOWN", + MAX_STRING)) + ret = tas256x_update_bop_shutdown_enable(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else if (strnstr(ucontrol->id.name, "VBAT LPF", + MAX_STRING)) + ret = tas256x_update_vbat_lpf(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else if (strnstr(ucontrol->id.name, "RECIEVER ENABLE", + MAX_STRING)) + ret = tas256x_enable_reciever_mode(p_tas256x, + ucontrol->value.integer.value[0], + channel_right); + else + dev_err(plat_data->dev, "Invalid control %s\n", + ucontrol->id.name); + } else { + dev_err(plat_data->dev, "Invalid Channel %s\n", + ucontrol->id.name); + } + return ret; +} + +static char const *tas256x_rx_switch_text[] = {"DISABLE", "ENABLE"}; +static const struct soc_enum tas256x_rx_switch_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas256x_rx_switch_text), + tas256x_rx_switch_text), +}; + +static char const *tas256x_version_text[] = {TAS256X_DRIVER_TAG}; +static const struct soc_enum tas256x_version_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas256x_version_text), + tas256x_version_text), +}; + +static const struct snd_kcontrol_new tas256x_left_controls[] = { + SOC_ENUM_EXT("TAS256X Version", tas256x_version_enum[0], + tas256x_enum_get, NULL), + SOC_SINGLE_EXT("TAS256X PLAYBACK VOLUME LEFT", DVC_PCM, 1, 56, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM MAX ATTN LEFT", LIM_MAX_ATN, 1, 15, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM THR MAX LEFT", LIMB_TH_MAX, + 1, 26, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM THR MIN LEFT", LIMB_TH_MIN, + 1, 26, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM INFLECTION POINT LEFT", LIMB_INF_PT, + 1, 40, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM SLOPE LEFT", LIMB_SLOPE, 1, 6, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP THR LEFT", BOP_TH, + 1, 15, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOSD THR LEFT", BOSD_TH, + 1, 15, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM ATTACT RATE LEFT", LIMB_ATK_RT, 1, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM RELEASE RATE LEFT", LIMB_RLS_RT, 1, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM ATTACK STEP LEFT", LIMB_ATK_ST, 1, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM RELEASE STEP LEFT", LIMB_RLS_ST, 1, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP ATTACK RATE LEFT", BOP_ATK_RT, 1, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP ATTACK STEP LEFT", BOP_ATK_ST, 1, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP HOLD TIME LEFT", BOP_HLD_TM, 1, 7, 0, + tas256x_get, tas256x_put), + SOC_ENUM_EXT("TAS256X LIMITER SWITCH LEFT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BOP ENABLE LEFT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BOP MUTE LEFT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BROWNOUT SHUTDOWN LEFT", + tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X CLASSH TIMER LEFT", CLASSH_TIMER, 1, 22, 0, + tas256x_get, tas256x_put), + SOC_ENUM_EXT("TAS256X RECIEVER ENABLE LEFT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), +}; + +static const struct snd_kcontrol_new tas256x_right_controls[] = { + SOC_SINGLE_EXT("TAS256X PLAYBACK VOLUME RIGHT", DVC_PCM, 2, 56, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM MAX ATTN RIGHT", LIM_MAX_ATN, 2, 15, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM THR MAX RIGHT", LIMB_TH_MAX, + 2, 26, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM THR MIN RIGHT", LIMB_TH_MIN, + 2, 26, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM INFLECTION POINT RIGHT", LIMB_INF_PT, + 2, 40, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM SLOPE RIGHT", LIMB_SLOPE, 2, 6, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP THR RIGHT", BOP_TH, + 2, 15, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOSD THR RIGHT", BOSD_TH, + 2, 15, 0, tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM ATTACT RATE RIGHT", LIMB_ATK_RT, 2, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM RELEASE RATE RIGHT", LIMB_RLS_RT, 2, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM ATTACK STEP RIGHT", LIMB_ATK_ST, 2, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X LIM RELEASE STEP RIGHT", LIMB_RLS_ST, 2, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP ATTACK RATE RIGHT", BOP_ATK_RT, 2, 7, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP ATTACK STEP RIGHT", BOP_ATK_ST, 2, 3, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOP HOLD TIME RIGHT", BOP_HLD_TM, 2, 7, 0, + tas256x_get, tas256x_put), + SOC_ENUM_EXT("TAS256X LIMITER SWITCH RIGHT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BOP ENABLE RIGHT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BOP MUTE RIGHT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_ENUM_EXT("TAS256X BROWNOUT SHUTDOWN RIGHT", + tas256x_rx_switch_enum[0], tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X CLASSH TIMER RIGHT", CLASSH_TIMER, 2, 22, 0, + tas256x_get, tas256x_put), + SOC_ENUM_EXT("TAS256X RECIEVER ENABLE RIGHT", tas256x_rx_switch_enum[0], + tas256x_enum_get, tas256x_enum_put), +}; + +static char const *tas2564_vbat_lpf_text[] = { + "DISABLE", "HZ_10", "HZ_100", "KHZ_1"}; +static const struct soc_enum tas2564_vbat_lpf_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas2564_vbat_lpf_text), + tas2564_vbat_lpf_text), +}; + +static char const *tas2562_vbat_lpf_text[] = { + "DISABLE", "HZ_100", "KHZ_1", "KHZ_10"}; +static const struct soc_enum tas2562_vbat_lpf_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas2562_vbat_lpf_text), + tas2562_vbat_lpf_text), +}; + +static const struct snd_kcontrol_new tas2564_left_controls[] = { + SOC_ENUM_EXT("TAS256X RX MODE LEFT", tas2564_rx_mode_enum[0], + tas2564_get, tas2564_put), + SOC_ENUM_EXT("TAS256X VBAT LPF LEFT", tas2564_vbat_lpf_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X BOOST VOLTAGE LEFT", BST_VREG, 1, 15, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOOST CURRENT LEFT", BST_ILIM, 1, 63, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X AMP OUTPUT LVL LEFT", AMPOUTPUT_LVL, 1, 0x1C, 0, + tas256x_get, tas256x_put), +}; + +static const struct snd_kcontrol_new tas2564_right_controls[] = { + SOC_ENUM_EXT("TAS256X RX MODE RIGHT", tas2564_rx_mode_enum[0], + tas2564_get, tas2564_put), + SOC_ENUM_EXT("TAS256X VBAT LPF RIGHT", tas2564_vbat_lpf_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X BOOST VOLTAGE RIGHT", BST_VREG, 2, 15, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOOST CURRENT RIGHT", BST_ILIM, 2, 63, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X AMP OUTPUT LVL RIGHT", AMPOUTPUT_LVL, 2, 0x1C, 0, + tas256x_get, tas256x_put), +}; + +static const struct snd_kcontrol_new tas2562_left_controls[] = { + SOC_ENUM_EXT("TAS256X VBAT LPF LEFT", tas2562_vbat_lpf_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X BOOST VOLTAGE LEFT", BST_VREG, 1, 12, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOOST CURRENT LEFT", BST_ILIM, 1, 55, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X AMP OUTPUT LVL LEFT", AMPOUTPUT_LVL, 1, 0x1C, 0, + tas256x_get, tas256x_put), +}; + +static const struct snd_kcontrol_new tas2562_right_controls[] = { + SOC_ENUM_EXT("TAS256X VBAT LPF RIGHT", tas2562_vbat_lpf_enum[0], + tas256x_enum_get, tas256x_enum_put), + SOC_SINGLE_EXT("TAS256X BOOST VOLTAGE RIGHT", BST_VREG, 2, 12, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X BOOST CURRENT RIGHT", BST_ILIM, 2, 55, 0, + tas256x_get, tas256x_put), + SOC_SINGLE_EXT("TAS256X AMP OUTPUT LVL RIGHT", AMPOUTPUT_LVL, 2, 0x1C, 0, + tas256x_get, tas256x_put), +}; + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static int tas2564_probe(struct tas256x_priv *p_tas256x, + struct snd_soc_component *codec, int chn) +{ + int ret = -1; + struct linux_platform *plat_data = NULL; + + if ((!p_tas256x) || (!codec)) { + pr_err("tas256x:%s p_tas256x or codec is Null\n", __func__); + return ret; + } + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s channel %d", __func__, chn); + + tas256x_update_default_params(p_tas256x, chn); + if (chn == channel_left) { + ret = snd_soc_add_component_controls(codec, tas256x_left_controls, + ARRAY_SIZE(tas256x_left_controls)); + ret = snd_soc_add_component_controls(codec, tas2564_left_controls, + ARRAY_SIZE(tas2564_left_controls)); + } else if (chn == channel_right) { + ret = snd_soc_add_component_controls(codec, tas256x_right_controls, + ARRAY_SIZE(tas256x_right_controls)); + ret = snd_soc_add_component_controls(codec, tas2564_right_controls, + ARRAY_SIZE(tas2564_right_controls)); + } else { + dev_err(plat_data->dev, "Invalid Channel %d\n", chn); + } + + return ret; +} +#else +static int tas2564_probe(struct tas256x_priv *p_tas256x, + struct snd_soc_codec *codec, int chn) +{ + int ret = -1; + struct linux_platform *plat_data = NULL; + + if ((!p_tas256x) || (!codec)) { + pr_err("tas256x:%s p_tas256x or codec is Null\n", __func__); + return ret; + } + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s channel %d", __func__, chn); + + tas256x_update_default_params(p_tas256x, chn); + if (chn == channel_left) { + ret = snd_soc_add_codec_controls(codec, tas256x_left_controls, + ARRAY_SIZE(tas256x_left_controls)); + ret = snd_soc_add_codec_controls(codec, tas2564_left_controls, + ARRAY_SIZE(tas2564_left_controls)); + } else if (chn == channel_right) { + ret = snd_soc_add_codec_controls(codec, tas256x_right_controls, + ARRAY_SIZE(tas256x_right_controls)); + ret = snd_soc_add_codec_controls(codec, tas2564_right_controls, + ARRAY_SIZE(tas2564_right_controls)); + } else { + dev_err(plat_data->dev, "Invalid Channel %d\n", chn); + } + + return ret; +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +static int tas2562_probe(struct tas256x_priv *p_tas256x, + struct snd_soc_component *codec, int chn) +{ + struct linux_platform *plat_data = NULL; + int ret = -1; + + if ((!p_tas256x) || (!codec)) { + pr_err("tas256x:%s p_tas256x or codec is Null\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s channel %d", __func__, chn); + + tas256x_update_default_params(p_tas256x, chn); + if (chn == channel_left) { + ret = snd_soc_add_component_controls(codec, tas256x_left_controls, + ARRAY_SIZE(tas256x_left_controls)); + ret = snd_soc_add_component_controls(codec, tas2562_left_controls, + ARRAY_SIZE(tas2562_left_controls)); + } else if (chn == channel_right) { + ret = snd_soc_add_component_controls(codec, tas256x_right_controls, + ARRAY_SIZE(tas256x_right_controls)); + ret = snd_soc_add_component_controls(codec, tas2562_right_controls, + ARRAY_SIZE(tas2562_right_controls)); + } else { + dev_err(plat_data->dev, "Invalid Channel %d\n", chn); + } + + return ret; +} +#else +static int tas2562_probe(struct tas256x_priv *p_tas256x, + struct snd_soc_codec *codec, int chn) +{ + struct linux_platform *plat_data = NULL; + int ret = -1; + + if ((!p_tas256x) || (!codec)) { + pr_err("tas256x:%s p_tas256x or codec is Null\n", __func__); + return ret; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s channel %d", __func__, chn); + + tas256x_update_default_params(p_tas256x, chn); + if (chn == channel_left) { + ret = snd_soc_add_codec_controls(codec, tas256x_left_controls, + ARRAY_SIZE(tas256x_left_controls)); + ret = snd_soc_add_codec_controls(codec, tas2562_left_controls, + ARRAY_SIZE(tas2562_left_controls)); + } else if (chn == channel_right) { + ret = snd_soc_add_codec_controls(codec, tas256x_right_controls, + ARRAY_SIZE(tas256x_right_controls)); + ret = snd_soc_add_codec_controls(codec, tas2562_right_controls, + ARRAY_SIZE(tas2562_right_controls)); + } else { + dev_err(plat_data->dev, "Invalid Channel %d\n", chn); + } + + return ret; +} +#endif + +static bool tas256x_volatile(struct device *dev, unsigned int reg) +{ + return true; +} + +static bool tas256x_writeable(struct device *dev, unsigned int reg) +{ + return true; +} +static const struct regmap_config tas256x_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = tas256x_writeable, + .volatile_reg = tas256x_volatile, + .cache_type = REGCACHE_NONE, + .max_register = 1 * 128, +}; + +static void tas256x_hw_reset(struct tas256x_priv *p_tas256x) +{ + struct linux_platform *plat_data = NULL; + int i = 0; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_reset_gpio)) { + gpio_direction_output( + p_tas256x->devs[i]->mn_reset_gpio, 0); + } + } + msleep(20); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_reset_gpio)) { + gpio_direction_output( + p_tas256x->devs[i]->mn_reset_gpio, 1); + } + p_tas256x->devs[i]->mn_current_book = -1; + p_tas256x->devs[i]->mn_current_page = -1; + } + msleep(20); + + dev_info(plat_data->dev, "reset gpio up !!\n"); +} + +void tas256x_enable_irq(struct tas256x_priv *p_tas256x, bool enable) +{ + static int irq_enabled[2] = {0}; + struct irq_desc *desc = NULL; + struct linux_platform *plat_data = NULL; + int i = 0; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + if (enable) { + if (p_tas256x->mb_irq_eable) + return; + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_irq_gpio) && + irq_enabled[i] == 0) { + if (i == 0) { + desc = irq_to_desc( + p_tas256x->devs[i]->mn_irq); + if (desc && desc->depth > 0) + enable_irq( + p_tas256x->devs[i]->mn_irq); + else + dev_info(plat_data->dev, + "### irq already enabled"); + } else { + enable_irq(p_tas256x->devs[i]->mn_irq); + } + irq_enabled[i] = 1; + } + } + p_tas256x->mb_irq_eable = true; + } else { + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_irq_gpio) + && irq_enabled[i] == 1) { + disable_irq_nosync(p_tas256x->devs[i]->mn_irq); + irq_enabled[i] = 0; + } + } + p_tas256x->mb_irq_eable = false; + } +} + +static void irq_work_routine(struct work_struct *work) +{ + struct tas256x_priv *p_tas256x = + container_of(work, struct tas256x_priv, irq_work.work); + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_info(plat_data->dev, "%s\n", __func__); +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + if (plat_data->mb_runtime_suspend) { + pr_info("%s, Runtime Suspended\n", __func__); + goto end; + } + /*Logical Layer IRQ function, return is ignored*/ + tas256x_irq_work_func(p_tas256x); + +end: +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif + return; +} + +static void init_work_routine(struct work_struct *work) +{ + struct tas256x_priv *p_tas256x = + container_of(work, struct tas256x_priv, init_work.work); + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + /*Init Work Function. return is ignored*/ + tas256x_init_work_func(p_tas256x); + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif +} + +static irqreturn_t tas256x_irq_handler(int irq, void *dev_id) +{ + struct tas256x_priv *p_tas256x = (struct tas256x_priv *)dev_id; + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + /* get IRQ status after 100 ms */ + schedule_delayed_work(&p_tas256x->irq_work, msecs_to_jiffies(100)); + return IRQ_HANDLED; +} + +static int tas256x_runtime_suspend(struct tas256x_priv *p_tas256x) +{ + struct linux_platform *plat_data = NULL; + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s\n", __func__); + + plat_data->mb_runtime_suspend = true; + + if (delayed_work_pending(&p_tas256x->irq_work)) { + dev_dbg(plat_data->dev, "cancel IRQ work\n"); + cancel_delayed_work_sync(&p_tas256x->irq_work); + } + + return 0; +} + +static int tas256x_runtime_resume(struct tas256x_priv *p_tas256x) +{ + struct linux_platform *plat_data = NULL; + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_dbg(plat_data->dev, "%s\n", __func__); + + plat_data->mb_runtime_suspend = false; + + return 0; +} + +static int tas256x_pm_suspend(struct device *dev) +{ + struct tas256x_priv *p_tas256x = dev_get_drvdata(dev); + struct linux_platform *plat_data = NULL; + + if (!p_tas256x) { + dev_err(plat_data->dev, "drvdata is NULL\n"); + return -EINVAL; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + mutex_lock(&p_tas256x->codec_lock); + tas256x_runtime_suspend(p_tas256x); + mutex_unlock(&p_tas256x->codec_lock); + return 0; +} + +static int tas256x_pm_resume(struct device *dev) +{ + struct tas256x_priv *p_tas256x = dev_get_drvdata(dev); + struct linux_platform *plat_data = NULL; + + if (!p_tas256x) { + dev_err(plat_data->dev, "drvdata is NULL\n"); + return -EINVAL; + } + plat_data = (struct linux_platform *) p_tas256x->platform_data; + + mutex_lock(&p_tas256x->codec_lock); + tas256x_runtime_resume(p_tas256x); + mutex_unlock(&p_tas256x->codec_lock); + return 0; +} + +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#if IS_ENABLED(CONFIG_PLATFORM_QCOM) +struct tas256x_priv *g_p_tas256x; + +void tas256x_software_reset(void *prv_data) +{ + pr_err("[TI-SmartPA:%s]\n", __func__); + schedule_delayed_work(&g_p_tas256x->dc_work, msecs_to_jiffies(10)); +} + +static void dc_work_routine(struct work_struct *work) +{ + struct tas256x_priv *p_tas256x = + container_of(work, struct tas256x_priv, dc_work.work); + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_lock(&p_tas256x->codec_lock); +#endif + tas256x_dc_work_func(p_tas256x, s_dc_detect.channel); + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_unlock(&p_tas256x->codec_lock); +#endif + +} +#endif/*CONFIG_PLATFORM_QCOM*/ +#endif /*CONFIG_TAS25XX_ALGO*/ + +void schedule_init_work(struct tas256x_priv *p_tas256x) +{ + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + schedule_delayed_work(&p_tas256x->init_work, msecs_to_jiffies(50)); +} + +static int tas256x_parse_dt(struct device *dev, + struct tas256x_priv *p_tas256x) +{ + struct device_node *np = dev->of_node; + int rc = 0, i = 0; + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + rc = of_property_read_u32(np, "ti,channels", &p_tas256x->mn_channels); + if (rc) { + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,channels", np->full_name, rc); + goto EXIT; + } else { + dev_dbg(plat_data->dev, "ti,channels=%d", + p_tas256x->mn_channels); + } + + /*the device structures array*/ + p_tas256x->devs = + kmalloc(p_tas256x->mn_channels * sizeof(struct tas_device *), + GFP_KERNEL); + for (i = 0; i < p_tas256x->mn_channels; i++) { + p_tas256x->devs[i] = kmalloc(sizeof(struct tas_device), + GFP_KERNEL); + if (p_tas256x->devs[i] == NULL) { + dev_err(plat_data->dev, + "%s:%u:kmalloc failed!\n", __func__, __LINE__); + rc = -1; + break; + } + + rc = of_property_read_u32(np, dts_tag[i][0], + &p_tas256x->devs[i]->mn_addr); + if (rc) { + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + dts_tag[i][0], np->full_name, rc); + break; + } else { + dev_dbg(plat_data->dev, "%s = 0x%02x", + dts_tag[i][0], p_tas256x->devs[i]->mn_addr); + } + + p_tas256x->devs[i]->mn_reset_gpio = + of_get_named_gpio(np, dts_tag[i][1], 0); + if (!gpio_is_valid(p_tas256x->devs[i]->mn_reset_gpio)) + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + dts_tag[i][1], np->full_name, + p_tas256x->devs[i]->mn_reset_gpio); + else + dev_dbg(plat_data->dev, "%s = %d", + dts_tag[i][1], + p_tas256x->devs[i]->mn_reset_gpio); + + p_tas256x->devs[i]->mn_irq_gpio = + of_get_named_gpio(np, dts_tag[i][2], 0); + if (!gpio_is_valid(p_tas256x->devs[i]->mn_irq_gpio)) { + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + dts_tag[i][2], np->full_name, + p_tas256x->devs[i]->mn_irq_gpio); + } else { + dev_dbg(plat_data->dev, "%s = %d", + dts_tag[i][2], + p_tas256x->devs[i]->mn_irq_gpio); + } + p_tas256x->devs[i]->spk_control = 1; + } + + if (rc) + goto EXIT; + + rc = of_property_read_u32(np, "ti,frame-start", &p_tas256x->mn_frame_start); + if (rc) { + dev_info(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,frame-start", np->full_name, rc); + p_tas256x->mn_frame_start = 0; + } else { + dev_dbg(plat_data->dev, "ti,frame-start=0x%x", + p_tas256x->mn_frame_start); + } + + rc = of_property_read_u32(np, "ti,rx-offset", &p_tas256x->mn_rx_offset); + if (rc) { + dev_info(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,rx-offset", np->full_name, rc); + p_tas256x->mn_rx_offset = 1; + } else { + dev_dbg(plat_data->dev, "ti,rx-offset=0x%x", + p_tas256x->mn_rx_offset); + } + + rc = of_property_read_u32(np, "ti,rx-edge", &p_tas256x->mn_rx_edge); + if (rc) { + dev_info(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,rx-edge", np->full_name, rc); + p_tas256x->mn_rx_edge = 1; + } else { + dev_dbg(plat_data->dev, "ti,rx-edge=0x%x", + p_tas256x->mn_rx_edge); + } + + rc = of_property_read_u32(np, "ti,tx-offset", &p_tas256x->mn_tx_offset); + if (rc) { + dev_info(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,tx-offset", np->full_name, rc); + p_tas256x->mn_tx_offset = 0; + } else { + dev_dbg(plat_data->dev, "ti,tx-offset=0x%x", + p_tas256x->mn_tx_offset); + } + + rc = of_property_read_u32(np, "ti,tx-edge", &p_tas256x->mn_tx_edge); + if (rc) { + dev_info(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,tx-edge", np->full_name, rc); + p_tas256x->mn_tx_edge = 0; + } else { + dev_dbg(plat_data->dev, "ti,tx-edge=0x%x", + p_tas256x->mn_tx_edge); + } + + rc = of_property_read_u32(np, "ti,iv-width", &p_tas256x->mn_iv_width); + if (rc) { + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,iv-width", np->full_name, rc); + } else { + dev_dbg(plat_data->dev, "ti,iv-width=0x%x", + p_tas256x->mn_iv_width); + } + + rc = of_property_read_u32(np, "ti,vbat-mon", &p_tas256x->mn_vbat); + if (rc) { + dev_err(plat_data->dev, + "Looking up %s property in node %s failed %d\n", + "ti,vbat-mon", np->full_name, rc); + } else { + dev_dbg(plat_data->dev, "ti,vbat-mon=0x%x", + p_tas256x->mn_vbat); + } +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + /* Needs to be enabled always */ + tas25xx_parse_algo_dt(np); +#endif /*CONFIG_TAS25XX_ALGO*/ +EXIT: + return rc; +} + +static int tas256x_i2c_probe(struct i2c_client *p_client, + const struct i2c_device_id *id) +{ + struct tas256x_priv *p_tas256x; + struct linux_platform *plat_data; + int n_result = 0; + int i = 0; + + dev_info(&p_client->dev, "Driver Tag: %s\n", TAS256X_DRIVER_TAG); + dev_info(&p_client->dev, "%s enter\n", __func__); + + p_tas256x = devm_kzalloc(&p_client->dev, + sizeof(struct tas256x_priv), GFP_KERNEL); + if (p_tas256x == NULL) { + dev_err(&p_client->dev, "failed to allocate memory\n"); + n_result = -ENOMEM; + goto err; + } + + plat_data = (struct linux_platform *)devm_kzalloc(&p_client->dev, + sizeof(struct linux_platform), GFP_KERNEL); + if (p_tas256x == NULL) { + dev_err(&p_client->dev, "failed to allocate memory\n"); + n_result = -ENOMEM; + goto err; + } + + p_tas256x->platform_data = plat_data; +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + p_tas256x->profile_cfg_id = -1; +#endif + p_tas256x->plat_write = tas256x_regmap_write; + p_tas256x->plat_read = tas256x_regmap_read; + p_tas256x->plat_bulk_write = tas256x_regmap_bulk_write; + p_tas256x->plat_bulk_read = tas256x_regmap_bulk_read; + p_tas256x->plat_update_bits = tas256x_regmap_update_bits; + + plat_data->client = p_client; + plat_data->dev = &p_client->dev; + i2c_set_clientdata(p_client, p_tas256x); + dev_set_drvdata(&p_client->dev, p_tas256x); + plat_data->regmap = devm_regmap_init_i2c(p_client, + &tas256x_i2c_regmap); + if (IS_ERR(plat_data->regmap)) { + n_result = PTR_ERR(plat_data->regmap); + dev_err(&p_client->dev, + "Failed to allocate register map: %d\n", + n_result); + goto err; + } + + mutex_init(&p_tas256x->dev_lock); + p_tas256x->hw_reset = tas256x_hw_reset; + p_tas256x->enable_irq = tas256x_enable_irq; + p_tas256x->schedule_init_work = schedule_init_work; +#if IS_ENABLED(CODEC_PM) + plat_data->runtime_suspend = tas256x_runtime_suspend; + plat_data->runtime_resume = tas256x_runtime_resume; + plat_data->mn_power_state = TAS256X_POWER_SHUTDOWN; +#endif + + if (p_client->dev.of_node) + tas256x_parse_dt(&p_client->dev, p_tas256x); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_reset_gpio)) { + n_result = gpio_request( + p_tas256x->devs[i]->mn_reset_gpio, + reset_gpio_label[i]); + if (n_result) { + dev_err(plat_data->dev, + "%s: Failed to request gpio %d\n", + __func__, + p_tas256x->devs[i]->mn_reset_gpio); + n_result = -EINVAL; + goto err; + } + } + } + + n_result = tas256x_register_device(p_tas256x); + if (n_result < 0) + goto err; + + for (i = 0; i < p_tas256x->mn_channels; i++) { + switch (p_tas256x->devs[i]->device_id) { + case DEVICE_TAS2562: + p_tas256x->devs[i]->dev_ops.tas_probe = tas2562_probe; + break; + case DEVICE_TAS2564: + p_tas256x->devs[i]->dev_ops.tas_probe = tas2564_probe; + break; + default: + p_tas256x->devs[i]->dev_ops.tas_probe = NULL; + break; + } + } + + INIT_DELAYED_WORK(&p_tas256x->irq_work, irq_work_routine); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_irq_gpio)) { + n_result = + gpio_request( + p_tas256x->devs[i]->mn_irq_gpio, + irq_gpio_label[i]); + if (n_result < 0) { + dev_err(plat_data->dev, + "%s:%u: ch 0x%02x: GPIO %d request error\n", + __func__, __LINE__, + p_tas256x->devs[i]->mn_addr, + p_tas256x->devs[i]->mn_irq_gpio); + goto err; + } + gpio_direction_input(p_tas256x->devs[i]->mn_irq_gpio); + /*tas256x_dev_write(p_tas256x, + * (i == 0) ? channel_left : channel_right, + * TAS256X_MISCCONFIGURATIONREG0, 0xce); + */ + + p_tas256x->devs[i]->mn_irq = + gpio_to_irq(p_tas256x->devs[i]->mn_irq_gpio); + dev_info(plat_data->dev, "irq = %d\n", + p_tas256x->devs[i]->mn_irq); + + n_result = request_threaded_irq( + p_tas256x->devs[i]->mn_irq, + tas256x_irq_handler, + NULL, + IRQF_TRIGGER_FALLING|IRQF_ONESHOT, + p_client->name, p_tas256x); + if (n_result < 0) { + dev_err(plat_data->dev, + "request_irq failed, %d\n", n_result); + goto err; + } + disable_irq_nosync(p_tas256x->devs[i]->mn_irq); + } + } + + tas256x_enable_irq(p_tas256x, true); + INIT_DELAYED_WORK(&p_tas256x->init_work, init_work_routine); + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + mutex_init(&p_tas256x->codec_lock); + n_result = tas256x_register_codec(p_tas256x); + if (n_result < 0) { + dev_err(plat_data->dev, + "register codec failed, %d\n", n_result); + goto err; + } +#endif + +#if IS_ENABLED(CONFIG_TAS256X_MISC) + mutex_init(&p_tas256x->file_lock); + n_result = tas256x_register_misc(p_tas256x); + if (n_result < 0) { + dev_err(plat_data->dev, "register codec failed %d\n", + n_result); + goto err; + } +#endif + + +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#if IS_ENABLED(CONFIG_PLATFORM_QCOM) + INIT_DELAYED_WORK(&p_tas256x->dc_work, dc_work_routine); + g_p_tas256x = p_tas256x; + register_tas256x_reset_func(tas256x_software_reset, &s_dc_detect); +#endif /*CONFIG_PLATFORM_QCOM*/ +#endif /*CONFIG_TAS25XX_ALGO*/ + + +err: + return n_result; +} + +static int tas256x_i2c_remove(struct i2c_client *p_client) +{ + int i = 0; + struct tas256x_priv *p_tas256x = i2c_get_clientdata(p_client); + struct linux_platform *plat_data = NULL; + + plat_data = (struct linux_platform *) p_tas256x->platform_data; + dev_info(plat_data->dev, "%s\n", __func__); + + /*Cancel all the work routine before exiting*/ + cancel_delayed_work_sync(&p_tas256x->irq_work); + cancel_delayed_work_sync(&p_tas256x->init_work); + cancel_delayed_work_sync(&p_tas256x->dc_work); + +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + tas256x_deregister_codec(p_tas256x); + mutex_destroy(&p_tas256x->codec_lock); +#endif + +#if IS_ENABLED(CONFIG_TAS256X_MISC) + tas256x_deregister_misc(p_tas256x); + mutex_destroy(&p_tas256x->file_lock); +#endif + + mutex_destroy(&p_tas256x->dev_lock); + + for (i = 0; i < p_tas256x->mn_channels; i++) { + if (gpio_is_valid(p_tas256x->devs[i]->mn_reset_gpio)) + gpio_free(p_tas256x->devs[i]->mn_reset_gpio); + if (gpio_is_valid(p_tas256x->devs[i]->mn_irq_gpio)) + gpio_free(p_tas256x->devs[i]->mn_irq_gpio); + if (p_tas256x->devs[i]) + kfree(p_tas256x->devs[i]); + } + + if (p_tas256x->devs) + kfree(p_tas256x->devs); + + return 0; +} + + +static const struct i2c_device_id tas256x_i2c_id[] = { + { "tas256x", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, tas256x_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id tas256x_of_match[] = { + { .compatible = "ti, tas256x" }, + { .compatible = "ti, tas2562" }, + { .compatible = "ti, tas2564" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tas256x_of_match); +#endif + +static const struct dev_pm_ops tas256x_pm_ops = { + .suspend = tas256x_pm_suspend, + .resume = tas256x_pm_resume +}; + +static struct i2c_driver tas256x_i2c_driver = { + .driver = { + .name = "tas256x", + .owner = THIS_MODULE, +#if defined(CONFIG_OF) + .of_match_table = of_match_ptr(tas256x_of_match), +#endif + .pm = &tas256x_pm_ops, + }, + .probe = tas256x_i2c_probe, + .remove = tas256x_i2c_remove, + .id_table = tas256x_i2c_id, +}; + +module_i2c_driver(tas256x_i2c_driver); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS256X I2C Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); +#endif diff --git a/asoc/codecs/tas256x/physical_layer/inc/tas2562.h b/asoc/codecs/tas256x/physical_layer/inc/tas2562.h new file mode 100644 index 00000000..c163986d --- /dev/null +++ b/asoc/codecs/tas256x/physical_layer/inc/tas2562.h @@ -0,0 +1,743 @@ +#ifndef __TAS2562_ +#define __TAS2562_ +/* Software Reset */ +#define TAS2562_SOFTWARERESET (TAS256X_SOFTWARERESET) +#define TAS2562_SOFTWARERESET_SOFTWARERESET_MASK \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_MASK) +#define TAS2562_SOFTWARERESET_SOFTWARERESET_DONTRESET \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_DONTRESET) +#define TAS2562_SOFTWARERESET_SOFTWARERESET_RESET \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_RESET) + +/* Power Control */ +#define TAS2562_POWERCONTROL (TAS256X_POWERCONTROL) +#define TAS2562_POWERCONTROL_ISNSPOWER_MASK \ + (TAS256X_POWERCONTROL_ISNSPOWER_MASK) +#define TAS2562_POWERCONTROL_ISNSPOWER_ACTIVE \ + (TAS256X_POWERCONTROL_ISNSPOWER_ACTIVE) +#define TAS2562_POWERCONTROL_ISNSPOWER_POWEREDDOWN \ + (TAS256X_POWERCONTROL_ISNSPOWER_POWEREDDOWN) +#define TAS2562_POWERCONTROL_VSNSPOWER_MASK \ + (TAS256X_POWERCONTROL_VSNSPOWER_MASK) +#define TAS2562_POWERCONTROL_VSNSPOWER_ACTIVE \ + (TAS256X_POWERCONTROL_VSNSPOWER_ACTIVE) +#define TAS2562_POWERCONTROL_VSNSPOWER_POWEREDDOWN \ + (TAS256X_POWERCONTROL_VSNSPOWER_POWEREDDOWN) +#define TAS2562_POWERCONTROL_OPERATIONALMODE10_MASK \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK) +#define TAS2562_POWERCONTROL_OPERATIONALMODE10_ACTIVE \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_ACTIVE) +#define TAS2562_POWERCONTROL_OPERATIONALMODE10_MUTE \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_MUTE) +#define TAS2562_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN) + + +/* Playback Configuration Reg0 */ +#define TAS2562_PLAYBACKCONFIGURATIONREG0 \ + (TAS256X_PLAYBACKCONFIGURATIONREG0) +#define TAS2562_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK) +#define TAS2562_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_ENABLED \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_ENABLED) +#define TAS2562_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED) +#define TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_MASK (0x1f << 1) +#define TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_SHIFT (1) + +/* Misc Configuration Reg0 */ +#define TAS2562_MISCCONFIGURATIONREG0 (TAS256X_MISCCONFIGURATIONREG0) +#define TAS2562_MISCCONFIGURATIONREG0_CPPGRETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_CPPGRETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_DONOTRETRY) +#define TAS2562_MISCCONFIGURATIONREG0_CPPGRETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_RETRY) +#define TAS2562_MISCCONFIGURATIONREG0_VBATPRORETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_VBATPRORETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_DONOTRETRY) +#define TAS2562_MISCCONFIGURATIONREG0_VBATPRORETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_RETRY) +#define TAS2562_MISCCONFIGURATIONREG0_OCERETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_OCERETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_DONOTRETRY) +#define TAS2562_MISCCONFIGURATIONREG0_OCERETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_RETRY) +#define TAS2562_MISCCONFIGURATIONREG0_OTERETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_OTERETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_DONOTRETRY) +#define TAS2562_MISCCONFIGURATIONREG0_OTERETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_RETRY) +#define TAS2562_MISCCONFIGURATIONREG0_IRQZPULL_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_IRQZPULL_DISABLED \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_DISABLED) +#define TAS2562_MISCCONFIGURATIONREG0_IRQZPULL_ENABLED \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_ENABLED) +#define TAS2562_MISCCONFIGURATIONREG0_AMPSS_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_MASK) +#define TAS2562_MISCCONFIGURATIONREG0_AMPSS_DISABLED \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_DISABLED) +#define TAS2562_MISCCONFIGURATIONREG0_AMPSS_ENABLED \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_ENABLED) + +/* TDM Configuration Reg0 */ +#define TAS2562_TDMCONFIGURATIONREG0 (TAS256X_TDMCONFIGURATIONREG0) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK) +#define TAS2562_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED) +#define TAS2562_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATE31_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATE31_14_7_16KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_14_7_16KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ) +#define TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_MASK) +#define TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH) +#define TAS2562_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW) + +/* TDM Configuration Reg1 */ +#define TAS2562_TDMCONFIGURATIONREG1 (TAS256X_TDMCONFIGURATIONREG1) +#define TAS2562_TDMCONFIGURATIONREG1_RXJUSTIFY_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_MASK) +#define TAS2562_TDMCONFIGURATIONREG1_RXJUSTIFY_LEFT \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_LEFT) +#define TAS2562_TDMCONFIGURATIONREG1_RXJUSTIFY_RIGHT \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_RIGHT) +#define TAS2562_TDMCONFIGURATIONREG1_RXOFFSET51_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_MASK) +#define TAS2562_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT \ + (TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT) +#define TAS2562_TDMCONFIGURATIONREG1_RXEDGE_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_MASK) +#define TAS2562_TDMCONFIGURATIONREG1_RXEDGE_RISING \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_RISING) +#define TAS2562_TDMCONFIGURATIONREG1_RXEDGE_FALLING \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_FALLING) + +/* TDM Configuration Reg2 */ +#define TAS2562_TDMCONFIGURATIONREG2 (TAS256X_TDMCONFIGURATIONREG2) +#define TAS2562_TDMCONFIGURATIONREG2_IVLEN76_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_IVLEN76_MASK) +#define TAS2562_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS) +#define TAS2562_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS) +#define TAS2562_TDMCONFIGURATIONREG2_IVLENCFG76_8BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_8BITS) +#define TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_MASK) +#define TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS) +#define TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS) +#define TAS2562_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXSCFG54_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MASK) +#define TAS2562_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C) +#define TAS2562_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT) +#define TAS2562_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT) +#define TAS2562_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX) +#define TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK) +#define TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_16BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_20BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_20BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_24BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_24BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXWLEN32_32BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_32BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXSLEN10_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_MASK) +#define TAS2562_TDMCONFIGURATIONREG2_RXSLEN10_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_16BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXSLEN10_24BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_24BITS) +#define TAS2562_TDMCONFIGURATIONREG2_RXSLEN10_32BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_32BITS) + +/* TDM Configuration Reg3 */ +#define TAS2562_TDMCONFIGURATIONREG3 (TAS256X_TDMCONFIGURATIONREG3) +#define TAS2562_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK \ + (TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK) +#define TAS2562_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask \ + (TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask) + +/* TDM Configuration Reg4 */ +#define TAS2562_TDMConfigurationReg4 (TAS256X_TDMConfigurationReg4) +#define TAS2562_TDMCONFIGURATIONREG4_TXKEEPER_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_MASK) +#define TAS2562_TDMCONFIGURATIONREG4_TXKEEPER_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_DISABLE) +#define TAS2562_TDMCONFIGURATIONREG4_TXKEEPER_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_ENABLE) +#define TAS2562_TDMCONFIGURATIONREG4_TXFILL_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_MASK) +#define TAS2562_TDMCONFIGURATIONREG4_TXFILL_TRANSMIT0 \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMIT0) +#define TAS2562_TDMCONFIGURATIONREG4_TXFILL_TRANSMITHIZ \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMITHIZ) +#define TAS2562_TDMCONFIGURATIONREG4_TXOFFSET31_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_MASK) +#define TAS2562_TDMCONFIGURATIONREG4_TXEDGE_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_MASK) +#define TAS2562_TDMCONFIGURATIONREG4_TXEDGE_RISING \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_RISING) +#define TAS2562_TDMCONFIGURATIONREG4_TXEDGE_FALLING \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_FALLING) + +/* TDM Configuration Reg5 */ +#define TAS2562_TDMCONFIGURATIONREG5 (TAS256X_TDMCONFIGURATIONREG5) +#define TAS2562_TDMCONFIGURATIONREG5_VSNSTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_MASK) +#define TAS2562_TDMCONFIGURATIONREG5_VSNSTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_DISABLE) +#define TAS2562_TDMCONFIGURATIONREG5_VSNSTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_ENABLE) +#define TAS2562_TDMCONFIGURATIONREG5_VSNSSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSSLOT50_MASK) + +/* TDM Configuration Reg6 */ +#define TAS2562_TDMCONFIGURATIONREG6 (TAS256X_TDMCONFIGURATIONREG6) +#define TAS2562_TDMCONFIGURATIONREG6_ISNSTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_MASK) +#define TAS2562_TDMCONFIGURATIONREG6_ISNSTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_DISABLE) +#define TAS2562_TDMCONFIGURATIONREG6_ISNSTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_ENABLE) +#define TAS2562_TDMCONFIGURATIONREG6_ISNSSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSSLOT50_MASK) + +/* TDM Configuration Reg7 */ +#define TAS2562_TDMCONFIGURATIONREG7 (TAS256X_TDMCONFIGURATIONREG7) +#define TAS2562_TDMCONFIGURATIONREG7_VBATSLEN_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_MASK) +#define TAS2562_TDMCONFIGURATIONREG7_VBATSLEN_8BITS \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_8BITS) +#define TAS2562_TDMCONFIGURATIONREG7_VBATSLEN_16BITS \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_16BITS) +#define TAS2562_TDMCONFIGURATIONREG7_VBATTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_MASK) +#define TAS2562_TDMCONFIGURATIONREG7_VBATTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_DISABLE) +#define TAS2562_TDMCONFIGURATIONREG7_VBATTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_ENABLE) +#define TAS2562_TDMCONFIGURATIONREG7_VBATSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLOT50_MASK) + +/* TDM Configuration Reg8 */ +#define TAS2562_TDMCONFIGURATIONREG8 TAS256X_REG(0x0, 0x0, 0x0E) +#define TAS2562_TDMCONFIGURATIONREG8_TEMPTX_MASK (0x1 << 6) +#define TAS2562_TDMCONFIGURATIONREG8_TEMPTX_DISABLE (0x0 << 6) +#define TAS2562_TDMCONFIGURATIONREG8_TEMPTX_ENABLE (0x1 << 6) +#define TAS2562_TDMCONFIGURATIONREG8_TEMPSLOT50_MASK (0x3f << 0) + +/* TDM Configuration Reg9 */ +#define TAS2562_TDMCONFIGURATIONREG9 TAS256X_REG(0x0, 0x0, 0x0F) +#define TAS2562_TDMCONFIGURATIONREG9_GAINTX_MASK (0x1 << 6) +#define TAS2562_TDMCONFIGURATIONREG9_GAINTX_DISABLE (0x0 << 6) +#define TAS2562_TDMCONFIGURATIONREG9_GAINTX_ENABLE (0x1 << 6) +#define TAS2562_TDMCONFIGURATIONREG9_GAINSLOT50_MASK (0x3f << 0) + +/* Limiter Configuration Reg0 */ +#define TAS2562_LIMITERCONFIGURATIONREG0 TAS256X_REG(0x0, 0x0, 0x12) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKST54_MASK (0x3 << 4) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKST54_1 (0x2 << 4) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKST54_2 (0x3 << 4) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKST54_0_25 (0x0 << 4) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKST54_0_5 (0x1 << 4) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_MASK (0x7 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_5 (0x0 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_10 (0x1 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_20 (0x2 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_40 (0x3 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_80 (0x4 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_160 (0x5 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_320 (0x6 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMATKRT31_640 (0x7 << 1) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMEN_MASK (0x1 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMEN_DISABLED (0x0 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG0_LIMEN_ENABLED (0x1 << 0) + +/* Limiter Configuration Reg1 */ +#define TAS2562_LIMITERCONFIGURATIONREG1 TAS256X_REG(0x0, 0x0, 0x13) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSST76_MASK (0x3 << 6) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSST76_1 (0x2 << 6) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSST76_2 (0x3 << 6) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSST76_0_25 (0x0 << 6) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSST76_0_5 (0x1 << 6) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_MASK (0x7 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_10 (0x0 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_50 (0x1 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_100 (0x2 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_250 (0x3 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_500 (0x4 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_750 (0x5 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_1000 (0x6 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMRLSRT53_1500 (0x7 << 3) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_MASK (0x7 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_0 (0x0 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_10 (0x1 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_25 (0x2 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_50 (0x3 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_100 (0x4 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_250 (0x5 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_500 (0x6 << 0) +#define TAS2562_LIMITERCONFIGURATIONREG1_LIMHLDTM20_1000 (0x7 << 0) + +/* Brown Out Prevention Reg0 */ +#define TAS2562_BROWNOUTPREVENTIONREG0 TAS256X_REG(0x0, 0x0, 0x14) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPSDEN_MASK (0x1 << 4) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPSDEN_DISABLED (0x0 << 4) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPSDEN_ENABLED (0x1 << 4) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPHLDCLR_MASK (0x1 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPHLDCLR_DONTCLEAR (0x0 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPHLDCLR_CLEAR (0x1 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPINFHLD_MASK (0x1 << 2) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPINFHLD_USEHOLDTIME (0x0 << 2) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPINFHLD_HOLDUNTILCLEARED (0x1 << 2) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPMUTE_MASK (0x1 << 1) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPMUTE_DONOTMUTE (0x0 << 1) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPMUTE_MUTE (0x1 << 1) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPEN_MASK (0x1 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPEN_DISABLED (0x0 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG0_BOPEN_ENABLED (0x1 << 0) + +/* Brown Out Prevention Reg1 */ +#define TAS2562_BROWNOUTPREVENTIONREG1 TAS256X_REG(0x0, 0x0, 0x15) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_MASK (0x7 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_1 (0x0 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_2 (0x1 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_4 (0x2 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_8 (0x3 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_16 (0x4 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_32 (0x5 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_64 (0x6 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKRT75_128 (0x7 << 5) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKST43_MASK (0x3 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKST43_1 (0x1 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKST43_2 (0x3 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKST43_0_5 (0x0 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPATKST43_1_5 (0x2 << 3) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_MASK (0x7 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_0 (0x0 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_10 (0x1 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_25 (0x2 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_50 (0x3 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_100 (0x4 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_250 (0x5 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_500 (0x6 << 0) +#define TAS2562_BROWNOUTPREVENTIONREG1_BOPHLDTM20_1000 (0x7 << 0) + +/* Interrupt Mask Reg0 */ +#define TAS2562_INTERRUPTMASKREG0 (TAS256X_INTERRUPTMASKREG0) +#define TAS2562_INTERRUPTMASKREG0_LIMMUTEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_LIMMUTEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_LIMMUTEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_LIMINFHLDINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_LIMINFHLDINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_LIMINFHLDINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_LIMMAXATNINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_LIMMAXATNINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_LIMMAXATNINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_OCEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_OCEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_OCEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_OTEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG0_OTEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG0_OTEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG0_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_DISABLE) + +/* Interrupt Mask Reg1 */ +#define TAS2562_INTERRUPTMASKREG1 \ + (TAS256X_INTERRUPTMASKREG1) +#define TAS2562_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG1_CRCINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG1_CRCINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG1_CRCINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG1_VBATOVLOINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG1_VBATOVLOINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG1_VBATOVLOINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG1_VBATUVLOINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG1_VBATUVLOINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG1_VBATUVLOINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_MASK) +#define TAS2562_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_UNMASK) +#define TAS2562_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_DISABLE) +#define TAS2562_INTERRUPTMASKREG1_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_DISABLE) + +/* Interrupt Mask Reg2 */ +#define TAS2562_INTERRUPTMASKREG2 TAS256X_REG(0x0, 0x0, 0x1C) +#define TAS2562_INTERRUPTMASKREG2_DACLKINTMASK_MASK (0x1 << 7) +#define TAS2562_INTERRUPTMASKREG2_DACLKINTMASK_UNMASK (0x0 << 7) +#define TAS2562_INTERRUPTMASKREG2_DACLKINTMASK_DISABLE (0x1 << 7) +#define TAS2562_INTERRUPTMASKREG2_BSTCLKINTMASK_MASK (0x1 << 6) +#define TAS2562_INTERRUPTMASKREG2_BSTCLKINTMASK_UNMASK (0x0 << 6) +#define TAS2562_INTERRUPTMASKREG2_BSTCLKINTMASK_DISABLE (0x1 << 6) +#define TAS2562_INTERRUPTMASKREG2_VBATPORCLKINTMASK_MASK (0x1 << 5) +#define TAS2562_INTERRUPTMASKREG2_VBATPORCLKINTMASK_UNMASK (0x0 << 5) +#define TAS2562_INTERRUPTMASKREG2_VBATPORCLKINTMASK_DISABLE (0x1 << 5) +#define TAS2562_INTERRUPTMASKREG2_PLLOCKINTMASK_MASK (0x1 << 4) +#define TAS2562_INTERRUPTMASKREG2_PLLOCKINTMASK_UNMASK (0x0 << 4) +#define TAS2562_INTERRUPTMASKREG2_PLLOCKINTMASK_DISABLE (0x1 << 4) +#define TAS2562_INTERRUPTMASKREG2_DCDETECTINTMASK_MASK (0x1 << 3) +#define TAS2562_INTERRUPTMASKREG2_DCDETECTINTMASK_UNMASK (0x0 << 3) +#define TAS2562_INTERRUPTMASKREG2_DCDETECTINTMASK_DISABLE (0x1 << 3) + +/* Live-Interrupt Reg0 */ +#define TAS2562_LIVEINTERRUPTREG0 TAS256X_REG(0x0, 0x0, 0x1F) +#define TAS2562_LIVEINTERRUPTREG0_LIMMUTE_MASK (0x1 << 7) +#define TAS2562_LIVEINTERRUPTREG0_LIMMUTE_NOINTERRUPT (0x0 << 7) +#define TAS2562_LIVEINTERRUPTREG0_LIMMUTE_INTERRUPT (0x1 << 7) +#define TAS2562_LIVEINTERRUPTREG0_LIMINFHLD_MASK (0x1 << 6) +#define TAS2562_LIVEINTERRUPTREG0_LIMINFHLD_NOINTERRUPT (0x0 << 6) +#define TAS2562_LIVEINTERRUPTREG0_LIMINFHLD_INTERRUPT (0x1 << 6) +#define TAS2562_LIVEINTERRUPTREG0_LIMMAXATN_MASK (0x1 << 5) +#define TAS2562_LIVEINTERRUPTREG0_LIMMAXATN_NOINTERRUPT (0x0 << 5) +#define TAS2562_LIVEINTERRUPTREG0_LIMMAXATN_INTERRUPT (0x1 << 5) +#define TAS2562_LIVEINTERRUPTREG0_VBATLESSTHANINF_MASK (0x1 << 4) +#define TAS2562_LIVEINTERRUPTREG0_VBATLESSTHANINF_NOINTERRUPT (0x0 << 4) +#define TAS2562_LIVEINTERRUPTREG0_VBATLESSTHANINF_INTERRUPT (0x1 << 4) +#define TAS2562_LIVEINTERRUPTREG0_LIMACTIVEFLAG_MASK (0x1 << 3) +#define TAS2562_LIVEINTERRUPTREG0_LIMACTIVEFLAG_NOINTERRUPT (0x0 << 3) +#define TAS2562_LIVEINTERRUPTREG0_LIMACTIVEFLAG_INTERRUPT (0x1 << 3) +#define TAS2562_LIVEINTERRUPTREG0_TDMCLOCKERROR_MASK (0x1 << 2) +#define TAS2562_LIVEINTERRUPTREG0_TDMCLOCKERROR_NOINTERRUPT (0x0 << 2) +#define TAS2562_LIVEINTERRUPTREG0_TDMCLOCKERROR_INTERRUPT (0x1 << 2) +#define TAS2562_LIVEINTERRUPTREG0_OCEFLAG_MASK (0x1 << 1) +#define TAS2562_LIVEINTERRUPTREG0_OCEFLAG_NOINTERRUPT (0x0 << 1) +#define TAS2562_LIVEINTERRUPTREG0_OCEFLAG_INTERRUPT (0x1 << 1) +#define TAS2562_LIVEINTERRUPTREG0_OTEFLAG_MASK (0x1 << 0) +#define TAS2562_LIVEINTERRUPTREG0_OTEFLAG_NOINTERRUPT (0x0 << 0) +#define TAS2562_LIVEINTERRUPTREG0_OTEFLAG_INTERRUPT (0x1 << 0) + +/* Live-Interrupt Reg1 */ +#define TAS2562_LIVEINTERRUPTREG1 TAS256X_REG(0x0, 0x0, 0x20) +#define TAS2562_LIVEINTERRUPTREG1_DSPINTOUTPUT_MASK (0x1 << 7) +#define TAS2562_LIVEINTERRUPTREG1_DSPINTOUTPUT_NOINTERRUPT (0x0 << 7) +#define TAS2562_LIVEINTERRUPTREG1_DSPINTOUTPUT_INTERRUPT (0x1 << 7) +#define TAS2562_LIVEINTERRUPTREG1_OTPCRC_MASK (0x1 << 6) +#define TAS2562_LIVEINTERRUPTREG1_OTPCRC_NOINTERRUPT (0x0 << 6) +#define TAS2562_LIVEINTERRUPTREG1_OTPCRC_INTERRUPT (0x1 << 6) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTFLAG_MASK (0x1 << 1) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTFLAG_NOINTERRUPT (0x0 << 1) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTFLAG_INTERRUPT (0x1 << 1) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTDETECTED_MASK (0x1 << 1) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTDETECTED_NOINTERRUPT (0x0 << 1) +#define TAS2562_LIVEINTERRUPTREG1_BROWNOUTDETECTED_INTERRUPT (0x1 << 1) + +/* Latched-Interrupt Reg0 */ +#define TAS2562_LATCHEDINTERRUPTREG0 (TAS256X_LATCHEDINTERRUPTREG0) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT) + +/* Latched-Interrupt Reg1 */ +#define TAS2562_LATCHEDINTERRUPTREG1 (TAS256X_LATCHEDINTERRUPTREG1) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_MASK) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_NOINTERRUPT) +#define TAS2562_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_INTERRUPT) + +/* VBAT MSB */ +#define TAS2562_VBATMSB TAS256X_REG(0x0, 0x0, 0x2A) +#define TAS2562_VBATMSB_VBATMSB70_MASK (0xff << 0) + +/* VBAT LSB */ +#define TAS2562_VBATLSB TAS256X_REG(0x0, 0x0, 0x2B) +#define TAS2562_VBATLSB_VBATLSB74_MASK (0xf << 4) + +/* TEMP */ +#define TAS2562_TEMP TAS256X_REG(0x0, 0x0, 0x2C) +#define TAS2562_TEMP_TEMPMSB70_MASK (0xff << 0) + + +/* Interrupt Configuration */ +#define TAS2562_INTERRUPTCONFIGURATION (TAS256X_INTERRUPTCONFIGURATION) +#define TAS2562_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK \ + (TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK) +#define TAS2562_INTERRUPTCONFIGURATION_LTCHINTCLEAR \ + (TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR) +#define TAS2562_INTERRUPTCONFIGURATION_PININTCONFIG10_MASK \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_MASK) +#define TAS2562_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLIVEINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLIVEINTERRUPTS) +#define \ + TAS2562_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLATCHEDINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLATCHEDINTERRUPTS) +#define \ + TAS2562_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLIVEINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLIVEINTERRUPTS) +#define \ + TAS2562_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLATCHEDINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLATCHEDINTERRUPTS) + +/* Digital Input Pin Pull Down */ +#define TAS2562_DIGITALINPUTPINPULLDOWN TAS256X_REG(0x0, 0x0, 0x31) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDOUT_MASK (0x1 << 7) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDOUT_DISABLED (0x0 << 7) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDOUT_ENABLED (0x1 << 7) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDIN_MASK (0x1 << 6) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDIN_DISABLED (0x0 << 6) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSDIN_ENABLED (0x1 << 6) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNFSYNC_MASK (0x1 << 5) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNFSYNC_DISABLED (0x0 << 5) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNFSYNC_ENABLED (0x1 << 5) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSBCLK_MASK (0x1 << 4) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSBCLK_DISABLED (0x0 << 4) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNSBCLK_ENABLED (0x1 << 4) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD0_MASK (0x1 << 3) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD0_DISABLED (0x0 << 3) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD0_ENABLED (0x1 << 3) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD1_MASK (0x1 << 2) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD1_DISABLED (0x0 << 2) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMD1_ENABLED (0x1 << 2) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK0_MASK (0x1 << 1) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK0_DISABLED (0x0 << 1) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK0_ENABLED (0x1 << 1) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK1_MASK (0x1 << 0) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK1_DISABLED (0x0 << 0) +#define TAS2562_DIGITALINPUTPINPULLDOWN_WKPULLDOWNPDMCK1_ENABLED (0x1 << 0) + +/* Misc IRQ */ +#define TAS2562_MISCIRQ TAS256X_REG(0x0, 0x0, 0x32) +#define TAS2562_MISCIRQ_IRQZREQD_MASK (0x1 << 7) +#define TAS2562_MISCIRQ_IRQZREQD_ACTIVEHIGH (0x0 << 7) +#define TAS2562_MISCIRQ_IRQZREQD_ACTIVELOW (0x1 << 7) +#define TAS2562_MISCIRQ_IRQZBITBANG_MASK (0x1 << 0) +#define TAS2562_MISCIRQ_IRQZBITBANG_IRQZINPUTBUF0 (0x0 << 0) +#define TAS2562_MISCIRQ_IRQZBITBANG_IRQZINPUTBUF1 (0x1 << 0) + +#define TAS2562_BOOSTCONFIGURATION2 TAS256X_REG(0x0, 0x0, 0x34) +#define TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK (0x0f << 0) +#define TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_SHIFT 0 +#define TAS2562_BOOSTCONFIGURATION4 (TAS256X_BOOSTCONFIGURATION4) +#define TAS2562_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK \ + (TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK) +#define TAS2562_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT \ + (TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT) + +#define TAS2562_BOOSTSLOPE (TAS256X_BOOSTSLOPE) +#define TAS2562_BOOSTSLOPE_MASK (TAS256X_BOOSTSLOPE_MASK) +#define TAS2562_BOOSTSLOPE_3AV (0x1 << 2) +#define TAS2562_BOOSTSLOPE_2AV (0x2 << 2) + +/* Clock Configuration */ +#define TAS2562_CLOCKCONFIGURATION (TAS256X_CLOCKCONFIGURATION) +#define TAS2562_CLOCKCONFIGURATION_SBCLKTOFS52_MASK \ + (TAS256X_CLOCKCONFIGURATION_SBCLKTOFS52_MASK) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_16 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_16) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_24 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_24) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_32 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_32) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_48 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_48) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_64 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_64) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_96 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_96) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_128 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_128) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_192 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_192) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_256 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_256) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_384 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_384) +#define TAS2562_CLOCKCONFIGURATION_SBCLKtoFS52_512 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_512) +#define TAS2562_CLOCKCONFIGURATION_DISCLKRATEDETECT10_MASK \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_MASK) +#define TAS2562_CLOCKCONFIGURATION_DISCLKRATEDETECT10_DISABLED \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_DISABLED) +#define TAS2562_CLOCKCONFIGURATION_DISCLKRATEDETECT10_ENABLED \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_ENABLED) + +#define TAS2562_VBATFILTER (TAS256X_VBATFILTER) +#define TAS2562_CLASSHRELEASETIMER (TAS256X_CLASSHRELEASETIMER) + +#define TAS2562_BOOST_CFG4 (TAS256X_BOOST_CFG4) +#define TAS2562_BOOST_CFG4_PEAK_CURRENT_LIMIT_MASK (0xff << 0) + +#define TAS2562_ICN_THRESHOLD_REG (TAS256X_ICN_THRESHOLD_REG) +#define TAS2562_ICN_HYSTERESIS_REG (TAS256X_ICN_HYSTERESIS_REG) + +#define TAS2562_ICN_SW_REG (TAS256X_ICN_SW_REG) +#define TAS2562_ICN_SW_MASK (TAS256X_ICN_SW_MASK) +#define TAS2562_ICN_SW_ENABLE (TAS256X_ICN_SW_ENABLE) +#define TAS2562_ICN_SW_DISABLE (TAS256X_ICN_SW_DISABLE) +#define TAS2562_TESTPAGECONFIGURATION (TAS256X_TESTPAGECONFIGURATION) +#define TAS2562_CLASSDCONFIGURATION1 (TAS256X_CLASSDCONFIGURATION1) +#define TAS2562_CLASSDCONFIGURATION2 (TAS256X_CLASSDCONFIGURATION2) +#define TAS2562_CLASSDCONFIGURATION3 (TAS256X_CLASSDCONFIGURATION3) +#define TAS2562_CLASSDCONFIGURATION4 (TAS256X_CLASSDCONFIGURATION4) +#define TAS2562_EFFICIENCYCONFIGURATION (TAS256X_EFFICIENCYCONFIGURATION) + +#define TAS2562_HPF (TAS256X_HPF) +#define TAS2562_CLASSHHEADROOM (TAS256X_CLASSHHEADROOM) +#define TAS2562_CLASSHHYSTERESIS (TAS256X_CLASSHHYSTERESIS) +#define TAS2562_CLASSHMTCT (TAS256X_CLASSHMTCT) + +/* Revision and PG ID */ +#define TAS2562_REVISIONANDPGID TAS256X_REG(0x0, 0x0, 0x7D) +#define TAS2562_REVISIONANDPGID_REVISIONID74_MASK (0xf << 4) +#define TAS2562_REVISIONANDPGID_PGID30_MASK (0xf << 0) + +/* I2C Checksum */ +#define TAS2562_I2CCHECKSUM TAS256X_REG(0x0, 0x0, 0x7E) +#define TAS2562_I2CCHECKSUM_I2CCHECKSUM70_MASK (0xff << 0) + +/* Book */ +#define TAS2562_BOOK (TAS256X_BOOK) +#define TAS2562_BOOK_BOOK70_MASK (TAS256X_BOOK_BOOK70_MASK) +#endif /* __TAS2562_ */ diff --git a/asoc/codecs/tas256x/physical_layer/inc/tas2564.h b/asoc/codecs/tas256x/physical_layer/inc/tas2564.h new file mode 100644 index 00000000..63f1338f --- /dev/null +++ b/asoc/codecs/tas256x/physical_layer/inc/tas2564.h @@ -0,0 +1,735 @@ +#ifndef __TAS2564_ +#define __TAS2564_ +/* Software Reset */ +#define TAS2564_SOFTWARERESET (TAS256X_SOFTWARERESET) +#define TAS2564_SOFTWARERESET_SOFTWARERESET_MASK \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_MASK) +#define TAS2564_SOFTWARERESET_SOFTWARERESET_DONTRESET \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_DONTRESET) +#define TAS2564_SOFTWARERESET_SOFTWARERESET_RESET \ + (TAS256X_SOFTWARERESET_SOFTWARERESET_RESET) + +/* Power Control */ +#define TAS2564_POWERCONTROL (TAS256X_POWERCONTROL) +/* NEW Beging */ +#define TAS2564_POWERCONTROL_VSNS2_PD_MASK (0x1 << 7) +#define TAS2564_POWERCONTROL_VSNS2_PD_ACTIVE (0x0 << 7) +#define TAS2564_POWERCONTROL_VSNS2_PD_POWEREDDOWN (0x1 << 7) +/* NEW End */ +#define TAS2564_POWERCONTROL_ISNSPOWER_MASK \ + (TAS256X_POWERCONTROL_ISNSPOWER_MASK) +#define TAS2564_POWERCONTROL_ISNSPOWER_ACTIVE \ + (TAS256X_POWERCONTROL_ISNSPOWER_ACTIVE) +#define TAS2564_POWERCONTROL_ISNSPOWER_POWEREDDOWN \ + (TAS256X_POWERCONTROL_ISNSPOWER_POWEREDDOWN) +#define TAS2564_POWERCONTROL_VSNSPOWER_MASK \ + (TAS256X_POWERCONTROL_VSNSPOWER_MASK) +#define TAS2564_POWERCONTROL_VSNSPOWER_ACTIVE \ + (TAS256X_POWERCONTROL_VSNSPOWER_ACTIVE) +#define TAS2564_POWERCONTROL_VSNSPOWER_POWEREDDOWN \ + (TAS256X_POWERCONTROL_VSNSPOWER_POWEREDDOWN) +#define TAS2564_POWERCONTROL_OPERATIONALMODE10_MASK \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK) +#define TAS2564_POWERCONTROL_OPERATIONALMODE10_ACTIVE \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_ACTIVE) +#define TAS2564_POWERCONTROL_OPERATIONALMODE10_MUTE \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_MUTE) +#define TAS2564_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN \ + (TAS256X_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN) + + +/* Playback Configuration Reg0 */ +#define TAS2564_PLAYBACKCONFIGURATIONREG0 \ + (TAS256X_PLAYBACKCONFIGURATIONREG0) +#define TAS2564_PLAYBACKCONFIGURATION_AMP_LEVEL_MASK (0x1F << 1) +#define TAS2564_AMP_LEVEL_16dBV (0x0D << 1) + +/* NEW Begin */ +#define TAS2564_PLAYBACKCONFIGURATIONREG_RX_SPKR_MODE_MASK \ + (0x1 << 7) +#define TAS2564_PLAYBACKCONFIGURATIONREG_SPKR_MODE \ + (0x0 << 7) +#define TAS2564_PLAYBACKCONFIGURATIONREG_RX_MODE \ + (0x1 << 7) +/* NEW End */ +#define TAS2564_BOOSTCONFIGURATION2 TAS256X_REG(0x0, 0x0, 0x48) +#define TAS2564_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK (0x1f << 3) +#define TAS2564_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK_SHIFT 3 +#define TAS2564_BOOSTCONFIGURATION4 (TAS256X_BOOSTCONFIGURATION4) +#define TAS2564_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK \ + (TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK) +#define TAS2564_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT \ + (TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT) + +#define TAS2564_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK) +#define TAS2564_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_ENABLED \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_ENABLED) +#define TAS2564_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED \ + (TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED) +#define TAS2564_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_MASK (0x1f << 1) +#define TAS2564_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_SHIFT (1) + +/* Misc Configuration Reg0 */ +#define TAS2564_MISCCONFIGURATIONREG0 (TAS256X_MISCCONFIGURATIONREG0) +#define TAS2564_MISCCONFIGURATIONREG0_CPPGRETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_CPPGRETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_DONOTRETRY) +#define TAS2564_MISCCONFIGURATIONREG0_CPPGRETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_RETRY) +#define TAS2564_MISCCONFIGURATIONREG0_VBATPRORETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_VBATPRORETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_DONOTRETRY) +#define TAS2564_MISCCONFIGURATIONREG0_VBATPRORETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_RETRY) +#define TAS2564_MISCCONFIGURATIONREG0_OCERETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_OCERETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_DONOTRETRY) +#define TAS2564_MISCCONFIGURATIONREG0_OCERETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OCERETRY_RETRY) +#define TAS2564_MISCCONFIGURATIONREG0_OTERETRY_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_OTERETRY_DONOTRETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_DONOTRETRY) +#define TAS2564_MISCCONFIGURATIONREG0_OTERETRY_RETRY \ + (TAS256X_MISCCONFIGURATIONREG0_OTERETRY_RETRY) +#define TAS2564_MISCCONFIGURATIONREG0_IRQZPULL_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_IRQZPULL_DISABLED \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_DISABLED) +#define TAS2564_MISCCONFIGURATIONREG0_IRQZPULL_ENABLED \ + (TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_ENABLED) +#define TAS2564_MISCCONFIGURATIONREG0_AMPSS_MASK \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_MASK) +#define TAS2564_MISCCONFIGURATIONREG0_AMPSS_DISABLED \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_DISABLED) +#define TAS2564_MISCCONFIGURATIONREG0_AMPSS_ENABLED \ + (TAS256X_MISCCONFIGURATIONREG0_AMPSS_ENABLED) + +/* TDM Configuration Reg0 */ +#define TAS2564_TDMCONFIGURATIONREG0 (TAS256X_TDMCONFIGURATIONREG0) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK) +#define TAS2564_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED) +#define TAS2564_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED \ + (TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATE31_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATE31_14_7_16KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_14_7_16KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ \ + (TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ) +#define TAS2564_TDMCONFIGURATIONREG0_FRAMESTART_MASK \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_MASK) +#define TAS2564_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH) +#define TAS2564_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW \ + (TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW) + +/* TDM Configuration Reg1 */ +#define TAS2564_TDMCONFIGURATIONREG1 (TAS256X_TDMCONFIGURATIONREG1) +#define TAS2564_TDMCONFIGURATIONREG1_RXJUSTIFY_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_MASK) +#define TAS2564_TDMCONFIGURATIONREG1_RXJUSTIFY_LEFT \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_LEFT) +#define TAS2564_TDMCONFIGURATIONREG1_RXJUSTIFY_RIGHT \ + (TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_RIGHT) +#define TAS2564_TDMCONFIGURATIONREG1_RXOFFSET51_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_MASK) +#define TAS2564_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT \ + (TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT) +#define TAS2564_TDMCONFIGURATIONREG1_RXEDGE_MASK \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_MASK) +#define TAS2564_TDMCONFIGURATIONREG1_RXEDGE_RISING \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_RISING) +#define TAS2564_TDMCONFIGURATIONREG1_RXEDGE_FALLING \ + (TAS256X_TDMCONFIGURATIONREG1_RXEDGE_FALLING) + +/* TDM Configuration Reg2 */ +#define TAS2564_TDMCONFIGURATIONREG2 (TAS256X_TDMCONFIGURATIONREG2) +#define TAS2564_TDMCONFIGURATIONREG2_IVLEN76_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_IVLEN76_MASK) +#define TAS2564_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS) +#define TAS2564_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS) +#define TAS2564_TDMCONFIGURATIONREG2_IVLENCFG76_8BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_8BITS) +#define TAS2564_TDMCONFIGURATIONREG2_IVMONLEN76_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_MASK) +#define TAS2564_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS) +#define TAS2564_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS) +#define TAS2564_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXSCFG54_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MASK) +#define TAS2564_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C) +#define TAS2564_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT) +#define TAS2564_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT) +#define TAS2564_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX \ + (TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX) +#define TAS2564_TDMCONFIGURATIONREG2_RXWLEN32_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK) +#define TAS2564_TDMCONFIGURATIONREG2_RXWLEN32_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_16BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXWLEN32_20BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_20BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXWLEN32_24BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_24BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXWLEN32_32BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_32BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXSLEN10_MASK \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_MASK) +#define TAS2564_TDMCONFIGURATIONREG2_RXSLEN10_16BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_16BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXSLEN10_24BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_24BITS) +#define TAS2564_TDMCONFIGURATIONREG2_RXSLEN10_32BITS \ + (TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_32BITS) + +/* TDM Configuration Reg3 */ +#define TAS2564_TDMCONFIGURATIONREG3 (TAS256X_TDMCONFIGURATIONREG3) +#define TAS2564_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK \ + (TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK) +#define TAS2564_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask \ + (TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask) + +/* TDM Configuration Reg4 */ +#define TAS2564_TDMConfigurationReg4 (TAS256X_TDMConfigurationReg4) +#define TAS2564_TDMCONFIGURATIONREG4_TXKEEPER_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_MASK) +#define TAS2564_TDMCONFIGURATIONREG4_TXKEEPER_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_DISABLE) +#define TAS2564_TDMCONFIGURATIONREG4_TXKEEPER_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_ENABLE) +#define TAS2564_TDMCONFIGURATIONREG4_TXFILL_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_MASK) +#define TAS2564_TDMCONFIGURATIONREG4_TXFILL_TRANSMIT0 \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMIT0) +#define TAS2564_TDMCONFIGURATIONREG4_TXFILL_TRANSMITHIZ \ + (TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMITHIZ) +#define TAS2564_TDMCONFIGURATIONREG4_TXOFFSET31_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_MASK) +#define TAS2564_TDMCONFIGURATIONREG4_TXEDGE_MASK \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_MASK) +#define TAS2564_TDMCONFIGURATIONREG4_TXEDGE_RISING \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_RISING) +#define TAS2564_TDMCONFIGURATIONREG4_TXEDGE_FALLING \ + (TAS256X_TDMCONFIGURATIONREG4_TXEDGE_FALLING) + +/* TDM Configuration Reg5 */ +#define TAS2564_TDMCONFIGURATIONREG5 (TAS256X_TDMCONFIGURATIONREG5) +#define TAS2564_TDMCONFIGURATIONREG5_VSNSTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_MASK) +#define TAS2564_TDMCONFIGURATIONREG5_VSNSTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_DISABLE) +#define TAS2564_TDMCONFIGURATIONREG5_VSNSTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSTX_ENABLE) +#define TAS2564_TDMCONFIGURATIONREG5_VSNSSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG5_VSNSSLOT50_MASK) + +/* TDM Configuration Reg6 */ +#define TAS2564_TDMCONFIGURATIONREG6 (TAS256X_TDMCONFIGURATIONREG6) +#define TAS2564_TDMCONFIGURATIONREG6_ISNSTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_MASK) +#define TAS2564_TDMCONFIGURATIONREG6_ISNSTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_DISABLE) +#define TAS2564_TDMCONFIGURATIONREG6_ISNSTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSTX_ENABLE) +#define TAS2564_TDMCONFIGURATIONREG6_ISNSSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG6_ISNSSLOT50_MASK) + +/* TDM Configuration Reg7 */ +#define TAS2564_TDMCONFIGURATIONREG7 (TAS256X_TDMCONFIGURATIONREG7) +#define TAS2564_TDMCONFIGURATIONREG7_VBATSLEN_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_MASK) +#define TAS2564_TDMCONFIGURATIONREG7_VBATSLEN_8BITS \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_8BITS) +#define TAS2564_TDMCONFIGURATIONREG7_VBATSLEN_16BITS \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_16BITS) +#define TAS2564_TDMCONFIGURATIONREG7_VBATTX_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_MASK) +#define TAS2564_TDMCONFIGURATIONREG7_VBATTX_DISABLE \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_DISABLE) +#define TAS2564_TDMCONFIGURATIONREG7_VBATTX_ENABLE \ + (TAS256X_TDMCONFIGURATIONREG7_VBATTX_ENABLE) +#define TAS2564_TDMCONFIGURATIONREG7_VBATSLOT50_MASK \ + (TAS256X_TDMCONFIGURATIONREG7_VBATSLOT50_MASK) + +/* TDM Configuration Reg8 */ +#define TAS2564_TDMCONFIGURATIONREG8 TAS256X_REG(0x0, 0x0, 0x0E) +#define TAS2564_TDMCONFIGURATIONREG8_TEMPTX_MASK (0x1 << 6) +#define TAS2564_TDMCONFIGURATIONREG8_TEMPTX_DISABLE (0x0 << 6) +#define TAS2564_TDMCONFIGURATIONREG8_TEMPTX_ENABLE (0x1 << 6) +#define TAS2564_TDMCONFIGURATIONREG8_TEMPSLOT50_MASK (0x3f << 0) + +/* TDM Configuration Reg9 */ +#define TAS2564_TDMCONFIGURATIONREG9 TAS256X_REG(0x0, 0x0, 0x0F) +#define TAS2564_TDMCONFIGURATIONREG9_GAINTX_MASK (0x1 << 6) +#define TAS2564_TDMCONFIGURATIONREG9_GAINTX_DISABLE (0x0 << 6) +#define TAS2564_TDMCONFIGURATIONREG9_GAINTX_ENABLE (0x1 << 6) +#define TAS2564_TDMCONFIGURATIONREG9_GAINSLOT50_MASK (0x3f << 0) + +/* Limiter Configuration Reg0 */ +#define TAS2564_LIMITERCONFIGURATIONREG0 TAS256X_REG(0x0, 0x0, 0x12) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKST54_MASK (0x3 << 4) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKST54_1 (0x2 << 4) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKST54_2 (0x3 << 4) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKST54_0_25 (0x0 << 4) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKST54_0_5 (0x1 << 4) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_MASK (0x7 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_5 (0x0 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_10 (0x1 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_20 (0x2 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_40 (0x3 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_80 (0x4 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_160 (0x5 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_320 (0x6 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMATKRT31_640 (0x7 << 1) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMEN_MASK (0x1 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMEN_DISABLED (0x0 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG0_LIMEN_ENABLED (0x1 << 0) + +/* Limiter Configuration Reg1 */ +#define TAS2564_LIMITERCONFIGURATIONREG1 TAS256X_REG(0x0, 0x0, 0x13) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSST76_MASK (0x3 << 6) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSST76_1 (0x2 << 6) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSST76_2 (0x3 << 6) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSST76_0_25 (0x0 << 6) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSST76_0_5 (0x1 << 6) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_MASK (0x7 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_10 (0x0 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_50 (0x1 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_100 (0x2 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_250 (0x3 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_500 (0x4 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_750 (0x5 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_1000 (0x6 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMRLSRT53_1500 (0x7 << 3) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_MASK (0x7 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_0 (0x0 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_10 (0x1 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_25 (0x2 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_50 (0x3 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_100 (0x4 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_250 (0x5 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_500 (0x6 << 0) +#define TAS2564_LIMITERCONFIGURATIONREG1_LIMHLDTM20_1000 (0x7 << 0) + +/* Brown Out Prevention Reg0 */ +#define TAS2564_BROWNOUTPREVENTIONREG0 TAS256X_REG(0x0, 0x0, 0x14) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPSDEN_MASK (0x1 << 4) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPSDEN_DISABLED (0x0 << 4) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPSDEN_ENABLED (0x1 << 4) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPHLDCLR_MASK (0x1 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPHLDCLR_DONTCLEAR (0x0 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPHLDCLR_CLEAR (0x1 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPINFHLD_MASK (0x1 << 2) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPINFHLD_USEHOLDTIME (0x0 << 2) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPINFHLD_HOLDUNTILCLEARED (0x1 << 2) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPMUTE_MASK (0x1 << 1) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPMUTE_DONOTMUTE (0x0 << 1) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPMUTE_MUTE (0x1 << 1) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPEN_MASK (0x1 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPEN_DISABLED (0x0 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG0_BOPEN_ENABLED (0x1 << 0) + +/* Brown Out Prevention Reg1 */ +#define TAS2564_BROWNOUTPREVENTIONREG1 TAS256X_REG(0x0, 0x0, 0x15) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_MASK (0x7 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_1 (0x0 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_2 (0x1 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_4 (0x2 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_8 (0x3 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_16 (0x4 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_32 (0x5 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_64 (0x6 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKRT75_128 (0x7 << 5) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKST43_MASK (0x3 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKST43_1 (0x1 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKST43_2 (0x3 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKST43_0_5 (0x0 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPATKST43_1_5 (0x2 << 3) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_MASK (0x7 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_0 (0x0 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_10 (0x1 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_25 (0x2 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_50 (0x3 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_100 (0x4 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_250 (0x5 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_500 (0x6 << 0) +#define TAS2564_BROWNOUTPREVENTIONREG1_BOPHLDTM20_1000 (0x7 << 0) + +/* Interrupt Mask Reg0 */ +#define TAS2564_INTERRUPTMASKREG0 (TAS256X_INTERRUPTMASKREG0) +#define TAS2564_INTERRUPTMASKREG0_LIMMUTEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_LIMMUTEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_LIMMUTEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_LIMINFHLDINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_LIMINFHLDINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_LIMINFHLDINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_LIMMAXATNINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_LIMMAXATNINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_LIMMAXATNINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_OCEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_OCEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_OCEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_OCEINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_OTEINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG0_OTEINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG0_OTEINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_OTEINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG0_DISABLE \ + (TAS256X_INTERRUPTMASKREG0_DISABLE) + +/* Interrupt Mask Reg1 */ +#define TAS2564_INTERRUPTMASKREG1 \ + (TAS256X_INTERRUPTMASKREG1) +#define TAS2564_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG1_CRCINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG1_CRCINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG1_CRCINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_CRCINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG1_VBATOVLOINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG1_VBATOVLOINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG1_VBATOVLOINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG1_VBATUVLOINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG1_VBATUVLOINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG1_VBATUVLOINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_MASK \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_MASK) +#define TAS2564_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_UNMASK \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_UNMASK) +#define TAS2564_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_DISABLE) +#define TAS2564_INTERRUPTMASKREG1_DISABLE \ + (TAS256X_INTERRUPTMASKREG1_DISABLE) + +/* Interrupt Mask Reg2 */ +#define TAS2564_INTERRUPTMASKREG2 TAS256X_REG(0x0, 0x0, 0x1C) +#define TAS2564_INTERRUPTMASKREG2_DACLKINTMASK_MASK (0x1 << 7) +#define TAS2564_INTERRUPTMASKREG2_DACLKINTMASK_UNMASK (0x0 << 7) +#define TAS2564_INTERRUPTMASKREG2_DACLKINTMASK_DISABLE (0x1 << 7) +#define TAS2564_INTERRUPTMASKREG2_BSTCLKINTMASK_MASK (0x1 << 6) +#define TAS2564_INTERRUPTMASKREG2_BSTCLKINTMASK_UNMASK (0x0 << 6) +#define TAS2564_INTERRUPTMASKREG2_BSTCLKINTMASK_DISABLE (0x1 << 6) +#define TAS2564_INTERRUPTMASKREG2_VBATPORCLKINTMASK_MASK (0x1 << 5) +#define TAS2564_INTERRUPTMASKREG2_VBATPORCLKINTMASK_UNMASK (0x0 << 5) +#define TAS2564_INTERRUPTMASKREG2_VBATPORCLKINTMASK_DISABLE (0x1 << 5) +#define TAS2564_INTERRUPTMASKREG2_PLLOCKINTMASK_MASK (0x1 << 4) +#define TAS2564_INTERRUPTMASKREG2_PLLOCKINTMASK_UNMASK (0x0 << 4) +#define TAS2564_INTERRUPTMASKREG2_PLLOCKINTMASK_DISABLE (0x1 << 4) +#define TAS2564_INTERRUPTMASKREG2_DCDETECTINTMASK_MASK (0x1 << 3) +#define TAS2564_INTERRUPTMASKREG2_DCDETECTINTMASK_UNMASK (0x0 << 3) +#define TAS2564_INTERRUPTMASKREG2_DCDETECTINTMASK_DISABLE (0x1 << 3) + +/* NEW Begin */ +/* Interrupt Mask Reg4 */ +#define TAS2564_INTERRUPTMASKREG4 TAS256X_REG(0x0, 0x0, 0x1E) +#define TAS2564_INTERRUPTMASKREG4_DSP_DC_DETECT_FLAG_MASK (0x1 << 7) +#define TAS2564_INTERRUPTMASKREG4_DSP_DC_DETECT_FLAG_UNMASK (0x0 << 7) +#define TAS2564_INTERRUPTMASKREG4_DSP_DC_DETECT_FLAG_DISABLE (0x1 << 7) +/* NEW End */ + +/* Latched-Interrupt Reg0 */ +#define TAS2564_LATCHEDINTERRUPTREG0 (TAS256X_LATCHEDINTERRUPTREG0) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT) + +/* Latched-Interrupt Reg1 */ +#define TAS2564_LATCHEDINTERRUPTREG1 (TAS256X_LATCHEDINTERRUPTREG1) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_MASK \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_MASK) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_NOINTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_NOINTERRUPT) +#define TAS2564_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_INTERRUPT \ + (TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_INTERRUPT) + +/* NEW Begin */ +/* Latched-Interrupt Reg4 */ +#define TAS2564_LATCHEDINTERRUPTREG4 TAS256X_REG(0x0, 0x0, 0x28) +#define TAS2564_LATCHEDINTERRUPTREG4_DSP_DC_DETECT_FLAG_MASK (0x1 << 7) +#define TAS2564_LATCHEDINTERRUPTREG4_DSP_DC_DETECT_FLAG_UNMASK (0x0 << 7) +#define TAS2564_LATCHEDINTERRUPTREG4_DSP_DC_DETECT_FLAG_DISABLE (0x1 << 7) +/* NEW End */ + +/* VBAT MSB */ +#define TAS2564_VBATMSB TAS256X_REG(0x0, 0x0, 0x2A) +#define TAS2564_VBATMSB_VBATMSB70_MASK (0xff << 0) + +/* VBAT LSB */ +#define TAS2564_VBATLSB TAS256X_REG(0x0, 0x0, 0x2B) +#define TAS2564_VBATLSB_VBATLSB74_MASK (0xf << 4) + +/* TEMP */ +#define TAS2564_TEMP TAS256X_REG(0x0, 0x0, 0x2C) +#define TAS2564_TEMP_TEMPMSB70_MASK (0xff << 0) + + +/* Interrupt Configuration */ +#define TAS2564_INTERRUPTCONFIGURATION (TAS256X_INTERRUPTCONFIGURATION) +#define TAS2564_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK \ + (TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK) +#define TAS2564_INTERRUPTCONFIGURATION_LTCHINTCLEAR \ + (TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR) +#define TAS2564_INTERRUPTCONFIGURATION_PININTCONFIG10_MASK \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_MASK) +#define TAS2564_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLIVEINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLIVEINTERRUPTS) +#define \ + TAS2564_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLATCHEDINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLATCHEDINTERRUPTS) +#define \ + TAS2564_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLIVEINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLIVEINTERRUPTS) +#define \ + TAS2564_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLATCHEDINTERRUPTS \ + (TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLATCHEDINTERRUPTS) + +/* Digital Input Pin Pull Down */ +/* NEW Begin */ +#define TAS2564_DIGITALINPUTPINPULLDOWN TAS256X_REG(0x0, 0x0, 0x31) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD1_MASK (0x1 << 5) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD1_DISABLED (0x0 << 5) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD1_ENABLED (0x1 << 5) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD0_MASK (0x1 << 4) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD0_DISABLED (0x0 << 4) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_AD0_ENABLED (0x1 << 4) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDOUT_MASK (0x1 << 3) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDOUT_DISABLED (0x0 << 3) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDOUT_ENABLED (0x1 << 3) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDIN_MASK (0x1 << 2) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDIN_DISABLED (0x0 << 2) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SDIN_ENABLED (0x1 << 2) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_FSYNC_MASK (0x1 << 1) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_FSYNC_DISABLED (0x0 << 1) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_FSYNC_ENABLED (0x1 << 1) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SBCLK_MASK (0x1 << 0) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SBCLK_DISABLED (0x0 << 0) +#define TAS2564_DIGITALINPUTPINPULLDOWN_WKPULLDOWN_SBCLK_ENABLED (0x1 << 0) +/* NEW End */ + +/* Misc IRQ */ +#define TAS2564_MISCIRQ TAS256X_REG(0x0, 0x0, 0x32) +#define TAS2564_MISCIRQ_IRQZREQD_MASK (0x1 << 7) +#define TAS2564_MISCIRQ_IRQZREQD_ACTIVEHIGH (0x0 << 7) +#define TAS2564_MISCIRQ_IRQZREQD_ACTIVELOW (0x1 << 7) +#define TAS2564_MISCIRQ_IRQZBITBANG_MASK (0x1 << 0) +#define TAS2564_MISCIRQ_IRQZBITBANG_IRQZINPUTBUF0 (0x0 << 0) +#define TAS2564_MISCIRQ_IRQZBITBANG_IRQZINPUTBUF1 (0x1 << 0) + +#define TAS2564_BOOSTSLOPE (TAS256X_BOOSTSLOPE) +#define TAS2564_BOOSTSLOPE_MASK (TAS256X_BOOSTSLOPE_MASK) +#define TAS2564_BOOSTSLOPE_3DOT67AV (0x1 << 2) +#define TAS2564_BOOSTSLOPE_2DOT93AV (0x2 << 2) + +/* Clock Configuration */ +#define TAS2564_CLOCKCONFIGURATION (TAS256X_CLOCKCONFIGURATION) +#define TAS2564_CLOCKCONFIGURATION_SBCLKTOFS52_MASK \ + (TAS256X_CLOCKCONFIGURATION_SBCLKTOFS52_MASK) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_16 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_16) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_24 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_24) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_32 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_32) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_48 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_48) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_64 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_64) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_96 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_96) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_128 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_128) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_192 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_192) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_256 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_256) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_384 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_384) +#define TAS2564_CLOCKCONFIGURATION_SBCLKtoFS52_512 \ + (TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_512) +#define TAS2564_CLOCKCONFIGURATION_DISCLKRATEDETECT10_MASK \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_MASK) +#define TAS2564_CLOCKCONFIGURATION_DISCLKRATEDETECT10_DISABLED \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_DISABLED) +#define TAS2564_CLOCKCONFIGURATION_DISCLKRATEDETECT10_ENABLED \ + (TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_ENABLED) + +#define TAS2564_VBATFILTER (TAS256X_VBATFILTER) +#define TAS2564_CLASSHRELEASETIMER (TAS256X_CLASSHRELEASETIMER) + +#define TAS2564_BOOST_CFG4 (TAS256X_BOOST_CFG4) +#define TAS2564_BOOST_CFG4_PEAK_CURRENT_LIMIT_MASK (0x3f << 0) + +#define TAS2564_BOOST_CFG5 TAS256X_REG(0x0, 0x0, 0x48) +#define TAS2564_BOOST_CFG5_BOOSTMAXVOLTAGE_MASK (0x1f << 3) +#define TAS2564_BOOST_CFG5_BOOSTMAXVOLTAGE_6V (0x7 << 3) + +#define TAS2564_ICN_THRESHOLD_REG (TAS256X_ICN_THRESHOLD_REG) +#define TAS2564_ICN_HYSTERESIS_REG (TAS256X_ICN_HYSTERESIS_REG) + +#define TAS2564_ICN_SW_REG (TAS256X_ICN_SW_REG) +#define TAS2564_ICN_SW_MASK (TAS256X_ICN_SW_MASK) +#define TAS2564_ICN_SW_ENABLE (TAS256X_ICN_SW_ENABLE) +#define TAS2564_ICN_SW_DISABLE (TAS256X_ICN_SW_DISABLE) +#define TAS2564_TESTPAGECONFIGURATION (TAS256X_TESTPAGECONFIGURATION) +#define TAS2564_CLASSDCONFIGURATION1 (TAS256X_CLASSDCONFIGURATION1) +#define TAS2564_CLASSDCONFIGURATION2 (TAS256X_CLASSDCONFIGURATION2) +#define TAS2564_CLASSDCONFIGURATION3 (TAS256X_CLASSDCONFIGURATION3) +#define TAS2564_CLASSDCONFIGURATION4 (TAS256X_CLASSDCONFIGURATION4) +#define TAS2564_EFFICIENCYCONFIGURATION (TAS256X_EFFICIENCYCONFIGURATION) + +#define TAS2564_HPF (TAS256X_HPF) +#define TAS2564_CLASSHHEADROOM (TAS256X_CLASSHHEADROOM) +#define TAS2564_CLASSHHYSTERESIS (TAS256X_CLASSHHYSTERESIS) +#define TAS2564_CLASSHMTCT (TAS256X_CLASSHMTCT) + +#define TAS2564_CLASSH_SLOPE TAS256X_REG(0x0, 0x0, 0x4a) + +/* Revision and PG ID */ +#define TAS2564_REVISIONANDPGID TAS256X_REG(0x0, 0x0, 0x7D) +#define TAS2564_REVISIONANDPGID_REVISIONID74_MASK (0xf << 4) +#define TAS2564_REVISIONANDPGID_PGID30_MASK (0xf << 0) + +/* I2C Checksum */ +#define TAS2564_I2CCHECKSUM TAS256X_REG(0x0, 0x0, 0x7E) +#define TAS2564_I2CCHECKSUM_I2CCHECKSUM70_MASK (0xff << 0) + +/* Book */ +#define TAS2564_BOOK (TAS256X_BOOK) +#define TAS2564_BOOK_BOOK70_MASK (TAS256X_BOOK_BOOK70_MASK) +#endif /* __TAS2564_ */ diff --git a/asoc/codecs/tas256x/physical_layer/inc/tas256x-device.h b/asoc/codecs/tas256x/physical_layer/inc/tas256x-device.h new file mode 100644 index 00000000..90687b5b --- /dev/null +++ b/asoc/codecs/tas256x/physical_layer/inc/tas256x-device.h @@ -0,0 +1,203 @@ +#ifndef __TAS256X_DEVICE_ +#define __TAS256X_DEVICE_ + +#include "tas256x.h" +#include <stdbool.h> +#define DEVICE_TAS2558 0x2558 +#define DEVICE_TAS2562 0x2562 +#define DEVICE_TAS2564 0x2564 + +#define DVC_PCM 0x1 +#define LIM_MAX_ATN 0x2 +#define LIMB_TH_MAX 0x3 +#define LIMB_TH_MIN 0x4 +#define LIMB_INF_PT 0x5 +#define LIMB_SLOPE 0x6 +#define BOP_TH 0x7 +#define BOSD_TH 0x8 +#define LIMB_ATK_RT 0x9 +#define LIMB_RLS_RT 0xA +#define LIMB_ATK_ST 0xB +#define LIMB_RLS_ST 0xC +#define BOP_ATK_RT 0xD +#define BOP_ATK_ST 0xE +#define BOP_HLD_TM 0xF +#define BST_VREG 0x10 +#define BST_ILIM 0x11 +#define CLASSH_TIMER 0x12 +#define AMPOUTPUT_LVL 0x13 + +#define TX_SLOT0 0 +#define TX_SLOT1 1 +#define TX_SLOT2 2 +#define TX_SLOT3 3 +#define TX_SLOT4 4 +#define TX_SLOT5 5 +#define TX_SLOT6 6 +#define TX_SLOT7 7 +#define TX_SLOT8 8 +#define TX_SLOT9 9 +#define TX_SLOTa 0xa +#define TX_SLOTb 0xb +#define TX_SLOTc 0xc +#define TX_SLOTd 0xd +#define TX_SLOTe 0xe +#define TX_SLOTf 0xf + +int tas56x_software_reset(struct tas256x_priv *p_tas256x, int ch); + +int tas56x_get_chipid(struct tas256x_priv *p_tas256x, int *chipid, int ch); + +/* Power Up related functions */ +int tas256x_set_power_up(struct tas256x_priv *p_tas256x, + enum channel chn); + +int tas256x_set_power_mute(struct tas256x_priv *p_tas256x, + enum channel chn); + +int tas256x_set_power_shutdown(struct tas256x_priv *p_tas256x, + enum channel chn); + +int tas256x_power_check(struct tas256x_priv *p_tas256x, int *state, + int ch); + +/* IV Sense Format Related functions */ +int tas256x_iv_sense_enable_set(struct tas256x_priv *p_tas256x, + bool enable, int ch); + +bool tas256x_iv_sense_enable_get(struct tas256x_priv *p_tas256x, int ch); + +int tas256x_set_iv_slot(struct tas256x_priv *p_tas256x, int ch, int vslot, int islot); + +int tas256x_set_vbat_slot(struct tas256x_priv *p_tas256x, int ch, int slot); + +int tas256x_iv_bitwidth_config(struct tas256x_priv *p_tas256x, int bitwidth, int ch); + +int tas256x_tx_set_edge(struct tas256x_priv *p_tas256x, + unsigned int tx_edge, int ch); + +int tas256x_tx_set_start_slot(struct tas256x_priv *p_tas256x, + unsigned int tx_start_slot, int ch); + +int tas256x_set_tx_config(struct tas256x_priv *p_tas256x, int value, int ch); + +/* Rx Format Related functions */ +int tas256x_set_samplerate(struct tas256x_priv *p_tas256x, + int samplerate, int ch); + +int tas256x_rx_set_edge(struct tas256x_priv *p_tas256x, + unsigned int rx_edge, int ch); + +int tas256x_rx_set_start_slot(struct tas256x_priv *p_tas256x, + unsigned int rx_start_slot, int ch); + +int tas256x_rx_set_slot_len(struct tas256x_priv *p_tas256x, + int slot_width, int ch); + +int tas256x_rx_set_slot(struct tas256x_priv *p_tas256x, + int slot, int ch); + +int tas256x_rx_set_bitwidth(struct tas256x_priv *p_tas256x, + int bitwidth, int ch); + +/* Interrupt Related Functions */ +int tas256x_interrupt_clear(struct tas256x_priv *p_tas256x, int ch); + +int tas256x_interrupt_enable(struct tas256x_priv *p_tas256x, + int val, int ch); + +int tas256x_interrupt_read(struct tas256x_priv *p_tas256x, + int *intr1, int *intr2, int ch); + +int tas256x_interrupt_determine(struct tas256x_priv *p_tas256x, int ch, + int int1status, int int2status); + +/* ICN Related Functions */ +int tas256x_icn_disable(struct tas256x_priv *p_tas256x, + int disable, int ch); + +int tas256x_icn_data(struct tas256x_priv *p_tas256x, int ch); + +int tas256x_icn_config(struct tas256x_priv *p_tas256x, int value, int ch); + +/* Boost/Volt Related functions */ +int tas256x_boost_volt_update(struct tas256x_priv *p_tas256x, + int value, int ch); + +int tas256x_set_misc_config(struct tas256x_priv *p_tas256x, int value, int ch); + +/* Clock Configuration */ +int tas256x_set_clock_config(struct tas256x_priv *p_tas256x, + int value, int ch); + +/* ClassH Configuration*/ +int tas256x_set_classH_config(struct tas256x_priv *p_tas256x, + int value, int ch); + +/* HPF Related functions*/ +int tas256x_HPF_FF_Bypass(struct tas256x_priv *p_tas256x, int value, int ch); + +int tas256x_HPF_FB_Bypass(struct tas256x_priv *p_tas256x, int value, int ch); + +/*Speaker Receiever mode - specific to TAS2564*/ +int tas2564_rx_mode_update(struct tas256x_priv *p_tas256x, + int rx_mode, int ch); + +/*Playback Volume*/ +int tas256x_update_playback_volume(struct tas256x_priv *p_tas256x, + int value, int ch); + +/*Feature Control Functions*/ +int tas256x_update_lim_max_attenuation(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_lim_max_thr(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_lim_min_thr(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_lim_inflection_point(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_lim_slope(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_thr(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_update_bosd_thr(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_update_boost_voltage(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_current_limit(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_limiter_enable(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_limiter_attack_rate(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_limiter_attack_step_size(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_limiter_release_rate(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_limiter_release_step_size(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_enable(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_mute(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_update_bop_shutdown_enable(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_attack_rate(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_attack_step_size(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_bop_hold_time(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_update_vbat_lpf(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_update_rx_cfg(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_rx_set_frame_start(struct tas256x_priv *p_tas256x, + unsigned int frame_start, int ch); +int tas256x_update_classh_timer(struct tas256x_priv *p_tas256x, int value, int ch); +int tas256x_set_auto_detect_clock(struct tas256x_priv *p_tas256x, + int value, int ch); +int tas256x_enable_reciever_mode(struct tas256x_priv *p_tas256x, int enable, + int ch); +int tas256x_update_ampoutput_level(struct tas256x_priv *p_tas256x, + int value, int ch); + +/*Initialize to defaults*/ +int tas256x_update_default_params(struct tas256x_priv *p_tas256x, int ch); + +#endif /* __TAS256X_DEVICE_ */
\ No newline at end of file diff --git a/asoc/codecs/tas256x/physical_layer/inc/tas256x.h b/asoc/codecs/tas256x/physical_layer/inc/tas256x.h new file mode 100644 index 00000000..4e1677cb --- /dev/null +++ b/asoc/codecs/tas256x/physical_layer/inc/tas256x.h @@ -0,0 +1,693 @@ +#ifndef __TAS256X_ +#define __TAS256X_ + +#include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/hrtimer.h> +#include <linux/printk.h> +#include <linux/delay.h> +#include <sound/soc.h> +#include <linux/version.h> + +#define TAS256X_DRIVER_TAG "TAS256X_REL_010306" + +/* Page Control Register */ +#define TAS256X_PAGECTL_REG 0 + +/* Book Control Register (available in page0 of each book) */ +#define TAS256X_BOOKCTL_PAGE 0 +#define TAS256X_BOOKCTL_REG 127 + +#define TAS256X_REG(book, page, reg) (((book * 256 * 128) + \ + (page * 128)) + reg) + +#define TAS256X_BOOK_ID(reg) (reg / (256 * 128)) + +#define TAS256X_PAGE_ID(reg) ((reg % (256 * 128)) / 128) + +#define TAS256X_BOOK_REG(reg) (reg % (256 * 128)) + +#define TAS256X_PAGE_REG(reg) ((reg % (256 * 128)) % 128) + +/* Software Reset */ +#define TAS256X_SOFTWARERESET TAS256X_REG(0x0, 0x0, 0x01) +#define TAS256X_SOFTWARERESET_SOFTWARERESET_MASK (0x1 << 0) +#define TAS256X_SOFTWARERESET_SOFTWARERESET_DONTRESET (0x0 << 0) +#define TAS256X_SOFTWARERESET_SOFTWARERESET_RESET (0x1 << 0) + +/* Power Control */ +#define TAS256X_POWERCONTROL TAS256X_REG(0x0, 0x0, 0x02) +#define TAS256X_POWERCONTROL_ISNSPOWER_MASK (0x1 << 3) +#define TAS256X_POWERCONTROL_ISNSPOWER_ACTIVE (0x0 << 3) +#define TAS256X_POWERCONTROL_ISNSPOWER_POWEREDDOWN (0x1 << 3) +#define TAS256X_POWERCONTROL_VSNSPOWER_MASK (0x1 << 2) +#define TAS256X_POWERCONTROL_VSNSPOWER_ACTIVE (0x0 << 2) +#define TAS256X_POWERCONTROL_VSNSPOWER_POWEREDDOWN (0x1 << 2) +#define TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK (0x3 << 0) +#define TAS256X_POWERCONTROL_OPERATIONALMODE10_ACTIVE (0x0 << 0) +#define TAS256X_POWERCONTROL_OPERATIONALMODE10_MUTE (0x1 << 0) +#define TAS256X_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN (0x2 << 0) + +/* Playback Configuration Reg0 */ +#define TAS256X_PLAYBACKCONFIGURATIONREG0 TAS256X_REG(0x0, 0x0, 0x03) +#define TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK (0x1 << 6) +#define TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_ENABLED (0x0 << 6) +#define TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED (0x1 << 6) + +/* Misc Configuration Reg0 */ +#define TAS256X_MISCCONFIGURATIONREG0 TAS256X_REG(0x0, 0x0, 0x04) +#define TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_MASK (0x1 << 7) +#define TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_DONOTRETRY (0x0 << 7) +#define TAS256X_MISCCONFIGURATIONREG0_CPPGRETRY_RETRY (0x1 << 7) +#define TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_MASK (0x1 << 6) +#define TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_DONOTRETRY (0x0 << 6) +#define TAS256X_MISCCONFIGURATIONREG0_VBATPRORETRY_RETRY (0x1 << 6) +#define TAS256X_MISCCONFIGURATIONREG0_OCERETRY_MASK (0x1 << 5) +#define TAS256X_MISCCONFIGURATIONREG0_OCERETRY_DONOTRETRY (0x0 << 5) +#define TAS256X_MISCCONFIGURATIONREG0_OCERETRY_RETRY (0x1 << 5) +#define TAS256X_MISCCONFIGURATIONREG0_OTERETRY_MASK (0x1 << 4) +#define TAS256X_MISCCONFIGURATIONREG0_OTERETRY_DONOTRETRY (0x0 << 4) +#define TAS256X_MISCCONFIGURATIONREG0_OTERETRY_RETRY (0x1 << 4) +#define TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_MASK (0x1 << 3) +#define TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_DISABLED (0x0 << 3) +#define TAS256X_MISCCONFIGURATIONREG0_IRQZPULL_ENABLED (0x1 << 3) +#define TAS256X_MISCCONFIGURATIONREG0_AMPSS_MASK (0x1 << 2) +#define TAS256X_MISCCONFIGURATIONREG0_AMPSS_DISABLED (0x0 << 2) +#define TAS256X_MISCCONFIGURATIONREG0_AMPSS_ENABLED (0x1 << 2) + +/* TDM Configuration Reg0 */ +#define TAS256X_TDMCONFIGURATIONREG0 TAS256X_REG(0x0, 0x0, 0x06) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK (0x1 << 5) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ (0x0 << 5) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ (0x1 << 5) +#define TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK (0x1 << 4) +#define TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED (0x1 << 4) +#define TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED (0x0 << 4) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK (0x7 << 1) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_14_7_16KHZ (0x1 << 1) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ (0x4 << 1) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ (0x5 << 1) +#define TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ (0x6 << 1) +#define TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_MASK (0x1 << 0) +#define TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_LOWTOHIGH (0x0 << 0) +#define TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_HIGHTOLOW (0x1 << 0) + +/* TDM Configuration Reg1 */ +#define TAS256X_TDMCONFIGURATIONREG1 TAS256X_REG(0x0, 0x0, 0x07) +#define TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_MASK (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_LEFT (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG1_RXJUSTIFY_RIGHT (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_MASK (0x1f << 1) +#define TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT (1) +#define TAS256X_TDMCONFIGURATIONREG1_RXEDGE_MASK (0x1 << 0) +#define TAS256X_TDMCONFIGURATIONREG1_RXEDGE_SHIFT (0) +#define TAS256X_TDMCONFIGURATIONREG1_RXEDGE_RISING (0x0 << 0) +#define TAS256X_TDMCONFIGURATIONREG1_RXEDGE_FALLING (0x1 << 0) + +/* TDM Configuration Reg2 */ +#define TAS256X_TDMCONFIGURATIONREG2 TAS256X_REG(0x0, 0x0, 0x08) +#define TAS256X_TDMCONFIGURATIONREG2_IVLEN76_MASK (0X3 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_8BITS (0x2 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_MASK (0x3 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS (0x2 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_12BITS (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_16BITS (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MASK (0x3 << 4) +#define TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C (0x0 << 4) +#define TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT (0x1 << 4) +#define TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT (0x2 << 4) +#define TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX (0x3 << 4) +#define TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK (0x3 << 2) +#define TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_16BITS (0x0 << 2) +#define TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_20BITS (0x1 << 2) +#define TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_24BITS (0x2 << 2) +#define TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_32BITS (0x3 << 2) +#define TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_MASK (0x3 << 0) +#define TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_16BITS (0x0 << 0) +#define TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_24BITS (0x1 << 0) +#define TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_32BITS (0x2 << 0) + +/* TDM Configuration Reg3 */ +#define TAS256X_TDMCONFIGURATIONREG3 TAS256X_REG(0x0, 0x0, 0x09) +#define TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK (0xf << 4) +#define TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_SHIFT (4) +#define TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask (0xf << 0) +#define TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_SHIFT (0) + +/* TDM Configuration Reg4 */ +#define TAS256X_TDMConfigurationReg4 TAS256X_REG(0x0, 0x0, 0x0A) +#define TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_MASK (0x1 << 5) +#define TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_DISABLE (0x0 << 5) +#define TAS256X_TDMCONFIGURATIONREG4_TXKEEPER_ENABLE (0x1 << 5) +#define TAS256X_TDMCONFIGURATIONREG4_TXFILL_MASK (0x1 << 4) +#define TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMIT0 (0x0 << 4) +#define TAS256X_TDMCONFIGURATIONREG4_TXFILL_TRANSMITHIZ (0x1 << 4) +#define TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_MASK (0x7 << 1) +#define TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_SHIFT (1) +#define TAS256X_TDMCONFIGURATIONREG4_TXEDGE_MASK (0x1 << 0) +#define TAS256X_TDMCONFIGURATIONREG4_TXEDGE_SHIFT (0) +#define TAS256X_TDMCONFIGURATIONREG4_TXEDGE_RISING (0x0 << 0) +#define TAS256X_TDMCONFIGURATIONREG4_TXEDGE_FALLING (0x1 << 0) + +/* TDM Configuration Reg5 */ +#define TAS256X_TDMCONFIGURATIONREG5 TAS256X_REG(0x0, 0x0, 0x0B) +#define TAS256X_TDMCONFIGURATIONREG5_VSNSTX_MASK (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG5_VSNSTX_DISABLE (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG5_VSNSTX_ENABLE (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG5_VSNSSLOT50_MASK (0x3f << 0) + +/* TDM Configuration Reg6 */ +#define TAS256X_TDMCONFIGURATIONREG6 TAS256X_REG(0x0, 0x0, 0x0C) +#define TAS256X_TDMCONFIGURATIONREG6_ISNSTX_MASK (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG6_ISNSTX_DISABLE (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG6_ISNSTX_ENABLE (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG6_ISNSSLOT50_MASK (0x3f << 0) + +/* TDM Configuration Reg7 */ +#define TAS256X_TDMCONFIGURATIONREG7 TAS256X_REG(0x0, 0x0, 0x0D) +#define TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_MASK (0x1 << 7) +#define TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_8BITS (0x0 << 7) +#define TAS256X_TDMCONFIGURATIONREG7_VBATSLEN_16BITS (0x1 << 7) +#define TAS256X_TDMCONFIGURATIONREG7_VBATTX_MASK (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG7_VBATTX_DISABLE (0x0 << 6) +#define TAS256X_TDMCONFIGURATIONREG7_VBATTX_ENABLE (0x1 << 6) +#define TAS256X_TDMCONFIGURATIONREG7_VBATSLOT50_MASK (0x3f << 0) + +/* Interrupt Mask Reg0 */ +#define TAS256X_INTERRUPTMASKREG0 TAS256X_REG(0x0, 0x0, 0x1A) +#define TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_MASK (0x1 << 7) +#define TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_UNMASK (0x0 << 7) +#define TAS256X_INTERRUPTMASKREG0_LIMMUTEINTMASK_DISABLE (0x1 << 7) +#define TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_MASK (0x1 << 6) +#define TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_UNMASK (0x0 << 6) +#define TAS256X_INTERRUPTMASKREG0_LIMINFHLDINTMASK_DISABLE (0x1 << 6) +#define TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_MASK (0x1 << 5) +#define TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_UNMASK (0x0 << 5) +#define TAS256X_INTERRUPTMASKREG0_LIMMAXATNINTMASK_DISABLE (0x1 << 5) +#define TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_MASK (0x1 << 4) +#define TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_UNMASK (0x0 << 4) +#define TAS256X_INTERRUPTMASKREG0_VBATLESSTHANINFINTMASK_DISABLE (0x1 << 4) +#define TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_MASK (0x1 << 3) +#define TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_UNMASK (0x0 << 3) +#define TAS256X_INTERRUPTMASKREG0_LIMACTIVEFLAGINTMASK_DISABLE (0x1 << 3) +#define TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_MASK (0x1 << 2) +#define TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_UNMASK (0x0 << 2) +#define TAS256X_INTERRUPTMASKREG0_TDMCLOCKERRORINTMASK_DISABLE (0x1 << 2) +#define TAS256X_INTERRUPTMASKREG0_OCEINTMASK_MASK (0x1 << 1) +#define TAS256X_INTERRUPTMASKREG0_OCEINTMASK_UNMASK (0x0 << 1) +#define TAS256X_INTERRUPTMASKREG0_OCEINTMASK_DISABLE (0x1 << 1) +#define TAS256X_INTERRUPTMASKREG0_OTEINTMASK_MASK (0x1 << 0) +#define TAS256X_INTERRUPTMASKREG0_OTEINTMASK_UNMASK (0x0 << 0) +#define TAS256X_INTERRUPTMASKREG0_OTEINTMASK_DISABLE (0x1 << 0) +#define TAS256X_INTERRUPTMASKREG0_DISABLE 0xff + +/* Interrupt Mask Reg1 */ +#define TAS256X_INTERRUPTMASKREG1 TAS256X_REG(0x0, 0x0, 0x1B) +#define TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_MASK (0x1 << 7) +#define TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_UNMASK (0x0 << 7) +#define TAS256X_INTERRUPTMASKREG1_DSPOUTPUTINTMASK_DISABLE (0x1 << 7) +#define TAS256X_INTERRUPTMASKREG1_CRCINTMASK_MASK (0x1 << 6) +#define TAS256X_INTERRUPTMASKREG1_CRCINTMASK_UNMASK (0x0 << 6) +#define TAS256X_INTERRUPTMASKREG1_CRCINTMASK_DISABLE (0x1 << 6) +#define TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_MASK (0x1 << 2) +#define TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_UNMASK (0x0 << 2) +#define TAS256X_INTERRUPTMASKREG1_VBATOVLOINTMASK_DISABLE (0x1 << 2) +#define TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_MASK (0x1 << 1) +#define TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_UNMASK (0x0 << 1) +#define TAS256X_INTERRUPTMASKREG1_VBATUVLOINTMASK_DISABLE (0x1 << 1) +#define TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_MASK (0x1 << 0) +#define TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_UNMASK (0x0 << 0) +#define TAS256X_INTERRUPTMASKREG1_BROWNOUTFLAGINTMASK_DISABLE (0x1 << 0) +#define TAS256X_INTERRUPTMASKREG1_DISABLE 0xff + +/* Latched-Interrupt Reg0 */ +#define TAS256X_LATCHEDINTERRUPTREG0 TAS256X_REG(0x0, 0x0, 0x24) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_MASK (0x1 << 7) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_NOINTERRUPT (0x0 << 7) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMUTESTICKY_INTERRUPT (0x1 << 7) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_MASK (0x1 << 6) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_NOINTERRUPT (0x0 << 6) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMINFHLDSTICKY_INTERRUPT (0x1 << 6) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_MASK (0x1 << 5) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_NOINTERRUPT (0x0 << 5) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMMAXATNSTICKY_INTERRUPT (0x1 << 5) +#define TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_MASK (0x1 << 4) +#define TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_NOINTERRUPT \ + (0x0 << 4) +#define TAS256X_LATCHEDINTERRUPTREG0_VBATLESSTHANINFSTICKY_INTERRUPT (0x1 << 4) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_MASK (0x1 << 3) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_NOINTERRUPT (0x0 << 3) +#define TAS256X_LATCHEDINTERRUPTREG0_LIMACTIVEFLAGSTICKY_INTERRUPT (0x1 << 3) +#define TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_MASK (0x1 << 2) +#define TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_NOINTERRUPT (0x0 << 2) +#define TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT (0x1 << 2) +#define TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_MASK (0x1 << 1) +#define TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_NOINTERRUPT (0x0 << 1) +#define TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT (0x1 << 1) +#define TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_MASK (0x1 << 0) +#define TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_NOINTERRUPT (0x0 << 0) +#define TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT (0x1 << 0) + +/* Latched-Interrupt Reg1 */ +#define TAS256X_LATCHEDINTERRUPTREG1 TAS256X_REG(0x0, 0x0, 0x25) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_MASK (0x1 << 7) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_NOINTERRUPT \ + (0x0 << 7) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMAUDDATAINVALIDSTICKY_INTERRUPT \ + (0x1 << 7) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_MASK (0x1 << 3) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_NOINTERRUPT (0x0 << 3) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT (0x1 << 3) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_MASK (0x1 << 2) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_NOINTERRUPT (0x0 << 2) +#define TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT (0x1 << 2) +#define TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_MASK (0x1 << 1) +#define TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_NOINTERRUPT (0x0 << 1) +#define TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT (0x1 << 1) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_MASK (0x1 << 0) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_NOINTERRUPT (0x0 << 0) +#define TAS256X_LATCHEDINTERRUPTREG1_PDMCLOCKERRORSTICKY_INTERRUPT (0x1 << 0) + +/* Interrupt Configuration */ +#define TAS256X_INTERRUPTCONFIGURATION TAS256X_REG(0x0, 0x0, 0x30) +#define TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK (0x1 << 2) +#define TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR (0x1 << 2) +#define TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_MASK (0x3 << 0) +#define TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLIVEINTERRUPTS \ + (0x0 << 0) +#define \ + TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERTONLATCHEDINTERRUPTS \ + (0x1 << 0) +#define \ + TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLIVEINTERRUPTS \ + (0x2 << 0) +#define \ + TAS256X_INTERRUPTCONFIGURATION_PININTCONFIG10_ASSERT2MSONLATCHEDINTERRUPTS \ + (0x3 << 0) + +#define TAS256X_CLOCK_HALT_TIMER_MASK (0x7 << 3) +#define TAS256X_CLOCK_HALT_1MS (0x0 << 3) +#define TAS256X_CLOCK_HALT_3MS (0x1 << 3) +#define TAS256X_CLOCK_HALT_26MS (0x2 << 3) +#define TAS256X_CLOCK_HALT_52MS (0x3 << 3) +#define TAS256X_CLOCK_HALT_104MS (0x4 << 3) +#define TAS256X_CLOCK_HALT_209MS (0x5 << 3) +#define TAS256X_CLOCK_HALT_419MS (0x6 << 3) +#define TAS256X_CLOCK_HALT_838MS (0x7 << 3) + +#define TAS256X_BOOSTSLOPE TAS256X_REG(0x0, 0x0, 0x35) +#define TAS256X_BOOSTSLOPE_MASK (0x3 << 2) + +/* Clock Configuration */ +#define TAS256X_CLOCKCONFIGURATION TAS256X_REG(0x0, 0x0, 0x38) +#define TAS256X_CLOCKCONFIGURATION_SBCLKTOFS52_MASK (0xf << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_16 (0x0 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_24 (0x1 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_32 (0x2 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_48 (0x3 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_64 (0x4 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_96 (0x5 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_128 (0x6 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_192 (0x7 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_256 (0x8 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_384 (0x9 << 2) +#define TAS256X_CLOCKCONFIGURATION_SBCLKtoFS52_512 (0xa << 2) +#define TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_MASK (0x3 << 0) +#define TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_DISABLED (0x1 << 0) +#define TAS256X_CLOCKCONFIGURATION_DISCLKRATEDETECT10_ENABLED (0x0 << 0) + +#define TAS256X_VBATFILTER TAS256X_REG(0x0, 0x0, 0x3b) +#define TAS256X_VBAT_LPF_MASK (0x3 << 5) +#define TAS256X_VBAT_LPF_SHIFT 5 + +#define TAS256X_CLASSHRELEASETIMER TAS256X_REG(0x0, 0x0, 0x3c) + +#define TAS256X_BOOST_CFG4 TAS256X_REG(0x0, 0x0, 0x40) + +#define TAS256X_CHIPID TAS256X_REG(0x0, 0x0, 0x7D) + +#define TAS256X_ICN_THRESHOLD_REG TAS256X_REG(0x0, 0x2, 0x64) +#define TAS256X_ICN_HYSTERESIS_REG TAS256X_REG(0x0, 0x2, 0x6c) + +#define TAS256X_ICN_SW_REG TAS256X_REG(0x0, 0x0, 0x3e) +#define TAS256X_ICN_SW_MASK (0x01 << 4) +#define TAS256X_ICN_SW_ENABLE (0x10) +#define TAS256X_ICN_SW_DISABLE (0x00) +#define TAS256X_ICN_IVSENSE_MASK (0x01 << 1) + +#define TAS256X_TESTPAGECONFIGURATION TAS256X_REG(0x0, 0xfd, 0xd) +#define TAS256X_CLASSDCONFIGURATION1 TAS256X_REG(0x0, 0xfd, 0x19) +#define TAS256X_CLASSDCONFIGURATION2 TAS256X_REG(0x0, 0xfd, 0x32) +#define TAS256X_CLASSDCONFIGURATION3 TAS256X_REG(0x0, 0xfd, 0x33) +#define TAS256X_CLASSDCONFIGURATION4 TAS256X_REG(0x0, 0xfd, 0x3f) +#define TAS256X_EFFICIENCYCONFIGURATION TAS256X_REG(0x0, 0xfd, 0x5f) + +#define TAS256X_HPF TAS256X_REG(0x0, 0x2, 0x70) +#define TAS256X_CLASSHHEADROOM TAS256X_REG(0x64, 0x7, 0x48) +#define TAS256X_CLASSHHYSTERESIS TAS256X_REG(0x64, 0x7, 0x4c) +#define TAS256X_CLASSHMTCT TAS256X_REG(0x64, 0x5, 0x4c) + +/*PCM Digital Volume Control*/ +#define TAS256X_DVC_PCM TAS256X_REG(0x0, 0x2, 0x0c) + +/*Limiter Controls*/ +#define TAS256X_LIM_MAX_ATN TAS256X_REG(0x0, 0x2, 0x14) +#define TAS256X_LIMB_TH_MAX TAS256X_REG(0x0, 0x2, 0x18) +#define TAS256X_LIMB_TH_MIN TAS256X_REG(0x0, 0x2, 0x1c) +#define TAS256X_LIMB_INF_PT TAS256X_REG(0x0, 0x2, 0x20) +#define TAS256X_LIMB_SLOPE TAS256X_REG(0x0, 0x2, 0x24) + +/*Brown Out Protection Control*/ +#define TAS256X_BOP_TH TAS256X_REG(0x0, 0x2, 0x28) +#define TAS256X_BOSD_TH TAS256X_REG(0x0, 0x2, 0x2c) + +#define TAS256X_BOOSTCONFIGURATION4 TAS256X_REG(0x0, 0x0, 0x40) +#define TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK (0x3f << 0) +#define TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT 0 + +#define TAS256X_LIMITERCONFIGURATION0 TAS256X_REG(0x0, 0x0, 0x12) +#define TAS256X_LIMITER_ENABLE_MASK (0x1 << 0) +#define TAS256X_LIMITER_ENABLE_SHIFT 0x0 +#define TAS256X_LIMITER_ATTACKRATE_MASK (0x7 << 1) +#define TAS256X_LIMITER_ATTACKRATE_SHIFT 0x1 +#define TAS256X_LIMITER_ATTACKSTEPSIZE_MASK (0x3 << 4) +#define TAS256X_LIMITER_ATTACKSTEPSIZE_SHIFT 0x4 + +#define TAS256X_LIMITERCONFIGURATION1 TAS256X_REG(0x0, 0x0, 0x13) +#define TAS256X_LIMITER_RELEASERATE_MASK (0x7 << 3) +#define TAS256X_LIMITER_RELEASERATE_SHIFT 0x3 +#define TAS256X_LIMITER_RELEASESTEPSIZE_MASK (0x3 << 6) +#define TAS256X_LIMITER_RELEASESTEPSIZE_SHIFT 0x6 + +#define TAS256X_BOPCONFIGURATION0 TAS256X_REG(0x0, 0x0, 0x14) +#define TAS256X_BOP_ENABLE_MASK (0x1 << 0) +#define TAS256X_BOP_ENABLE_SHIFT 0x0 +#define TAS256X_BOP_MUTE_MASK (0x1 << 1) +#define TAS256X_BOP_MUTE_SHIFT 0x1 +#define TAS256X_BOP_SHUTDOWN_ENABLE_MASK (0x1 << 4) +#define TAS256X_BOP_SHUTDOWN_ENABLE_SHIFT 0x4 + +#define TAS256X_BOPCONFIGURATION1 TAS256X_REG(0x0, 0x0, 0x15) +#define TAS256X_BOP_ATTACKRATE_MASK (0x7 << 5) +#define TAS256X_BOP_ATTACKRATE_SHIFT 0x5 +#define TAS256X_BOP_ATTACKSTEPSIZE_MASK (0x3 << 0x3) +#define TAS256X_BOP_ATTACKSTEPSIZE_SHIFT 0x3 +#define TAS256X_BOP_HOLDTIME_MASK (0x7 << 0x0) +#define TAS256X_BOP_HOLDTIME_SHIFT 0x0 + +#define TAS256X_MISC_CLASSD TAS256X_REG(0x0, 0x01, 0x21) +#define TAS256X_CMP_HYST_MASK (0x1 << 3) +#define TAS256X_CMP_HYST_SHIFT (0x3) + +#define TAS256X_CLASSH_TIMER TAS256X_REG(0x64, 0x8, 0x1c) +#define TAS256X_CLASSH_TIMER_RELEASE TAS256X_REG(0x0, 0x0, 0x3c) +#define TAS256X_CLASSH_TIMER_RELEASE_MASK (0x1f << 2) + +/*Test Page*/ +#define TAS256X_TEST_PAGE_LOCK TAS256X_REG(0x00, 0xfd, 0x0d) +#define TAS256X_DAC_MODULATOR TAS256X_REG(0x00, 0xfd, 0x12) +#define TAS256X_DAC_MUTE TAS256X_REG(0x00, 0xfd, 0x47) +#define TAS256X_ICN_MODE TAS256X_REG(0x00, 0xfd, 0x64) +#define TAS256X_ICN_IMPROVE TAS256X_REG(0x00, 0xfd, 0x46) + +/* Book */ +#define TAS256X_BOOK TAS256X_REG(0x0, 0x0, 0x7F) +#define TAS256X_BOOK_BOOK70_MASK (0xff << 0) + +/* data format */ +#define TAS256X_DATAFORMAT_SHIFT 2 +#define TAS256X_DATAFORMAT_I2S 0x0 +#define TAS256X_DATAFORMAT_DSP 0x1 +#define TAS256X_DATAFORMAT_RIGHT_J 0x2 +#define TAS256X_DATAFORMAT_LEFT_J 0x3 + +#define TAS256X_DAI_FMT_MASK (0x7 << TAS256X_DATAFORMAT_SHIFT) + +#define TAS256X_POWER_ACTIVE 0 +#define TAS256X_POWER_MUTE 1 +#define TAS256X_POWER_SHUTDOWN 2 + +#define ERROR_NONE 0x0000000 +#define ERROR_PLL_ABSENT 0x0000001 +#define ERROR_DEVA_I2C_COMM 0x0000002 +#define ERROR_DEVB_I2C_COMM 0x0000004 +#define ERROR_CLOCK 0x0000008 +#define ERROR_YRAM_CRCCHK 0x0000010 +#define ERROR_OVER_CURRENT 0x0000020 +#define ERROR_DIE_OVERTEMP 0x0000040 +#define ERROR_OVER_VOLTAGE 0x0000080 +#define ERROR_UNDER_VOLTAGE 0x0000100 +#define ERROR_BROWNOUT 0x0000200 +#define ERROR_CLASSD_PWR 0x0000400 +#define ERROR_FAILSAFE 0x0000800 + +/* 5 second */ +#define CHECK_PERIOD 5000 + +#define TAS256X_I2C_RETRY_COUNT 3 +#define ERROR_I2C_SUSPEND -1 +#define ERROR_I2C_FAILED -2 + +#define TAS256X_LEFT_SWITCH 0x10000001 +#define TAS256X_RIGHT_SWITCH 0x10000002 +#define RX_SCFG_LEFT 0x10000003 +#define RX_SCFG_RIGHT 0x10000004 + +#define RESTART_MAX 3 + +struct tas256x_priv; +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +struct snd_soc_component; +#else +struct snd_soc_codec; +#endif + +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) +#define TAS256X_CONFIG_SIZE (10) +#define TAS256X_DEVICE_SUM (8) + +#define TAS256X_CMD_SING_W (0x1) +#define TAS256X_CMD_BURST (0x2) +#define TAS256X_CMD_DELAY (0x3) +#define TAS256X_CMD_FIELD_W (0x4) + +#define SMS_HTONS(a, b) ((((a)&0x00FF) << 8) | \ + ((b) & 0x00FF)) +#define SMS_HTONL(a, b, c, d) ((((a) & 0x000000FF) << 24) |\ + (((b) & 0x000000FF) << 16) | \ + (((c) & 0x000000FF) << 8) | \ + ((d) & 0x000000FF)) + +enum tas256x_dsp_fw_state { + TAS256X_DSP_FW_NONE = 0, + TAS256X_DSP_FW_PENDING, + TAS256X_DSP_FW_FAIL, + TAS256X_DSP_FW_OK, +}; + +enum tas256x_bin_blk_type { + TAS256X_BIN_BLK_COEFF = 1, + TAS256X_BIN_BLK_POST_POWER_UP, + TAS256X_BIN_BLK_PRE_SHUTDOWN, + TAS256X_BIN_BLK_PRE_POWER_UP, + TAS256X_BIN_BLK_POST_SHUTDOWN +}; + +struct tas256x_fw_hdr { + unsigned int img_sz; + unsigned int checksum; + unsigned int binnary_version_num; + unsigned int drv_fw_version; + unsigned int timestamp; + unsigned char plat_type; + unsigned char dev_family; + unsigned char reserve; + unsigned char ndev; + unsigned char devs[TAS256X_DEVICE_SUM]; + unsigned int nconfig; + unsigned int config_size[TAS256X_CONFIG_SIZE]; +}; + +struct tas256x_block_data { + unsigned char dev_idx; + unsigned char block_type; + unsigned short yram_checksum; + unsigned int block_size; + unsigned int nSublocks; + unsigned char *regdata; +}; + +struct tas256x_config_info { + unsigned int nblocks; + unsigned int real_nblocks; + struct tas256x_block_data **blk_data; +}; + +void tas256x_select_cfg_blk(void *pContext, int conf_no, unsigned char block_type); +int tas256x_load_container(struct tas256x_priv *pTAS256x); +void tas256x_config_info_remove(void *pContext); +#endif /*CONFIG_TAS256X_REGBIN_PARSER*/ + +struct tas256x_register { +int book; +int page; +int reg; +}; + +struct tas256x_dai_cfg { +unsigned int dai_fmt; +unsigned int tdm_delay; +}; + +/*struct tas256x_buf_cfg { + unsigned short bufSize; + unsigned char *buf; +}; +*/ + +enum channel { + channel_left = 0x01, + channel_right = 0x02, + channel_both = channel_left | channel_right +}; + +/* + * device ops function structure + */ +struct tas_device_ops { + /**< init typically for loading optimal settings */ + int (*tas_init)(struct tas256x_priv *p_tas256x, int chn); +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + int (*tas_probe)(struct tas256x_priv *p_tas256x, + struct snd_soc_component *codec, int chn); +#else + int (*tas_probe)(struct tas256x_priv *p_tas256x, + struct snd_soc_codec *codec, int chn); +#endif +/*TODO:*/ +}; + + +struct tas_device { + int mn_chip_id; + int mn_current_book; + int mn_current_page; + int mn_addr; + int mn_reset_gpio; + int mn_irq_gpio; + int mn_irq; + int spk_control; + int device_id; + int rx_mode; + int dvc_pcm; + int bst_vltg; + int bst_ilm; + int ampoutput_lvl; + int lim_switch; + int lim_max_attn; + int lim_thr_max; + int lim_thr_min; + int lim_att_rate; + int lim_rel_rate; + int lim_att_stp_size; + int lim_rel_stp_size; + int lim_max_thd; + int lim_min_thd; + int lim_infl_pt; + int lim_trk_slp; + int bop_enable; + int bop_thd; + int bop_att_rate; + int bop_att_stp_size; + int bop_hld_time; + int bop_mute; + int bosd_enable; + int bosd_thd; + int vbat_lpf; + int rx_cfg; + int classh_timer; + int reciever_enable; + struct tas_device_ops dev_ops; +}; + +struct tas256x_priv { + void *platform_data; + bool mb_power_up; + int mn_power_state; + bool mb_irq_eable; + int mn_sampling_rate; + int mn_frame_size; + int mn_ppg; + int mn_ch_size; + int mn_rx_slot_width; + int mn_rx_width; + int mn_tx_slot_width; + int mn_iv_width; + int mn_vbat; + bool mb_mute; + bool dac_mute; + int mn_channels; + int mn_slots; + int mn_rx_slot_map[2]; + int mn_fmt; + int mn_fmt_mode; + int mn_frame_start; + int mn_rx_edge; + int mn_rx_offset; + int mn_tx_edge; + int mn_tx_offset; + struct tas_device **devs; + int icn_sw; + int (*read)(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned int *pValue); + int (*write)(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned int Value); + int (*bulk_read)(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned char *p_data, unsigned int len); + int (*bulk_write)(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned char *p_data, unsigned int len); + int (*update_bits)(struct tas256x_priv *p_tas256x, enum channel chn, + unsigned int reg, unsigned int mask, unsigned int value); + void (*hw_reset)(struct tas256x_priv *p_tas256x); + void (*clear_irq)(struct tas256x_priv *p_tas256x); + void (*enable_irq)(struct tas256x_priv *p_tas256x, bool enable); + unsigned int mn_err_code; + unsigned int mn_restart; + int (*plat_write)(void *plat_data, + unsigned int i2c_addr, unsigned int reg, unsigned int value); + int (*plat_bulk_write)(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned char *pData, + unsigned int nLength); + int (*plat_read)(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned int *value); + int (*plat_bulk_read)(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned char *pData, + unsigned int nLength); + int (*plat_update_bits)(void *plat_data, unsigned int i2c_addr, + unsigned int reg, unsigned int mask, + unsigned int value); + void (*schedule_init_work)(struct tas256x_priv *p_tas256x); + + struct mutex dev_lock; +#if IS_ENABLED(CONFIG_TAS256X_CODEC) + struct mutex codec_lock; +#endif +#if IS_ENABLED(CONFIG_TAS256X_MISC) + struct mutex file_lock; +#endif + struct delayed_work irq_work; + struct delayed_work init_work; + struct delayed_work dc_work; + int iv_enable; +#if IS_ENABLED(CONFIG_TAS256X_REGBIN_PARSER) + int fw_state; + struct tas256x_fw_hdr fw_hdr; + int ncfgs; + struct tas256x_config_info **cfg_info; + int profile_cfg_id; +#endif +}; + +#endif /* __TAS256X_ */ diff --git a/asoc/codecs/tas256x/physical_layer/src/tas256x.c b/asoc/codecs/tas256x/physical_layer/src/tas256x.c new file mode 100644 index 00000000..86febd5f --- /dev/null +++ b/asoc/codecs/tas256x/physical_layer/src/tas256x.c @@ -0,0 +1,1588 @@ +#include "physical_layer/inc/tas256x.h" +#include "physical_layer/inc/tas2562.h" +#include "physical_layer/inc/tas2564.h" +#include "physical_layer/inc/tas256x-device.h" + +#define LOG_TAG "[tas256x]" + +#define TAS256X_MDELAY 0xFFFFFFFE +#define TAS256X_MSLEEP 0xFFFFFFFD +#define TAS256X_IVSENSER_ENABLE 1 +#define TAS256X_IVSENSER_DISABLE 0 +static char p_icn_threshold[] = {0x00, 0x01, 0x2f, 0x2c}; +static char p_icn_hysteresis[] = {0x00, 0x01, 0x5d, 0xc0}; + +static unsigned int p_tas256x_classh_d_data[] = { + /* reg address size values */ + TAS256X_CLASSHHEADROOM, 0x4, 0x09, 0x99, 0x99, 0x9a, + TAS256X_CLASSHHYSTERESIS, 0x4, 0x0, 0x0, 0x0, 0x0, + TAS256X_CLASSHMTCT, 0x4, 0xb, 0x0, 0x0, 0x0, + TAS256X_VBATFILTER, 0x1, 0x38, + TAS256X_CLASSHRELEASETIMER, 0x1, 0x3c, + TAS256X_BOOSTSLOPE, 0x1, 0x78, + TAS256X_TESTPAGECONFIGURATION, 0x1, 0xd, + TAS256X_CLASSDCONFIGURATION3, 0x1, 0x8e, + TAS256X_CLASSDCONFIGURATION2, 0x1, 0x49, + TAS256X_CLASSDCONFIGURATION4, 0x1, 0x21, + TAS256X_CLASSDCONFIGURATION1, 0x1, 0x80, + TAS256X_EFFICIENCYCONFIGURATION, 0x1, 0xc1, + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static char HPF_reverse_path[] = { + 0x7F, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static char dvc_pcm[57][4] = { + {0x00, 0x00, 0x0D, 0x43}, {0x00, 0x00, 0x10, 0xB3}, {0x00, 0x00, 0x15, 0x05}, + {0x00, 0x00, 0x1A, 0x77}, {0x00, 0x00, 0x21, 0x51}, {0x00, 0x00, 0x29, 0xF1}, + {0x00, 0x00, 0x34, 0xCE}, {0x00, 0x00, 0x42, 0x7A}, {0x00, 0x00, 0x53, 0xB0}, + {0x00, 0x00, 0x69, 0x5B}, {0x00, 0x00, 0x84, 0xA3}, {0x00, 0x00, 0xA6, 0xFA}, + {0x00, 0x00, 0xD2, 0x37}, {0x00, 0x01, 0x08, 0xA5}, {0x00, 0x01, 0x4D, 0x2A}, + {0x00, 0x01, 0xA3, 0x6E}, {0x00, 0x02, 0x10, 0x08}, {0x00, 0x02, 0x98, 0xC1}, + {0x00, 0x03, 0x44, 0xE0}, {0x00, 0x04, 0x1D, 0x90}, {0x00, 0x05, 0x2E, 0x5B}, + {0x00, 0x06, 0x85, 0xC8}, {0x00, 0x08, 0x36, 0x22}, {0x00, 0x0A, 0x56, 0x6D}, + {0x00, 0x0D, 0x03, 0xA7}, {0x00, 0x10, 0x62, 0x4E}, {0x00, 0x14, 0xA0, 0x51}, + {0x00, 0x19, 0xF7, 0x86}, {0x00, 0x20, 0xB0, 0xBD}, {0x00, 0x29, 0x27, 0x9E}, + {0x00, 0x33, 0xCF, 0x8E}, {0x00, 0x41, 0x39, 0xD3}, {0x00, 0x52, 0x1D, 0x51}, + {0x00, 0x67, 0x60, 0x45}, {0x00, 0x82, 0x24, 0x8A}, {0x00, 0xA3, 0xD7, 0x0A}, + {0x00, 0xCE, 0x43, 0x29}, {0x01, 0x03, 0xAB, 0x3D}, {0x01, 0x46, 0xE7, 0x5E}, + {0x01, 0x9B, 0x8C, 0x27}, {0x02, 0x06, 0x1B, 0x8A}, {0x02, 0x8C, 0x42, 0x40}, + {0x03, 0x35, 0x25, 0x29}, {0x04, 0x09, 0xC2, 0xB1}, {0x05, 0x15, 0x6D, 0x69}, + {0x06, 0x66, 0x66, 0x66}, {0x08, 0x0E, 0x9F, 0x97}, {0x0A, 0x24, 0xB0, 0x63}, + {0x0C, 0xC5, 0x09, 0xAC}, {0x10, 0x13, 0x79, 0x88}, {0x14, 0x3D, 0x13, 0x62}, + {0x19, 0x7A, 0x96, 0x7F}, {0x20, 0x13, 0x73, 0x9E}, {0x28, 0x61, 0x9A, 0xEA}, + {0x32, 0xD6, 0x46, 0x18}, {0x40, 0x00, 0x00, 0x00}, {0x50, 0x92, 0x3B, 0xE4} +}; + +static char lim_max_attn[16][4] = { + {0x14, 0x49, 0x60, 0xC5}, {0x16, 0xC3, 0x10, 0xE3}, {0x19, 0x8A, 0x13, 0x57}, + {0x1C, 0xA7, 0xD7, 0x68}, {0x20, 0x26, 0xF3, 0x10}, {0x24, 0x13, 0x46, 0xF6}, + {0x28, 0x7A, 0x26, 0xC5}, {0x2D, 0x6A, 0x86, 0x6F}, {0x32, 0xF5, 0x2C, 0xFF}, + {0x39, 0x2C, 0xED, 0x8E}, {0x40, 0x26, 0xE7, 0x3D}, {0x47, 0xFA, 0xCC, 0xF0}, + {0x50, 0xC3, 0x35, 0xD4}, {0x5A, 0x9D, 0xF7, 0xAC}, {0x65, 0xAC, 0x8C, 0x2F}, + {0x72, 0x14, 0x82, 0xC0} +}; + +static char vbat_lim_max_thd[27][4] = { + {0x14, 0x00, 0x00, 0x00}, {0x18, 0x00, 0x00, 0x00}, {0x1C, 0x00, 0x00, 0x00}, + {0x20, 0x00, 0x00, 0x00}, {0x24, 0x00, 0x00, 0x00}, {0x28, 0x00, 0x00, 0x00}, + {0x2C, 0x00, 0x00, 0x00}, {0x30, 0x00, 0x00, 0x00}, {0x34, 0x00, 0x00, 0x00}, + {0x38, 0x00, 0x00, 0x00}, {0x3C, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, + {0x44, 0x00, 0x00, 0x00}, {0x48, 0x00, 0x00, 0x00}, {0x4C, 0x00, 0x00, 0x00}, + {0x50, 0x00, 0x00, 0x00}, {0x54, 0x00, 0x00, 0x00}, {0x58, 0x00, 0x00, 0x00}, + {0x5C, 0x00, 0x00, 0x00}, {0x60, 0x00, 0x00, 0x00}, {0x64, 0x00, 0x00, 0x00}, + {0x68, 0x00, 0x00, 0x00}, {0x6C, 0x00, 0x00, 0x00}, {0x70, 0x00, 0x00, 0x00}, + {0x74, 0x00, 0x00, 0x00}, {0x78, 0x00, 0x00, 0x00}, {0x7C, 0x00, 0x00, 0x00} +}; + +static char vbat_lim_min_thd[27][4] = { + {0x14, 0x00, 0x00, 0x00}, {0x18, 0x00, 0x00, 0x00}, {0x1C, 0x00, 0x00, 0x00}, + {0x20, 0x00, 0x00, 0x00}, {0x24, 0x00, 0x00, 0x00}, {0x28, 0x00, 0x00, 0x00}, + {0x2C, 0x00, 0x00, 0x00}, {0x30, 0x00, 0x00, 0x00}, {0x34, 0x00, 0x00, 0x00}, + {0x38, 0x00, 0x00, 0x00}, {0x3C, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, + {0x44, 0x00, 0x00, 0x00}, {0x48, 0x00, 0x00, 0x00}, {0x4C, 0x00, 0x00, 0x00}, + {0x50, 0x00, 0x00, 0x00}, {0x54, 0x00, 0x00, 0x00}, {0x58, 0x00, 0x00, 0x00}, + {0x5C, 0x00, 0x00, 0x00}, {0x60, 0x00, 0x00, 0x00}, {0x64, 0x00, 0x00, 0x00}, + {0x68, 0x00, 0x00, 0x00}, {0x6C, 0x00, 0x00, 0x00}, {0x70, 0x00, 0x00, 0x00}, + {0x74, 0x00, 0x00, 0x00}, {0x78, 0x00, 0x00, 0x00}, {0x7C, 0x00, 0x00, 0x00} +}; + +static char vbat_lim_infl_pt[41][4] = { + {0x20, 0x00, 0x00, 0x00}, {0x21, 0x99, 0x99, 0x99}, {0x23, 0x33, 0x33, 0x33}, + {0x24, 0xCC, 0xCC, 0xCC}, {0x26, 0x66, 0x66, 0x66}, {0x28, 0x00, 0x00, 0x00}, + {0x29, 0x99, 0x99, 0x99}, {0x2B, 0x33, 0x33, 0x33}, {0x2C, 0xCC, 0xCC, 0xCC}, + {0x2E, 0x66, 0x66, 0x66}, {0x30, 0x00, 0x00, 0x00}, {0x31, 0x99, 0x99, 0x99}, + {0x33, 0x33, 0x33, 0x33}, {0x34, 0xCC, 0xCC, 0xCC}, {0x36, 0x66, 0x66, 0x66}, + {0x38, 0x00, 0x00, 0x00}, {0x39, 0x99, 0x99, 0x99}, {0x3B, 0x33, 0x33, 0x33}, + {0x3C, 0xCC, 0xCC, 0xCC}, {0x3E, 0x66, 0x66, 0x66}, {0x40, 0x00, 0x00, 0x00}, + {0x41, 0x99, 0x99, 0x99}, {0x43, 0x33, 0x33, 0x33}, {0x44, 0xCC, 0xCC, 0xCC}, + {0x46, 0x66, 0x66, 0x66}, {0x48, 0x00, 0x00, 0x00}, {0x49, 0x99, 0x99, 0x99}, + {0x4B, 0x33, 0x33, 0x33}, {0x4C, 0xCC, 0xCC, 0xCC}, {0x4E, 0x66, 0x66, 0x66}, + {0x4F, 0xFF, 0xFF, 0xFF}, {0x51, 0x99, 0x99, 0x99}, {0x53, 0x33, 0x33, 0x33}, + {0x54, 0xCC, 0xCC, 0xCC}, {0x56, 0x66, 0x66, 0x66}, {0x57, 0xFF, 0xFF, 0xFF}, + {0x59, 0x99, 0x99, 0x99}, {0x5B, 0x33, 0x33, 0x33}, {0x5C, 0xCC, 0xCC, 0xCC}, + {0x5E, 0x66, 0x66, 0x66}, {0x5F, 0xFF, 0xFF, 0xFF} +}; + +static char vbat_lim_track_slope[7][4] = { + {0x10, 0x00, 0x00, 0x00}, {0x18, 0x00, 0x00, 0x00}, {0x20, 0x00, 0x00, 0x00}, + {0x28, 0x00, 0x00, 0x00}, {0x30, 0x00, 0x00, 0x00}, {0x38, 0x00, 0x00, 0x00}, + {0x40, 0x00, 0x00, 0x00} +}; + +static char bop_thd[16][4] = { + {0x28, 0x00, 0x00, 0x00}, {0x29, 0x99, 0x99, 0x99}, {0x2B, 0x33, 0x33, 0x33}, + {0x2C, 0xCC, 0xCC, 0xCC}, {0x2E, 0x66, 0x66, 0x66}, {0x30, 0x00, 0x00, 0x00}, + {0x31, 0x99, 0x99, 0x99}, {0x33, 0x33, 0x33, 0x33}, {0x34, 0xCC, 0xCC, 0xCC}, + {0x36, 0x66, 0x66, 0x66}, {0x38, 0x00, 0x00, 0x00}, {0x39, 0x99, 0x99, 0x99}, + {0x3B, 0x33, 0x33, 0x33}, {0x3C, 0xCC, 0xCC, 0xCC}, {0x3E, 0x66, 0x66, 0x66}, + {0x40, 0x00, 0x00, 0x00} +}; + +static char bsd_thd[16][4] = { + {0x28, 0x00, 0x00, 0x00}, {0x29, 0x99, 0x99, 0x99}, {0x2B, 0x33, 0x33, 0x33}, + {0x2C, 0xCC, 0xCC, 0xCC}, {0x2E, 0x66, 0x66, 0x66}, {0x30, 0x00, 0x00, 0x00}, + {0x31, 0x99, 0x99, 0x99}, {0x33, 0x33, 0x33, 0x33}, {0x34, 0xCC, 0xCC, 0xCC}, + {0x36, 0x66, 0x66, 0x66}, {0x38, 0x00, 0x00, 0x00}, {0x39, 0x99, 0x99, 0x99}, + {0x3B, 0x33, 0x33, 0x33}, {0x3C, 0xCC, 0xCC, 0xCC}, {0x3E, 0x66, 0x66, 0x66}, + {0x40, 0x00, 0x00, 0x00} +}; + +static char classH_timer[23][4] = { + {0x40, 0x0F, 0x01, 0xC0}, {0x50, 0x11, 0x01, 0xC0}, {0x50, 0x13, 0x01, 0xC0}, + {0x50, 0x15, 0x01, 0xC0}, {0x50, 0x17, 0x01, 0xC0}, {0x50, 0x19, 0x01, 0xC0}, + {0x50, 0x1B, 0x01, 0xC0}, {0x50, 0x1D, 0x01, 0xC0}, {0x50, 0x1F, 0x01, 0xC0}, + {0x60, 0x21, 0x01, 0xC0}, {0x60, 0x23, 0x01, 0xC0}, {0x60, 0x25, 0x01, 0xC0}, + {0x60, 0x27, 0x01, 0xC0}, {0x60, 0x29, 0x01, 0xC0}, {0x60, 0x2B, 0x01, 0xC0}, + {0x60, 0x2D, 0x01, 0xC0}, {0x60, 0x2F, 0x01, 0xC0}, {0x60, 0x31, 0x01, 0xC0}, + {0x60, 0x33, 0x01, 0xC0}, {0x60, 0x35, 0x01, 0xC0}, {0x60, 0x37, 0x01, 0xC0}, + {0x60, 0x39, 0x01, 0xC0}, {0x60, 0x3B, 0x01, 0xC0} +}; + +static char classH_slope[23] = { + 0x2E, 0x28, 0x24, 0x21, 0x1E, 0x1C, 0x1A, 0x18, 0x17, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x11, 0x10, 0xF, 0xF, 0xE, 0xD, 0xD, + 0xD, 0xC +}; + +static int tas256x_i2c_load_data(struct tas256x_priv *p_tas256x, + enum channel chn, + unsigned int *p_data) +{ + unsigned int n_register; + unsigned int *n_data; + unsigned char buf[128] = {0}; + unsigned int n_length = 0; + unsigned int i = 0; + unsigned int n_size = 0; + int n_result = 0; + + do { + n_register = p_data[n_length]; + n_size = p_data[n_length + 1]; + n_data = &p_data[n_length + 2]; + if (n_register == TAS256X_MSLEEP) { + msleep(n_data[0]); + pr_debug("%s %s, msleep = %d\n", LOG_TAG, + __func__, n_data[0]); + } else if (n_register == TAS256X_MDELAY) { + msleep(n_data[0]); + pr_debug("%s %s, mdelay = %d\n", LOG_TAG, + __func__, n_data[0]); + } else { + if (n_register != 0xFFFFFFFF) { + if (n_size > 128) { + pr_err("%s %s, Line=%d, invalid size, maximum is 128 bytes!\n", + LOG_TAG, __func__, __LINE__); + break; + } + if (n_size > 1) { + for (i = 0; i < n_size; i++) + buf[i] = (unsigned char)n_data[i]; + n_result = p_tas256x->bulk_write( + p_tas256x, chn, + n_register, buf, n_size); + if (n_result < 0) + break; + } else if (n_size == 1) { + n_result = p_tas256x->write(p_tas256x, + chn, + n_register, n_data[0]); + if (n_result < 0) + break; + } else { + pr_err("%s %s, Line=%d,invalid size, minimum is 1 bytes!\n", + LOG_TAG, __func__, __LINE__); + } + } + } + n_length = n_length + 2 + p_data[n_length + 1]; + } while (n_register != 0xFFFFFFFF); + return n_result; +} + +int tas256x_update_default_params(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + /*Initialize to default values*/ + if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2562) { + p_tas256x->devs[ch-1]->dvc_pcm = 55; /*0dB*/ + p_tas256x->devs[ch-1]->lim_max_attn = 7; /*-9dB*/ + p_tas256x->devs[ch-1]->lim_thr_max = 13; /*9V*/ + p_tas256x->devs[ch-1]->lim_thr_min = 3; /*4V*/ + p_tas256x->devs[ch-1]->lim_infl_pt = 13; /*3.3V*/ + p_tas256x->devs[ch-1]->lim_trk_slp = 0; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_thd = 4; /*2.9 V*/ + p_tas256x->devs[ch-1]->bosd_thd = 2; /*2.7 V*/ + p_tas256x->devs[ch-1]->bst_vltg = 0xA; /*Mode = speaker*/ + p_tas256x->devs[ch-1]->bst_ilm = 0x36; /*0dB*/ + p_tas256x->devs[ch-1]->ampoutput_lvl = 0x10; /*15.5dBV: 8 + 0.5 * ampoutput_lvl */ + p_tas256x->devs[ch-1]->lim_switch = 0; /*-9dB*/ + p_tas256x->devs[ch-1]->lim_att_rate = 1; /*9V*/ + p_tas256x->devs[ch-1]->lim_att_stp_size = 1; /*4V*/ + p_tas256x->devs[ch-1]->lim_rel_rate = 6; /*3.3V*/ + p_tas256x->devs[ch-1]->lim_rel_stp_size = 1; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_enable = 1; /*2.9 V*/ + p_tas256x->devs[ch-1]->bop_mute = 0; /*2.7 V*/ + p_tas256x->devs[ch-1]->bosd_enable = 0; /*3.3V*/ + p_tas256x->devs[ch-1]->bop_att_rate = 1; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_att_stp_size = 1; /*2.9 V*/ + p_tas256x->devs[ch-1]->bop_hld_time = 6; /*2.7 V*/ + p_tas256x->devs[ch-1]->vbat_lpf = 2; /*2.7 V*/ + p_tas256x->devs[ch-1]->rx_cfg = 0; + p_tas256x->devs[ch-1]->classh_timer = 5; + p_tas256x->devs[ch-1]->reciever_enable = 0; + } else if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2564) { + p_tas256x->devs[ch-1]->rx_mode = 0; /*Mode = speaker*/ + p_tas256x->devs[ch-1]->dvc_pcm = 55; /*0dB*/ + p_tas256x->devs[ch-1]->lim_max_attn = 7; /*-9dB*/ + p_tas256x->devs[ch-1]->lim_thr_max = 13; /*9V*/ + p_tas256x->devs[ch-1]->lim_thr_min = 3; /*4V*/ + p_tas256x->devs[ch-1]->lim_infl_pt = 13; /*3.3V*/ + p_tas256x->devs[ch-1]->lim_trk_slp = 0; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_thd = 4; /*2.9 V*/ + p_tas256x->devs[ch-1]->bosd_thd = 2; /*2.7 V*/ + p_tas256x->devs[ch-1]->bst_vltg = 13; /*Mode = speaker*/ + p_tas256x->devs[ch-1]->bst_ilm = 0x39; /*0dB*/ + p_tas256x->devs[ch-1]->ampoutput_lvl = 0xD; /*16dBV: 9.5 + 0.5 * ampoutput_lvl */ + p_tas256x->devs[ch-1]->lim_switch = 0; /*-9dB*/ + p_tas256x->devs[ch-1]->lim_att_rate = 1; /*9V*/ + p_tas256x->devs[ch-1]->lim_att_stp_size = 1; /*4V*/ + p_tas256x->devs[ch-1]->lim_rel_rate = 6; /*3.3V*/ + p_tas256x->devs[ch-1]->lim_rel_stp_size = 1; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_enable = 1; /*2.9 V*/ + p_tas256x->devs[ch-1]->bop_mute = 0; /*2.7 V*/ + p_tas256x->devs[ch-1]->bosd_enable = 0; /*3.3V*/ + p_tas256x->devs[ch-1]->bop_att_rate = 1; /*1 V/V*/ + p_tas256x->devs[ch-1]->bop_att_stp_size = 1; /*2.9 V*/ + p_tas256x->devs[ch-1]->bop_hld_time = 6; /*2.7 V*/ + p_tas256x->devs[ch-1]->vbat_lpf = 2; /*2.7 V*/ + p_tas256x->devs[ch-1]->rx_cfg = 0; + p_tas256x->devs[ch-1]->classh_timer = 5; + p_tas256x->devs[ch-1]->reciever_enable = 0; + } + p_tas256x->icn_sw = 0; + p_tas256x->mn_rx_slot_map[0] = 0; + p_tas256x->mn_rx_slot_map[1] = 1; + return n_result; +} + +int tas256x_set_power_up(struct tas256x_priv *p_tas256x, + enum channel chn) +{ + int n_result = 0; + + n_result = p_tas256x->update_bits(p_tas256x, + chn, TAS256X_POWERCONTROL, + TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK, + TAS256X_POWERCONTROL_OPERATIONALMODE10_ACTIVE); + + /* Let Power on the device */ + usleep_range(2000, 2100); + /* Enable Comparator Hysteresis */ + n_result = p_tas256x->update_bits(p_tas256x, chn, + TAS256X_MISC_CLASSD, + TAS256X_CMP_HYST_MASK, + (0x01 << TAS256X_CMP_HYST_SHIFT)); + + return n_result; +} + +int tas256x_set_power_mute(struct tas256x_priv *p_tas256x, + enum channel chn) +{ + int n_result = 0; + + n_result = p_tas256x->update_bits(p_tas256x, chn, + TAS256X_POWERCONTROL, + TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK, + TAS256X_POWERCONTROL_OPERATIONALMODE10_MUTE); + + return n_result; +} + +int tas256x_set_power_shutdown(struct tas256x_priv *p_tas256x, + enum channel chn) +{ + int n_result = 0; + + /*Disable Comparator Hysteresis befor Power Down */ + n_result = p_tas256x->update_bits(p_tas256x, chn, + TAS256X_MISC_CLASSD, + TAS256X_CMP_HYST_MASK, + (0x00 << TAS256X_CMP_HYST_SHIFT)); + + n_result = p_tas256x->update_bits(p_tas256x, chn, + TAS256X_POWERCONTROL, + TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK, + TAS256X_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN); + + return n_result; +} + +int tas256x_power_check(struct tas256x_priv *p_tas256x, int *state, int ch) +{ + int n_result = 0; + int status; + + n_result = p_tas256x->read(p_tas256x, ch, + TAS256X_POWERCONTROL, &status); + + status &= TAS256X_POWERCONTROL_OPERATIONALMODE10_MASK; + + if ((status != TAS256X_POWERCONTROL_OPERATIONALMODE10_SHUTDOWN) + && (status != TAS256X_POWERCONTROL_OPERATIONALMODE10_MUTE)) + *state = 1; + else + *state = 0; + + return n_result; +} + +/* + *bool enable = 1; IV Sense Power UP = 0; + * IV Sense Power Down + */ +int tas256x_iv_sense_enable_set(struct tas256x_priv *p_tas256x, bool enable, + int ch) +{ + int n_result = 0; + + if (enable) /*IV Sense Power Up*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_POWERCONTROL, + TAS256X_POWERCONTROL_ISNSPOWER_MASK | + TAS256X_POWERCONTROL_VSNSPOWER_MASK, + TAS256X_POWERCONTROL_VSNSPOWER_ACTIVE | + TAS256X_POWERCONTROL_ISNSPOWER_ACTIVE); + else /*IV Sense Power Down*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_POWERCONTROL, + TAS256X_POWERCONTROL_ISNSPOWER_MASK | + TAS256X_POWERCONTROL_VSNSPOWER_MASK, + TAS256X_POWERCONTROL_VSNSPOWER_POWEREDDOWN | + TAS256X_POWERCONTROL_ISNSPOWER_POWEREDDOWN); + + p_tas256x->iv_enable = enable; + return n_result; +} + +bool tas256x_iv_sense_enable_get(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + bool enable = 0; + int value = 0; + + n_result = p_tas256x->read(p_tas256x, ch, + TAS256X_POWERCONTROL, &value); + if (n_result < 0) + pr_err("%s can't get ivsensor state %s, L=%d\n", + LOG_TAG, __func__, __LINE__); + else if (((value & TAS256X_POWERCONTROL_ISNSPOWER_MASK) + == TAS256X_POWERCONTROL_ISNSPOWER_ACTIVE) + && ((value & TAS256X_POWERCONTROL_VSNSPOWER_MASK) + == TAS256X_POWERCONTROL_VSNSPOWER_ACTIVE)) { + enable = TAS256X_IVSENSER_ENABLE; + } else { + enable = TAS256X_IVSENSER_DISABLE; + } + return enable; +} + +/*No need channel argument*/ +int tas256x_set_iv_slot(struct tas256x_priv *p_tas256x, int ch, int vslot, + int islot) +{ + int n_result = 0; + + vslot |= TAS256X_TDMCONFIGURATIONREG5_VSNSTX_ENABLE; + islot |= TAS256X_TDMCONFIGURATIONREG6_ISNSTX_ENABLE; + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG5, vslot); + + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG6, islot); + + return n_result; +} + +int tas256x_set_vbat_slot(struct tas256x_priv *p_tas256x, int ch, int slot) +{ + int n_result = 0; + + slot |= TAS256X_TDMCONFIGURATIONREG7_VBATTX_ENABLE; + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG7, + slot); + + return n_result; +} + +/*No need channel argument*/ +int tas256x_iv_bitwidth_config(struct tas256x_priv *p_tas256x, int bitwidth, + int ch) +{ + int n_result = 0; + + if (bitwidth == 8) + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_MASK, + TAS256X_TDMCONFIGURATIONREG2_IVMONLEN76_8BITS); + else if (p_tas256x->mn_iv_width == 12) + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_IVLEN76_MASK, + TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_12BITS); + else /*mn_iv_width == 16*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_IVLEN76_MASK, + TAS256X_TDMCONFIGURATIONREG2_IVLENCFG76_16BITS); + + return n_result; +} + +int tas256x_set_auto_detect_clock(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = 0; + + if (value == 0) + value = TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_DISABLED; + else + value = TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_ENABLED; + + /*Set Sample Rate for auto detection only in case of TDM*/ + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_DETECTSAMPRATE_MASK, + value); + + return n_result; +} + +/**/ +int tas256x_set_samplerate(struct tas256x_priv *p_tas256x, + int samplerate, int ch) +{ + int n_result = 0; + + switch (samplerate) { + case 48000: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ); + break; + case 44100: + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_44_1_48KHZ); + break; + case 96000: + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ); + break; + case 88200: + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_88_2_96KHZ); + break; + case 19200: + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_48KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ); + break; + case 17640: + n_result = p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATERAMP_44_1KHZ); + n_result |= p_tas256x->update_bits(p_tas256x, channel_both, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_MASK, + TAS256X_TDMCONFIGURATIONREG0_SAMPRATE31_176_4_192KHZ); + break; + default: + n_result = -1; + pr_info("%s %s, unsupported sample rate, %d\n", + LOG_TAG, __func__, samplerate); + } + + if (n_result == 0) + p_tas256x->mn_sampling_rate = samplerate; + + return n_result; +} + +/* + *rx_edge = 0; Rising + *= 1; Falling + */ +int tas256x_tx_set_edge(struct tas256x_priv *p_tas256x, + unsigned int tx_edge, int ch) +{ + int n_result = 0; + + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMConfigurationReg4, + TAS256X_TDMCONFIGURATIONREG4_TXEDGE_MASK, + (tx_edge << TAS256X_TDMCONFIGURATIONREG4_TXEDGE_SHIFT)); + + if (n_result == 0) + p_tas256x->mn_tx_edge = tx_edge; + + return n_result; +} + +/* + *rx_edge = 0; Rising + *= 1; Falling + */ +int tas256x_rx_set_edge(struct tas256x_priv *p_tas256x, + unsigned int rx_edge, int ch) +{ + int n_result = 0; + + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG1, + TAS256X_TDMCONFIGURATIONREG1_RXEDGE_MASK, + (rx_edge << TAS256X_TDMCONFIGURATIONREG1_RXEDGE_SHIFT)); + + if (n_result == 0) + p_tas256x->mn_rx_edge = rx_edge; + + return n_result; +} +int tas256x_rx_set_start_slot(struct tas256x_priv *p_tas256x, + unsigned int rx_start_slot, int ch) +{ + int n_result = 0; + + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG1, + TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_MASK, + (rx_start_slot << + TAS256X_TDMCONFIGURATIONREG1_RXOFFSET51_SHIFT)); + + if (n_result == 0) + p_tas256x->mn_rx_offset = rx_start_slot; + + return n_result; +} + +int tas256x_tx_set_start_slot(struct tas256x_priv *p_tas256x, + unsigned int tx_start_slot, int ch) +{ + int n_result = 0; + + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMConfigurationReg4, + TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_MASK, + (tx_start_slot << + TAS256X_TDMCONFIGURATIONREG4_TXOFFSET31_SHIFT)); + + if (n_result == 0) + p_tas256x->mn_tx_offset = tx_start_slot; + + return n_result; +} + +int tas256x_rx_set_frame_start(struct tas256x_priv *p_tas256x, + unsigned int frame_start, int ch) +{ + int n_result = 0; + + p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG0, + TAS256X_TDMCONFIGURATIONREG0_FRAMESTART_MASK, + frame_start); + + if (n_result == 0) + p_tas256x->mn_frame_start = frame_start; + + return n_result; +} + +int tas256x_rx_set_slot_len(struct tas256x_priv *p_tas256x, + int slot_width, int ch) +{ + int n_result = -1; + + switch (slot_width) { + case 16: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_MASK, + TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_16BITS); + break; + case 24: + case 32: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_MASK, + TAS256X_TDMCONFIGURATIONREG2_RXSLEN10_32BITS); + break; + case 0: + /* Do not change slot width */ + break; + } + + if (n_result == 0) + p_tas256x->mn_rx_slot_width = slot_width; + + return n_result; +} + +int tas256x_rx_set_slot(struct tas256x_priv *p_tas256x, + int slot, int ch) +{ + int n_result = -1; + if (ch == channel_right) + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG3, + TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_MASK, + (slot << TAS256X_TDMCONFIGURATIONREG3_RXSLOTRIGHT74_SHIFT)); + else/*Assumed Left*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG3, + TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_Mask, + (slot << TAS256X_TDMCONFIGURATIONREG3_RXSLOTLeft30_SHIFT)); + + if (n_result == 0) + p_tas256x->mn_rx_slot_map[ch-1] = slot; + return n_result; +} + +int tas256x_rx_set_bitwidth(struct tas256x_priv *p_tas256x, + int bitwidth, int ch) +{ + int n_result = -1; + + switch (bitwidth) { + case 16: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_16BITS); + break; + case 24: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_24BITS); + break; + case 32: + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_MASK, + TAS256X_TDMCONFIGURATIONREG2_RXWLEN32_32BITS); + break; + default: + pr_info("%s Not supported params format\n", LOG_TAG); + break; + } + + if (n_result == 0) + p_tas256x->mn_rx_width = bitwidth; + + return n_result; +} + +int tas256x_interrupt_clear(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + p_tas256x->update_bits(p_tas256x, ch, + TAS256X_INTERRUPTCONFIGURATION, + TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR_MASK, + TAS256X_INTERRUPTCONFIGURATION_LTCHINTCLEAR); + + return n_result; +} + +int tas256x_interrupt_enable(struct tas256x_priv *p_tas256x, + int val, int ch) +{ + int n_result = 0; + + if (val) { + /*Enable Interrupts*/ + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_INTERRUPTMASKREG0, 0xf8); + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_INTERRUPTMASKREG1, 0xb1); + } else { + /*Disable Interrupts*/ + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_INTERRUPTMASKREG0, + TAS256X_INTERRUPTMASKREG0_DISABLE); + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_INTERRUPTMASKREG1, + TAS256X_INTERRUPTMASKREG1_DISABLE); + } + + return n_result; +} + +int tas256x_interrupt_read(struct tas256x_priv *p_tas256x, + int *intr1, int *intr2, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->read(p_tas256x, ch, + TAS256X_LATCHEDINTERRUPTREG0, intr1); + n_result |= p_tas256x->read(p_tas256x, ch, + TAS256X_LATCHEDINTERRUPTREG1, intr2); + + return n_result; +} + +int tas256x_icn_disable(struct tas256x_priv *p_tas256x, int disable, int ch) +{ + int n_result = 0; + + if (disable) { /*Disable*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_ICN_SW_REG, + TAS256X_ICN_SW_MASK, + TAS256X_ICN_SW_DISABLE); + pr_info("%s %s: ICN Disable!\n", LOG_TAG, __func__); + } else { /*Enable*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_ICN_SW_REG, + TAS256X_ICN_SW_MASK, + TAS256X_ICN_SW_ENABLE); + pr_info("%s %s: ICN Enable!\n", LOG_TAG, __func__); + } + + if (n_result == 0) + p_tas256x->icn_sw = disable; + + return n_result; +} + +/* icn_hysteresis & p_icn_thresholds*/ +int tas256x_icn_data(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_ICN_THRESHOLD_REG, + p_icn_threshold, + sizeof(p_icn_threshold)); + n_result |= p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_ICN_HYSTERESIS_REG, + p_icn_hysteresis, + sizeof(p_icn_hysteresis)); + + return n_result; +} + +int tas256x_icn_config(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_REG(0, 253, 13), 0x0d); + + n_result |= p_tas256x->write(p_tas256x, ch, + TAS256X_REG(0, 253, 25), 0x80); + + return n_result; +} + +int tas256x_boost_volt_update(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = 0; + + if (value == DEVICE_TAS2558) { + /* Max voltage to 9V */ + /*TODO: Need to be fixed*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS2562_BOOSTCONFIGURATION2, + TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK, + 0x7); + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS2562_PLAYBACKCONFIGURATIONREG0, + TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_MASK, + 0xd << 1); + } else if (value == DEVICE_TAS2562) { + /*TODO: ??*/ + } else if (value == DEVICE_TAS2564) { + /*Update Channel Gain to 16dBV*/ + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS2564_PLAYBACKCONFIGURATIONREG0, + TAS2564_PLAYBACKCONFIGURATION_AMP_LEVEL_MASK, + TAS2564_AMP_LEVEL_16dBV); + } + return n_result; +} + +int tas256x_set_misc_config(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_MISCCONFIGURATIONREG0, 0xcf); + + return n_result; + +} + +int tas256x_set_tx_config(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + +#if IS_ENABLED(CONFIG_PLATFORM_EXYNOS) + if (p_tas256x->mn_channels == 2) { + n_result = p_tas256x->write(p_tas256x, channel_left, + TAS256X_TDMConfigurationReg4, 0xf3); + if (n_result < 0) + return n_result; + n_result = p_tas256x->write(p_tas256x, channel_right, + TAS256X_TDMConfigurationReg4, 0x13); + if (n_result < 0) + return n_result; + } else { + n_result = p_tas256x->write(p_tas256x, channel_both, + TAS256X_TDMConfigurationReg4, 0x03); + if (n_result < 0) + return n_result; + } +#else + if (p_tas256x->mn_channels == 2) { + n_result = p_tas256x->write(p_tas256x, channel_left, + TAS256X_TDMConfigurationReg4, 0xf1); + if (n_result < 0) + return n_result; + n_result = p_tas256x->write(p_tas256x, channel_right, + TAS256X_TDMConfigurationReg4, 0x11); + if (n_result < 0) + return n_result; + } else { + n_result = p_tas256x->write(p_tas256x, channel_both, + TAS256X_TDMConfigurationReg4, 0x01); + if (n_result < 0) + return n_result; + } +#endif + + return n_result; +} + +int tas256x_set_clock_config(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + + if (p_tas256x->mn_fmt_mode == 2) {/*TDM Mode*/ + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_CLOCKCONFIGURATION, 0x19); + } else { + n_result = p_tas256x->write(p_tas256x, ch, + TAS256X_CLOCKCONFIGURATION, 0x0c); + } + /* Increase the clock halt timer to 838ms to avoid + * TDM Clock errors during playback start/stop + */ + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_INTERRUPTCONFIGURATION, + TAS256X_CLOCK_HALT_TIMER_MASK, + TAS256X_CLOCK_HALT_838MS); + + return n_result; +} + +int tas256x_set_classH_config(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = 0; + + n_result = tas256x_i2c_load_data(p_tas256x, ch, + p_tas256x_classh_d_data); + + return n_result; +} + +int tas256x_HPF_FF_Bypass(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_PLAYBACKCONFIGURATIONREG0, + TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_MASK, + TAS256X_PLAYBACKCONFIGURATIONREG0_DCBLOCKER_DISABLED); + + return n_result; +} + +int tas256x_HPF_FB_Bypass(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_HPF, HPF_reverse_path, + sizeof(HPF_reverse_path)/sizeof(HPF_reverse_path[0])); + + return n_result; + +} + +int tas56x_software_reset(struct tas256x_priv *p_tas256x, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->write(p_tas256x, ch, TAS256X_SOFTWARERESET, + TAS256X_SOFTWARERESET_SOFTWARERESET_RESET); + + msleep(20); + + return n_result; +} + +int tas256x_interrupt_determine(struct tas256x_priv *p_tas256x, int ch, + int int1status, int int2status) +{ + int mn_err_code = 0; + + if (((int1status & 0x7) != 0) + || ((int2status & 0x0f) != 0)) { + + if (int1status & + TAS256X_LATCHEDINTERRUPTREG0_TDMCLOCKERRORSTICKY_INTERRUPT) { + mn_err_code |= ERROR_CLOCK; + pr_err("%s TDM clock error!\n", LOG_TAG); + } + + if (int1status & + TAS256X_LATCHEDINTERRUPTREG0_OCEFLAGSTICKY_INTERRUPT) { + mn_err_code |= ERROR_OVER_CURRENT; + pr_err("%s SPK over current!\n", LOG_TAG); + } + + if (int1status & + TAS256X_LATCHEDINTERRUPTREG0_OTEFLAGSTICKY_INTERRUPT) { + mn_err_code |= ERROR_DIE_OVERTEMP; + pr_err("%s die over temperature!\n", LOG_TAG); + } + + if (int2status & + TAS256X_LATCHEDINTERRUPTREG1_VBATOVLOSTICKY_INTERRUPT) { + mn_err_code |= ERROR_OVER_VOLTAGE; + pr_err("%s SPK over voltage!\n", LOG_TAG); + } + + if (int2status & + TAS256X_LATCHEDINTERRUPTREG1_VBATUVLOSTICKY_INTERRUPT) { + mn_err_code |= ERROR_UNDER_VOLTAGE; + pr_err("%s SPK under voltage!\n", LOG_TAG); + } + + if (int2status & + TAS256X_LATCHEDINTERRUPTREG1_BROWNOUTFLAGSTICKY_INTERRUPT) { + mn_err_code |= ERROR_BROWNOUT; + pr_err("%s brownout!\n", LOG_TAG); + } + } else { + return 0; + } + + return mn_err_code; +} + +int tas56x_get_chipid(struct tas256x_priv *p_tas256x, int *chipid, int ch) +{ + int n_result = 0; + + n_result = p_tas256x->read(p_tas256x, ch, + TAS256X_CHIPID, chipid); + + return n_result; +} + +int tas2564_rx_mode_update(struct tas256x_priv *p_tas256x, int rx_mode, int ch) +{ + int n_result = 0; + + if (rx_mode) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2564_PLAYBACKCONFIGURATIONREG0, + TAS2564_PLAYBACKCONFIGURATIONREG_RX_SPKR_MODE_MASK, + TAS2564_PLAYBACKCONFIGURATIONREG_RX_MODE); + else + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2564_PLAYBACKCONFIGURATIONREG0, + TAS2564_PLAYBACKCONFIGURATIONREG_RX_SPKR_MODE_MASK, + TAS2564_PLAYBACKCONFIGURATIONREG_SPKR_MODE); + + if (n_result == 0) + p_tas256x->devs[ch-1]->rx_mode = rx_mode; + + return n_result; +} + +int tas256x_update_playback_volume(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 57)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_DVC_PCM, + (char *)&(dvc_pcm[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->dvc_pcm = value; + } + + return n_result; +} + +int tas256x_update_lim_max_attenuation(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 16)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_LIM_MAX_ATN, + (char *)&(lim_max_attn[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_max_attn = value; + } + + return n_result; +} + +int tas256x_update_lim_max_thr(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 27)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_LIMB_TH_MAX, + (char *)&(vbat_lim_max_thd[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_thr_max = value; + } + + return n_result; +} + +int tas256x_update_lim_min_thr(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 27)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_LIMB_TH_MIN, + (char *)&(vbat_lim_min_thd[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_thr_min = value; + } + + return n_result; +} + +int tas256x_update_lim_inflection_point(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 41)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_LIMB_INF_PT, + (char *)&(vbat_lim_infl_pt[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_infl_pt = value; + } + + return n_result; +} + +int tas256x_update_lim_slope(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 7)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_LIMB_SLOPE, + (char *)&(vbat_lim_track_slope[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_trk_slp = value; + } + + return n_result; +} + +int tas256x_update_bop_thr(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 16)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_BOP_TH, + (char *)&(bop_thd[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_thd = value; + } + return n_result; +} + +int tas256x_update_bosd_thr(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 16)) { + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_BOSD_TH, + (char *)&(bsd_thd[value][0]), sizeof(int)); + if (n_result == 0) + p_tas256x->devs[ch-1]->bosd_thd = value; + } + + return n_result; +} + +int tas256x_update_boost_voltage(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2562) { + if ((value >= 0) && (value < 16)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2562_BOOSTCONFIGURATION2, + TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK, + (value+1) << TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_SHIFT); + } else if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2564) { + if ((value >= 0) && (value < 32)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2564_BOOSTCONFIGURATION2, + TAS2564_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_MASK, + (value+7) << TAS2562_BOOSTCONFIGURATION2_BOOSTMAXVOLTAGE_SHIFT); + } + + if (n_result == 0) + p_tas256x->devs[ch-1]->bst_vltg = value; + + return n_result; +} + +int tas256x_update_ampoutput_level(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 1) && (value < 0x1C)) { + if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2562) { + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2562_PLAYBACKCONFIGURATIONREG0, + TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_MASK, + value << TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_SHIFT); + } else if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2564) { + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS2564_PLAYBACKCONFIGURATIONREG0, + TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_MASK, + value << TAS2562_PLAYBACKCONFIGURATIONREG0_AMPLIFIERLEVEL51_SHIFT); + } + } + + if (n_result == 0) + p_tas256x->devs[ch-1]->ampoutput_lvl = value; + + return n_result; +} + +int tas256x_update_current_limit(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 64)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOOSTCONFIGURATION4, + TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_MASK, + (value) << TAS256X_BOOSTCONFIGURATION4_BOOSTCURRENTLIMIT_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bst_ilm = value; + + return n_result; +} + +int tas256x_update_limiter_enable(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 2)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_LIMITERCONFIGURATION0, + TAS256X_LIMITER_ENABLE_MASK, + (value) << TAS256X_LIMITER_ENABLE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_switch = value; + + return n_result; +} + +int tas256x_update_limiter_attack_rate(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 8)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_LIMITERCONFIGURATION0, + TAS256X_LIMITER_ATTACKRATE_MASK, + (value) << TAS256X_LIMITER_ATTACKRATE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_att_rate = value; + + return n_result; +} + +int tas256x_update_limiter_attack_step_size(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 4)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_LIMITERCONFIGURATION0, + TAS256X_LIMITER_ATTACKSTEPSIZE_MASK, + (value) << TAS256X_LIMITER_ATTACKSTEPSIZE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_att_stp_size = value; + + return n_result; +} + +int tas256x_update_limiter_release_rate(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 8)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_LIMITERCONFIGURATION1, + TAS256X_LIMITER_RELEASERATE_MASK, + (value) << TAS256X_LIMITER_RELEASERATE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_rel_rate = value; + + return n_result; +} + +int tas256x_update_limiter_release_step_size(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 4)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_LIMITERCONFIGURATION1, + TAS256X_LIMITER_RELEASESTEPSIZE_MASK, + (value) << TAS256X_LIMITER_RELEASESTEPSIZE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->lim_rel_stp_size = value; + + return n_result; +} + +int tas256x_update_bop_enable(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 2)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION0, + TAS256X_BOP_ENABLE_MASK, + (value) << TAS256X_BOP_ENABLE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_enable = value; + + return n_result; +} + +int tas256x_update_bop_mute(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 2)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION0, + TAS256X_BOP_MUTE_MASK, + (value) << TAS256X_BOP_MUTE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_mute = value; + + return n_result; +} + +int tas256x_update_bop_shutdown_enable(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 2)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION0, + TAS256X_BOP_SHUTDOWN_ENABLE_MASK, + (value) << TAS256X_BOP_SHUTDOWN_ENABLE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bosd_enable = value; + + return n_result; +} + +int tas256x_update_bop_attack_rate(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 8)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION1, + TAS256X_BOP_ATTACKRATE_MASK, + (value) << TAS256X_BOP_ATTACKRATE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_att_rate = value; + + return n_result; +} + +int tas256x_update_bop_attack_step_size(struct tas256x_priv *p_tas256x, + int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 4)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION1, + TAS256X_BOP_ATTACKSTEPSIZE_MASK, + (value) << TAS256X_BOP_ATTACKSTEPSIZE_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_att_stp_size = value; + + return n_result; +} + +int tas256x_update_bop_hold_time(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 8)) + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_BOPCONFIGURATION1, + TAS256X_BOP_HOLDTIME_MASK, + (value) << TAS256X_BOP_HOLDTIME_SHIFT); + + if (n_result == 0) + p_tas256x->devs[ch-1]->bop_hld_time = value; + + return n_result; +} + +int tas256x_update_vbat_lpf(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = -1; + + if ((value >= 0) && (value < 4)) { + n_result = p_tas256x->update_bits(p_tas256x, + ch, TAS256X_VBATFILTER, + TAS256X_VBAT_LPF_MASK, + (value) << TAS256X_VBAT_LPF_SHIFT); + if (n_result == 0) + p_tas256x->devs[ch-1]->vbat_lpf = value; + } + + return n_result; +} + +int tas256x_update_rx_cfg(struct tas256x_priv *p_tas256x, int value, int ch) +{ + int n_result = -1; + int data = -1; + + switch (value) { + case 0: + data = TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_I2C; + break; + case 1: + data = TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_LEFT; + break; + case 2: + data = TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MONO_RIGHT; + break; + case 3: + data = TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_STEREO_DOWNMIX; + break; + } + + if (data >= 0) + n_result = p_tas256x->update_bits(p_tas256x, ch, + TAS256X_TDMCONFIGURATIONREG2, + TAS256X_TDMCONFIGURATIONREG2_RXSCFG54_MASK, + data); + + if (n_result == 0) + p_tas256x->devs[ch-1]->rx_cfg = value; + + return n_result; +} + +int tas256x_update_classh_timer(struct tas256x_priv *p_tas256x, int value, + int ch) +{ + int n_result = -1; + + /*value = 255/(0.07*value)*/ + if (p_tas256x->devs[ch-1]->device_id == DEVICE_TAS2564) { + n_result = + p_tas256x->write(p_tas256x, ch, TAS2564_CLASSH_SLOPE, + classH_slope[value]); + } + + n_result = p_tas256x->bulk_write(p_tas256x, ch, + TAS256X_CLASSH_TIMER, + (char *)&(classH_timer[value][0]), sizeof(int)); + + value += 8; /*Offset*/ + + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_CLASSH_TIMER_RELEASE, + TAS256X_CLASSH_TIMER_RELEASE_MASK, + value+1); + + value -= 8; + + if (n_result == 0) + p_tas256x->devs[ch-1]->classh_timer = value; + + return n_result; +} + +int tas256x_enable_reciever_mode(struct tas256x_priv *p_tas256x, int enable, + int ch) +{ + int n_result = -1; + + if (enable) { + /*Unlock test page*/ + n_result = + p_tas256x->write(p_tas256x, ch, TAS256X_TEST_PAGE_LOCK, + 0xd); + /*Keep DAC modulator dither to minimum*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_DAC_MODULATOR, + 0xc0); + /*Force DAC unmute*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_DAC_MUTE, + 0x04); + /*Force the device in idle channel mode*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_ICN_MODE, + 0x14); + /* ICN improvement*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_ICN_IMPROVE, + 0x1f); + /*Enable IRQ pull-up, disable SSM*/ + n_result |= + p_tas256x->write(p_tas256x, ch, + TAS256X_MISCCONFIGURATIONREG0, + 0xca); + /*Mask reaction of idle channel detect on IV sense*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_ICN_SW_REG, + 0x02); + } else { + /*Unlock test page*/ + n_result = + p_tas256x->write(p_tas256x, ch, TAS256X_TEST_PAGE_LOCK, + 0xd); + /*Keep DAC modulator dither to minimum*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_DAC_MODULATOR, + 0x00); + /*Force DAC unmute*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_DAC_MUTE, + 0x00); + /*Force the device in idle channel mode*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_ICN_MODE, + 0x10); + /* ICN improvement*/ + n_result |= + p_tas256x->write(p_tas256x, ch, TAS256X_ICN_IMPROVE, + 0x1d); + /*Enable IRQ pull-up, disable SSM*/ + n_result |= + p_tas256x->write(p_tas256x, ch, + TAS256X_MISCCONFIGURATIONREG0, + 0xcf); + /*Mask reaction of idle channel detect on IV sense*/ + n_result |= p_tas256x->update_bits(p_tas256x, ch, + TAS256X_ICN_SW_REG, + TAS256X_ICN_IVSENSE_MASK, + 0x00); + n_result |= + tas256x_icn_disable(p_tas256x, p_tas256x->icn_sw, ch); + } + + if (n_result == 0) + p_tas256x->devs[ch-1]->reciever_enable = enable; + + return n_result; +}
\ No newline at end of file diff --git a/asoc/kona.c b/asoc/kona.c index acf81a80..edacc1f8 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -4841,6 +4841,10 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, } } #endif +#if IS_ENABLED(CONFIG_SND_SOC_TAS256X) + if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_RX) + slots = 4; +#endif /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); @@ -4864,6 +4868,27 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, __func__, ret); goto end; } +#if IS_ENABLED(CONFIG_SND_SOC_TAS256X) + if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_RX) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, slot_mask, + slots, slot_width); + if (ret < 0) { + pr_err("%s: failed to set tdm tx slot for codec, err:%d\n", + __func__, ret); + goto end; + } + + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_DSP_A); + if (ret < 0) { + pr_err("%s: failed to set rx fmt for codec, err:%d\n", + __func__, ret); + goto end; + } + } +#endif } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { #if IS_ENABLED(CONFIG_SND_SOC_CS35L41) if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_TX) { @@ -4877,6 +4902,10 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, } } #endif +#if IS_ENABLED(CONFIG_SND_SOC_TAS256X) + if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_TX) + slots = 4; +#endif /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); @@ -4904,6 +4933,27 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, __func__, ret); goto end; } +#if IS_ENABLED(CONFIG_SND_SOC_TAS256X) + if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_TX) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, slot_mask, 0, + slots, slot_width); + if (ret < 0) { + pr_err("%s: failed to set tdm tx slot for codec, err:%d\n", + __func__, ret); + goto end; + } + + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_DSP_A); + if (ret < 0) { + pr_err("%s: failed to set rx fmt for codec, err:%d\n", + __func__, ret); + goto end; + } + } +#endif } else { ret = -EINVAL; pr_err("%s: invalid use case, err:%d\n", @@ -7425,7 +7475,7 @@ static struct snd_soc_dai_link msm_tdm_fe_dai_link[] = { .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", }, -#if IS_ENABLED(CONFIG_SND_SOC_CS35L41) +#if IS_ENABLED(CONFIG_SND_SOC_CS35L41) || IS_ENABLED(CONFIG_SND_SOC_TAS256X) { .name = "Quinary TDM TX 0 Hostless", .stream_name = "Quinary TDM TX 0 Hostless", diff --git a/asoc/msm-dai-fe.c b/asoc/msm-dai-fe.c index 6fce8798..667c7f8e 100644 --- a/asoc/msm-dai-fe.c +++ b/asoc/msm-dai-fe.c @@ -2105,7 +2105,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "QUIN_TDM_RX_0_HOSTLESS", .probe = fe_dai_probe, }, -#if IS_ENABLED(CONFIG_SND_SOC_CS35L41) +#if IS_ENABLED(CONFIG_SND_SOC_CS35L41) || IS_ENABLED(CONFIG_SND_SOC_TAS256X) { .capture = { .stream_name = "Quinary TDM0 Hostless Capture", diff --git a/config/litoauto.conf b/config/litoauto.conf index 25d8031f..0af06d24 100644 --- a/config/litoauto.conf +++ b/config/litoauto.conf @@ -42,3 +42,8 @@ CONFIG_SND_SOC_RT5514=m CONFIG_SND_SOC_RT5514_SPI=m CONFIG_MI2S_DISABLE=m CONFIG_AUXPCM_DISABLE=m +CONFIG_SND_SOC_TAS256X=m +CONFIG_TAS256X_MISC=y +CONFIG_PLATFORM_QCOM=y +CONFIG_TAS25XX_ALGO=y +CONFIG_TISA_KBIN_INTF=y diff --git a/config/litoautoconf.h b/config/litoautoconf.h index e0da4d17..cfd489c4 100644 --- a/config/litoautoconf.h +++ b/config/litoautoconf.h @@ -45,3 +45,12 @@ #define CONFIG_SND_SOC_RT5514 1 #define CONFIG_SND_SOC_RT5514_SPI 1 #define CONFIG_AUXPCM_DISABLE 1 +#define CONFIG_SND_SOC_TAS256X 1 +#define CONFIG_TAS256X_REGMAP 1 +#define CONFIG_TAS256X_CODEC 1 +#define CONFIG_TAS256X_MISC 1 +#define CONFIG_TAS256X_REGBIN_PARSER 1 +#define CONFIG_TAS25XX_ALGO 1 +#define CONFIG_PLATFORM_QCOM 1 +#define CONFIG_TISA_KBIN_INTF 1 +#define CONFIG_TAS25XX_ALGO_STEREO 1 diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 65796915..e7cba919 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -22,6 +22,19 @@ #include <ipc/apr_tal.h> #include "adsp_err.h" #include "q6afecal-hwdep.h" +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#include <dsp/tas_qualcomm.h> +#endif + +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +#ifdef INSTANCE_ID_0 /*APR Version 3*/ +static int32_t tas_smartamp_algo_callback(uint32_t opcode, uint32_t *payload, + uint32_t payload_size); +#else /*APR Version 2*/ +static int32_t tas_smartamp_algo_callback(uint32_t *payload, + uint32_t payload_size); +#endif /*INSTANCE_ID_0*/ +#endif /*CONFIG_TAS25XX_ALGO*/ #define WAKELOCK_TIMEOUT 5000 #define AFE_CLK_TOKEN 1024 @@ -247,6 +260,11 @@ struct afe_ctl { /* FTM spk params */ uint32_t initial_cal; uint32_t v_vali_flag; +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + struct afe_smartamp_calib_get_resp tas_calib_data; + uint32_t tas_module_rx; + uint32_t tas_module_tx; +#endif /*CONFIG_TAS25XX_ALGO*/ uint32_t num_spkrs; uint32_t cps_ch_mask; struct afe_cps_hw_intf_cfg *cps_config; @@ -945,9 +963,28 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) av_dev_drift_afe_cb_handler(data->opcode, data->payload, data->payload_size); } else { +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) + u32 *payload32 = data->payload; + pr_debug("TI-SmartPA: payload1 = 0x%x, 0x%x", payload32[0], payload32[1]); + + if ((payload32[1] == this_afe.tas_module_rx) || + (payload32[1] == this_afe.tas_module_tx)) { +#ifdef INSTANCE_ID_0 /*APR Version 3*/ + if (tas_smartamp_algo_callback(data->opcode, data->payload, data->payload_size)) + return -EINVAL; +#else /*APR Version 2*/ + if (tas_smartamp_algo_callback(data->payload, data->payload_size)) + return -EINVAL; +#endif /* INSTANCE_ID_0 */ + } else if (sp_make_afe_callback(data->opcode, data->payload, + data->payload_size)) { + return -EINVAL; + } +#else if (sp_make_afe_callback(data->opcode, data->payload, data->payload_size)) return -EINVAL; +#endif /*CONFIG_TAS25XX_ALGO*/ } if (afe_token_is_valid(data->token)) wake_up(&this_afe.wait[data->token]); @@ -6529,6 +6566,406 @@ int afe_start_pseudo_port(u16 port_id) return ret; } +#if IS_ENABLED(CONFIG_TAS25XX_ALGO) +/*For DC Detection*/ +void (*tas256x_sw_reset)(void *data); +dc_detection_data_t *s_dc_detect; +void register_tas256x_reset_func(void *fptr, dc_detection_data_t *data) +{ + pr_info("[TI-SmartPA:%s] ", __func__); + tas256x_sw_reset = fptr; + s_dc_detect = data; +} +EXPORT_SYMBOL(register_tas256x_reset_func); + +void afe_tas_smartamp_init(uint32_t module_id_rx, uint32_t module_id_tx) +{ + this_afe.tas_module_rx = module_id_rx; + this_afe.tas_module_tx = module_id_tx; +} +EXPORT_SYMBOL(afe_tas_smartamp_init); + +#ifdef INSTANCE_ID_0 /* APR Version 3 */ +static int32_t tas_smartamp_algo_callback(uint32_t opcode, uint32_t *payload, + uint32_t payload_size) +{ + struct param_hdr_v3 param_hdr; + u32 *data_dest = NULL; + u32 *data_start = NULL; + + pr_debug("[TI-SmartPA:%s] ", __func__); + memset(¶m_hdr, 0, sizeof(param_hdr)); + switch (opcode) { + case AFE_PORT_CMDRSP_GET_PARAM_V2: + param_hdr.module_id = payload[1]; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = payload[2]; + param_hdr.param_size = payload[3]; + data_start = &payload[4]; + break; + case AFE_PORT_CMDRSP_GET_PARAM_V3: + memcpy(¶m_hdr, &payload[1], sizeof(struct param_hdr_v3)); + data_start = &payload[5]; + break; + default: + pr_err("[TI-SmartPA:%s] Unrecognized command %d\n", __func__, opcode); + return -EINVAL; + } + data_dest = (u32 *) &this_afe.tas_calib_data; + data_dest[0] = payload[0]; + memcpy(&data_dest[1], ¶m_hdr, sizeof(struct param_hdr_v3)); + memcpy(&data_dest[5], data_start, param_hdr.param_size); + if (param_hdr.param_id == CAPI_V2_TAS_SA_DC_DETECT) { + pr_err("[TI-SmartPA:%s] Detected DC, Calling TAS256X Software Reset \n", __func__); + s_dc_detect->channel = this_afe.tas_calib_data.res_cfg.payload[0]; + tas256x_sw_reset(s_dc_detect); + } + if (!data_dest[0]) { + atomic_set(&this_afe.state, 0); + } else { + pr_debug("[TI-SmartPA:%s] status: %d", __func__, data_dest[0]); + atomic_set(&this_afe.state, -1); + } + return 0; +} + +int afe_tas_smartamp_get_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id) +{ + int ret = -EINVAL; + struct param_hdr_v3 param_hdr; + uint32_t port = 0x0; + + if (!data || length <= 0) { + pr_err("[TI-SmartPA:%s] Invalid params, length: %d\n", + __func__, length); + goto fail_cmd; + } + + pr_debug("[TI-SmartPA:%s] module id : 0x%x ", __func__, module_id); + if (module_id == this_afe.tas_module_rx) { + port = port_id; + } else if (module_id == this_afe.tas_module_tx) { + port = port_id + 1; + } else { + pr_err("[TI-SmartPA:%s] invalid module id %d\n", module_id); + goto fail_cmd; + } + + memset(¶m_hdr, 0, sizeof(param_hdr)); + param_hdr.module_id = module_id; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = param_id; + param_hdr.param_size = sizeof(struct afe_smartamp_get_calib); + ret = q6afe_get_params(port, NULL, ¶m_hdr); + if (ret < 0) { + pr_err("[TI-SmartPA:%s] get param port 0x%x param id[0x%x]failed %d\n", + __func__, port, param_hdr.param_id, ret); + goto fail_cmd; + } + + memcpy(data, &this_afe.tas_calib_data.res_cfg, length); + + ret = 0; +fail_cmd: + return ret; +} +EXPORT_SYMBOL(afe_tas_smartamp_get_calib_data); + +int afe_tas_smartamp_set_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id) +{ + int ret = -EINVAL; + uint32_t port = 0x0; + struct param_hdr_v3 param_hdr; + + u8 *packed_param_data = NULL; + u32 packed_param_size = 0; + u32 single_param_size = 0; + pr_debug("[TI-SmartPA:%s] length: %d\n", __func__, length); + if (!data || (length < 0)) { + pr_err("[TI-SmartPA:%s] Invalid params\n", __func__); + return ret; + } + + pr_debug("[TI-SmartPA:%s] module id : 0x%x \n", __func__, module_id); + if (module_id == this_afe.tas_module_rx) { + port = port_id; + } else if (module_id == this_afe.tas_module_tx) { + port = port_id + 1; + } else { + pr_err("[TI-SmartPA:%s] invalid module id %d\n", module_id); + return ret; + } + + packed_param_size = sizeof(param_hdr) + length; + packed_param_data = kzalloc(packed_param_size, GFP_KERNEL); + if (!packed_param_data) + return -ENOMEM; + + packed_param_size = 0; + param_hdr.module_id = module_id; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = param_id; + param_hdr.param_size = length; + ret = q6common_pack_pp_params(packed_param_data, ¶m_hdr, + (u8 *) data, &single_param_size); + if (ret) { + pr_err("[TI-SmartPA:%s] Failed to pack param data, error %d\n", __func__, + ret); + goto done; + } + packed_param_size += single_param_size; + ret = q6afe_set_params(port, q6audio_get_port_index(port), + NULL, packed_param_data, packed_param_size); +done: + kfree(packed_param_data); + return ret; +} +EXPORT_SYMBOL(afe_tas_smartamp_set_calib_data); + +#else /* APR Version 2 */ +static int32_t tas_smartamp_algo_callback(uint32_t *payload, uint32_t payload_size) +{ + struct afe_smartamp_calib_get_resp *resp = + (struct afe_smartamp_calib_get_resp *) payload; + + pr_debug("[TI-SmartPA:%s] callback\n", __func__); + + if (!(&(resp->pdata))) { + pr_err("[TI-SmartPA:%s] Error: resp pdata is NULL", __func__); + return -EINVAL; + } + + memcpy(&this_afe.tas_calib_data, payload, + sizeof(this_afe.tas_calib_data)); + + pr_debug("[TI-SmartPA:%s] callback, 0x%x\n", __func__, resp->pdata.param_id); + + if (resp->pdata.param_id == CAPI_V2_TAS_SA_DC_DETECT) { + s_dc_detect->channel = resp->res_cfg.payload[0]; + pr_err("[TI-SmartPA:%s] Detected DC, Calling TAS256X Software Reset Channel-%s\n", __func__, + (s_dc_detect->channel == 0)?"Left":"Right"); + tas256x_sw_reset(s_dc_detect); + } + + if (!this_afe.tas_calib_data.status) { + atomic_set(&this_afe.state, 0); + } else { + pr_debug("[TI-SmartPA:%s] calib resp status: %d", __func__, + this_afe.tas_calib_data.status); + atomic_set(&this_afe.state, -1); + } + + return 0; +} + +/* +* data is writable memroy +* length is the max size of the data +* retuns number of bytes returned by the algorithm +* -ve error number in case of failure. +*/ +int afe_tas_smartamp_get_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id) +{ + int ret = -EINVAL; + int index = 0; + struct afe_smartamp_get_calib calib_resp_o; + struct afe_smartamp_get_calib *calib_resp = &calib_resp_o; + + if (!data || (length <= 0)) { + pr_err("[TI-SmartPA: %s] Invalid params\n", __func__); + goto fail_cmd; + } + if ((q6audio_validate_port(port_id) < 0)) { + pr_err("%s invalid port %d\n", __func__, port_id); + goto fail_cmd; + } + + index = q6audio_get_port_index(port_id); + memset (calib_resp, 0, sizeof(*calib_resp)); + + //header + calib_resp->hdr.hdr_field = + APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + calib_resp->hdr.src_svc = APR_SVC_AFE; + calib_resp->hdr.src_domain = APR_DOMAIN_APPS; + calib_resp->hdr.dest_svc = APR_SVC_AFE; + calib_resp->hdr.dest_domain = APR_DOMAIN_ADSP; + calib_resp->hdr.pkt_size = sizeof(*calib_resp); + calib_resp->hdr.src_port = 0; + calib_resp->hdr.dest_port = 0; + calib_resp->hdr.token = index; + calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; + + //parameter + calib_resp->get_param.mem_map_handle = 0; + calib_resp->get_param.module_id = module_id; + calib_resp->get_param.param_id = param_id; + calib_resp->get_param.payload_address_lsw = 0; + calib_resp->get_param.payload_address_msw = 0; + calib_resp->get_param.payload_size = sizeof(*calib_resp) + - sizeof(calib_resp->hdr) + - sizeof(calib_resp->get_param); + calib_resp->get_param.port_id = q6audio_get_port_id(port_id); + + //data + calib_resp->pdata.module_id = module_id; + calib_resp->pdata.param_id = param_id; + calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg); + calib_resp->pdata.reserved = 0; + atomic_set(&this_afe.state, 1); + + ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp); + + if (ret < 0) { + pr_err("[TI-SmartPA %s]: get param port %d param id[0x%x]failed", + __func__, port_id, calib_resp->get_param.param_id); + goto fail_cmd; + } + + ret = wait_event_timeout(this_afe.wait[index], + (atomic_read(&this_afe.state) == 0), + msecs_to_jiffies(TIMEOUT_MS * 5)); + if (!ret) { + pr_err("[TI-SmartPA %s]: wait_event timeout", __func__); + ret = -EINVAL; + goto fail_cmd; + } + if (atomic_read(&this_afe.status) != 0) { + pr_err("[TI-SmartPA %s]: config cmd failed", __func__); + ret = -EINVAL; + goto fail_cmd; + } + + if (length <= sizeof (this_afe.tas_calib_data.res_cfg)) { + memcpy(data, &this_afe.tas_calib_data.res_cfg, length); + ret = 0; + } else { + ret = -EINVAL; + memcpy(data, &this_afe.tas_calib_data.res_cfg, length); + } + pr_debug("[TI-SmartPA: %s] ret=%d", __func__, ret); + +fail_cmd: + return ret; +} +EXPORT_SYMBOL(afe_tas_smartamp_get_calib_data); + +/* +* length -> length in bytes of 'data' +*/ +int afe_tas_smartamp_set_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id) +{ + int ret = -EINVAL; + int index = 0; + struct afe_smartamp_config_command *config = NULL; + u8 *cfg = NULL; + + int size = sizeof(struct afe_smartamp_config_command) + - sizeof(struct afe_smartamp_get_set_params_t) + + length; + if (!data) { + pr_err("[TI-SmartPA:%s] Invalid params\n", __func__); + goto fail_cmd; + } + + cfg = kzalloc(size, GFP_KERNEL); + if (!cfg) { + pr_err("[TI-SmartPA:%s] memory allocation failed\n", __func__); + ret = -ENOMEM; + goto fail_cmd; + } + + config = (struct afe_smartamp_config_command *)cfg; + if (module_id == this_afe.tas_module_rx) { + port_id = port_id; + } else if (module_id == this_afe.tas_module_tx) { + port_id = port_id + 1; + } else { + pr_err("[TI-SmartPA: %s] invalid module id %d", __func__, module_id); + goto fail_cmd; + } + + if ((q6audio_validate_port(port_id) < 0)) { + pr_err("[TI-SmartPA: %s] invalid port %d", __func__, port_id); + goto fail_cmd; + } + + index = q6audio_get_port_index(port_id); + + //header + config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + config->hdr.pkt_size = sizeof(struct afe_smartamp_config_command) + - sizeof(struct afe_smartamp_get_set_params_t) + + length; + config->hdr.src_port = 0; + config->hdr.dest_port = 0; + config->hdr.token = index; + config->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; + + //param + config->param.port_id = q6audio_get_port_id(port_id); + config->param.payload_size = sizeof(struct afe_smartamp_config_command) + - sizeof(struct apr_hdr) + - sizeof(struct afe_port_cmd_set_param_v2) + - sizeof(struct afe_smartamp_get_set_params_t) + + length; + + //data + config->pdata.module_id = module_id; + config->pdata.param_id = param_id; + config->pdata.param_size = length; //should be same as + /* + sizeof(struct afe_smartamp_config_command) + - sizeof(struct apr_hdr) + - sizeof(struct afe_port_cmd_set_param_v2) + - sizeof(struct afe_port_param_data_v2); + */ + + //access payload pointer + cfg += (size - length); + memcpy(cfg, data, length); + atomic_set(&this_afe.state, 1); + ret = apr_send_pkt(this_afe.apr, (uint32_t *) config); + + if (ret < 0) { + pr_err("[TI-SmartPA %s]: Setting param for port %d param[0x%x]failed\n", + __func__, port_id, param_id); + goto fail_cmd; + } + + ret = wait_event_timeout(this_afe.wait[index], + (atomic_read(&this_afe.state) == 0), + msecs_to_jiffies(TIMEOUT_MS*10)); + if (!ret) { + pr_err("[TI-SmartPA %s]: wait_event timeout\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + if (atomic_read(&this_afe.status) != 0) { + pr_err("[TI-SmartPA %s]: config cmd failed\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + ret = 0; + +fail_cmd: + pr_debug("[TI-SmartPA %s]: config->pdata.param_id %x status %d\n", + __func__, config->pdata.param_id, ret); + + kfree(config); + + return ret; +} +EXPORT_SYMBOL(afe_tas_smartamp_set_calib_data); +#endif /* INSTANCE_ID_0 */ +#endif /*CONFIG_TAS25XX_ALGO*/ + int afe_pseudo_port_stop_nowait(u16 port_id) { int ret = 0; diff --git a/include/dsp/tas_qualcomm.h b/include/dsp/tas_qualcomm.h new file mode 100644 index 00000000..e08f6505 --- /dev/null +++ b/include/dsp/tas_qualcomm.h @@ -0,0 +1,69 @@ +/* + * TAS256X Algorithm Support + * Qualcomm Platform Support File + * + * Author: Vijeth P O + * Date: 21-05-20 + */ + +#ifndef __TAS_QUALCOMM__ +#define __TAS_QUALCOMM__ + +#include <dsp/apr_audio-v2.h> + +/*Added for DC Detection*/ +#define CAPI_V2_TAS_SA_DC_DETECT 0x40404040 + +#define TAS_PAYLOAD_SIZE 14 + +struct afe_smartamp_get_set_params_t { + uint32_t payload[TAS_PAYLOAD_SIZE]; +} __packed; + +#ifdef INSTANCE_ID_0 +struct afe_smartamp_get_calib { + struct apr_hdr hdr; + struct mem_mapping_hdr mem_hdr; + struct param_hdr_v3 pdata; + struct afe_smartamp_get_set_params_t res_cfg; +} __packed; + +struct afe_smartamp_calib_get_resp { + uint32_t status; + struct param_hdr_v3 pdata; + struct afe_smartamp_get_set_params_t res_cfg; +} __packed; +#else +struct afe_smartamp_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + struct afe_smartamp_get_set_params_t prot_config; +} __packed; + +struct afe_smartamp_get_calib { + struct apr_hdr hdr; + struct afe_port_cmd_get_param_v2 get_param; + struct afe_port_param_data_v2 pdata; + struct afe_smartamp_get_set_params_t res_cfg; +} __packed; + +struct afe_smartamp_calib_get_resp { + uint32_t status; + struct afe_port_param_data_v2 pdata; + struct afe_smartamp_get_set_params_t res_cfg; +} __packed; +#endif /*APR_VERSION_V3*/ + +typedef struct { + int channel; +} dc_detection_data_t; + +void register_tas256x_reset_func(void *fptr, dc_detection_data_t *data); +void afe_tas_smartamp_init(uint32_t rx_module_id, uint32_t tx_module_id); +int afe_tas_smartamp_get_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id); +int afe_tas_smartamp_set_calib_data(uint32_t module_id, uint32_t param_id, + int32_t length, uint8_t *data, uint16_t port_id); + +#endif /*__TAS_QUALCOMM__*/ |