From 42c96a8ee542cbbe894d1a275bf42d95e40bc5cf Mon Sep 17 00:00:00 2001 From: William Liu Date: Tue, 29 Aug 2023 14:51:46 +0800 Subject: [PATCH] Initial t(CR) driver bringup Integrate the t(CR) driver from awinic to support the new vibrator features Change-Id: If32088e4b63c149e39555de8cde85de9acc5d137 Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2723567 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Wei Deng Reviewed-on: https://gerrit.mot.com/2748055 Reviewed-by: Xiangpo Zhao --- .../awinic/aw862x_haptic_nv_v1/Android.mk | 12 + .../misc/awinic/aw862x_haptic_nv_v1/Kbuild | 14 + .../misc/awinic/aw862x_haptic_nv_v1/Makefile | 14 + .../misc/awinic/aw862x_haptic_nv_v1/aw8623x.c | 1439 +++++++ .../misc/awinic/aw862x_haptic_nv_v1/aw8624x.c | 1392 ++++++ .../misc/awinic/aw862x_haptic_nv_v1/aw862x.c | 1392 ++++++ .../misc/awinic/aw862x_haptic_nv_v1/aw862xx.c | 1444 +++++++ .../awinic/aw862x_haptic_nv_v1/haptic_nv.c | 3813 +++++++++++++++++ .../awinic/aw862x_haptic_nv_v1/haptic_nv.h | 705 +++ .../aw862x_haptic_nv_v1/haptic_nv_reg.h | 1990 +++++++++ 10 files changed, 12215 insertions(+) create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/Android.mk create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/Kbuild create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/Makefile create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/aw8623x.c create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/aw8624x.c create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/aw862x.c create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.h create mode 100644 drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv_reg.h diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/Android.mk b/drivers/misc/awinic/aw862x_haptic_nv_v1/Android.mk new file mode 100644 index 000000000000..3d11361ad3fb --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/Android.mk @@ -0,0 +1,12 @@ +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := aw862x_haptic_nv_v1.ko +LOCAL_MODULE_TAGS := optional +ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true) +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/ +else +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +endif +include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/Kbuild b/drivers/misc/awinic/aw862x_haptic_nv_v1/Kbuild new file mode 100644 index 000000000000..3e3ac01952dc --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/Kbuild @@ -0,0 +1,14 @@ +# add -Wall to try to catch everything we can. +EXTRA_CFLAGS += -Wall +EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \ + -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/misc/awinic/aw862x_haptic_nv_v1 + +obj-m += aw862x_haptic_nv_v1.o + +aw862x_haptic_nv_v1-objs += haptic_nv.o +aw862x_haptic_nv_v1-objs += aw862x.o +aw862x_haptic_nv_v1-objs += aw8623x.o +aw862x_haptic_nv_v1-objs += aw8624x.o +aw862x_haptic_nv_v1-objs += aw862xx.o + + diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/Makefile b/drivers/misc/awinic/aw862x_haptic_nv_v1/Makefile new file mode 100644 index 000000000000..bfbdc14740ef --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/Makefile @@ -0,0 +1,14 @@ +all: modules + +modules: + $(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install + +%: + $(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS) + +clean: + rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers + rm -rf .tmp_versions diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8623x.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8623x.c new file mode 100644 index 000000000000..d5247f07c856 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8623x.c @@ -0,0 +1,1439 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * aw8623x.c + * + * Copyright (c) 2022 AWINIC Technology CO., LTD + * + * Author: + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "haptic_nv.h" +#include "haptic_nv_reg.h" + +static void aw8623x_interrupt_setup(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("reg SYSINT=0x%02X", reg_val); + /* edge int mode */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL3, AW8623X_BIT_SYSCTRL3_INTMODE_MASK, + AW8623X_BIT_SYSCTRL3_INTMODE_POS_EDGE); + /* int enable */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSINTM, + (AW8623X_BIT_SYSINTM_UVLM_MASK & AW8623X_BIT_SYSINTM_FF_AEM_MASK & + AW8623X_BIT_SYSINTM_FF_AFM_MASK & AW8623X_BIT_SYSINTM_OCDM_MASK & + AW8623X_BIT_SYSINTM_OTM_MASK & AW8623X_BIT_SYSINTM_DONEM_MASK), + (AW8623X_BIT_SYSINTM_UVLM_ON | AW8623X_BIT_SYSINTM_FF_AEM_OFF | + AW8623X_BIT_SYSINTM_FF_AFM_OFF | AW8623X_BIT_SYSINTM_OCDM_ON | + AW8623X_BIT_SYSINTM_OTM_ON | AW8623X_BIT_SYSINTM_DONEM_OFF)); +} + +static void aw8623x_set_rtp_data(struct aw_haptic *aw_haptic, uint8_t *data, uint32_t len) +{ + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_RTPDATA, data, len); +} + +static uint8_t aw8623x_get_glb_state(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_GLBRD5, &state, AW_I2C_BYTE_ONE); + + return state; +} + +static int aw8623x_get_irq_state(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + int ret = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_dbg("reg SYSINT=0x%02X", reg_val); + if (reg_val & AW8623X_BIT_SYSINT_UVLI) + aw_err("chip uvlo int error"); + if (reg_val & AW8623X_BIT_SYSINT_OCDI) + aw_err("chip over current int error"); + if (reg_val & AW8623X_BIT_SYSINT_OTI) + aw_err("chip over temperature int error"); + if (reg_val & AW8623X_BIT_SYSINT_DONEI) + aw_info("chip playback done"); + if (reg_val & AW8623X_BIT_SYSINT_FF_AFI) + aw_info("rtp mode fifo almost full!"); + if (reg_val & AW8623X_BIT_SYSINT_FF_AEI) { + aw_info("rtp fifo almost empty"); + ret = AW_IRQ_ALMOST_EMPTY; + } + + return ret; +} + +static uint8_t aw8623x_rtp_get_fifo_afs(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW8623X_BIT_SYSST_FF_AFS; + reg_val = reg_val >> 3; + + return reg_val; +} + +static uint8_t aw8623x_rtp_get_fifo_aes(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW8623X_BIT_SYSST_FF_AES; + reg_val = reg_val >> 4; + + return reg_val; +} + +static void aw8623x_set_rtp_aei(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSINTM, + AW8623X_BIT_SYSINTM_FF_AEM_MASK, + AW8623X_BIT_SYSINTM_FF_AEM_ON); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSINTM, + AW8623X_BIT_SYSINTM_FF_AEM_MASK, + AW8623X_BIT_SYSINTM_FF_AEM_OFF); + } +} + +static void aw8623x_sram_size(struct aw_haptic *aw_haptic, uint8_t size_flag) +{ + switch (size_flag) { + case AW8623X_HAPTIC_SRAM_1K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_DIS); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + break; + case AW8623X_HAPTIC_SRAM_2K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_DIS); + break; + case AW8623X_HAPTIC_SRAM_3K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + break; + default: + aw_err("size_flag is error"); + break; + } +} + +static void aw8623x_auto_brk_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8623X_BIT_PLAYCFG3_BRK_ENABLE); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8623X_BIT_PLAYCFG3_BRK_DISABLE); + } +} + +static void aw8623x_play_stop(struct aw_haptic *aw_haptic) +{ + bool force_flag = true; + uint8_t val = 0; + int cnt = 40; + + aw_haptic->play_mode = AW_STANDBY_MODE; + val = AW8623X_BIT_PLAYCFG4_STOP_ON; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_GLBRD5, &val, AW_I2C_BYTE_ONE); + if ((val & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + force_flag = false; + aw_info("entered standby! glb_state=0x%02X", val); + break; + } + cnt--; + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + } + if (force_flag) { + aw_err("force to enter standby mode!"); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL2, + AW8623X_BIT_SYSCTRL2_STANDBY_MASK, + AW8623X_BIT_SYSCTRL2_STANDBY_ON); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL2, + AW8623X_BIT_SYSCTRL2_STANDBY_MASK, + AW8623X_BIT_SYSCTRL2_STANDBY_OFF); + } +} + +static void aw8623x_set_pwm(struct aw_haptic *aw_haptic, uint8_t mode) +{ + switch (mode) { + case AW_PWM_48K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL2, + AW8623X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8623X_BIT_SYSCTRL2_RATE_48K); + break; + case AW_PWM_24K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL2, + AW8623X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8623X_BIT_SYSCTRL2_RATE_24K); + break; + case AW_PWM_12K: + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL2, + AW8623X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8623X_BIT_SYSCTRL2_RATE_12K); + break; + default: + break; + } +} + +static void aw8623x_vbat_mode_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + aw_info("enter"); + if (flag == AW_CONT_VBAT_HW_COMP_MODE) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_VBATCTRL, + AW8623X_BIT_VBATCTRL_VBAT_MODE_MASK, + AW8623X_BIT_VBATCTRL_VBAT_MODE_HW); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_VBATCTRL, + AW8623X_BIT_VBATCTRL_VBAT_MODE_MASK, + AW8623X_BIT_VBATCTRL_VBAT_MODE_SW); + } +} + +static void aw8623x_play_mode(struct aw_haptic *aw_haptic, uint8_t play_mode) +{ + switch (play_mode) { + case AW_STANDBY_MODE: + aw_info("enter standby mode"); + aw_haptic->play_mode = AW_STANDBY_MODE; + aw8623x_play_stop(aw_haptic); + break; + case AW_RAM_MODE: + aw_info("enter ram mode"); + aw_haptic->play_mode = AW_RAM_MODE; + aw8623x_vbat_mode_config(aw_haptic, AW_CONT_VBAT_SW_COMP_MODE); + aw8623x_set_pwm(aw_haptic, AW_PWM_12K); + aw8623x_auto_brk_config(aw_haptic, false); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_RAM_LOOP_MODE: + aw_info("enter ram loop mode"); + aw_haptic->play_mode = AW_RAM_LOOP_MODE; + aw8623x_vbat_mode_config(aw_haptic, AW_CONT_VBAT_SW_COMP_MODE); + aw8623x_set_pwm(aw_haptic, AW_PWM_12K); + aw8623x_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_CONT_MODE: + aw_info("enter cont mode"); + aw_haptic->play_mode = AW_CONT_MODE; + aw8623x_vbat_mode_config(aw_haptic, AW_CONT_VBAT_HW_COMP_MODE); + aw8623x_auto_brk_config(aw_haptic, aw_haptic->info.is_enabled_auto_brk); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_CONT); + break; + case AW_RTP_MODE: + aw_info("enter rtp mode"); + aw_haptic->play_mode = AW_RTP_MODE; + aw8623x_vbat_mode_config(aw_haptic, AW_CONT_VBAT_SW_COMP_MODE); + aw8623x_set_pwm(aw_haptic, AW_PWM_24K); + aw8623x_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_RTP); + break; + case AW_TRIG_MODE: + aw_info("enter trig mode"); + aw_haptic->play_mode = AW_TRIG_MODE; + aw8623x_set_pwm(aw_haptic, AW_PWM_12K); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8623X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + default: + aw_err("play mode %u error", play_mode); + break; + } +} + +static void aw8623x_irq_clear(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSINT, &val, AW_I2C_BYTE_ONE); + aw_info("SYSINT=0x%02X", val); +} + +static void aw8623x_play_go(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + + aw_info("enter"); + val = AW8623X_BIT_PLAYCFG4_GO_ON; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + usleep_range(AW_PLAY_DELAY_MIN, AW_PLAY_DELAY_MAX); +} + +static void aw8623x_raminit(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_RAMINIT_MASK, + AW8623X_BIT_SYSCTRL1_RAMINIT_ON); + usleep_range(1000, 1050); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_RAMINIT_MASK, + AW8623X_BIT_SYSCTRL1_RAMINIT_OFF); + } +} + +static int aw8623x_select_d2s_gain(uint8_t reg) +{ + int d2s_gain = 0; + + switch (reg) { + case AW8623X_BIT_DETCFG2_D2S_GAIN_1: + d2s_gain = 1; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_2: + d2s_gain = 2; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_4: + d2s_gain = 4; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_5: + d2s_gain = 5; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_8: + d2s_gain = 8; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_10: + d2s_gain = 10; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_20: + d2s_gain = 20; + break; + case AW8623X_BIT_DETCFG2_D2S_GAIN_40: + d2s_gain = 40; + break; + default: + d2s_gain = -1; + break; + } + + return d2s_gain; +} + +static void aw8623x_get_vbat(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val[2] = {0}; + uint32_t vbat_code = 0; + + aw_info("enter"); + aw8623x_play_stop(aw_haptic); + aw8623x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG2, AW8623X_BIT_DETCFG2_DET_SEQ0_MASK, + AW8623X_BIT_DETCFG2_DET_SEQ0_VBAT); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_ON); + usleep_range(3000, 3500); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_OFF); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETRD1, reg_val, AW_I2C_BYTE_TWO); + vbat_code = reg_val[0] & (~AW8623X_BIT_DETRD1_AVG_DATA_H_MASK); + vbat_code = (vbat_code << 8) | reg_val[1]; + aw_haptic->vbat = AW8623X_VBAT_FORMULA(vbat_code); + if (aw_haptic->vbat > AW_VBAT_MAX) { + aw_haptic->vbat = AW_VBAT_MAX; + aw_info("vbat max limit = %dmV", aw_haptic->vbat); + } + if (aw_haptic->vbat < AW_VBAT_MIN) { + aw_haptic->vbat = AW_VBAT_MIN; + aw_info("vbat min limit = %dmV", aw_haptic->vbat); + } + aw_info("vbat=%dmV, vbat_code=0x%02X", aw_haptic->vbat, vbat_code); + aw8623x_raminit(aw_haptic, false); +} + +static void aw8623x_set_gain(struct aw_haptic *aw_haptic, uint8_t gain) +{ + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_PLAYCFG2, &gain, AW_I2C_BYTE_ONE); +} + +static void aw8623x_set_trim_lra(struct aw_haptic *aw_haptic, uint8_t val) +{ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_TRIMCFG2, + AW8623X_BIT_TRIMCFG2_TRIM_LRA_MASK, val); +} + +static void aw8623x_cont_config(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + /* work mode */ + aw8623x_play_mode(aw_haptic, AW_CONT_MODE); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG6, + (AW8623X_BIT_CONTCFG6_TRACK_EN_MASK & + AW8623X_BIT_CONTCFG6_DRV1_LVL_MASK), + ((aw_haptic->info.is_enabled_track_en << 7) | + (uint8_t)aw_haptic->info.cont_drv1_lvl)); + reg_val = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG7, ®_val, AW_I2C_BYTE_ONE); + /* DRV2_TIME */ + reg_val = 0xFF; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG9, ®_val, AW_I2C_BYTE_ONE); + /* cont play go */ + aw8623x_play_go(aw_haptic); +} + +static ssize_t aw8623x_get_reg(struct aw_haptic *aw_haptic, ssize_t len, char *buf) +{ + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8623X_REG_RSTCFG, + AW8623X_REG_RTPDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8623X_REG_RTPDATA + 1, + AW8623X_REG_RAMDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8623X_REG_RAMDATA + 1, + AW8623X_REG_ANACFG10); + return len; +} + +static void aw8623x_protect_config(struct aw_haptic *aw_haptic, uint8_t prtime, uint8_t prlvl) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PWMCFG1, AW8623X_BIT_PWMCFG1_PRC_EN_MASK, + AW8623X_BIT_PWMCFG1_PRC_DISABLE); + if (prlvl != 0) { + /* Enable protection mode */ + aw_info("enable protection mode"); + reg_val = AW8623X_BIT_PWMCFG3_PR_ENABLE | + (prlvl & (~AW8623X_BIT_PWMCFG3_PRLVL_MASK)); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_PWMCFG4, &prtime, AW_I2C_BYTE_ONE); + } else { + /* Disable */ + aw_info("disable protection mode"); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PWMCFG3, + AW8623X_BIT_PWMCFG3_PR_EN_MASK, + AW8623X_BIT_PWMCFG3_PR_DISABLE); + } +} + +static void aw8623x_misc_para_init(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + uint8_t array[8] = {0}; + + aw_info("enter"); + /* Get seq and gain */ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_WAVCFG1, &val, AW_I2C_BYTE_ONE); + aw_haptic->index = val & AW8623X_BIT_WAVCFG_SEQ; + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_PLAYCFG2, &val, AW_I2C_BYTE_ONE); + aw_haptic->gain = val; + aw_info("gain=0x%02X, index=0x%02X", aw_haptic->gain, aw_haptic->index); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_WAVCFG1, array, AW_SEQUENCER_SIZE); + memcpy(aw_haptic->seq, array, AW_SEQUENCER_SIZE); + /* GAIN_BYPASS config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_GAIN_BYPASS_MASK, + aw_haptic->info.gain_bypass << 3); + /* Open the input OVP function of ADC */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_ANACFG3, + AW8623X_BIT_ANACFG3_EN_OVP_SAR_MASK, + AW8623X_BIT_ANACFG3_EN_OVP_SAR_ENABLE); + + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_TRIG1_MODE_MASK, + AW8623X_BIT_SYSCTRL1_TRIG1_TRIG); + + if (aw_haptic->info.d2s_gain) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG2, + AW8623X_BIT_DETCFG2_D2S_GAIN_MASK, + aw_haptic->info.d2s_gain); + } + + if (aw_haptic->info.cont_brk_time) { + val = (uint8_t)aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG10, &val, AW_I2C_BYTE_ONE); + } + + if (aw_haptic->info.cont_brk_gain) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG5, + AW8623X_BIT_CONTCFG5_BRK_GAIN_MASK, + aw_haptic->info.cont_brk_gain); + } + + aw_haptic->info.cont_drv2_lvl = AW8623X_DRV2_LVL_FORMULA( + aw_haptic->info.f0_pre, aw_haptic->info.lra_vrms); + if (aw_haptic->info.cont_drv2_lvl > AW8623X_DRV2_LVL_MAX) + aw_haptic->info.cont_drv2_lvl = AW8623X_DRV2_LVL_MAX; + + aw8623x_sram_size(aw_haptic, AW8623X_HAPTIC_SRAM_3K); + aw8623x_set_pwm(aw_haptic, AW_PWM_12K); + aw8623x_protect_config(aw_haptic, AW8623X_PWMCFG4_PRTIME_DEFAULT_VALUE, + AW8623X_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE); +} + +static int aw8623x_offset_cali(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val[2] = {0}; + int os_code = 0; + int d2s_gain = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETCFG2, reg_val, AW_I2C_BYTE_ONE); + reg_val[0] = (~AW8623X_BIT_DETCFG2_D2S_GAIN_MASK) & reg_val[0]; + d2s_gain = aw8623x_select_d2s_gain(reg_val[0]); + if (d2s_gain < 0) { + aw_err("d2s_gain is error"); + return -ERANGE; + } + aw8623x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG2, AW8623X_BIT_DETCFG2_DET_SEQ0_MASK, + AW8623X_BIT_DETCFG2_DET_SEQ0_OS); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_ON); + usleep_range(3000, 3500); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_OFF); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETRD1, reg_val, AW_I2C_BYTE_TWO); + aw8623x_raminit(aw_haptic, false); + os_code = reg_val[0] & (~AW8623X_BIT_DETRD1_AVG_DATA_H_MASK); + os_code = (os_code << 8) | reg_val[1]; + os_code = AW8623X_OS_FORMULA(os_code, d2s_gain); + aw_info("os_code is %d mV", os_code); + if (os_code > 15 || os_code < -15) + return -ERANGE; + + return 0; +} + +static void aw8623x_calculate_cali_data(struct aw_haptic *aw_haptic) +{ + char f0_cali_lra = 0; + int f0_cali_step = 0; + + f0_cali_step = 100000 * ((int)aw_haptic->f0 - (int)aw_haptic->info.f0_pre) / + ((int)aw_haptic->info.f0_pre * AW8623X_F0_CALI_ACCURACY); + aw_info("f0_cali_step=%d", f0_cali_step); + if (f0_cali_step >= 0) { /*f0_cali_step >= 0 */ + if (f0_cali_step % 10 >= 5) + f0_cali_step = 32 + (f0_cali_step / 10 + 1); + else + f0_cali_step = 32 + f0_cali_step / 10; + } else { /* f0_cali_step < 0 */ + if (f0_cali_step % 10 <= -5) + f0_cali_step = 32 + (f0_cali_step / 10 - 1); + else + f0_cali_step = 32 + f0_cali_step / 10; + } + if (f0_cali_step > 31) + f0_cali_lra = (char)f0_cali_step - 32; + else + f0_cali_lra = (char)f0_cali_step + 32; + /* update cali step */ + aw_haptic->f0_cali_data = (int)f0_cali_lra; + aw_info("f0_cali_data=0x%02X", aw_haptic->f0_cali_data); +} + +static void aw8623x_read_cont_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_CONTRD16, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_err("didn't get cont f0 because f0_reg value is 0!"); + aw_haptic->cont_f0 = 0; + return; + } + f0_tmp = AW8623X_F0_FORMULA(f0_reg); + aw_haptic->cont_f0 = (uint32_t)f0_tmp; + aw_info("cont_f0=%u", aw_haptic->cont_f0); +} + +static int aw8623x_read_lra_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + aw_info("enter"); + /* F_LRA_F0 */ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_CONTRD14, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_haptic->f0 = 0; + aw_err("didn't get lra f0 because f0_reg value is 0!"); + return -ERANGE; + } + f0_tmp = AW8623X_F0_FORMULA(f0_reg); + aw_haptic->f0 = (uint32_t)f0_tmp; + aw_info("lra_f0=%u", aw_haptic->f0); + + return 0; +} + +static int aw8623x_get_f0(struct aw_haptic *aw_haptic) +{ + bool get_f0_flag = false; + uint8_t brk_en_temp = 0; + uint8_t val[3] = {0}; + int drv_width = 0; + int cnt = 200; + int ret = 0; + + aw_info("enter"); + aw_haptic->f0 = aw_haptic->info.f0_pre; + /* enter standby mode */ + aw8623x_play_stop(aw_haptic); + /* f0 calibrate work mode */ + aw8623x_play_mode(aw_haptic, AW_CONT_MODE); + /* enable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG1, + AW8623X_BIT_CONTCFG1_EN_F0_DET_MASK, + AW8623X_BIT_CONTCFG1_F0_DET_ENABLE); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG6, + AW8623X_BIT_CONTCFG6_TRACK_EN_MASK, + (aw_haptic->info.is_enabled_track_en << 7)); + /* enable auto brake */ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_PLAYCFG3, &val[0], AW_I2C_BYTE_ONE); + brk_en_temp = AW8623X_BIT_PLAYCFG3_BRK & val[0]; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, AW8623X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8623X_BIT_PLAYCFG3_BRK_ENABLE); + /* f0 driver level */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG6, + AW8623X_BIT_CONTCFG6_DRV1_LVL_MASK, aw_haptic->info.cont_drv1_lvl); + val[0] = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG7, + AW8623X_BIT_CONTCFG7_DRV2_LVL_MASK, val[0]); + val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG8, val, AW_I2C_BYTE_TWO); + /* TRACK_MARGIN */ + if (!aw_haptic->info.cont_track_margin) { + aw_err("dts_info.cont_track_margin = 0!"); + } else { + val[0] = (uint8_t)aw_haptic->info.cont_track_margin; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG11, &val[0], AW_I2C_BYTE_ONE); + } + /* DRV_WIDTH */ + if (!aw_haptic->info.f0_pre) + return -ERANGE; + drv_width = AW8623X_DRV_WIDTH_FORMULA(aw_haptic->info.f0_pre, + aw_haptic->info.cont_track_margin, + aw_haptic->info.cont_brk_gain); + if (drv_width < AW_DRV_WIDTH_MIN) + drv_width = AW_DRV_WIDTH_MIN; + if (drv_width > AW_DRV_WIDTH_MAX) + drv_width = AW_DRV_WIDTH_MAX; + val[0] = (uint8_t)drv_width; + aw_info("cont_drv_width=0x%02X", val[0]); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG3, &val[0], AW_I2C_BYTE_ONE); + /* cont play go */ + aw8623x_play_go(aw_haptic); + usleep_range(20000, 20500); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_GLBRD5, &val[0], AW_I2C_BYTE_ONE); + if ((val[0] & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + get_f0_flag = true; + aw_info("entered standby! glb_state=0x%02X", val[0]); + break; + } + cnt--; + usleep_range(AW_F0_DELAY_MIN, AW_F0_DELAY_MAX); + } + if (get_f0_flag) { + ret = aw8623x_read_lra_f0(aw_haptic); + if (ret < 0) + aw_err("read lra f0 is failed"); + aw8623x_read_cont_f0(aw_haptic); + } else { + ret = -ERANGE; + aw_err("enter standby mode failed, stop reading f0!"); + } + /* disable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG1, + AW8623X_BIT_CONTCFG1_EN_F0_DET_MASK, + AW8623X_BIT_CONTCFG1_F0_DET_DISABLE); + /* recover auto break config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_PLAYCFG3, + AW8623X_BIT_PLAYCFG3_BRK_EN_MASK, brk_en_temp); + + return ret; +} + +static void aw8623x_set_base_addr(struct aw_haptic *aw_haptic) +{ + uint32_t base_addr = 0; + uint8_t val = 0; + + aw_info("enter"); + base_addr = aw_haptic->ram.base_addr; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG1, AW8623X_BIT_RTPCFG1_ADDRH_MASK, + (uint8_t)AW_SET_BASEADDR_H(base_addr)); + val = (uint8_t)AW_SET_BASEADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_RTPCFG2, &val, AW_I2C_BYTE_ONE); +} + +static void aw8623x_set_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t val[3] = {0}; + + aw_info("enter"); + ae_addr_h = (uint8_t)AW8623X_SET_AEADDR_H(aw_haptic->ram.base_addr); + af_addr_h = (uint8_t)AW8623X_SET_AFADDR_H(aw_haptic->ram.base_addr); + val[0] = ae_addr_h | af_addr_h; + val[1] = (uint8_t)AW8623X_SET_AEADDR_L(aw_haptic->ram.base_addr); + val[2] = (uint8_t)AW8623X_SET_AFADDR_L(aw_haptic->ram.base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); +} + +static void aw8623x_get_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t ae_addr_l = 0; + uint8_t af_addr_l = 0; + uint8_t val[3] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); + ae_addr_h = ((val[0]) & AW8623X_BIT_RTPCFG3_FIFO_AEH) >> 4; + ae_addr_l = val[1]; + af_addr_h = ((val[0]) & AW8623X_BIT_RTPCFG3_FIFO_AFH); + af_addr_l = val[2]; + aw_info("almost_empty_threshold = %u,almost_full_threshold = %u", + (uint16_t)((ae_addr_h << 8) | ae_addr_l), + (uint16_t)((af_addr_h << 8) | af_addr_l)); +} + +static void aw8623x_set_ram_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + val[0] = (uint8_t)AW_SET_RAMADDR_H(base_addr); + val[1] = (uint8_t)AW_SET_RAMADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_RAMADDRH, val, AW_I2C_BYTE_TWO); +} + +static void aw8623x_set_ram_data(struct aw_haptic *aw_haptic, uint8_t *data, int len) +{ + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_RAMDATA, data, len); +} + +static void aw8623x_get_first_wave_addr(struct aw_haptic *aw_haptic, uint32_t *first_wave_addr) +{ + uint8_t val[3] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_RAMDATA, val, AW_I2C_BYTE_THREE); + *first_wave_addr = (val[1] << 8 | val[2]); +} + +static void aw8623x_select_pin(struct aw_haptic *aw_haptic, uint8_t pin) +{ + if (pin == AW_TRIG1) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_INTN_PIN_MASK, + AW8623X_BIT_SYSCTRL1_TRIG1); + aw_info("TRIG1 pin used as TRIG1"); + } else if (pin == AW_IRQ) { + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_SYSCTRL1, + AW8623X_BIT_SYSCTRL1_INTN_PIN_MASK, + AW8623X_BIT_SYSCTRL1_INTN); + aw_info("TRIG1 pin used as INIT"); + } else { + aw_err("There is no such option"); + } +} + +static void aw8623x_trig_param_init(struct aw_haptic *aw_haptic, uint8_t pin) +{ + struct aw_haptic_dts_info info = aw_haptic->info; + + switch (pin) { + case AW_TRIG1: + aw_haptic->trig[0].trig_level = info.trig_cfg[0]; + aw_haptic->trig[0].trig_polar = info.trig_cfg[1]; + aw_haptic->trig[0].pos_enable = info.trig_cfg[2]; + aw_haptic->trig[0].pos_sequence = info.trig_cfg[3]; + aw_haptic->trig[0].neg_enable = info.trig_cfg[4]; + aw_haptic->trig[0].neg_sequence = info.trig_cfg[5]; + aw_haptic->trig[0].trig_brk = info.trig_cfg[6]; + break; + case AW_TRIG2: + aw_haptic->trig[1].trig_level = info.trig_cfg[7 + 0]; + aw_haptic->trig[1].trig_polar = info.trig_cfg[7 + 1]; + aw_haptic->trig[1].pos_enable = info.trig_cfg[7 + 2]; + aw_haptic->trig[1].pos_sequence = info.trig_cfg[7 + 3]; + aw_haptic->trig[1].neg_enable = info.trig_cfg[7 + 4]; + aw_haptic->trig[1].neg_sequence = info.trig_cfg[7 + 5]; + aw_haptic->trig[1].trig_brk = info.trig_cfg[7 + 6]; + break; + case AW_TRIG3: + aw_haptic->trig[2].trig_level = info.trig_cfg[14 + 0]; + aw_haptic->trig[2].trig_polar = info.trig_cfg[14 + 1]; + aw_haptic->trig[2].pos_enable = info.trig_cfg[14 + 2]; + aw_haptic->trig[2].pos_sequence = info.trig_cfg[14 + 3]; + aw_haptic->trig[2].neg_enable = info.trig_cfg[14 + 4]; + aw_haptic->trig[2].neg_sequence = info.trig_cfg[14 + 5]; + aw_haptic->trig[2].trig_brk = info.trig_cfg[14 + 6]; + break; + default: + break; + } +} + +static int aw8623x_trig_param_config(struct aw_haptic *aw_haptic, uint8_t pin) +{ + uint8_t trig_polar_lev_brk = 0x00; + uint8_t trig_pos_seq = 0x00; + uint8_t trig_neg_seq = 0x00; + + switch (pin) { + case AW_TRIG1: + if (aw_haptic->is_used_irq_pin) { + aw8623x_trig_param_init(aw_haptic, AW_TRIG1); + aw8623x_select_pin(aw_haptic, AW_IRQ); + return 0; + } + aw8623x_select_pin(aw_haptic, AW_TRIG1); + trig_polar_lev_brk = aw_haptic->trig[0].trig_polar << 2 | + aw_haptic->trig[0].trig_level << 1 | + aw_haptic->trig[0].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_TRGCFG7, + AW8623X_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 3); + trig_pos_seq = aw_haptic->trig[0].pos_enable << 7 | aw_haptic->trig[0].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG1, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[0].neg_enable << 7 | aw_haptic->trig[0].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG4, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig1 config ok!"); + break; + case AW_TRIG2: + trig_polar_lev_brk = aw_haptic->trig[1].trig_polar << 2 | + aw_haptic->trig[1].trig_level << 1 | + aw_haptic->trig[1].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_TRGCFG7, + AW8623X_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 0); + trig_pos_seq = aw_haptic->trig[1].pos_enable << 7 | aw_haptic->trig[1].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG2, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[1].neg_enable << 7 | aw_haptic->trig[1].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG5, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig2 config ok!"); + break; + case AW_TRIG3: + trig_polar_lev_brk = aw_haptic->trig[2].trig_polar << 2 | + aw_haptic->trig[2].trig_level << 1 | + aw_haptic->trig[2].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_TRGCFG8, + AW8623X_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 3); + trig_pos_seq = aw_haptic->trig[2].pos_enable << 7 | aw_haptic->trig[2].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG3, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[2].neg_enable << 7 | aw_haptic->trig[2].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_TRGCFG6, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig3 config ok!"); + break; + default: + break; + } + + return 0; +} + +static void aw8623x_set_trig(struct aw_haptic *aw_haptic, uint8_t pin) +{ + aw8623x_trig_param_init(aw_haptic, pin); + aw8623x_trig_param_config(aw_haptic, pin); +} + +static void aw8623x_trig_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw8623x_set_trig(aw_haptic, AW_TRIG1); + aw8623x_set_trig(aw_haptic, AW_TRIG2); + aw8623x_set_trig(aw_haptic, AW_TRIG3); +} + +static void aw8623x_parse_dts(struct aw_haptic *aw_haptic, struct device_node *np) +{ + uint32_t duration_time[3]; + uint32_t trig_config_temp[21]; + uint32_t val = 0; + + val = of_property_read_u32(np, "aw8623x_gain_bypass", &aw_haptic->info.gain_bypass); + if (val != 0) + aw_info("aw8623x_gain_bypass not found"); + val = of_property_read_u32(np, "aw8623x_vib_lk_f0_cali", &aw_haptic->info.lk_f0_cali); + if (val != 0) + aw_info("aw8623x_vib_lk_f0_cali not found"); + val = of_property_read_u32(np, "aw8623x_vib_mode", &aw_haptic->info.mode); + if (val != 0) + aw_info("aw8623x_vib_mode not found"); + val = of_property_read_u32(np, "aw8623x_vib_f0_pre", &aw_haptic->info.f0_pre); + if (val != 0) + aw_info("vib_f0_pre not found"); + val = of_property_read_u32(np, "aw8623x_vib_f0_cali_percen", + &aw_haptic->info.f0_cali_percent); + if (val != 0) + aw_info("vib_f0_cali_percent not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_drv1_lvl", &aw_haptic->info.cont_drv1_lvl); + if (val != 0) + aw_info("vib_cont_drv1_lvl not found"); + val = of_property_read_u32(np, "aw8623x_vib_lra_vrms", &aw_haptic->info.lra_vrms); + if (val != 0) + aw_info("vib_cont_lra_vrms not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_brk_time", &aw_haptic->info.cont_brk_time); + if (val != 0) + aw_info("vib_cont_brk_time not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_brk_gain", &aw_haptic->info.cont_brk_gain); + if (val != 0) + aw_info("vib_cont_brk_gain not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_drv1_time", + &aw_haptic->info.cont_drv1_time); + if (val != 0) + aw_info("vib_cont_drv1_time not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_drv2_time", + &aw_haptic->info.cont_drv2_time); + if (val != 0) + aw_info("vib_cont_drv2_time not found"); + val = of_property_read_u32(np, "aw8623x_vib_cont_track_margin", + &aw_haptic->info.cont_track_margin); + if (val != 0) + aw_info("vib_cont_track_margin not found"); + val = of_property_read_u32(np, "aw8623x_vib_d2s_gain", &aw_haptic->info.d2s_gain); + if (val != 0) + aw_info("vib_d2s_gain not found"); + val = of_property_read_u32_array(np, "aw8623x_vib_trig_config", trig_config_temp, + ARRAY_SIZE(trig_config_temp)); + if (val != 0) + aw_info("vib_trig_config not found"); + else + memcpy(aw_haptic->info.trig_cfg, trig_config_temp, sizeof(trig_config_temp)); + val = of_property_read_u32_array(np, "aw8623x_vib_duration_time", duration_time, + ARRAY_SIZE(duration_time)); + if (val != 0) + aw_info("aw8623x_vib_duration_time not found"); + else + memcpy(aw_haptic->info.duration_time, duration_time, sizeof(duration_time)); + aw_haptic->info.is_enabled_track_en = + of_property_read_bool(np, "aw8623x_vib_is_enabled_track_en"); + aw_info("aw_haptic->info.is_enabled_track_en = %d", aw_haptic->info.is_enabled_track_en); + aw_haptic->info.is_enabled_auto_brk = + of_property_read_bool(np, "aw8623x_vib_is_enabled_auto_brk"); + aw_info("aw_haptic->info.is_enabled_auto_brk = %d", + aw_haptic->info.is_enabled_auto_brk); +} + +static void aw8623x_get_wav_seq(struct aw_haptic *aw_haptic, uint32_t len) +{ + if (len > AW_SEQUENCER_SIZE) + len = AW_SEQUENCER_SIZE; + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_WAVCFG1, aw_haptic->seq, len); +} + +static void aw8623x_set_wav_seq(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t seq) +{ + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_WAVCFG1 + wav, &seq, AW_I2C_BYTE_ONE); +} + +static void aw8623x_set_wav_loop(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t loop) +{ + uint8_t tmp = 0; + + if (wav % 2) { + tmp = loop << 0; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_WAVCFG9 + (wav / 2), + AW8623X_BIT_WAVLOOP_SEQ_EVEN_MASK, tmp); + } else { + tmp = loop << 4; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_WAVCFG9 + (wav / 2), + AW8623X_BIT_WAVLOOP_SEQ_ODD_MASK, tmp); + } +} + +static void aw8623x_set_repeat_seq(struct aw_haptic *aw_haptic, uint8_t seq) +{ + aw8623x_set_wav_seq(aw_haptic, 0x00, seq); + aw8623x_set_wav_seq(aw_haptic, 0x01, 0x00); + aw8623x_set_wav_loop(aw_haptic, 0x00, AW8623X_BIT_WAVLOOP_INIFINITELY); +} + +static void aw8623x_get_gain(struct aw_haptic *aw_haptic, uint8_t *gain) +{ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_PLAYCFG2, gain, AW_I2C_BYTE_ONE); +} + +static void aw8623x_get_wav_loop(struct aw_haptic *aw_haptic, uint8_t *val) +{ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_WAVCFG9, val, AW_SEQUENCER_LOOP_SIZE); +} + +static void aw8623x_get_ram_data(struct aw_haptic *aw_haptic, uint8_t *ram_data, int size) +{ + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_RAMDATA, ram_data, size); +} + +static void aw8623x_get_lra_resistance(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val[2] = {0}; + uint8_t adc_fs = 0; + uint32_t lra_code = 0; + int d2s_gain = 0; + + /* enter standby mode */ + aw8623x_play_stop(aw_haptic); + aw8623x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG2, AW8623X_BIT_DETCFG2_DET_SEQ0_MASK, + AW8623X_BIT_DETCFG2_DET_SEQ0_RL); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETCFG1, &adc_fs, AW_I2C_BYTE_ONE); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_ADC_FS_MASK, + AW8623X_BIT_DETCFG1_ADC_FS_24K); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_ON); + usleep_range(AW_RL_DELAY_MIN, AW_RL_DELAY_MAX); + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_DET_GO_MASK, + AW8623X_BIT_DETCFG1_DET_GO_OFF); + aw8623x_raminit(aw_haptic, false); + /* restore adc fs */ + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_DETCFG1, AW8623X_BIT_DETCFG1_ADC_FS_MASK, + adc_fs); + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETCFG2, reg_val, AW_I2C_BYTE_ONE); + reg_val[0] = (~AW8623X_BIT_DETCFG2_D2S_GAIN_MASK) & reg_val[0]; + d2s_gain = aw8623x_select_d2s_gain(reg_val[0]); + if (d2s_gain <= 0) { + aw_err("d2s_gain is error"); + return; + } + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_DETRD1, reg_val, AW_I2C_BYTE_TWO); + lra_code = reg_val[0] & (~AW8623X_BIT_DETRD1_AVG_DATA_H_MASK); + lra_code = (lra_code << 8) | reg_val[1]; + /* 2num */ + aw_haptic->lra = AW8623X_RL_FORMULA(lra_code, d2s_gain); +} + +static uint8_t aw8623x_get_prctmode(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + reg_val >>= 7; + + return reg_val; +} + +static uint8_t aw8623x_judge_rtp_going(struct aw_haptic *aw_haptic) +{ + uint8_t glb_state = 0; + uint8_t rtp_state = 0; + + glb_state = aw8623x_get_glb_state(aw_haptic); + if (glb_state == AW_BIT_STATE_RTP_GO) { + rtp_state = 1; /*is going on */ + aw_info("rtp_routine_on"); + } + + return rtp_state; +} + +static uint64_t aw8623x_get_theory_time(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t fre_val = 0; + uint64_t theory_time = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSCTRL2, ®_val, AW_I2C_BYTE_ONE); + fre_val = reg_val & AW8623X_BIT_SYSCTRL2_RATE; + if (fre_val == AW8623X_BIT_SYSCTRL2_RATE_48K) + theory_time = (aw_haptic->rtp_len / 48) * 1000; /*48K*/ + else if (fre_val == AW8623X_BIT_SYSCTRL2_RATE_24K) + theory_time = (aw_haptic->rtp_len / 24) * 1000; /*24K*/ + else + theory_time = (aw_haptic->rtp_len / 12) * 1000; /*12K*/ + aw_info("microsecond:%llu theory_time = %llu", aw_haptic->microsecond, theory_time); + + return theory_time; +} + +static uint8_t aw8623x_get_osc_status(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_SYSST2, &state, AW_I2C_BYTE_ONE); + state &= AW8623X_BIT_SYSST2_FF_EMPTY; + + return state; +} + +static int aw8623x_check_qualify(struct aw_haptic *aw_haptic) +{ + uint8_t reg = 0; + int ret = 0; + + aw_info("enter"); + ret = haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_EFCFG6, ®, AW_I2C_BYTE_ONE); + if (ret < 0) + return ret; + if ((reg & 0x80) == 0x80) + return 0; + aw_err("register 0x64 error: 0x%02X", reg); + + return -ERANGE; +} + +static ssize_t cont_drv_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_lvl = 0x%02X, cont_drv2_lvl = 0x%02X\n", + aw_haptic->info.cont_drv1_lvl, aw_haptic->info.cont_drv2_lvl); + + return len; +} + +static ssize_t cont_drv_lvl_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_val = 0; + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_lvl = databuf[0]; + aw_haptic->info.cont_drv2_lvl = databuf[1]; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_CONTCFG6, + AW8623X_BIT_CONTCFG6_DRV1_LVL_MASK, + aw_haptic->info.cont_drv1_lvl); + reg_val = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG7, ®_val, AW_I2C_BYTE_ONE); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_drv_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_time = 0x%02X, cont_drv2_time = 0x%02X\n", + aw_haptic->info.cont_drv1_time, aw_haptic->info.cont_drv2_time); + + return len; +} + +static ssize_t cont_drv_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_val[2] = {0}; + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_time = databuf[0]; + aw_haptic->info.cont_drv2_time = databuf[1]; + reg_val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + reg_val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG8, reg_val, AW_I2C_BYTE_TWO); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_brk_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "cont_brk_time = 0x%02X\n", + aw_haptic->info.cont_brk_time); + + return len; +} + +static ssize_t cont_brk_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint8_t reg_val = 0; + int err, val; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + err = kstrtoint(buf, 16, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_brk_time = val; + reg_val = aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW8623X_REG_CONTCFG10, ®_val, AW_I2C_BYTE_ONE); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int i = 0; + ssize_t len = 0; + uint8_t trig_num = 3; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + for (i = 0; i < trig_num; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, "trig%d: trig_level=%u, trig_polar=%u", + i + 1, aw_haptic->trig[i].trig_level, + aw_haptic->trig[i].trig_polar); + len += snprintf(buf + len, PAGE_SIZE - len, "pos_enable=%u, pos_sequence=%u,", + aw_haptic->trig[i].pos_enable, aw_haptic->trig[i].pos_sequence); + len += snprintf(buf + len, PAGE_SIZE - len, + "neg_enable=%u, neg_sequence=%u trig_brk=%u\n", + aw_haptic->trig[i].neg_enable, aw_haptic->trig[i].neg_sequence, + aw_haptic->trig[i].trig_brk); + } + + return len; +} + +static ssize_t trig_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[9] = { 0 }; + + if (sscanf(buf, "%u %u %u %u %u %u %u %u", &databuf[0], &databuf[1], &databuf[2], + &databuf[3], &databuf[4], &databuf[5], &databuf[6], &databuf[7]) == 8) { + aw_info("%u, %u, %u, %u, %u, %u, %u, %u", databuf[0], databuf[1], databuf[2], + databuf[3], databuf[4], databuf[5], databuf[6], databuf[7]); + if (databuf[0] < 0 || databuf[0] > 2) { + aw_err("input seq value out of range!"); + return count; + } + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + if (databuf[4] > aw_haptic->ram.ram_num || databuf[6] > aw_haptic->ram.ram_num) { + aw_err("input seq value out of range!"); + return count; + } + aw_haptic->trig[databuf[0]].trig_level = databuf[1]; + aw_haptic->trig[databuf[0]].trig_polar = databuf[2]; + aw_haptic->trig[databuf[0]].pos_enable = databuf[3]; + aw_haptic->trig[databuf[0]].pos_sequence = databuf[4]; + aw_haptic->trig[databuf[0]].neg_enable = databuf[5]; + aw_haptic->trig[databuf[0]].neg_sequence = databuf[6]; + aw_haptic->trig[databuf[0]].trig_brk = databuf[7]; + mutex_lock(&aw_haptic->lock); + aw8623x_trig_param_config(aw_haptic, databuf[0]); + mutex_unlock(&aw_haptic->lock); + } else + aw_err("please input eight parameters"); + + return count; +} + +static ssize_t rtp_autosin_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len = snprintf(buf, PAGE_SIZE, "rtp_cnt = %u\n", aw_haptic->rtp_cnt); + + return len; +} + +static ssize_t rtp_autosin_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + if (!aw_haptic->ram.base_addr) { + aw_err("no set FIFO space for autosin rtp play!"); + return count; + } + + mutex_lock(&aw_haptic->lock); + if ((val > 0) && (val < aw_haptic->rtp_num_max)) { + aw_haptic->state = 1; + aw_haptic->rtp_file_num = val; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG6, + AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_MASK, + AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_ENABLE); + } else if (val == 0) { + aw_haptic->state = 0; + haptic_nv_i2c_write_bits(aw_haptic, AW8623X_REG_RTPCFG6, + AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_MASK, + AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_DISABLE); + } else { + aw_haptic->state = 0; + aw_err("input number error:%u", val); + } + mutex_unlock(&aw_haptic->lock); + queue_work(aw_haptic->work_queue, &aw_haptic->rtp_work); + + return count; +} + +static DEVICE_ATTR_RW(cont_drv_lvl); +static DEVICE_ATTR_RW(cont_drv_time); +static DEVICE_ATTR_RW(cont_brk_time); +static DEVICE_ATTR_RW(trig); +static DEVICE_ATTR_RW(rtp_autosin); + +static struct attribute *aw8623x_vibrator_attributes[] = { + &dev_attr_cont_drv_lvl.attr, + &dev_attr_cont_drv_time.attr, + &dev_attr_cont_brk_time.attr, + &dev_attr_trig.attr, + &dev_attr_rtp_autosin.attr, + NULL +}; + +static struct attribute_group aw8623x_vibrator_attribute_group = { + .attrs = aw8623x_vibrator_attributes +}; + +static void aw8623x_creat_node(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &aw8623x_vibrator_attribute_group); + if (ret < 0) + aw_err("error create aw8623x sysfs attr files"); +} + +struct aw_haptic_func aw8623x_func_list = { + .ram_init = aw8623x_raminit, + .parse_dts = aw8623x_parse_dts, + .trig_init = aw8623x_trig_init, + .play_mode = aw8623x_play_mode, + .play_stop = aw8623x_play_stop, + .irq_clear = aw8623x_irq_clear, + .creat_node = aw8623x_creat_node, + .cont_config = aw8623x_cont_config, + .offset_cali = aw8623x_offset_cali, + .haptic_start = aw8623x_play_go, + .read_cont_f0 = aw8623x_read_cont_f0, + .check_qualify = aw8623x_check_qualify, + .judge_rtp_going = aw8623x_judge_rtp_going, + .protect_config = aw8623x_protect_config, + .misc_para_init = aw8623x_misc_para_init, + .interrupt_setup = aw8623x_interrupt_setup, + .rtp_get_fifo_afs = aw8623x_rtp_get_fifo_afs, + .rtp_get_fifo_aes = aw8623x_rtp_get_fifo_aes, + .vbat_mode_config = aw8623x_vbat_mode_config, + .calculate_cali_data = aw8623x_calculate_cali_data, + .set_gain = aw8623x_set_gain, + .get_gain = aw8623x_get_gain, + .set_wav_seq = aw8623x_set_wav_seq, + .get_wav_seq = aw8623x_get_wav_seq, + .set_wav_loop = aw8623x_set_wav_loop, + .get_wav_loop = aw8623x_get_wav_loop, + .set_ram_data = aw8623x_set_ram_data, + .get_ram_data = aw8623x_get_ram_data, + .set_fifo_addr = aw8623x_set_fifo_addr, + .get_fifo_addr = aw8623x_get_fifo_addr, + .set_rtp_aei = aw8623x_set_rtp_aei, + .set_rtp_data = aw8623x_set_rtp_data, + .set_ram_addr = aw8623x_set_ram_addr, + .set_trim_lra = aw8623x_set_trim_lra, + .set_base_addr = aw8623x_set_base_addr, + .set_repeat_seq = aw8623x_set_repeat_seq, + .get_f0 = aw8623x_get_f0, + .get_reg = aw8623x_get_reg, + .get_vbat = aw8623x_get_vbat, + .get_prctmode = aw8623x_get_prctmode, + .get_irq_state = aw8623x_get_irq_state, + .get_glb_state = aw8623x_get_glb_state, + .get_osc_status = aw8623x_get_osc_status, + .get_theory_time = aw8623x_get_theory_time, + .get_lra_resistance = aw8623x_get_lra_resistance, + .get_first_wave_addr = aw8623x_get_first_wave_addr, +}; diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8624x.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8624x.c new file mode 100644 index 000000000000..c13dc2f481b4 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw8624x.c @@ -0,0 +1,1392 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * aw8624x.c + * + * Copyright (c) 2021 AWINIC Technology CO., LTD + * + * Author: + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "haptic_nv.h" +#include "haptic_nv_reg.h" + +static void aw8624x_interrupt_setup(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("reg SYSINT=0x%02X", reg_val); + /* edge int mode */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL5, + (AW8624X_BIT_SYSCTRL5_INT_MODE_MASK & + AW8624X_BIT_SYSCTRL5_INT_EDGE_MODE_MASK), + (AW8624X_BIT_SYSCTRL5_INT_MODE_EDGE | + AW8624X_BIT_SYSCTRL5_INT_EDGE_MODE_POS)); + /* int enable */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSINTM, + (AW8624X_BIT_SYSINTM_UVLM_MASK & AW8624X_BIT_SYSINTM_FF_AEM_MASK & + AW8624X_BIT_SYSINTM_FF_AFM_MASK & AW8624X_BIT_SYSINTM_OCDM_MASK & + AW8624X_BIT_SYSINTM_OTM_MASK & AW8624X_BIT_SYSINTM_DONEM_MASK), + (AW8624X_BIT_SYSINTM_UVLM_ON | AW8624X_BIT_SYSINTM_FF_AEM_OFF | + AW8624X_BIT_SYSINTM_FF_AFM_OFF | AW8624X_BIT_SYSINTM_OCDM_ON | + AW8624X_BIT_SYSINTM_OTM_ON | AW8624X_BIT_SYSINTM_DONEM_OFF)); +} + +static void aw8624x_set_rtp_data(struct aw_haptic *aw_haptic, uint8_t *data, uint32_t len) +{ + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_RTPDATA, data, len); +} + +static uint8_t aw8624x_get_glb_state(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_GLBRD5, &state, AW_I2C_BYTE_ONE); + + return state; +} + +static int aw8624x_get_irq_state(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + int ret = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_dbg("reg SYSINT=0x%02X", reg_val); + if (reg_val & AW8624X_BIT_SYSINT_UVLI) + aw_err("chip uvlo int error"); + if (reg_val & AW8624X_BIT_SYSINT_OCDI) + aw_err("chip over current int error"); + if (reg_val & AW8624X_BIT_SYSINT_OTI) + aw_err("chip over temperature int error"); + if (reg_val & AW8624X_BIT_SYSINT_DONEI) + aw_info("chip playback done"); + if (reg_val & AW8624X_BIT_SYSINT_FF_AFI) + aw_info("rtp mode fifo almost full!"); + if (reg_val & AW8624X_BIT_SYSINT_FF_AEI) { + aw_info("rtp fifo almost empty"); + ret = AW_IRQ_ALMOST_EMPTY; + } + + return ret; +} + +static uint8_t aw8624x_rtp_get_fifo_afs(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW8624X_BIT_SYSST_FF_AFS; + reg_val = reg_val >> 3; + + return reg_val; +} + +static uint8_t aw8624x_rtp_get_fifo_aes(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW8624X_BIT_SYSST_FF_AES; + reg_val = reg_val >> 4; + + return reg_val; +} + +static void aw8624x_set_rtp_aei(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSINTM, + AW8624X_BIT_SYSINTM_FF_AEM_MASK, + AW8624X_BIT_SYSINTM_FF_AEM_ON); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSINTM, + AW8624X_BIT_SYSINTM_FF_AEM_MASK, + AW8624X_BIT_SYSINTM_FF_AEM_OFF); + } +} + +static void aw8624x_auto_brk_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8624X_BIT_PLAYCFG3_BRK_ENABLE); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8624X_BIT_PLAYCFG3_BRK_DISABLE); + } +} + +static void aw8624x_config(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_ANACFG8, + AW8624X_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK, + AW8624X_BIT_ANACFG8_TRTF_CTRL_HDRV); + if (aw_haptic->info.cont_brk_time) { + reg_val = (uint8_t)aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG10, ®_val, AW_I2C_BYTE_ONE); + } else { + aw_err("dts_info.cont_brk_time=0"); + } + if (aw_haptic->info.cont_brk_gain) { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG5, + AW8624X_BIT_CONTCFG5_BRK_GAIN_MASK, + aw_haptic->info.cont_brk_gain); + } else { + aw_err("dts_info.cont_brk_gain=0"); + } + +} + +static void aw8624x_play_stop(struct aw_haptic *aw_haptic) +{ + bool force_flag = true; + uint8_t val = 0; + int cnt = 40; + + aw_info("enter"); + aw_haptic->play_mode = AW_STANDBY_MODE; + val = AW8624X_BIT_PLAYCFG4_STOP_ON; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_GLBRD5, &val, AW_I2C_BYTE_ONE); + if ((val & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + force_flag = false; + aw_info("entered standby! glb_state=0x%02X", val); + break; + } + cnt--; + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + } + if (force_flag) { + aw_err("force to enter standby mode!"); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, + AW8624X_BIT_SYSCTRL2_STANDBY_MASK, + AW8624X_BIT_SYSCTRL2_STANDBY_ON); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, + AW8624X_BIT_SYSCTRL2_STANDBY_MASK, + AW8624X_BIT_SYSCTRL2_STANDBY_OFF); + } +} + +static void aw8624x_set_pwm(struct aw_haptic *aw_haptic, uint8_t mode) +{ + switch (mode) { + case AW_PWM_48K: + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, + AW8624X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8624X_BIT_SYSCTRL2_RATE_48K); + break; + case AW_PWM_24K: + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, + AW8624X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8624X_BIT_SYSCTRL2_RATE_24K); + break; + case AW_PWM_12K: + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, + AW8624X_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW8624X_BIT_SYSCTRL2_RATE_12K); + break; + default: + break; + } +} + +static void aw8624x_play_mode(struct aw_haptic *aw_haptic, uint8_t play_mode) +{ + switch (play_mode) { + case AW_STANDBY_MODE: + aw_info("enter standby mode"); + aw_haptic->play_mode = AW_STANDBY_MODE; + aw8624x_play_stop(aw_haptic); + break; + case AW_RAM_MODE: + aw_info("enter ram mode"); + aw_haptic->play_mode = AW_RAM_MODE; + aw8624x_set_pwm(aw_haptic, AW_PWM_12K); + aw8624x_auto_brk_config(aw_haptic, false); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_RAM_LOOP_MODE: + aw_info("enter ram loop mode"); + aw_haptic->play_mode = AW_RAM_LOOP_MODE; + aw8624x_set_pwm(aw_haptic, AW_PWM_12K); + aw8624x_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_CONT_MODE: + aw_info("enter cont mode"); + aw_haptic->play_mode = AW_CONT_MODE; + aw8624x_auto_brk_config(aw_haptic, aw_haptic->info.is_enabled_auto_brk); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_CONT); + break; + case AW_RTP_MODE: + aw_info("enter rtp mode"); + aw_haptic->play_mode = AW_RTP_MODE; + aw8624x_set_pwm(aw_haptic, AW_PWM_24K); + aw8624x_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_RTP); + break; + case AW_TRIG_MODE: + aw_info("enter trig mode"); + aw_haptic->play_mode = AW_TRIG_MODE; + aw8624x_set_pwm(aw_haptic, AW_PWM_12K); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW8624X_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + default: + aw_err("play mode %u error", play_mode); + break; + } +} + +static void aw8624x_irq_clear(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSINT, &val, AW_I2C_BYTE_ONE); + aw_info("SYSINT=0x%02X", val); +} + +static void aw8624x_play_go(struct aw_haptic *aw_haptic, bool flag) +{ + uint8_t val = 0; + + aw_info("enter"); + if (flag == true) { + val = AW8624X_BIT_PLAYCFG4_GO_ON; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + } else { + val = AW8624X_BIT_PLAYCFG4_STOP_ON; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + } + val = aw8624x_get_glb_state(aw_haptic); + aw_info("reg:0x%02X=0x%02X", AW8624X_REG_GLBRD5, val); +} + +static void aw8624x_haptic_start(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw8624x_play_go(aw_haptic, true); +} + +static void aw8624x_raminit(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL1, + AW8624X_BIT_SYSCTRL1_RAMINIT_MASK, + AW8624X_BIT_SYSCTRL1_RAMINIT_ON); + usleep_range(1000, 1050); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL1, + AW8624X_BIT_SYSCTRL1_RAMINIT_MASK, + AW8624X_BIT_SYSCTRL1_RAMINIT_OFF); + } +} + +static void aw8624x_get_vbat(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t vbat_code = 0; + + aw_info("enter"); + aw8624x_play_stop(aw_haptic); + aw8624x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_DETCFG2, AW8624X_BIT_DETCFG2_VBAT_GO_MASK, + AW8624X_BIT_DETCFG2_VABT_GO_ON); + usleep_range(AW_VBAT_DELAY_MIN, AW_VBAT_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_VBAT, ®_val, AW_I2C_BYTE_ONE); + vbat_code = (vbat_code | reg_val) << 2; + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_LO, ®_val, AW_I2C_BYTE_ONE); + vbat_code = vbat_code | ((reg_val & AW8624X_BIT_DET_LO_VBAT) >> 4); + aw8624x_raminit(aw_haptic, false); + aw_haptic->vbat = AW8624X_VBAT_FORMULA(vbat_code); + if (aw_haptic->vbat > AW_VBAT_MAX) { + aw_haptic->vbat = AW_VBAT_MAX; + aw_info("vbat max limit = %dmV", aw_haptic->vbat); + } + if (aw_haptic->vbat < AW_VBAT_MIN) { + aw_haptic->vbat = AW_VBAT_MIN; + aw_info("vbat min limit = %dmV", aw_haptic->vbat); + } + aw_info("vbat=%dmV, vbat_code=0x%02X", aw_haptic->vbat, vbat_code); +} + +static void aw8624x_set_gain(struct aw_haptic *aw_haptic, uint8_t gain) +{ + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PLAYCFG2, &gain, AW_I2C_BYTE_ONE); +} + +static void aw8624x_set_trim_lra(struct aw_haptic *aw_haptic, uint8_t val) +{ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_TRIMCFG3, + AW8624X_BIT_TRIMCFG3_TRIM_LRA_MASK, val); +} + +static void aw8624x_cont_config(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + /* work mode */ + aw8624x_play_mode(aw_haptic, AW_CONT_MODE); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG6, + (AW8624X_BIT_CONTCFG6_TRACK_EN_MASK & + AW8624X_BIT_CONTCFG6_DRV1_LVL_MASK), + ((aw_haptic->info.is_enabled_track_en << 7) | + (uint8_t)aw_haptic->info.cont_drv1_lvl)); + reg_val = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG7, ®_val, AW_I2C_BYTE_ONE); + /* DRV2_TIME */ + reg_val = 0xFF; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG9, ®_val, AW_I2C_BYTE_ONE); + /* cont play go */ + aw8624x_play_go(aw_haptic, true); +} + +static ssize_t aw8624x_get_reg(struct aw_haptic *aw_haptic, ssize_t len, char *buf) +{ + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8624X_REG_ID, + AW8624X_REG_RTPDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8624X_REG_RTPDATA + 1, + AW8624X_REG_RAMDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW8624X_REG_RAMDATA + 1, + AW8624X_REG_ANACFG8); + + return len; +} + +static void aw8624x_protect_config(struct aw_haptic *aw_haptic, uint8_t prtime, uint8_t prlvl) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PWMCFG1, AW8624X_BIT_PWMCFG1_PRC_EN_MASK, + AW8624X_BIT_PWMCFG1_PRC_DISABLE); + if (prlvl != 0) { + /* Enable protection mode */ + aw_info("enable protection mode"); + reg_val = AW8624X_BIT_PWMCFG3_PR_ENABLE | + (prlvl & (~AW8624X_BIT_PWMCFG3_PRLVL_MASK)); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_PWMCFG4, &prtime, AW_I2C_BYTE_ONE); + } else { + /* Disable */ + aw_info("disable protection mode"); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PWMCFG3, + AW8624X_BIT_PWMCFG3_PR_EN_MASK, + AW8624X_BIT_PWMCFG3_PR_DISABLE); + } +} + +static void aw8624x_misc_para_init(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + uint8_t array[8] = {0}; + + aw_info("enter"); + /* Get seq and gain */ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_WAVCFG1, &val, AW_I2C_BYTE_ONE); + aw_haptic->index = val & AW8624X_BIT_WAVCFG_SEQ; + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_PLAYCFG2, &val, AW_I2C_BYTE_ONE); + aw_haptic->gain = val; + aw_info("gain=0x%02X, index=0x%02X", aw_haptic->gain, aw_haptic->index); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_WAVCFG1, array, AW_SEQUENCER_SIZE); + memcpy(aw_haptic->seq, array, AW_SEQUENCER_SIZE); + /* GAIN_BYPASS config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL5, + AW8624X_BIT_SYSCTRL5_GAIN_BYPASS_MASK, + aw_haptic->info.gain_bypass << 6); + /* CONT SMART_LOOP config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG5, + AW8624X_BIT_CONTCFG5_SMART_LOOP_MASK, + aw_haptic->info.is_enabled_smart_loop << 4); + /* RTP INT_BRK config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL1, + AW8624X_BIT_SYSCTRL1_INT_BRK_MASK, + aw_haptic->info.is_enabled_inter_brake << 6); + + /* d2s_gain */ + if (!aw_haptic->info.d2s_gain) { + aw_err("dts_info.d2s_gain = 0!"); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL5, + AW8624X_BIT_SYSCTRL5_D2S_GAIN_MASK, + aw_haptic->info.d2s_gain); + } + + if (!aw_haptic->info.f0_d2s_gain) { + aw_err("dts_info.f0_d2s_gain = 0!"); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL6, + AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_MASK, + aw_haptic->info.f0_d2s_gain); + } + + aw_haptic->info.cont_drv2_lvl = AW8624X_DRV2_LVL_FORMULA(aw_haptic->info.f0_pre, + aw_haptic->info.lra_vrms); + aw_info("lra_vrms=%u, cont_drv2_lvl=0x%02X", aw_haptic->info.lra_vrms, + aw_haptic->info.cont_drv2_lvl); + if (aw_haptic->info.cont_drv2_lvl > AW8624X_DRV2_LVL_MAX) { + aw_err("cont_drv2_lvl[0x%02X] is error, restore max vale[0x%02X]", + aw_haptic->info.cont_drv2_lvl, AW8624X_DRV2_LVL_MAX); + aw_haptic->info.cont_drv2_lvl = AW8624X_DRV2_LVL_MAX; + } + aw8624x_config(aw_haptic); + aw8624x_set_pwm(aw_haptic, AW_PWM_12K); + aw8624x_protect_config(aw_haptic, AW8624X_PWMCFG4_PRTIME_DEFAULT_VALUE, + AW8624X_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE); +} + +static int aw8624x_select_d2s_gain(uint8_t reg) +{ + int d2s_gain = 0; + + switch (reg) { + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_1: + d2s_gain = 1; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_2: + d2s_gain = 2; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_4: + d2s_gain = 4; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_5: + d2s_gain = 5; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_8: + d2s_gain = 8; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_10: + d2s_gain = 10; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_20: + d2s_gain = 20; + break; + case AW8624X_BIT_SYSCTRL5_D2S_GAIN_40: + d2s_gain = 40; + break; + default: + d2s_gain = -1; + break; + } + + return d2s_gain; +} + +static int aw8624x_offset_cali(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val[2] = {0}; + int os_code = 0; + int d2s_gain = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSCTRL5, reg_val, AW_I2C_BYTE_ONE); + reg_val[0] = (~AW8624X_BIT_SYSCTRL5_D2S_GAIN_MASK) & reg_val[0]; + d2s_gain = aw8624x_select_d2s_gain(reg_val[0]); + if (d2s_gain < 0) { + aw_err("d2s_gain is error"); + return -ERANGE; + } + aw8624x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_DETCFG1, AW8624X_BIT_DETCFG1_RL_OS_MASK, + AW8624X_BIT_DETCFG1_OS); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_DETCFG2, AW8624X_BIT_DETCFG2_DIAG_GO_MASK, + AW8624X_BIT_DETCFG2_DIAG_GO_ON); + usleep_range(3000, 3500); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_OS, ®_val[0], AW_I2C_BYTE_ONE); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_LO, ®_val[1], AW_I2C_BYTE_ONE); + aw8624x_raminit(aw_haptic, false); + os_code = (reg_val[1] & (~AW8624X_BIT_DET_LO_OS_MASK)) >> 2; + os_code = (reg_val[0] << 2) | os_code; + os_code = AW8624X_OS_FORMULA(os_code, d2s_gain); + aw_info("os_code is %d mV", os_code); + if (os_code > 15 || os_code < -15) + return -ERANGE; + + return 0; +} + +static void aw8624x_vbat_mode_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + uint8_t val = 0; + + aw_info("enter"); + if (flag == AW_CONT_VBAT_HW_COMP_MODE) { + val = AW8624X_BIT_GLBCFG2_START_DLY_250US; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_GLBCFG2, &val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL1, + AW8624X_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW8624X_BIT_SYSCTRL1_VBAT_MODE_HW); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL1, + AW8624X_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW8624X_BIT_SYSCTRL1_VBAT_MODE_SW); + } +} + +static void aw8624x_calculate_cali_data(struct aw_haptic *aw_haptic) +{ + char f0_cali_lra = 0; + int f0_cali_step = 0; + + f0_cali_step = 100000 * ((int)aw_haptic->f0 - (int)aw_haptic->info.f0_pre) / + ((int)aw_haptic->info.f0_pre * AW8624X_F0_CALI_ACCURACY); + aw_info("f0_cali_step=%d", f0_cali_step); + if (f0_cali_step >= 0) { /*f0_cali_step >= 0 */ + if (f0_cali_step % 10 >= 5) + f0_cali_step = 64 + (f0_cali_step / 10 + 1); + else + f0_cali_step = 64 + f0_cali_step / 10; + } else { /* f0_cali_step < 0 */ + if (f0_cali_step % 10 <= -5) + f0_cali_step = 64 + (f0_cali_step / 10 - 1); + else + f0_cali_step = 64 + f0_cali_step / 10; + } + if (f0_cali_step >= 64) + f0_cali_lra = (char)f0_cali_step - 64; + else + f0_cali_lra = (char)f0_cali_step + 64; + /* update cali step */ + aw_haptic->f0_cali_data = (int)f0_cali_lra; + aw_info("f0_cali_data=0x%02X", aw_haptic->f0_cali_data); +} + +static void aw8624x_read_cont_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_CONTCFG13, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_err("didn't get cont f0 because f0_reg value is 0!"); + aw_haptic->cont_f0 = 0; + return; + } + aw_haptic->cont_f0 = AW8624X_F0_FORMULA(f0_reg); + aw_info("cont_f0=%u", aw_haptic->cont_f0); +} + +static int aw8624x_read_lra_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + + aw_info("enter"); + /* F_LRA_F0 */ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_CONTCFG11, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_haptic->f0 = 0; + aw_err("didn't get lra f0 because f0_reg value is 0!"); + return -ERANGE; + } + aw_haptic->f0 = AW8624X_F0_FORMULA(f0_reg); + aw_info("lra_f0=%u", aw_haptic->f0); + + return 0; +} + +static int aw8624x_get_f0(struct aw_haptic *aw_haptic) +{ + bool get_f0_flag = false; + uint8_t brk_en_temp = 0; + uint8_t val[3] = {0}; + int drv_width = 0; + int cnt = 200; + int ret = 0; + + aw_info("enter"); + aw_haptic->f0 = aw_haptic->info.f0_pre; + /* enter standby mode */ + aw8624x_play_stop(aw_haptic); + /* f0 calibrate work mode */ + aw8624x_play_mode(aw_haptic, AW_CONT_MODE); + /* enable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG1, + AW8624X_BIT_CONTCFG1_PEAK_NUM_MASK, + AW8624X_BIT_CONTCFG1_PEAK_NUM_3); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG6, + AW8624X_BIT_CONTCFG6_TRACK_EN_MASK, + (aw_haptic->info.is_enabled_track_en << 7)); + /* enable auto brake */ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_PLAYCFG3, &val[0], AW_I2C_BYTE_ONE); + brk_en_temp = AW8624X_BIT_PLAYCFG3_BRK & val[0]; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, AW8624X_BIT_PLAYCFG3_BRK_EN_MASK, + AW8624X_BIT_PLAYCFG3_BRK_ENABLE); + /* f0 driver level */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG6, + AW8624X_BIT_CONTCFG6_DRV1_LVL_MASK, aw_haptic->info.cont_drv1_lvl); + val[0] = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG7, val, AW_I2C_BYTE_ONE); + val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG8, val, AW_I2C_BYTE_TWO); + /* TRACK_MARGIN */ + if (!aw_haptic->info.cont_track_margin) { + aw_err("dts_info.cont_track_margin = 0!"); + } else { + val[0] = (uint8_t)aw_haptic->info.cont_track_margin; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG4, &val[0], AW_I2C_BYTE_ONE); + } + /* DRV_WIDTH */ + if (!aw_haptic->info.f0_pre) + return -ERANGE; + drv_width = AW8624X_DRV_WIDTH_FORMULA(aw_haptic->info.f0_pre, + aw_haptic->info.cont_track_margin, + aw_haptic->info.cont_brk_gain); + if (drv_width < AW_DRV_WIDTH_MIN) + drv_width = AW_DRV_WIDTH_MIN; + if (drv_width > AW_DRV_WIDTH_MAX) + drv_width = AW_DRV_WIDTH_MAX; + val[0] = (uint8_t)drv_width; + aw_info("cont_drv_width=0x%02X", val[0]); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG3, &val[0], AW_I2C_BYTE_ONE); + /* cont play go */ + aw8624x_play_go(aw_haptic, true); + usleep_range(20000, 20500); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_GLBRD5, &val[0], AW_I2C_BYTE_ONE); + if ((val[0] & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + get_f0_flag = true; + aw_info("entered standby! glb_state=0x%02X", val[0]); + break; + } + cnt--; + aw_dbg("waitting for standby,glb_state=0x%02X", val[0]); + usleep_range(AW_F0_DELAY_MIN, AW_F0_DELAY_MAX); + } + if (get_f0_flag) { + ret = aw8624x_read_lra_f0(aw_haptic); + if (ret < 0) + aw_err("read lra f0 is failed"); + aw8624x_read_cont_f0(aw_haptic); + } else { + ret = -ERANGE; + aw_err("enter standby mode failed, stop reading f0!"); + } + /* disable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG1, + AW8624X_BIT_CONTCFG1_PEAK_NUM_MASK, + AW8624X_BIT_CONTCFG1_PEAK_NUM_NO_F0_DET); + /* recover auto break config */ + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_PLAYCFG3, + AW8624X_BIT_PLAYCFG3_BRK_EN_MASK, brk_en_temp); + + return ret; +} + +static void aw8624x_set_base_addr(struct aw_haptic *aw_haptic) +{ + uint32_t base_addr = 0; + uint8_t val = 0; + + aw_info("enter"); + base_addr = aw_haptic->ram.base_addr; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_RTPCFG1, AW8624X_BIT_RTPCFG1_ADDRH_MASK, + (uint8_t)AW_SET_BASEADDR_H(base_addr)); + val = (uint8_t)AW_SET_BASEADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_RTPCFG2, &val, AW_I2C_BYTE_ONE); +} + +static void aw8624x_set_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t val[3] = {0}; + + aw_info("enter"); + ae_addr_h = (uint8_t)AW8624X_SET_AEADDR_H(aw_haptic->ram.base_addr); + af_addr_h = (uint8_t)AW8624X_SET_AFADDR_H(aw_haptic->ram.base_addr); + val[0] = ae_addr_h | af_addr_h; + val[1] = (uint8_t)AW8624X_SET_AEADDR_L(aw_haptic->ram.base_addr); + val[2] = (uint8_t)AW8624X_SET_AFADDR_L(aw_haptic->ram.base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); +} + +static void aw8624x_get_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t ae_addr_l = 0; + uint8_t af_addr_l = 0; + uint8_t val[3] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); + ae_addr_h = ((val[0]) & AW8624X_BIT_RTPCFG3_FIFO_AEH) >> 4; + ae_addr_l = val[1]; + af_addr_h = ((val[0]) & AW8624X_BIT_RTPCFG3_FIFO_AFH); + af_addr_l = val[2]; + aw_info("almost_empty_threshold = %u,almost_full_threshold = %u", + (uint16_t)((ae_addr_h << 8) | ae_addr_l), + (uint16_t)((af_addr_h << 8) | af_addr_l)); +} + +static void aw8624x_set_ram_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + aw_info("enter"); + val[0] = (uint8_t)AW_SET_RAMADDR_H(base_addr); + val[1] = (uint8_t)AW_SET_RAMADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_RAMADDRH, val, AW_I2C_BYTE_TWO); +} + +static void aw8624x_set_ram_data(struct aw_haptic *aw_haptic, uint8_t *data, int len) +{ + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_RAMDATA, data, len); +} + +static void aw8624x_get_first_wave_addr(struct aw_haptic *aw_haptic, uint32_t *first_wave_addr) +{ + uint8_t val[3] = {0}; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_RAMDATA, val, AW_I2C_BYTE_THREE); + *first_wave_addr = (val[1] << 8 | val[2]); +} + +static void aw8624x_haptic_trig_param_init(struct aw_haptic *aw_haptic, uint8_t pin) +{ + struct aw_haptic_dts_info info = aw_haptic->info; + + switch (pin) { + case AW_TRIG1: + aw_haptic->trig[0].trig_level = info.trig_cfg[0]; + aw_haptic->trig[0].trig_polar = info.trig_cfg[1]; + aw_haptic->trig[0].pos_enable = info.trig_cfg[2]; + aw_haptic->trig[0].pos_sequence = info.trig_cfg[3]; + aw_haptic->trig[0].neg_enable = info.trig_cfg[4]; + aw_haptic->trig[0].neg_sequence = info.trig_cfg[5]; + aw_haptic->trig[0].trig_brk = info.trig_cfg[6]; + break; + default: + break; + } +} + +static int aw8624x_haptic_trig_param_config(struct aw_haptic *aw_haptic, uint8_t pin) +{ + uint8_t trig_polar_lev_brk = 0x00; + uint8_t trig_pos_seq = 0x00; + uint8_t trig_neg_seq = 0x00; + + switch (pin) { + case AW_TRIG1: + trig_polar_lev_brk = aw_haptic->trig[0].trig_polar << 2 | + aw_haptic->trig[0].trig_level << 1 | + aw_haptic->trig[0].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_TRGCFG7, + AW8624X_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 5); + trig_pos_seq = aw_haptic->trig[0].pos_enable << 7 | aw_haptic->trig[0].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_TRGCFG1, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[0].neg_enable << 7 | aw_haptic->trig[0].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_TRGCFG4, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig1 config ok!"); + break; + default: + break; + } + + return 0; +} + +static void aw8624x_set_trig(struct aw_haptic *aw_haptic, uint8_t pin) +{ + aw_info("enter"); + aw8624x_haptic_trig_param_init(aw_haptic, pin); + aw8624x_haptic_trig_param_config(aw_haptic, pin); +} + +static void aw8624x_trig_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw8624x_set_trig(aw_haptic, AW_TRIG1); +} + +static void aw8624x_parse_dts(struct aw_haptic *aw_haptic, struct device_node *np) +{ + uint32_t duration_time[3]; + uint32_t trig_config_temp[21]; + uint32_t val = 0; + + val = of_property_read_u32(np, "aw8624x_gain_bypass", &aw_haptic->info.gain_bypass); + if (val != 0) + aw_info("aw8624x_gain_bypass not found"); + val = of_property_read_u32(np, "aw8624x_vib_lk_f0_cali", &aw_haptic->info.lk_f0_cali); + if (val != 0) + aw_info("aw8624x_vib_lk_f0_cali not found"); + val = of_property_read_u32(np, "aw8624x_vib_mode", &aw_haptic->info.mode); + if (val != 0) + aw_info("aw8624x_vib_mode not found"); + val = of_property_read_u32(np, "aw8624x_vib_f0_pre", &aw_haptic->info.f0_pre); + if (val != 0) + aw_info("vib_f0_pre not found"); + val = of_property_read_u32(np, "aw8624x_vib_f0_cali_percen", + &aw_haptic->info.f0_cali_percent); + if (val != 0) + aw_info("vib_f0_cali_percent not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_drv1_lvl", &aw_haptic->info.cont_drv1_lvl); + if (val != 0) + aw_info("vib_cont_drv1_lvl not found"); + val = of_property_read_u32(np, "aw8624x_vib_lra_vrms", &aw_haptic->info.lra_vrms); + if (val != 0) + aw_info("vib_cont_lra_vrms not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_brk_time", &aw_haptic->info.cont_brk_time); + if (val != 0) + aw_info("vib_cont_brk_time not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_brk_gain", &aw_haptic->info.cont_brk_gain); + if (val != 0) + aw_info("vib_cont_brk_gain not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_drv1_time", + &aw_haptic->info.cont_drv1_time); + if (val != 0) + aw_info("vib_cont_drv1_time not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_drv2_time", + &aw_haptic->info.cont_drv2_time); + if (val != 0) + aw_info("vib_cont_drv2_time not found"); + val = of_property_read_u32(np, "aw8624x_vib_cont_track_margin", + &aw_haptic->info.cont_track_margin); + if (val != 0) + aw_info("vib_cont_track_margin not found"); + val = of_property_read_u32(np, "aw8624x_vib_d2s_gain", &aw_haptic->info.d2s_gain); + if (val != 0) + aw_info("vib_d2s_gain not found"); + val = of_property_read_u32(np, "aw8624x_vib_f0_d2s_gain", &aw_haptic->info.f0_d2s_gain); + if (val != 0) + aw_err("vib_f0_d2s_gain not found"); + val = of_property_read_u32_array(np, "aw8624x_vib_trig_config", trig_config_temp, + ARRAY_SIZE(trig_config_temp)); + if (val != 0) + aw_info("vib_trig_config not found"); + else + memcpy(aw_haptic->info.trig_cfg, trig_config_temp, sizeof(trig_config_temp)); + val = of_property_read_u32_array(np, "aw8624x_vib_duration_time", duration_time, + ARRAY_SIZE(duration_time)); + if (val != 0) + aw_info("aw8624x_duration_time not found"); + else + memcpy(aw_haptic->info.duration_time, duration_time, sizeof(duration_time)); + aw_haptic->info.is_enabled_track_en = + of_property_read_bool(np, "aw8624x_vib_is_enabled_track_en"); + aw_info("aw_haptic->info.is_enabled_track_en = %d", aw_haptic->info.is_enabled_track_en); + aw_haptic->info.is_enabled_smart_loop = + of_property_read_bool(np, "aw8624x_vib_is_enabled_smart_loop"); + aw_info("aw_haptic->info.is_enabled_smart_loop = %d", + aw_haptic->info.is_enabled_smart_loop); + aw_haptic->info.is_enabled_inter_brake = + of_property_read_bool(np, "aw8624x_vib_is_enabled_inter_brake"); + aw_info("aw_haptic->info.is_enabled_inter_brake = %d", + aw_haptic->info.is_enabled_inter_brake); + aw_haptic->info.is_enabled_auto_brk = + of_property_read_bool(np, "aw8624x_vib_is_enabled_auto_brk"); + aw_info("aw_haptic->info.is_enabled_auto_brk = %d", + aw_haptic->info.is_enabled_auto_brk); +} + +static void aw8624x_get_wav_seq(struct aw_haptic *aw_haptic, uint32_t len) +{ + if (len > AW_SEQUENCER_SIZE) + len = AW_SEQUENCER_SIZE; + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_WAVCFG1, aw_haptic->seq, len); +} + +static void aw8624x_set_wav_seq(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t seq) +{ + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_WAVCFG1 + wav, &seq, AW_I2C_BYTE_ONE); +} + +static void aw8624x_set_wav_loop(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t loop) +{ + uint8_t tmp = 0; + + if (wav % 2) { + tmp = loop << 0; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_WAVCFG9 + (wav / 2), + AW8624X_BIT_WAVLOOP_SEQ_EVEN_MASK, tmp); + } else { + tmp = loop << 4; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_WAVCFG9 + (wav / 2), + AW8624X_BIT_WAVLOOP_SEQ_ODD_MASK, tmp); + } +} + +static void aw8624x_set_repeat_seq(struct aw_haptic *aw_haptic, uint8_t seq) +{ + aw8624x_set_wav_seq(aw_haptic, 0x00, seq); + aw8624x_set_wav_seq(aw_haptic, 0x01, 0x00); + aw8624x_set_wav_loop(aw_haptic, 0x00, AW8624X_BIT_WAVLOOP_INIFINITELY); +} + +static void aw8624x_get_gain(struct aw_haptic *aw_haptic, uint8_t *gain) +{ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_PLAYCFG2, gain, AW_I2C_BYTE_ONE); +} + +static void aw8624x_get_wav_loop(struct aw_haptic *aw_haptic, uint8_t *val) +{ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_WAVCFG9, val, AW_SEQUENCER_LOOP_SIZE); +} + +static void aw8624x_get_ram_data(struct aw_haptic *aw_haptic, uint8_t *ram_data, int size) +{ + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_RAMDATA, ram_data, size); +} + +static void aw8624x_get_lra_resistance(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t lra_code = 0; + int d2s_gain = 0; + + d2s_gain = aw8624x_select_d2s_gain(aw_haptic->info.d2s_gain); + if (d2s_gain <= 0) { + aw_err("d2s_gain is error"); + return; + } + aw8624x_raminit(aw_haptic, true); + /* enter standby mode */ + aw8624x_play_stop(aw_haptic); + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL2, AW8624X_BIT_SYSCTRL2_STANDBY_MASK, + AW8624X_BIT_SYSCTRL2_STANDBY_OFF); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_DETCFG1, AW8624X_BIT_DETCFG1_RL_OS_MASK, + AW8624X_BIT_DETCFG1_RL); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_DETCFG2, AW8624X_BIT_DETCFG2_DIAG_GO_MASK, + AW8624X_BIT_DETCFG2_DIAG_GO_ON); + usleep_range(AW_RL_DELAY_MIN, AW_RL_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_RL, ®_val, AW_I2C_BYTE_ONE); + lra_code = (lra_code | reg_val) << 2; + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_DET_LO, ®_val, AW_I2C_BYTE_ONE); + lra_code = lra_code | (reg_val & AW8624X_BIT_DET_LO_RL); + aw8624x_raminit(aw_haptic, false); + aw_haptic->lra = AW8624X_RL_FORMULA(lra_code, d2s_gain); + aw_info("aw_haptic->lra = %u", aw_haptic->lra); +} + +static uint8_t aw8624x_get_prctmode(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + reg_val >>= 7; + + return reg_val; +} + +static uint8_t aw8624x_judge_rtp_going(struct aw_haptic *aw_haptic) +{ + uint8_t glb_state = 0; + uint8_t rtp_state = 0; + + glb_state = aw8624x_get_glb_state(aw_haptic); + if (glb_state == AW_BIT_STATE_RTP_GO) { + rtp_state = 1; /*is going on */ + aw_info("rtp_routine_on"); + } + + return rtp_state; +} + +static uint64_t aw8624x_get_theory_time(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t fre_val = 0; + uint64_t theory_time = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSCTRL2, ®_val, AW_I2C_BYTE_ONE); + fre_val = reg_val & AW8624X_BIT_SYSCTRL2_RATE; + if (fre_val == AW8624X_BIT_SYSCTRL2_RATE_48K) + theory_time = aw_haptic->rtp_len * 1000 / 48; /*48K*/ + else if (fre_val == AW8624X_BIT_SYSCTRL2_RATE_24K) + theory_time = aw_haptic->rtp_len * 1000 / 24; /*24K*/ + else + theory_time = aw_haptic->rtp_len * 1000 / 12 ; /*12K*/ + aw_info("microsecond:%llu theory_time = %llu", aw_haptic->microsecond, theory_time); + + return theory_time; +} + +static uint8_t aw8624x_get_osc_status(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_SYSST2, &state, AW_I2C_BYTE_ONE); + state &= AW8624X_BIT_SYSST2_FF_EMPTY; + + return state; +} + +static int aw8624x_check_qualify(struct aw_haptic *aw_haptic) +{ + uint8_t reg = 0; + int ret = 0; + + aw_info("enter"); + ret = haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_EFRD9, ®, AW_I2C_BYTE_ONE); + if (ret < 0) + return ret; + if ((reg & 0x80) == 0x80) + return 0; + aw_err("register 0x64 error: 0x%02X", reg); + + return -ERANGE; +} + +static ssize_t cont_drv_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_lvl = 0x%02X, cont_drv2_lvl = 0x%02X\n", + aw_haptic->info.cont_drv1_lvl, aw_haptic->info.cont_drv2_lvl); + + return len; +} + +static ssize_t cont_drv_lvl_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_lvl = databuf[0]; + aw_haptic->info.cont_drv2_lvl = databuf[1]; + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG6, + AW8624X_BIT_CONTCFG6_DRV1_LVL_MASK, + (uint8_t)aw_haptic->info.cont_drv1_lvl); + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_CONTCFG7, + AW8624X_BIT_CONTCFG7_DRV2_LVL_MASK, + (uint8_t)aw_haptic->info.cont_drv2_lvl); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_drv_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_time = 0x%02X, cont_drv2_time = 0x%02X\n", + aw_haptic->info.cont_drv1_time, aw_haptic->info.cont_drv2_time); + + return len; +} + +static ssize_t cont_drv_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_val[2] = {0}; + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_time = databuf[0]; + aw_haptic->info.cont_drv2_time = databuf[1]; + reg_val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + reg_val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG8, reg_val, AW_I2C_BYTE_TWO); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_brk_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "cont_brk_time = 0x%02X\n", + aw_haptic->info.cont_brk_time); + + return len; +} + +static ssize_t cont_brk_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint8_t reg_val = 0; + int err, val; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + err = kstrtoint(buf, 16, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_brk_time = val; + reg_val = aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW8624X_REG_CONTCFG10, ®_val, AW_I2C_BYTE_ONE); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int i = 0; + ssize_t len = 0; + uint8_t trig_num = 3; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + for (i = 0; i < trig_num; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, "trig%d: trig_level=%u, trig_polar=%u", + i + 1, aw_haptic->trig[i].trig_level, + aw_haptic->trig[i].trig_polar); + len += snprintf(buf + len, PAGE_SIZE - len, "pos_enable=%u, pos_sequence=%u,", + aw_haptic->trig[i].pos_enable, aw_haptic->trig[i].pos_sequence); + len += snprintf(buf + len, PAGE_SIZE - len, + "neg_enable=%u, neg_sequence=%u trig_brk=%u\n", + aw_haptic->trig[i].neg_enable, aw_haptic->trig[i].neg_sequence, + aw_haptic->trig[i].trig_brk); + } + + return len; +} + +static ssize_t trig_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[9] = { 0 }; + + if (sscanf(buf, "%u %u %u %u %u %u %u %u", &databuf[0], &databuf[1], &databuf[2], + &databuf[3], &databuf[4], &databuf[5], &databuf[6], &databuf[7]) == 8) { + aw_info("%u, %u, %u, %u, %u, %u, %u, %u", databuf[0], databuf[1], databuf[2], + databuf[3], databuf[4], databuf[5], databuf[6], databuf[7]); + if (databuf[0] < 0 || databuf[0] > 2) { + aw_err("input seq value out of range!"); + return count; + } + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + if (databuf[4] > aw_haptic->ram.ram_num || databuf[6] > aw_haptic->ram.ram_num) { + aw_err("input seq value out of range!"); + return count; + } + aw_haptic->trig[databuf[0]].trig_level = databuf[1]; + aw_haptic->trig[databuf[0]].trig_polar = databuf[2]; + aw_haptic->trig[databuf[0]].pos_enable = databuf[3]; + aw_haptic->trig[databuf[0]].pos_sequence = databuf[4]; + aw_haptic->trig[databuf[0]].neg_enable = databuf[5]; + aw_haptic->trig[databuf[0]].neg_sequence = databuf[6]; + aw_haptic->trig[databuf[0]].trig_brk = databuf[7]; + mutex_lock(&aw_haptic->lock); + aw8624x_haptic_trig_param_config(aw_haptic, databuf[0]); + mutex_unlock(&aw_haptic->lock); + } else + aw_err("please input eight parameters"); + + return count; +} + +static ssize_t f0_d2s_gain_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw_haptic->lock); + switch (val) { + case 1: + aw_haptic->info.f0_d2s_gain = 0; + break; + case 2: + aw_haptic->info.f0_d2s_gain = 1; + break; + case 4: + aw_haptic->info.f0_d2s_gain = 2; + break; + case 5: + aw_haptic->info.f0_d2s_gain = 3; + break; + case 8: + aw_haptic->info.f0_d2s_gain = 4; + break; + case 10: + aw_haptic->info.f0_d2s_gain = 5; + break; + case 20: + aw_haptic->info.f0_d2s_gain = 6; + break; + case 40: + aw_haptic->info.f0_d2s_gain = 7; + break; + default: + aw_err("err f0_d2s_gain param"); + } + haptic_nv_i2c_write_bits(aw_haptic, AW8624X_REG_SYSCTRL6, + AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_MASK, + aw_haptic->info.f0_d2s_gain); + mutex_unlock(&aw_haptic->lock); + + return count; +} + + +static ssize_t f0_d2s_gain_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + int f0_d2s_gain = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + f0_d2s_gain = aw8624x_select_d2s_gain(aw_haptic->info.f0_d2s_gain); + len += snprintf(buf + len, PAGE_SIZE - len, "f0_d2s_gain = %d\n", f0_d2s_gain); + + return len; +} + +static DEVICE_ATTR_RW(cont_drv_lvl); +static DEVICE_ATTR_RW(cont_drv_time); +static DEVICE_ATTR_RW(cont_brk_time); +static DEVICE_ATTR_RW(trig); +static DEVICE_ATTR_RW(f0_d2s_gain); + +static struct attribute *aw8624x_vibrator_attributes[] = { + &dev_attr_cont_drv_lvl.attr, + &dev_attr_cont_drv_time.attr, + &dev_attr_cont_brk_time.attr, + &dev_attr_trig.attr, + &dev_attr_f0_d2s_gain.attr, + NULL +}; + +static struct attribute_group aw8624x_vibrator_attribute_group = { + .attrs = aw8624x_vibrator_attributes +}; + +static void aw8624x_creat_node(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &aw8624x_vibrator_attribute_group); + if (ret < 0) + aw_err("error create aw8624x sysfs attr files"); +} + +struct aw_haptic_func aw8624x_func_list = { + .ram_init = aw8624x_raminit, + .parse_dts = aw8624x_parse_dts, + .trig_init = aw8624x_trig_init, + .play_mode = aw8624x_play_mode, + .play_stop = aw8624x_play_stop, + .irq_clear = aw8624x_irq_clear, + .creat_node = aw8624x_creat_node, + .cont_config = aw8624x_cont_config, + .offset_cali = aw8624x_offset_cali, + .haptic_start = aw8624x_haptic_start, + .read_cont_f0 = aw8624x_read_cont_f0, + .check_qualify = aw8624x_check_qualify, + .judge_rtp_going = aw8624x_judge_rtp_going, + .protect_config = aw8624x_protect_config, + .misc_para_init = aw8624x_misc_para_init, + .interrupt_setup = aw8624x_interrupt_setup, + .rtp_get_fifo_afs = aw8624x_rtp_get_fifo_afs, + .rtp_get_fifo_aes = aw8624x_rtp_get_fifo_aes, + .vbat_mode_config = aw8624x_vbat_mode_config, + .calculate_cali_data = aw8624x_calculate_cali_data, + .set_gain = aw8624x_set_gain, + .get_gain = aw8624x_get_gain, + .set_wav_seq = aw8624x_set_wav_seq, + .get_wav_seq = aw8624x_get_wav_seq, + .set_wav_loop = aw8624x_set_wav_loop, + .get_wav_loop = aw8624x_get_wav_loop, + .set_ram_data = aw8624x_set_ram_data, + .get_ram_data = aw8624x_get_ram_data, + .set_fifo_addr = aw8624x_set_fifo_addr, + .get_fifo_addr = aw8624x_get_fifo_addr, + .set_rtp_aei = aw8624x_set_rtp_aei, + .set_rtp_data = aw8624x_set_rtp_data, + .set_ram_addr = aw8624x_set_ram_addr, + .set_trim_lra = aw8624x_set_trim_lra, + .set_base_addr = aw8624x_set_base_addr, + .set_repeat_seq = aw8624x_set_repeat_seq, + .get_f0 = aw8624x_get_f0, + .get_reg = aw8624x_get_reg, + .get_vbat = aw8624x_get_vbat, + .get_prctmode = aw8624x_get_prctmode, + .get_irq_state = aw8624x_get_irq_state, + .get_glb_state = aw8624x_get_glb_state, + .get_osc_status = aw8624x_get_osc_status, + .get_theory_time = aw8624x_get_theory_time, + .get_lra_resistance = aw8624x_get_lra_resistance, + .get_first_wave_addr = aw8624x_get_first_wave_addr, +}; diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862x.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862x.c new file mode 100644 index 000000000000..79ba98ce1853 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862x.c @@ -0,0 +1,1392 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * aw862x.c + * + * Copyright (c) 2021 AWINIC Technology CO., LTD + * + * Author: + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "haptic_nv.h" +#include "haptic_nv_reg.h" + +static int aw862x_get_irq_state(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint8_t glb_st = 0; + int ret = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_dbg("reg SYSINT=0x%02X", reg_val); + if (reg_val & AW862X_BIT_SYSINT_OCDI) + aw_err("chip over current int error"); + if (reg_val & AW862X_BIT_SYSINT_OTI) + aw_err("chip over temperature int error"); + if (reg_val & AW862X_BIT_SYSINT_DONEI) + aw_info("chip playback done"); + if (reg_val & AW862X_BIT_SYSINT_UVLI) { + aw_err("chip uvlo int error"); + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_GLB_STATE, &glb_st, AW_I2C_BYTE_ONE); + if (glb_st == 0) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, + AW862X_BIT_SYSINTM_UVLO_MASK, + AW862X_BIT_SYSINTM_UVLO_OFF); + } + } + if (reg_val & AW862X_BIT_SYSINT_FF_AFI) + aw_info("rtp mode fifo full"); + if (reg_val & AW862X_BIT_SYSINT_FF_AEI) { + aw_info("rtp fifo almost empty"); + ret = AW_IRQ_ALMOST_EMPTY; + } + + return ret; +} + +static void aw862x_interrupt_setup(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("reg SYSINT=0x%X", reg_val); + + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DBGCTRL, AW862X_BIT_DBGCTRL_INT_MODE_MASK, + AW862X_BIT_DBGCTRL_INT_MODE_EDGE); + + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, (AW862X_BIT_SYSINTM_OV_MASK & + AW862X_BIT_SYSINTM_UVLO_MASK & AW862X_BIT_SYSINTM_FF_AE_MASK & + AW862X_BIT_SYSINTM_FF_AF_MASK & AW862X_BIT_SYSINTM_OCD_MASK & + AW862X_BIT_SYSINTM_OT_MASK & AW862X_BIT_SYSINTM_DONE_MASK), + (AW862X_BIT_SYSINTM_OV_OFF | AW862X_BIT_SYSINTM_UVLO_EN | + AW862X_BIT_SYSINTM_FF_AE_OFF | AW862X_BIT_SYSINTM_FF_AF_OFF | + AW862X_BIT_SYSINTM_OCD_EN | AW862X_BIT_SYSINTM_OT_EN | + AW862X_BIT_SYSINTM_DONE_OFF)); +} + +static void aw862x_set_rtp_data(struct aw_haptic *aw_haptic, uint8_t *data, uint32_t len) +{ + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_RTP_DATA, data, len); +} + +static uint8_t aw862x_get_glb_state(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_GLB_STATE, &state, AW_I2C_BYTE_ONE); + + return state; +} + +static uint8_t aw862x_rtp_get_fifo_afs(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW862X_BIT_SYSST_FF_AFS; + reg_val = reg_val >> 3; + + return reg_val; +} + +static uint8_t aw862x_rtp_get_fifo_aes(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW862X_BIT_SYSST_FF_AES; + reg_val = reg_val >> 4; + + return reg_val; +} + +static void aw862x_set_rtp_aei(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, + AW862X_BIT_SYSINTM_FF_AE_MASK, + AW862X_BIT_SYSINTM_FF_AE_EN); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, + AW862X_BIT_SYSINTM_FF_AE_MASK, + AW862X_BIT_SYSINTM_FF_AE_OFF); + } +} + +static int aw862x_haptic_play_init(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + if (aw_haptic->play_mode == AW_CONT_MODE) + reg_val = (uint8_t)(aw_haptic->info.sw_brake[0]); + else + reg_val = (uint8_t)(aw_haptic->info.sw_brake[1]); + + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_SW_BRAKE, ®_val, AW_I2C_BYTE_ONE); + + return 0; +} + +static void aw862x_interrupt_clear(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("reg SYSINT=0x%2X", reg_val); +} + +static void aw862x_haptic_active(struct aw_haptic *aw_haptic) +{ + aw862x_haptic_play_init(aw_haptic); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, AW862X_BIT_SYSCTRL_WORK_MODE_MASK, + AW862X_BIT_SYSCTRL_ACTIVE); + aw862x_interrupt_clear(aw_haptic); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, AW862X_BIT_SYSINTM_UVLO_MASK, + AW862X_BIT_SYSINTM_UVLO_EN); +} + +static void aw862x_play_mode(struct aw_haptic *aw_haptic, uint8_t play_mode) +{ + switch (play_mode) { + case AW_STANDBY_MODE: + aw_info("enter standby mode"); + aw_haptic->play_mode = AW_STANDBY_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSINTM, + AW862X_BIT_SYSINTM_UVLO_MASK, AW862X_BIT_SYSINTM_UVLO_OFF); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_WORK_MODE_MASK, + AW862X_BIT_SYSCTRL_STANDBY); + break; + case AW_RAM_MODE: + aw_info("enter ram mode"); + aw_haptic->play_mode = AW_RAM_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_PLAY_MODE_MASK, + AW862X_BIT_SYSCTRL_PLAY_MODE_RAM); + aw862x_haptic_active(aw_haptic); + break; + case AW_RAM_LOOP_MODE: + aw_info("enter ram loop mode"); + aw_haptic->play_mode = AW_RAM_LOOP_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_PLAY_MODE_MASK, + AW862X_BIT_SYSCTRL_PLAY_MODE_RAM); + aw862x_haptic_active(aw_haptic); + break; + case AW_RTP_MODE: + aw_info("enter rtp mode"); + aw_haptic->play_mode = AW_RTP_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_PLAY_MODE_MASK, + AW862X_BIT_SYSCTRL_PLAY_MODE_RTP); + aw862x_haptic_active(aw_haptic); + break; + case AW_TRIG_MODE: + aw_info("enter trig mode"); + aw_haptic->play_mode = AW_TRIG_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_PLAY_MODE_MASK, + AW862X_BIT_SYSCTRL_PLAY_MODE_RAM); + aw862x_haptic_active(aw_haptic); + break; + case AW_CONT_MODE: + aw_info("enter cont mode"); + aw_haptic->play_mode = AW_CONT_MODE; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_PLAY_MODE_MASK, + AW862X_BIT_SYSCTRL_PLAY_MODE_CONT); + aw862x_haptic_active(aw_haptic); + break; + default: + aw_err("play mode %u error", play_mode); + break; + } +} + +static int aw862x_play_go(struct aw_haptic *aw_haptic, bool flag) +{ + uint8_t val = 0; + + aw_info("enter, flag = %d", flag); + if (!flag) { + aw_haptic->current_t = ktime_get(); + aw_haptic->interval_us = ktime_to_us(ktime_sub(aw_haptic->current_t, + aw_haptic->pre_enter_t)); + if (aw_haptic->interval_us < 2000) { + aw_info("interval_us=%u", aw_haptic->interval_us); + usleep_range(AW_PLAY_DELAY_MIN, AW_PLAY_DELAY_MAX); + } + } + if (flag == true) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_GO, AW862X_BIT_GO_MASK, + AW862X_BIT_GO_ENABLE); + aw_haptic->pre_enter_t = ktime_get(); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_GO, AW862X_BIT_GO_MASK, + AW862X_BIT_GO_DISABLE); + } + val = aw862x_get_glb_state(aw_haptic); + aw_info("reg:0x%02X=0x%02X", AW862X_REG_GLB_STATE, val); + + return 0; +} + +static int aw862x_stop_delay(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + int cnt = 100; + + while (cnt--) { + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_GLB_STATE, ®_val, AW_I2C_BYTE_ONE); + if ((reg_val & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + aw_info("enter standby,reg glb_state=0x%02X", reg_val); + return 0; + } + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + } + aw_err("do not enter standby automatically"); + + return 0; +} + +static void aw862x_play_stop(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw862x_play_go(aw_haptic, false); + aw862x_stop_delay(aw_haptic); + aw862x_play_mode(aw_haptic, AW_STANDBY_MODE); +} + +static void aw862x_haptic_start(struct aw_haptic *aw_haptic) +{ + aw862x_haptic_active(aw_haptic); + aw862x_play_go(aw_haptic, true); +} + +static void aw862x_raminit(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_RAMINIT_MASK, + AW862X_BIT_SYSCTRL_RAMINIT_EN); + usleep_range(1000, 1050); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_SYSCTRL, + AW862X_BIT_SYSCTRL_RAMINIT_MASK, + AW862X_BIT_SYSCTRL_RAMINIT_OFF); + } +} + +static void aw862x_get_vbat(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw862x_play_stop(aw_haptic); + /*step 1:EN_RAMINIT*/ + aw862x_raminit(aw_haptic, true); + /*step 2 :launch power supply testing */ + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DETCTRL, AW862X_BIT_DETCTRL_VBAT_GO_MASK, + AW862X_BIT_DETCTRL_VABT_GO_ENABLE); + usleep_range(AW_VBAT_DELAY_MIN, AW_VBAT_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_VBATDET, ®_val, AW_I2C_BYTE_ONE); + aw_haptic->vbat = AW862X_VBAT_FORMULA(reg_val); + aw_info("get_vbat=%dmV, vbat_code=0x%02X", aw_haptic->vbat, reg_val); + /*step 3: return val*/ + aw862x_raminit(aw_haptic, false); +} + +static void aw862x_set_gain(struct aw_haptic *aw_haptic, uint8_t gain) +{ + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_DATDBG, &gain, AW_I2C_BYTE_ONE); +} + +static void aw862x_set_trim_lra(struct aw_haptic *aw_haptic, uint8_t val) +{ + uint8_t reg_val = 0; + + reg_val = val & AW862X_BIT_TRIM_LRA; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TRIM_LRA, ®_val, AW_I2C_BYTE_ONE); +} + +static int aw862x_set_f0_preset(struct aw_haptic *aw_haptic, uint32_t f0_pre) +{ + uint32_t f0_reg = 0; + uint8_t reg_array[2] = {0}; + + if (!f0_pre || !aw_haptic->info.f0_coeff) { + aw_err("f0_pre or f0_coeff is error, f0_pre=%u, f0_coeff=%u", + f0_pre, aw_haptic->info.f0_coeff); + return -ERANGE; + } + f0_reg = 1000000000 / (f0_pre * aw_haptic->info.f0_coeff); + reg_array[0] = (uint8_t)((f0_reg >> 8) & 0xff); + reg_array[1] = (uint8_t)((f0_reg >> 0) & 0xff); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_F_PRE_H, reg_array, AW_I2C_BYTE_TWO); + + return 0; +} + +static void aw862x_cont_config(struct aw_haptic *aw_haptic) +{ + uint8_t brake0_level = 0; + uint8_t time_nzc = 0; + uint8_t en_brake1 = 0; + uint8_t brake1_level = 0; + uint8_t en_brake2 = 0; + uint8_t brake2_level = 0; + uint8_t brake2_num = 0; + uint8_t brake1_num = 0; + uint8_t brake0_num = 0; + uint8_t val[4] = {0}; + int ret = 0; + + aw_info("enter"); + aw862x_haptic_active(aw_haptic); + aw862x_play_mode(aw_haptic, AW_CONT_MODE); + /* preset f0 */ + if (aw_haptic->f0 <= 0) + ret = aw862x_set_f0_preset(aw_haptic, aw_haptic->info.f0_pre); + else + ret = aw862x_set_f0_preset(aw_haptic, aw_haptic->f0); + if (ret < 0) + return; + /* lpf */ + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DATCTRL, (AW862X_BIT_DATCTRL_FC_MASK & + AW862X_BIT_DATCTRL_LPF_ENABLE_MASK), + (AW862X_BIT_DATCTRL_FC_1000HZ | AW862X_BIT_DATCTRL_LPF_ENABLE)); + /* brake */ + en_brake1 = aw_haptic->info.cont_brake[0]; + en_brake2 = aw_haptic->info.cont_brake[1]; + brake0_level = aw_haptic->info.cont_brake[2]; + brake1_level = aw_haptic->info.cont_brake[3]; + brake2_level = aw_haptic->info.cont_brake[4]; + brake0_num = aw_haptic->info.cont_brake[5]; + brake1_num = aw_haptic->info.cont_brake[6]; + brake2_num = aw_haptic->info.cont_brake[7]; + val[0] = brake0_level << 0; + val[1] = (en_brake1 << 7)|(brake1_level << 0); + val[2] = (en_brake2 << 7)|(brake2_level << 0); + val[3] = (brake2_num << 6) | (brake1_num << 3) | (brake0_num << 0); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_BRAKE0_CTRL, val, AW_I2C_BYTE_FOUR); + /* cont config */ + val[0] = AW862X_BIT_CONT_CTRL_ZC_DETEC_ENABLE | AW862X_BIT_CONT_CTRL_WAIT_1PERIOD | + AW862X_BIT_CONT_CTRL_BY_GO_SIGNAL | AW862X_BIT_CONT_CTRL_CLOSE_PLAYBACK | + AW862X_BIT_CONT_CTRL_F0_DETECT_DISABLE | AW862X_BIT_CONT_CTRL_O2C_DISABLE; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_CONT_CTRL, val, AW_I2C_BYTE_ONE); + /* TD time */ + val[0] = (uint8_t)(aw_haptic->info.cont_td>>8); + val[1] = (uint8_t)(aw_haptic->info.cont_td>>0); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TD_H, val, AW_I2C_BYTE_TWO); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_BEMF_NUM, AW862X_BIT_BEMF_NUM_BRK_MASK, + aw_haptic->info.cont_num_brk); + time_nzc = AW862X_BIT_TIME_NZC_DEF_VAL; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TIME_NZC, &time_nzc, AW_I2C_BYTE_ONE); + /* f0 driver level */ + val[0] = aw_haptic->info.cont_drv1_lvl; + val[1] = aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_DRV_LVL, val, AW_I2C_BYTE_TWO); + aw862x_play_go(aw_haptic, true); +} + +static ssize_t aw862x_get_reg(struct aw_haptic *aw_haptic, ssize_t len, char *buf) +{ + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862X_REG_ID, AW862X_REG_RTP_DATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862X_REG_RTP_DATA + 1, + AW862X_REG_RAMDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862X_REG_RAMDATA + 1, + AW862X_REG_NUM_F0_3); + return len; +} + +static void aw862x_set_pwm(struct aw_haptic *aw_haptic, uint8_t mode) +{ + switch (mode) { + case AW_PWM_48K: + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_PWMDBG, + AW862X_BIT_PWMDBG_PWM_MODE_MASK, + AW862X_BIT_PWMDBG_PWM_48K); + break; + case AW_PWM_24K: + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_PWMDBG, + AW862X_BIT_PWMDBG_PWM_MODE_MASK, + AW862X_BIT_PWMDBG_PWM_24K); + break; + case AW_PWM_12K: + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_PWMDBG, + AW862X_BIT_PWMDBG_PWM_MODE_MASK, + AW862X_BIT_PWMDBG_PWM_12K); + break; + default: + break; + } +} + +static void aw862x_protect_config(struct aw_haptic *aw_haptic, uint8_t prtime, uint8_t prlvl) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_PWMPRC, AW862X_BIT_PWMPRC_PRC_EN_MASK, + AW862X_BIT_PWMPRC_PRC_DISABLE); + if (prlvl != 0) { + /* Enable protection mode */ + aw_info("enable protection mode"); + reg_val = AW862X_BIT_PRLVL_PR_ENABLE | (prlvl & (~AW862X_BIT_PRLVL_PRLVL_MASK)); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_PRLVL, ®_val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_PRTIME, &prtime, AW_I2C_BYTE_ONE); + } else { + /* Disable */ + aw_info("disable protection mode"); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_PRLVL, AW862X_BIT_PRLVL_PR_EN_MASK, + AW862X_BIT_PRLVL_PR_DISABLE); + } +} + +static void aw862x_misc_para_init(struct aw_haptic *aw_haptic) +{ + int ret = 0; + uint8_t reg_val = 0; + uint8_t reg_flag = 0; + uint8_t reg_array[8] = {0}; + + /* Get chipid_flag */ + ret = haptic_nv_i2c_reads(aw_haptic, AW862X_REG_EF_RDATAH, ®_flag, AW_I2C_BYTE_ONE); + if ((ret >= 0) && ((reg_flag & 0x1) == 1)) + aw_haptic->chipid_flag = 1; + else + aw_err("to read register AW862X_REG_EF_RDATAH: %d", ret); + /* Get seq and gain */ + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_DATDBG, ®_val, AW_I2C_BYTE_ONE); + aw_haptic->gain = reg_val & 0xFF; + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_WAVSEQ1, reg_array, AW_SEQUENCER_SIZE); + aw_haptic->index = reg_array[0] & 0x7F; + memcpy(aw_haptic->seq, reg_array, AW_SEQUENCER_SIZE); + /* r_spare */ + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_R_SPARE, AW862X_BIT_R_SPARE_MASK, + AW862X_BIT_R_SPARE_ENABLE); + /* LRA trim source select register */ + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_ANACTRL, AW862X_BIT_ANACTRL_LRA_SRC_MASK, + AW862X_BIT_ANACTRL_LRA_SRC_REG); + /* brake */ + reg_val = (uint8_t)aw_haptic->info.sw_brake[0]; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_SW_BRAKE, ®_val, AW_I2C_BYTE_ONE); + reg_val = 0x00; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_THRS_BRA_END, ®_val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_WAVECTRL, + AW862X_BIT_WAVECTRL_NUM_OV_DRIVER_MASK, + AW862X_BIT_WAVECTRL_NUM_OV_DRIVER); + /* zero cross */ + reg_array[0] = (uint8_t)(aw_haptic->info.cont_zc_thr >> 8); + reg_array[1] = (uint8_t)(aw_haptic->info.cont_zc_thr >> 0); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_ZC_THRSH_H, reg_array, AW_I2C_BYTE_TWO); + /* cont_tset */ + reg_val = (uint8_t)aw_haptic->info.cont_tset; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TSET, ®_val, AW_I2C_BYTE_ONE); + /* bemf */ + reg_array[0] = (uint8_t)(aw_haptic->info.bemf_config[0]); + reg_array[1] = (uint8_t)(aw_haptic->info.bemf_config[1]); + reg_array[2] = (uint8_t)(aw_haptic->info.bemf_config[2]); + reg_array[3] = (uint8_t)(aw_haptic->info.bemf_config[3]); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_BEMF_VTHH_H, reg_array, AW_I2C_BYTE_FOUR); + aw862x_set_pwm(aw_haptic, AW_PWM_24K); + aw862x_protect_config(aw_haptic, AW862X_REG_PRTIME_DEFAULT_VALUE, + AW862X_BIT_PRLVL_PRLVL_DEFAULT_VALUE); +} + +static int aw862x_offset_cali(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + int cont = 2000; + + aw_info("enter"); + + aw862x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DETCTRL, AW862X_BIT_DETCTRL_DIAG_GO_MASK, + AW862X_BIT_DETCTRL_DIAG_GO_ENABLE); + while (cont) { + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_DETCTRL, ®_val, AW_I2C_BYTE_ONE); + if ((reg_val & 0x01) == 0 || cont == 0) + break; + cont--; + } + aw862x_raminit(aw_haptic, false); + if (cont == 0) { + aw_err("calibration offset failed!"); + return -ERANGE; + } + + return 0; +} + +static void aw862x_vbat_mode_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + if (flag == AW_CONT_VBAT_HW_COMP_MODE) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_ADCTEST, + AW862X_BIT_DETCTRL_VBAT_MODE_MASK, + AW862X_BIT_DETCTRL_VBAT_HW_COMP); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_ADCTEST, + AW862X_BIT_DETCTRL_VBAT_MODE_MASK, + AW862X_BIT_DETCTRL_VBAT_SW_COMP); + } +} + +static void aw862x_calculate_cali_data(struct aw_haptic *aw_haptic) +{ + char f0_cali_lra = 0; + int f0_cali_step = 0; + uint8_t chipid_flag = aw_haptic->chipid_flag; + + f0_cali_step = 100000 * ((int)aw_haptic->f0 - (int)aw_haptic->info.f0_pre) / + ((int)aw_haptic->info.f0_pre * AW862X_F0_CALI_ACCURACY); + if (f0_cali_step >= 0) { + if (f0_cali_step % 10 >= 5) + f0_cali_step = f0_cali_step / 10 + 1 + (chipid_flag == 1 ? 32 : 16); + else + f0_cali_step = f0_cali_step / 10 + (chipid_flag == 1 ? 32 : 16); + } else { + if (f0_cali_step % 10 <= -5) + f0_cali_step = (chipid_flag == 1 ? 32 : 16) + (f0_cali_step / 10 - 1); + else + f0_cali_step = (chipid_flag == 1 ? 32 : 16) + f0_cali_step / 10; + } + if (chipid_flag == 1) { + if (f0_cali_step > 31) + f0_cali_lra = (char)f0_cali_step - 32; + else + f0_cali_lra = (char)f0_cali_step + 32; + } else { + if (f0_cali_step < 16 || (f0_cali_step > 31 && f0_cali_step < 48)) + f0_cali_lra = (char)f0_cali_step + 16; + else + f0_cali_lra = (char)f0_cali_step - 16; + } + if ((chipid_flag != 1) && (aw_haptic->f0 <= aw_haptic->info.f0_pre * 97 / 100)) + f0_cali_lra = 16; + aw_haptic->f0_cali_data = (int)f0_cali_lra; + aw_info("f0_cali_data=0x%02X", aw_haptic->f0_cali_data); +} + +static int aw862x_read_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_F_LRA_F0_H, val, AW_I2C_BYTE_TWO); + f0_reg = (val[0] << 8) | val[1]; + if (!f0_reg || !aw_haptic->info.f0_coeff) { + aw_haptic->f0 = 0; + aw_info("get f0 failed with the value becoming 0!"); + return -ERANGE; + } + f0_tmp = AW862X_F0_FORMULA(f0_reg, aw_haptic->info.f0_coeff); + aw_haptic->f0 = (uint32_t)f0_tmp; + aw_info("f0=%u", aw_haptic->f0); + + return 0; +} + +static void aw862x_read_beme(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_WAIT_VOL_MP, val, AW_I2C_BYTE_TWO); + aw_haptic->max_pos_beme = val[0]; + aw_haptic->max_neg_beme = val[1]; + aw_info("max_pos_beme=%u", aw_haptic->max_pos_beme); + aw_info("max_neg_beme=%u", aw_haptic->max_neg_beme); +} + +static int aw862x_get_f0(struct aw_haptic *aw_haptic) +{ + bool get_f0_flag = false; + uint8_t val[3] = {0}; + uint8_t f0_pre_num = 0; + uint8_t f0_wait_num = 0; + uint8_t f0_repeat_num = 0; + uint8_t f0_trace_num = 0; + uint32_t t_f0_ms = 0; + uint32_t t_f0_trace_ms = 0; + int ret = 0; + int cnt = 50; + + aw_info("enter"); + /* f0 calibrate work mode */ + aw862x_play_stop(aw_haptic); + aw862x_play_mode(aw_haptic, AW_CONT_MODE); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_CONT_CTRL, + (AW862X_BIT_CONT_CTRL_EN_CLOSE_MASK & + AW862X_BIT_CONT_CTRL_F0_DETECT_MASK), + (AW862X_BIT_CONT_CTRL_OPEN_PLAYBACK | + AW862X_BIT_CONT_CTRL_F0_DETECT_ENABLE)); + /* LPF */ + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DATCTRL, + (AW862X_BIT_DATCTRL_FC_MASK & AW862X_BIT_DATCTRL_LPF_ENABLE_MASK), + (AW862X_BIT_DATCTRL_FC_1000HZ | AW862X_BIT_DATCTRL_LPF_ENABLE)); + /* preset f0 */ + ret = aw862x_set_f0_preset(aw_haptic, aw_haptic->f0_pre); + if (ret < 0) + return -ERANGE; + /* f0 driver level */ + val[0] = (uint8_t)(aw_haptic->info.cont_drv1_lvl); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_DRV_LVL, &val[0], AW_I2C_BYTE_ONE); + /* f0 trace parameter */ + if (!aw_haptic->f0_pre) { + aw_info("fail to get t_f0_ms"); + return 0; + } + f0_pre_num = aw_haptic->info.f0_trace_parameter[0]; + f0_wait_num = aw_haptic->info.f0_trace_parameter[1]; + f0_repeat_num = aw_haptic->info.f0_trace_parameter[2]; + f0_trace_num = aw_haptic->info.f0_trace_parameter[3]; + val[0] = (f0_pre_num << 4)|(f0_wait_num << 0); + val[1] = f0_repeat_num << 0; + val[2] = f0_trace_num << 0; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_NUM_F0_1, val, AW_I2C_BYTE_THREE); + /* clear aw862x interrupt */ + ret = haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSINT, &val[0], AW_I2C_BYTE_ONE); + /* play go and start f0 calibration */ + aw862x_play_go(aw_haptic, true); + /* f0 trace time */ + t_f0_ms = 1000*10 / aw_haptic->f0_pre; + t_f0_trace_ms = t_f0_ms * (f0_pre_num + f0_wait_num + + (f0_trace_num + f0_wait_num) * (f0_repeat_num - 1)); + aw_info("t_f0_trace_ms = %dms", t_f0_trace_ms); + usleep_range(t_f0_trace_ms * 1000, t_f0_trace_ms * 1000 + 500); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_GLB_STATE, &val[0], AW_I2C_BYTE_ONE); + if (val[0] == AW_BIT_STATE_STANDBY) { + get_f0_flag = true; + aw_info("entered standby! glb_state=0x%02X", val[0]); + break; + } + cnt--; + aw_dbg("waitting for standby,glb_state=0x%02X", val[0]); + usleep_range(AW_F0_DELAY_MIN, AW_F0_DELAY_MAX); + } + if (get_f0_flag) { + ret = aw862x_read_f0(aw_haptic); + if (ret < 0) + aw_err("read lra f0 is failed"); + aw862x_read_beme(aw_haptic); + } else { + ret = -ERANGE; + aw_err("enter standby mode failed, stop reading f0!"); + } + + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_CONT_CTRL, + (AW862X_BIT_CONT_CTRL_EN_CLOSE_MASK & + AW862X_BIT_CONT_CTRL_F0_DETECT_MASK), + (AW862X_BIT_CONT_CTRL_CLOSE_PLAYBACK | + AW862X_BIT_CONT_CTRL_F0_DETECT_DISABLE)); + + return ret; +} + +#ifdef AW862X_MUL_GET_F0 +static int aw862x_multiple_get_f0(struct aw_haptic *aw_haptic) +{ + int i = 0; + int ret = 0; + int f0_max = aw_haptic->info.f0_pre + AW862X_MUL_GET_F0_RANGE; + int f0_min = aw_haptic->info.f0_pre - AW862X_MUL_GET_F0_RANGE; + + aw_haptic->f0_pre = aw_haptic->info.f0_pre; + for (i = 0; i < AW862X_MUL_GET_F0_NUM; i++) { + aw_info("f0_pre=%u", aw_haptic->f0_pre); + ret = aw862x_get_f0(aw_haptic); + if (ret) + return ret; + if (aw_haptic->f0 >= f0_max || aw_haptic->f0 <= f0_min) + break; + aw_haptic->f0_pre = aw_haptic->f0; + usleep_range(4000, 4500); + } + + return 0; +} +#endif + +static void aw862x_get_wav_seq(struct aw_haptic *aw_haptic, uint32_t len) +{ + if (len > AW_SEQUENCER_SIZE) + len = AW_SEQUENCER_SIZE; + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_WAVSEQ1, aw_haptic->seq, len); +} + +static void aw862x_set_wav_seq(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t seq) +{ + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_WAVSEQ1 + wav, &seq, AW_I2C_BYTE_ONE); +} + +static void aw862x_set_wav_loop(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t loop) +{ + uint8_t tmp = 0; + + if (wav % 2) { + tmp = loop << 0; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_WAVLOOP1 + (wav / 2), + AW862X_BIT_WAVLOOP_SEQNP1_MASK, tmp); + } else { + tmp = loop << 4; + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_WAVLOOP1 + (wav / 2), + AW862X_BIT_WAVLOOP_SEQN_MASK, tmp); + } + +} + +static void aw862x_set_repeat_seq(struct aw_haptic *aw_haptic, uint8_t seq) +{ + aw862x_set_wav_seq(aw_haptic, 0x00, seq); + aw862x_set_wav_seq(aw_haptic, 0x01, 0x00); + aw862x_set_wav_loop(aw_haptic, 0x00, AW862X_BIT_WAVLOOP_INIFINITELY); +} + +static void aw862x_get_gain(struct aw_haptic *aw_haptic, uint8_t *gain) +{ + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_DATDBG, gain, AW_I2C_BYTE_ONE); +} + +static void aw862x_get_wav_loop(struct aw_haptic *aw_haptic, uint8_t *val) +{ + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_WAVLOOP1, val, AW_SEQUENCER_LOOP_SIZE); +} + +static void aw862x_get_ram_data(struct aw_haptic *aw_haptic, uint8_t *ram_data, int size) +{ + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_RAMDATA, ram_data, size); +} + +static void aw862x_read_cont_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_F_LRA_CONT_H, val, AW_I2C_BYTE_TWO); + f0_reg = (val[0] << 8) | val[1]; + + if (!f0_reg) { + aw_haptic->cont_f0 = 0; + aw_info("failed to reading cont f0 with 0"); + return; + } + + f0_tmp = AW862X_F0_FORMULA(f0_reg, aw_haptic->info.f0_coeff); + aw_haptic->cont_f0 = (uint32_t)f0_tmp; + aw_info("cont_f0=%u", aw_haptic->cont_f0); +} + +static void aw862x_get_lra_resistance(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint8_t anactrl = 0; + uint8_t d2scfg = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_ANACTRL, &anactrl, AW_I2C_BYTE_ONE); + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_D2SCFG, &d2scfg, AW_I2C_BYTE_ONE); + aw862x_play_stop(aw_haptic); + aw862x_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_ANACTRL, AW862X_BIT_ANACTRL_EN_IO_PD1_MASK, + AW862X_BIT_ANACTRL_EN_IO_PD1_HIGH); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_D2SCFG, AW862X_BIT_D2SCFG_CLK_ADC_MASK, + AW862X_BIT_D2SCFG_CLK_ASC_1P5MHZ); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DETCTRL, (AW862X_BIT_DETCTRL_RL_OS_MASK & + AW862X_BIT_DETCTRL_DIAG_GO_MASK), (AW862X_BIT_DETCTRL_RL_DETECT | + AW862X_BIT_DETCTRL_DIAG_GO_ENABLE)); + usleep_range(AW_RL_DELAY_MIN, AW_RL_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_RLDET, ®_val, AW_I2C_BYTE_ONE); + aw_haptic->lra = AW862X_RL_FORMULA(reg_val); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_D2SCFG, &d2scfg, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_ANACTRL, &anactrl, AW_I2C_BYTE_ONE); + aw862x_raminit(aw_haptic, false); +} + +static uint8_t aw862x_get_prctmode(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_PRLVL, ®_val, AW_I2C_BYTE_ONE); + reg_val >>= 7; + + return reg_val; +} + +static uint8_t aw862x_judge_rtp_going(struct aw_haptic *aw_haptic) +{ + uint8_t glb_state = 0; + uint8_t rtp_state = 0; + + glb_state = aw862x_get_glb_state(aw_haptic); + if (glb_state == AW_BIT_STATE_RTP_GO) { + rtp_state = 1; /*is going on */ + aw_info("rtp_routine_on"); + } + + return rtp_state; +} + +static uint64_t aw862x_get_theory_time(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t fre_val = 0; + uint64_t theory_time = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_PWMDBG, ®_val, AW_I2C_BYTE_ONE); + fre_val = (reg_val & 0x006f) >> 5; + if (fre_val == AW862X_CLK_12K) + theory_time = (aw_haptic->rtp_len / 12) * 1000; /*12K*/ + else if (fre_val == AW862X_CLK_24K) + theory_time = (aw_haptic->rtp_len / 24) * 1000; /*24K*/ + else + theory_time = (aw_haptic->rtp_len / 48) * 1000; /*48K*/ + aw_info("microsecond:%llu theory_time = %llu", aw_haptic->microsecond, theory_time); + + return theory_time; +} + +static uint8_t aw862x_get_osc_status(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_DBGSTAT, &state, AW_I2C_BYTE_ONE); + state &= AW862X_BIT_SYSINT_DONEI; + + return state; +} + +static int aw862x_check_qualify(struct aw_haptic *aw_haptic) +{ + return 0; +} + +static void aw862x_irq_clear(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("SYSINT=0x%02X", reg_val); +} + +static void aw862x_set_base_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + aw_info("enter"); + val[0] = (uint8_t)AW_SET_BASEADDR_H(base_addr); + val[1] = (uint8_t)AW_SET_BASEADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_BASE_ADDRH, val, AW_I2C_BYTE_TWO); +} + +static void aw862x_set_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[4] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + aw_info("enter"); + val[0] = (uint8_t)AW862X_SET_AEADDR_H(base_addr); + val[1] = (uint8_t)AW862X_SET_AEADDR_L(base_addr); + val[2] = (uint8_t)AW862X_SET_AFADDR_H(base_addr); + val[3] = (uint8_t)AW862X_SET_AFADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_FIFO_AEH, val, AW_I2C_BYTE_FOUR); +} + +static void aw862x_get_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[4] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_FIFO_AEH, val, AW_I2C_BYTE_FOUR); + aw_info("almost_empty_threshold = %u, almost_full_threshold = %u", + (uint16_t)((val[0] << 8) | val[1]), (uint16_t)((val[2] << 8) | val[3])); +} + +static void aw862x_set_ram_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + aw_info("enter"); + val[0] = (uint8_t)AW_SET_RAMADDR_H(base_addr); + val[1] = (uint8_t)AW_SET_RAMADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_RAMADDRH, val, AW_I2C_BYTE_TWO); +} + +static void aw862x_set_ram_data(struct aw_haptic *aw_haptic, uint8_t *data, int len) +{ + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_RAMDATA, data, len); +} + +static void aw862x_get_first_wave_addr(struct aw_haptic *aw_haptic, uint32_t *first_wave_addr) +{ + uint8_t val[3] = {0}; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW862X_REG_RAMDATA, val, AW_I2C_BYTE_THREE); + *first_wave_addr = (val[1] << 8 | val[2]); +} + +static void aw862x_haptic_select_pin(struct aw_haptic *aw_haptic, uint8_t pin) +{ + if (pin == AW_TRIG1) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DBGCTRL, + AW862X_BIT_DBGCTRL_INTN_TRG_SEL_MASK, + AW862X_BIT_DBGCTRL_TRG_SEL_ENABLE); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_TRG_CFG2, + AW862X_BIT_TRGCFG2_TRG1_ENABLE_MASK, + AW862X_BIT_TRGCFG2_TRG1_ENABLE); + aw_info("select TRIG1 pin"); + } else if (pin == AW_IRQ) { + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_DBGCTRL, + AW862X_BIT_DBGCTRL_INTN_TRG_SEL_MASK, + AW862X_BIT_DBGCTRL_INTN_SEL_ENABLE); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_TRG_CFG2, + AW862X_BIT_TRGCFG2_TRG1_ENABLE_MASK, + AW862X_BIT_TRGCFG2_TRG1_DISABLE); + aw_info("select INIT pin"); + } else + aw_err("There is no such option"); +} + +static void aw862x_haptic_trig1_param_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw_haptic->trig[0].enable = aw_haptic->info.trig_cfg[0]; + aw_haptic->trig[0].trig_edge = aw_haptic->info.trig_cfg[1]; + aw_haptic->trig[0].trig_polar = aw_haptic->info.trig_cfg[2]; + aw_haptic->trig[0].pos_sequence = aw_haptic->info.trig_cfg[3]; + aw_haptic->trig[0].neg_sequence = aw_haptic->info.trig_cfg[4]; +} + +static void aw862x_haptic_trig1_param_config(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + if (!(aw_haptic->trig[0].enable) || (aw_haptic->is_used_irq_pin && + aw_haptic->name == AW8624)) { + aw862x_haptic_trig1_param_init(aw_haptic); + if (aw_haptic->name == AW8624) + aw862x_haptic_select_pin(aw_haptic, AW_IRQ); + return; + } + aw862x_haptic_select_pin(aw_haptic, AW_TRIG1); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_TRG_CFG1, AW862X_BIT_TRGCFG1_TRG1_EDGE_MASK, + aw_haptic->trig[0].trig_edge); + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_TRG_CFG1, AW862X_BIT_TRGCFG1_TRG1_POLAR_MASK, + aw_haptic->trig[0].trig_polar << 1); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TRG1_SEQP, + &aw_haptic->trig[0].pos_sequence, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TRG1_SEQN, + &aw_haptic->trig[0].neg_sequence, AW_I2C_BYTE_ONE); +} + +static void aw862x_haptic_set_trig1(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw862x_haptic_trig1_param_init(aw_haptic); + aw862x_haptic_trig1_param_config(aw_haptic); +} + +static void aw862x_trig_init(struct aw_haptic *aw_haptic) +{ + if (aw_haptic->is_used_irq_pin && aw_haptic->name == AW8624) { + aw862x_haptic_select_pin(aw_haptic, AW_IRQ); + return; + } + aw_info("enter"); + aw862x_haptic_set_trig1(aw_haptic); +} + +static void aw862x_parse_dts(struct aw_haptic *aw_haptic, struct device_node *np) +{ + uint32_t f0_trace_parameter[4]; + uint32_t brake_cont_config[24]; + uint32_t bemf_config[4]; + uint32_t sw_brake[2]; + uint32_t duration_time[3]; + uint32_t trig_config_temp[5]; + uint32_t val = 0; + + val = of_property_read_u32(np, "aw862x_vib_lk_f0_cali", &aw_haptic->info.lk_f0_cali); + if (val != 0) + aw_info("lk_f0_cali not found"); + val = of_property_read_u32(np, "aw862x_vib_mode", &aw_haptic->info.mode); + if (val != 0) + aw_info("vib mode not found"); + val = of_property_read_u32(np, "aw862x_vib_f0_pre", &aw_haptic->info.f0_pre); + if (val != 0) + aw_info("f0_pre not found"); + val = of_property_read_u32(np, "aw862x_vib_f0_cali_percen", + &aw_haptic->info.f0_cali_percent); + if (val != 0) + aw_info("f0_cali_percent not found"); + val = of_property_read_u32(np, "aw862x_vib_cont_drv_lev", &aw_haptic->info.cont_drv1_lvl); + if (val != 0) + aw_info("aw862x_vib_cont_drv_lev not found"); + val = of_property_read_u32(np, "aw862x_vib_cont_drv_lvl_ov", + &aw_haptic->info.cont_drv2_lvl); + if (val != 0) + aw_info("aw862x_vib_cont_drv_lvl_ov not found"); + val = of_property_read_u32(np, "aw862x_vib_cont_td", &aw_haptic->info.cont_td); + if (val != 0) + aw_info("aw862x_vib_cont_td not found"); + val = of_property_read_u32(np, "aw862x_vib_cont_zc_thr", &aw_haptic->info.cont_zc_thr); + if (val != 0) + aw_info("aw862x_vib_cont_zc_thr not found"); + val = of_property_read_u32(np, "aw862x_vib_cont_num_brk", &aw_haptic->info.cont_num_brk); + if (val != 0) + aw_info("aw862x_vib_cont_num_brk not found"); + val = of_property_read_u32(np, "aw862x_vib_f0_coeff", &aw_haptic->info.f0_coeff); + if (val != 0) + aw_info("aw862x_vib_f0_coeff not found"); + val = of_property_read_u32_array(np, "aw862x_vib_brake_cont_config", brake_cont_config, + ARRAY_SIZE(brake_cont_config)); + if (val != 0) + aw_info("aw862x_vib_brake_cont_config not found"); + else + memcpy(aw_haptic->info.cont_brake, brake_cont_config, sizeof(brake_cont_config)); + val = of_property_read_u32_array(np, "aw862x_vib_f0_trace_parameter", f0_trace_parameter, + ARRAY_SIZE(f0_trace_parameter)); + if (val != 0) + aw_info("aw862x_vib_f0_trace_parameter not found"); + else + memcpy(aw_haptic->info.f0_trace_parameter, f0_trace_parameter, + sizeof(f0_trace_parameter)); + val = of_property_read_u32_array(np, "aw862x_vib_bemf_config", bemf_config, + ARRAY_SIZE(bemf_config)); + if (val != 0) + aw_info("aw862x_vib_bemf_config not found"); + else + memcpy(aw_haptic->info.bemf_config, bemf_config, sizeof(bemf_config)); + val = of_property_read_u32_array(np, "aw862x_vib_sw_brake", sw_brake, ARRAY_SIZE(sw_brake)); + if (val != 0) + aw_info("aw862x_vib_sw_brake not found"); + else + memcpy(aw_haptic->info.sw_brake, sw_brake, sizeof(sw_brake)); + val = of_property_read_u32_array(np, "aw862x_vib_trig_config", trig_config_temp, + ARRAY_SIZE(trig_config_temp)); + if (val != 0) + aw_info("vib_trig_config not found"); + else + memcpy(aw_haptic->info.trig_cfg, trig_config_temp, sizeof(trig_config_temp)); + val = of_property_read_u32(np, "aw862x_vib_tset", &aw_haptic->info.cont_tset); + if (val != 0) + aw_info("aw862x_vib_tset not found"); + val = of_property_read_u32_array(np, "aw862x_vib_duration_time", duration_time, + ARRAY_SIZE(duration_time)); + if (val != 0) + aw_info("aw862x_vib_duration_time not found"); + else + memcpy(aw_haptic->info.duration_time, duration_time, sizeof(duration_time)); +} + +static ssize_t cont_td_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf+len, PAGE_SIZE-len, "cont_delay_time = 0x%04X\n", + aw_haptic->info.cont_td); + + return len; +} + +static ssize_t cont_td_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + int err, val; + uint8_t reg_array[2] = {0}; + + err = kstrtoint(buf, 16, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_td = val; + reg_array[0] = (uint8_t)(val >> 8); + reg_array[1] = (uint8_t)(val >> 0); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_TD_H, reg_array, AW_I2C_BYTE_TWO); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_drv_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf+len, PAGE_SIZE-len, "cont drv level = 0x%02X\n", + aw_haptic->info.cont_drv1_lvl); + len += snprintf(buf+len, PAGE_SIZE-len, "cont drv level overdrive= 0x%02X\n", + aw_haptic->info.cont_drv2_lvl); + + return len; +} + +static ssize_t cont_drv_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint8_t reg_array[2] = {0}; + uint32_t databuf[2] = {0}; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%X %X", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_lvl = databuf[0]; + aw_haptic->info.cont_drv2_lvl = databuf[1]; + reg_array[0] = aw_haptic->info.cont_drv1_lvl; + reg_array[1] = aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_DRV_LVL, reg_array, AW_I2C_BYTE_TWO); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_num_brk_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf+len, PAGE_SIZE-len, "cont_brk_num = 0x%02x\n", + aw_haptic->info.cont_num_brk); + + return len; +} + +static ssize_t cont_num_brk_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int err, val; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + err = kstrtoint(buf, 16, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_num_brk = val; + if (aw_haptic->info.cont_num_brk > 7) + aw_haptic->info.cont_num_brk = 7; + + haptic_nv_i2c_write_bits(aw_haptic, AW862X_REG_BEMF_NUM, AW862X_BIT_BEMF_NUM_BRK_MASK, + aw_haptic->info.cont_num_brk); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_zc_thr_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + ssize_t len = 0; + + len += snprintf(buf+len, PAGE_SIZE-len, "cont_zero_cross_thr = 0x%04X\n", + aw_haptic->info.cont_zc_thr); + + return len; +} + +static ssize_t cont_zc_thr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint8_t reg_array[2] = {0}; + int err, val; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + err = kstrtoint(buf, 0, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_num_brk = val; + aw_info("val=%d", val); + if (val > 0) { + reg_array[0] = (uint8_t)(val >> 8); + reg_array[1] = (uint8_t)(val >> 0); + haptic_nv_i2c_writes(aw_haptic, AW862X_REG_ZC_THRSH_H, reg_array, AW_I2C_BYTE_TWO); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "trig: trig_enable=%u, trig_edge=%u\n", + aw_haptic->trig[0].enable, aw_haptic->trig[0].trig_edge); + len += snprintf(buf + len, PAGE_SIZE - len, + "trig_polar=%u, pos_sequence=%u, neg_sequence=%u\n", + aw_haptic->trig[0].trig_polar, aw_haptic->trig[0].pos_sequence, + aw_haptic->trig[0].neg_sequence); + + return len; + +} + +static ssize_t trig_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t databuf[5] = { 0 }; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + if (sscanf(buf, "%u %u %u %u %u", &databuf[0], &databuf[1], &databuf[2], &databuf[3], + &databuf[4]) == 5) { + if (databuf[0] > 1) + databuf[0] = 1; + if (databuf[0] < 0) + databuf[0] = 0; + if (databuf[1] > 1) + databuf[0] = 1; + if (databuf[1] < 0) + databuf[0] = 0; + if (databuf[2] > 1) + databuf[0] = 1; + if (databuf[2] < 0) + databuf[0] = 0; + if (databuf[3] > aw_haptic->ram.ram_num || databuf[4] > aw_haptic->ram.ram_num) { + aw_err("input seq value out of range!"); + return count; + } + aw_haptic->trig[0].enable = databuf[0]; + aw_haptic->trig[0].trig_edge = databuf[1]; + aw_haptic->trig[0].trig_polar = databuf[2]; + aw_haptic->trig[0].pos_sequence = databuf[3]; + aw_haptic->trig[0].neg_sequence = databuf[4]; + mutex_lock(&aw_haptic->lock); + aw862x_haptic_trig1_param_config(aw_haptic); + mutex_unlock(&aw_haptic->lock); + } else + aw_err("please input five parameters"); + + return count; +} + +static DEVICE_ATTR_RW(cont_td); +static DEVICE_ATTR_RW(cont_drv); +static DEVICE_ATTR_RW(cont_num_brk); +static DEVICE_ATTR_RW(cont_zc_thr); +static DEVICE_ATTR_RW(trig); + +static struct attribute *aw862x_vibrator_attributes[] = { + &dev_attr_cont_td.attr, + &dev_attr_cont_drv.attr, + &dev_attr_cont_num_brk.attr, + &dev_attr_cont_zc_thr.attr, + &dev_attr_trig.attr, + NULL +}; + +static struct attribute_group aw862x_vibrator_attribute_group = { + .attrs = aw862x_vibrator_attributes +}; + +static void aw862x_creat_node(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &aw862x_vibrator_attribute_group); + if (ret < 0) + aw_err("error create aw862x sysfs attr files"); +} + +struct aw_haptic_func aw862x_func_list = { + .ram_init = aw862x_raminit, + .parse_dts = aw862x_parse_dts, + .trig_init = aw862x_trig_init, + .play_mode = aw862x_play_mode, + .play_stop = aw862x_play_stop, + .irq_clear = aw862x_irq_clear, + .creat_node = aw862x_creat_node, + .cont_config = aw862x_cont_config, + .offset_cali = aw862x_offset_cali, + .haptic_start = aw862x_haptic_start, + .read_cont_f0 = aw862x_read_cont_f0, + .check_qualify = aw862x_check_qualify, + .judge_rtp_going = aw862x_judge_rtp_going, + .protect_config = aw862x_protect_config, + .misc_para_init = aw862x_misc_para_init, + .interrupt_setup = aw862x_interrupt_setup, + .rtp_get_fifo_afs = aw862x_rtp_get_fifo_afs, + .rtp_get_fifo_aes = aw862x_rtp_get_fifo_aes, + .vbat_mode_config = aw862x_vbat_mode_config, + .calculate_cali_data = aw862x_calculate_cali_data, + .set_gain = aw862x_set_gain, + .get_gain = aw862x_get_gain, + .set_wav_seq = aw862x_set_wav_seq, + .get_wav_seq = aw862x_get_wav_seq, + .set_wav_loop = aw862x_set_wav_loop, + .get_wav_loop = aw862x_get_wav_loop, + .set_ram_data = aw862x_set_ram_data, + .get_ram_data = aw862x_get_ram_data, + .set_fifo_addr = aw862x_set_fifo_addr, + .get_fifo_addr = aw862x_get_fifo_addr, + .set_rtp_aei = aw862x_set_rtp_aei, + .set_rtp_data = aw862x_set_rtp_data, + .set_ram_addr = aw862x_set_ram_addr, + .set_trim_lra = aw862x_set_trim_lra, + .set_base_addr = aw862x_set_base_addr, + .set_repeat_seq = aw862x_set_repeat_seq, +#ifdef AW862X_MUL_GET_F0 + .get_f0 = aw862x_multiple_get_f0, +#else + .get_f0 = aw862x_get_f0, +#endif + .get_reg = aw862x_get_reg, + .get_vbat = aw862x_get_vbat, + .get_prctmode = aw862x_get_prctmode, + .get_irq_state = aw862x_get_irq_state, + .get_glb_state = aw862x_get_glb_state, + .get_osc_status = aw862x_get_osc_status, + .get_theory_time = aw862x_get_theory_time, + .get_lra_resistance = aw862x_get_lra_resistance, + .get_first_wave_addr = aw862x_get_first_wave_addr, +}; diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c new file mode 100644 index 000000000000..6d072b63cb52 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c @@ -0,0 +1,1444 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * aw862xx.c + * + * Copyright (c) 2021 AWINIC Technology CO., LTD + * + * Author: + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "haptic_nv.h" +#include "haptic_nv_reg.h" + +static void aw862xx_interrupt_setup(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_info("reg SYSINT=0x%02X", reg_val); + /* edge int mode */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL7, + (AW862XX_BIT_SYSCTRL7_INT_MODE_MASK & + AW862XX_BIT_SYSCTRL7_INT_EDGE_MODE_MASK), + (AW862XX_BIT_SYSCTRL7_INT_MODE_EDGE | + AW862XX_BIT_SYSCTRL7_INT_EDGE_MODE_POS)); + /* int enable */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSINTM, + (AW862XX_BIT_SYSINTM_UVLM_MASK & AW862XX_BIT_SYSINTM_FF_AEM_MASK & + AW862XX_BIT_SYSINTM_FF_AFM_MASK & AW862XX_BIT_SYSINTM_OCDM_MASK & + AW862XX_BIT_SYSINTM_OTM_MASK & AW862XX_BIT_SYSINTM_DONEM_MASK), + (AW862XX_BIT_SYSINTM_UVLM_ON | AW862XX_BIT_SYSINTM_FF_AEM_OFF | + AW862XX_BIT_SYSINTM_FF_AFM_OFF | AW862XX_BIT_SYSINTM_OCDM_ON | + AW862XX_BIT_SYSINTM_OTM_ON | AW862XX_BIT_SYSINTM_DONEM_OFF)); +} + +static void aw862xx_set_rtp_data(struct aw_haptic *aw_haptic, uint8_t *data, uint32_t len) +{ + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_RTPDATA, data, len); +} + +static uint8_t aw862xx_get_glb_state(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_GLBRD5, &state, AW_I2C_BYTE_ONE); + + return state; +} + +static int aw862xx_get_irq_state(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + int ret = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSINT, ®_val, AW_I2C_BYTE_ONE); + aw_dbg("reg SYSINT=0x%02X", reg_val); + if (reg_val & AW862XX_BIT_SYSINT_UVLI) + aw_err("chip uvlo int error"); + if (reg_val & AW862XX_BIT_SYSINT_OCDI) + aw_err("chip over current int error"); + if (reg_val & AW862XX_BIT_SYSINT_OTI) + aw_err("chip over temperature int error"); + if (reg_val & AW862XX_BIT_SYSINT_DONEI) + aw_info("chip playback done"); + if (reg_val & AW862XX_BIT_SYSINT_FF_AFI) + aw_info("rtp mode fifo almost full!"); + if (reg_val & AW862XX_BIT_SYSINT_FF_AEI) { + aw_info("rtp fifo almost empty"); + ret = AW_IRQ_ALMOST_EMPTY; + } + + return ret; +} + +static uint8_t aw862xx_rtp_get_fifo_afs(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW862XX_BIT_SYSST_FF_AFS; + reg_val = reg_val >> 3; + + return reg_val; +} + +static uint8_t aw862xx_rtp_get_fifo_aes(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSST, ®_val, AW_I2C_BYTE_ONE); + reg_val &= AW862XX_BIT_SYSST_FF_AES; + reg_val = reg_val >> 4; + + return reg_val; +} + +static void aw862xx_set_rtp_aei(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSINTM, + AW862XX_BIT_SYSINTM_FF_AEM_MASK, + AW862XX_BIT_SYSINTM_FF_AEM_ON); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSINTM, + AW862XX_BIT_SYSINTM_FF_AEM_MASK, + AW862XX_BIT_SYSINTM_FF_AEM_OFF); + } +} + +static void aw862xx_sram_size(struct aw_haptic *aw_haptic, uint8_t size_flag) +{ + switch (size_flag) { + case AW862XX_HAPTIC_SRAM_1K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_DIS); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + break; + case AW862XX_HAPTIC_SRAM_2K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_DIS); + break; + case AW862XX_HAPTIC_SRAM_3K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + break; + default: + aw_err("size_flag is error"); + break; + } +} + +static void aw862xx_auto_brk_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_BRK_EN_MASK, + AW862XX_BIT_PLAYCFG3_BRK_ENABLE); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_BRK_EN_MASK, + AW862XX_BIT_PLAYCFG3_BRK_DISABLE); + } +} + +static void aw862xx_config(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + aw862xx_sram_size(aw_haptic, AW862XX_HAPTIC_SRAM_3K); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_TRGCFG8, + AW862XX_BIT_TRGCFG8_TRG_TRIG1_MODE_MASK, + AW862XX_BIT_TRGCFG8_TRIG1); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_ANACFG8, + AW862XX_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK, + AW862XX_BIT_ANACFG8_TRTF_CTRL_HDRV); + if (aw_haptic->info.cont_brk_time) { + reg_val = (uint8_t)aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG10, ®_val, AW_I2C_BYTE_ONE); + } else { + aw_err("dts_info.cont_brk_time=0"); + } + if (aw_haptic->info.cont_brk_gain) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG5, + AW862XX_BIT_CONTCFG5_BRK_GAIN_MASK, + aw_haptic->info.cont_brk_gain); + } else { + aw_err("dts_info.cont_brk_gain=0"); + } + +} + +static void aw862xx_play_stop(struct aw_haptic *aw_haptic) +{ + bool force_flag = true; + uint8_t val = 0; + int cnt = 40; + + aw_info("enter"); + aw_haptic->play_mode = AW_STANDBY_MODE; + val = AW862XX_BIT_PLAYCFG4_STOP_ON; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_GLBRD5, &val, AW_I2C_BYTE_ONE); + if ((val & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + force_flag = false; + aw_info("entered standby! glb_state=0x%02X", val); + break; + } + cnt--; + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + } + if (force_flag) { + aw_err("force to enter standby mode!"); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_STANDBY_MASK, + AW862XX_BIT_SYSCTRL2_STANDBY_ON); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_STANDBY_MASK, + AW862XX_BIT_SYSCTRL2_STANDBY_OFF); + } +} + +static void aw862xx_set_pwm(struct aw_haptic *aw_haptic, uint8_t mode) +{ + switch (mode) { + case AW_PWM_48K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW862XX_BIT_SYSCTRL2_RATE_48K); + break; + case AW_PWM_24K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW862XX_BIT_SYSCTRL2_RATE_24K); + break; + case AW_PWM_12K: + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW862XX_BIT_SYSCTRL2_RATE_12K); + break; + default: + break; + } +} + +static void aw862xx_play_mode(struct aw_haptic *aw_haptic, uint8_t play_mode) +{ + switch (play_mode) { + case AW_STANDBY_MODE: + aw_info("enter standby mode"); + aw_haptic->play_mode = AW_STANDBY_MODE; + aw862xx_play_stop(aw_haptic); + break; + case AW_RAM_MODE: + aw_info("enter ram mode"); + aw_haptic->play_mode = AW_RAM_MODE; + aw862xx_set_pwm(aw_haptic, AW_PWM_12K); + aw862xx_auto_brk_config(aw_haptic, false); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_RAM_LOOP_MODE: + aw_info("enter ram loop mode"); + aw_haptic->play_mode = AW_RAM_LOOP_MODE; + aw862xx_set_pwm(aw_haptic, AW_PWM_12K); + aw862xx_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + case AW_CONT_MODE: + aw_info("enter cont mode"); + aw_haptic->play_mode = AW_CONT_MODE; + aw862xx_auto_brk_config(aw_haptic, aw_haptic->info.is_enabled_auto_brk); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_CONT); + break; + case AW_RTP_MODE: + aw_info("enter rtp mode"); + aw_haptic->play_mode = AW_RTP_MODE; + aw862xx_set_pwm(aw_haptic, AW_PWM_24K); + aw862xx_auto_brk_config(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_RTP); + break; + case AW_TRIG_MODE: + aw_info("enter trig mode"); + aw_haptic->play_mode = AW_TRIG_MODE; + aw862xx_set_pwm(aw_haptic, AW_PWM_12K); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW862XX_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + default: + aw_err("play mode %u error", play_mode); + break; + } +} + +static void aw862xx_irq_clear(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSINT, &val, AW_I2C_BYTE_ONE); + aw_info("SYSINT=0x%02X", val); +} + +static void aw862xx_play_go(struct aw_haptic *aw_haptic, bool flag) +{ + uint8_t val = 0; + + aw_info("enter"); + if (flag == true) { + val = AW862XX_BIT_PLAYCFG4_GO_ON; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + usleep_range(AW_PLAY_DELAY_MIN, AW_PLAY_DELAY_MAX); + } else { + val = AW862XX_BIT_PLAYCFG4_STOP_ON; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PLAYCFG4, &val, AW_I2C_BYTE_ONE); + } + val = aw862xx_get_glb_state(aw_haptic); + aw_info("reg:0x%02X=0x%02X", AW862XX_REG_GLBRD5, val); +} + +static void aw862xx_haptic_start(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw862xx_play_go(aw_haptic, true); +} + +static void aw862xx_raminit(struct aw_haptic *aw_haptic, bool flag) +{ + if (flag) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL1, + AW862XX_BIT_SYSCTRL1_RAMINIT_MASK, + AW862XX_BIT_SYSCTRL1_RAMINIT_ON); + usleep_range(1000, 1050); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL1, + AW862XX_BIT_SYSCTRL1_RAMINIT_MASK, + AW862XX_BIT_SYSCTRL1_RAMINIT_OFF); + } +} + +static void aw862xx_get_vbat(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t vbat_code = 0; + + aw_info("enter"); + aw862xx_play_stop(aw_haptic); + aw862xx_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_DETCFG2, AW862XX_BIT_DETCFG2_VBAT_GO_MASK, + AW862XX_BIT_DETCFG2_VABT_GO_ON); + usleep_range(AW_VBAT_DELAY_MIN, AW_VBAT_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_VBAT, ®_val, AW_I2C_BYTE_ONE); + vbat_code = (vbat_code | reg_val) << 2; + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_LO, ®_val, AW_I2C_BYTE_ONE); + vbat_code = vbat_code | ((reg_val & AW862XX_BIT_DET_LO_VBAT) >> 4); + aw_haptic->vbat = AW862XX_VBAT_FORMULA(vbat_code); + if (aw_haptic->vbat > AW_VBAT_MAX) { + aw_haptic->vbat = AW_VBAT_MAX; + aw_info("vbat max limit = %dmV", aw_haptic->vbat); + } + if (aw_haptic->vbat < AW_VBAT_MIN) { + aw_haptic->vbat = AW_VBAT_MIN; + aw_info("vbat min limit = %dmV", aw_haptic->vbat); + } + aw_info("vbat=%dmV, vbat_code=0x%02X", aw_haptic->vbat, vbat_code); + aw862xx_raminit(aw_haptic, false); +} + +static void aw862xx_set_gain(struct aw_haptic *aw_haptic, uint8_t gain) +{ + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PLAYCFG2, &gain, AW_I2C_BYTE_ONE); +} + +static void aw862xx_set_trim_lra(struct aw_haptic *aw_haptic, uint8_t val) +{ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_TRIMCFG3, + AW862XX_BIT_TRIMCFG3_TRIM_LRA_MASK, val); +} + +static void aw862xx_cont_config(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + aw_info("enter"); + /* work mode */ + aw862xx_play_mode(aw_haptic, AW_CONT_MODE); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG6, + (AW862XX_BIT_CONTCFG6_TRACK_EN_MASK & + AW862XX_BIT_CONTCFG6_DRV1_LVL_MASK), + ((aw_haptic->info.is_enabled_track_en << 7) | + (uint8_t)aw_haptic->info.cont_drv1_lvl)); + reg_val = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG7, ®_val, AW_I2C_BYTE_ONE); + /* DRV2_TIME */ + reg_val = 0xFF; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG9, ®_val, AW_I2C_BYTE_ONE); + /* cont play go */ + aw862xx_play_go(aw_haptic, true); +} + +static ssize_t aw862xx_get_reg(struct aw_haptic *aw_haptic, ssize_t len, char *buf) +{ + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862XX_REG_ID, + AW862XX_REG_RTPDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862XX_REG_RTPDATA + 1, + AW862XX_REG_RAMDATA - 1); + if (!len) + return len; + len = haptic_nv_read_reg_array(aw_haptic, buf, len, AW862XX_REG_RAMDATA + 1, + AW862XX_REG_ANACFG8); + + return len; +} + +static void aw862xx_protect_config(struct aw_haptic *aw_haptic, uint8_t prtime, uint8_t prlvl) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PWMCFG1, AW862XX_BIT_PWMCFG1_PRC_EN_MASK, + AW862XX_BIT_PWMCFG1_PRC_DISABLE); + if (prlvl != 0) { + /* Enable protection mode */ + aw_info("enable protection mode"); + reg_val = AW862XX_BIT_PWMCFG3_PR_ENABLE | + (prlvl & (~AW862XX_BIT_PWMCFG3_PRLVL_MASK)); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_PWMCFG4, &prtime, AW_I2C_BYTE_ONE); + } else { + /* Disable */ + aw_info("disable protection mode"); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PWMCFG3, + AW862XX_BIT_PWMCFG3_PR_EN_MASK, + AW862XX_BIT_PWMCFG3_PR_DISABLE); + } +} + +static void aw862xx_misc_para_init(struct aw_haptic *aw_haptic) +{ + uint8_t val = 0; + uint8_t array[8] = {0}; + + aw_info("enter"); + /* Get seq and gain */ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_WAVCFG1, &val, AW_I2C_BYTE_ONE); + aw_haptic->index = val & AW862XX_BIT_WAVCFG_SEQ; + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_PLAYCFG2, &val, AW_I2C_BYTE_ONE); + aw_haptic->gain = val; + aw_info("gain=0x%02X, index=0x%02X", aw_haptic->gain, aw_haptic->index); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_WAVCFG1, array, AW_SEQUENCER_SIZE); + memcpy(aw_haptic->seq, array, AW_SEQUENCER_SIZE); + /* GAIN_BYPASS config */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL7, + AW862XX_BIT_SYSCTRL7_GAIN_BYPASS_MASK, + aw_haptic->info.gain_bypass << 6); + + if (!aw_haptic->info.d2s_gain) { + aw_err("dts_info.d2s_gain = 0!"); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL7, + AW862XX_BIT_SYSCTRL7_D2S_GAIN_MASK, + aw_haptic->info.d2s_gain); + } + + aw_haptic->info.cont_drv2_lvl = AW862XX_DRV2_LVL_FORMULA(aw_haptic->info.f0_pre, + aw_haptic->info.lra_vrms); + aw_info("lra_vrms=%u, cont_drv2_lvl=0x%02X", aw_haptic->info.lra_vrms, + aw_haptic->info.cont_drv2_lvl); + if (aw_haptic->info.cont_drv2_lvl > AW862XX_DRV2_LVL_MAX) { + aw_err("cont_drv2_lvl[0x%02X] is error, restore max vale[0x%02X]", + aw_haptic->info.cont_drv2_lvl, AW862XX_DRV2_LVL_MAX); + aw_haptic->info.cont_drv2_lvl = AW862XX_DRV2_LVL_MAX; + } + aw862xx_config(aw_haptic); + aw862xx_set_pwm(aw_haptic, AW_PWM_12K); + aw862xx_protect_config(aw_haptic, AW862XX_PWMCFG4_PRTIME_DEFAULT_VALUE, + AW862XX_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE); +} + +static int aw862xx_select_d2s_gain(uint8_t reg) +{ + int d2s_gain = 0; + + switch (reg) { + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_1: + d2s_gain = 1; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_2: + d2s_gain = 2; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_4: + d2s_gain = 4; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_5: + d2s_gain = 5; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_8: + d2s_gain = 8; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_10: + d2s_gain = 10; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_20: + d2s_gain = 20; + break; + case AW862XX_BIT_SYSCTRL7_D2S_GAIN_40: + d2s_gain = 40; + break; + default: + d2s_gain = -1; + break; + } + + return d2s_gain; +} + +static int aw862xx_offset_cali(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val[2] = {0}; + int os_code = 0; + int d2s_gain = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSCTRL7, reg_val, AW_I2C_BYTE_ONE); + reg_val[0] = (~AW862XX_BIT_SYSCTRL7_D2S_GAIN_MASK) & reg_val[0]; + d2s_gain = aw862xx_select_d2s_gain(reg_val[0]); + if (d2s_gain < 0) { + aw_err("d2s_gain is error"); + return -ERANGE; + } + aw862xx_raminit(aw_haptic, true); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_DETCFG1, AW862XX_BIT_DETCFG1_RL_OS_MASK, + AW862XX_BIT_DETCFG1_OS); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_DETCFG2, AW862XX_BIT_DETCFG2_DIAG_GO_MASK, + AW862XX_BIT_DETCFG2_DIAG_GO_ON); + usleep_range(3000, 3500); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_OS, ®_val[0], AW_I2C_BYTE_ONE); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_LO, ®_val[1], AW_I2C_BYTE_ONE); + aw862xx_raminit(aw_haptic, false); + os_code = (reg_val[1] & (~AW862XX_BIT_DET_LO_OS_MASK)) >> 2; + os_code = (reg_val[0] << 2) | os_code; + os_code = AW862XX_OS_FORMULA(os_code, d2s_gain); + aw_info("os_code is %d mV", os_code); + if (os_code > 15 || os_code < -15) + return -ERANGE; + + return 0; +} + +static void aw862xx_vbat_mode_config(struct aw_haptic *aw_haptic, uint8_t flag) +{ + uint8_t val = 0; + + aw_info("enter"); + if (flag == AW_CONT_VBAT_HW_COMP_MODE) { + val = AW862XX_BIT_GLBCFG2_START_DLY_250US; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_GLBCFG2, &val, AW_I2C_BYTE_ONE); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL1, + AW862XX_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW862XX_BIT_SYSCTRL1_VBAT_MODE_HW); + } else { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL1, + AW862XX_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW862XX_BIT_SYSCTRL1_VBAT_MODE_SW); + } +} + +static void aw862xx_calculate_cali_data(struct aw_haptic *aw_haptic) +{ + char f0_cali_lra = 0; + int f0_cali_step = 0; + + f0_cali_step = 100000 * ((int)aw_haptic->f0 - (int)aw_haptic->info.f0_pre) / + ((int)aw_haptic->info.f0_pre * AW862XX_F0_CALI_ACCURACY); + aw_info("f0_cali_step=%d", f0_cali_step); + if (f0_cali_step >= 0) { /*f0_cali_step >= 0 */ + if (f0_cali_step % 10 >= 5) + f0_cali_step = 32 + (f0_cali_step / 10 + 1); + else + f0_cali_step = 32 + f0_cali_step / 10; + } else { /* f0_cali_step < 0 */ + if (f0_cali_step % 10 <= -5) + f0_cali_step = 32 + (f0_cali_step / 10 - 1); + else + f0_cali_step = 32 + f0_cali_step / 10; + } + if (f0_cali_step > 31) + f0_cali_lra = (char)f0_cali_step - 32; + else + f0_cali_lra = (char)f0_cali_step + 32; + /* update cali step */ + aw_haptic->f0_cali_data = (int)f0_cali_lra; + aw_info("f0_cali_data=0x%02X", aw_haptic->f0_cali_data); +} + +static void aw862xx_read_cont_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_CONTRD16, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_err("didn't get cont f0 because f0_reg value is 0!"); + aw_haptic->cont_f0 = 0; + return; + } + f0_tmp = AW862XX_F0_FORMULA(f0_reg); + aw_haptic->cont_f0 = (uint32_t)f0_tmp; + aw_info("cont_f0=%u", aw_haptic->cont_f0); +} + +static int aw862xx_read_lra_f0(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t f0_reg = 0; + uint64_t f0_tmp = 0; + + aw_info("enter"); + /* F_LRA_F0 */ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_CONTRD14, val, AW_I2C_BYTE_TWO); + f0_reg = (f0_reg | val[0]) << 8; + f0_reg |= (val[1] << 0); + if (!f0_reg) { + aw_haptic->f0 = 0; + aw_err("didn't get lra f0 because f0_reg value is 0!"); + return -ERANGE; + } + f0_tmp = AW862XX_F0_FORMULA(f0_reg); + aw_haptic->f0 = (uint32_t)f0_tmp; + aw_info("lra_f0=%u", aw_haptic->f0); + + return 0; +} + +static int aw862xx_get_f0(struct aw_haptic *aw_haptic) +{ + bool get_f0_flag = false; + uint8_t brk_en_temp = 0; + uint8_t val[3] = {0}; + int drv_width = 0; + int cnt = 200; + int ret = 0; + + aw_info("enter"); + aw_haptic->f0 = aw_haptic->info.f0_pre; + /* enter standby mode */ + aw862xx_play_stop(aw_haptic); + /* f0 calibrate work mode */ + aw862xx_play_mode(aw_haptic, AW_CONT_MODE); + /* enable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG1, + AW862XX_BIT_CONTCFG1_EN_F0_DET_MASK, + AW862XX_BIT_CONTCFG1_F0_DET_ENABLE); + /* cont config */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG6, + AW862XX_BIT_CONTCFG6_TRACK_EN_MASK, + (aw_haptic->info.is_enabled_track_en << 7)); + /* enable auto brake */ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_PLAYCFG3, &val[0], AW_I2C_BYTE_ONE); + brk_en_temp = AW862XX_BIT_PLAYCFG3_BRK & val[0]; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, AW862XX_BIT_PLAYCFG3_BRK_EN_MASK, + AW862XX_BIT_PLAYCFG3_BRK_ENABLE); + /* f0 driver level */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG6, + AW862XX_BIT_CONTCFG6_DRV1_LVL_MASK, aw_haptic->info.cont_drv1_lvl); + val[0] = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG7, val, AW_I2C_BYTE_ONE); + val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG8, val, AW_I2C_BYTE_TWO); + /* TRACK_MARGIN */ + if (!aw_haptic->info.cont_track_margin) { + aw_err("dts_info.cont_track_margin = 0!"); + } else { + val[0] = (uint8_t)aw_haptic->info.cont_track_margin; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG11, &val[0], AW_I2C_BYTE_ONE); + } + /* DRV_WIDTH */ + if (!aw_haptic->info.f0_pre) + return -ERANGE; + drv_width = AW862XX_DRV_WIDTH_FORMULA(aw_haptic->info.f0_pre, + aw_haptic->info.cont_track_margin, + aw_haptic->info.cont_brk_gain); + if (drv_width < AW_DRV_WIDTH_MIN) + drv_width = AW_DRV_WIDTH_MIN; + if (drv_width > AW_DRV_WIDTH_MAX) + drv_width = AW_DRV_WIDTH_MAX; + val[0] = (uint8_t)drv_width; + aw_info("cont_drv_width=0x%02X", val[0]); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG3, &val[0], AW_I2C_BYTE_ONE); + /* cont play go */ + aw862xx_play_go(aw_haptic, true); + usleep_range(20000, 20500); + while (cnt) { + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_GLBRD5, &val[0], AW_I2C_BYTE_ONE); + if ((val[0] & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY) { + get_f0_flag = true; + aw_info("entered standby! glb_state=0x%02X", val[0]); + break; + } + cnt--; + aw_dbg("waitting for standby,glb_state=0x%02X", val[0]); + usleep_range(AW_F0_DELAY_MIN, AW_F0_DELAY_MAX); + } + if (get_f0_flag) { + ret = aw862xx_read_lra_f0(aw_haptic); + if (ret < 0) + aw_err("read lra f0 is failed"); + aw862xx_read_cont_f0(aw_haptic); + } else { + ret = -ERANGE; + aw_err("enter standby mode failed, stop reading f0!"); + } + /* disable f0 detect */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG1, + AW862XX_BIT_CONTCFG1_EN_F0_DET_MASK, + AW862XX_BIT_CONTCFG1_F0_DET_DISABLE); + /* recover auto break config */ + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, + AW862XX_BIT_PLAYCFG3_BRK_EN_MASK, brk_en_temp); + + return ret; +} + +static void aw862xx_set_base_addr(struct aw_haptic *aw_haptic) +{ + uint32_t base_addr = 0; + uint8_t val = 0; + + aw_info("enter"); + base_addr = aw_haptic->ram.base_addr; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_RTPCFG1, AW862XX_BIT_RTPCFG1_ADDRH_MASK, + (uint8_t)AW_SET_BASEADDR_H(base_addr)); + val = (uint8_t)AW_SET_BASEADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_RTPCFG2, &val, AW_I2C_BYTE_ONE); +} + +static void aw862xx_set_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t val[3] = {0}; + + aw_info("enter"); + ae_addr_h = (uint8_t)AW862XX_SET_AEADDR_H(aw_haptic->ram.base_addr); + af_addr_h = (uint8_t)AW862XX_SET_AFADDR_H(aw_haptic->ram.base_addr); + val[0] = ae_addr_h | af_addr_h; + val[1] = (uint8_t)AW862XX_SET_AEADDR_L(aw_haptic->ram.base_addr); + val[2] = (uint8_t)AW862XX_SET_AFADDR_L(aw_haptic->ram.base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); +} + +static void aw862xx_get_fifo_addr(struct aw_haptic *aw_haptic) +{ + uint8_t ae_addr_h = 0; + uint8_t af_addr_h = 0; + uint8_t ae_addr_l = 0; + uint8_t af_addr_l = 0; + uint8_t val[3] = {0}; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_RTPCFG3, val, AW_I2C_BYTE_THREE); + ae_addr_h = ((val[0]) & AW862XX_BIT_RTPCFG3_FIFO_AEH) >> 4; + ae_addr_l = val[1]; + af_addr_h = ((val[0]) & AW862XX_BIT_RTPCFG3_FIFO_AFH); + af_addr_l = val[2]; + aw_info("almost_empty_threshold = %u,almost_full_threshold = %u", + (uint16_t)((ae_addr_h << 8) | ae_addr_l), + (uint16_t)((af_addr_h << 8) | af_addr_l)); +} + +static void aw862xx_set_ram_addr(struct aw_haptic *aw_haptic) +{ + uint8_t val[2] = {0}; + uint32_t base_addr = aw_haptic->ram.base_addr; + + aw_info("enter"); + val[0] = (uint8_t)AW_SET_RAMADDR_H(base_addr); + val[1] = (uint8_t)AW_SET_RAMADDR_L(base_addr); + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_RAMADDRH, val, AW_I2C_BYTE_TWO); +} + +static void aw862xx_set_ram_data(struct aw_haptic *aw_haptic, uint8_t *data, int len) +{ + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_RAMDATA, data, len); +} + +static void aw862xx_get_first_wave_addr(struct aw_haptic *aw_haptic, uint32_t *first_wave_addr) +{ + uint8_t val[3] = {0}; + + aw_info("enter"); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_RAMDATA, val, AW_I2C_BYTE_THREE); + *first_wave_addr = (val[1] << 8 | val[2]); +} + +static void aw862xx_haptic_select_pin(struct aw_haptic *aw_haptic, uint8_t pin) +{ + if (pin == AW_TRIG1) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_INTN_PIN_MASK, + AW862XX_BIT_SYSCTRL2_TRIG1); + aw_info("select TRIG1 pin"); + } else if (pin == AW_IRQ) { + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, + AW862XX_BIT_SYSCTRL2_INTN_PIN_MASK, + AW862XX_BIT_SYSCTRL2_INTN); + aw_info("select INIT pin"); + } else + aw_err("There is no such option"); +} + +static void aw862xx_haptic_trig_param_init(struct aw_haptic *aw_haptic, uint8_t pin) +{ + struct aw_haptic_dts_info info = aw_haptic->info; + + switch (pin) { + case AW_TRIG1: + aw_haptic->trig[0].trig_level = info.trig_cfg[0]; + aw_haptic->trig[0].trig_polar = info.trig_cfg[1]; + aw_haptic->trig[0].pos_enable = info.trig_cfg[2]; + aw_haptic->trig[0].pos_sequence = info.trig_cfg[3]; + aw_haptic->trig[0].neg_enable = info.trig_cfg[4]; + aw_haptic->trig[0].neg_sequence = info.trig_cfg[5]; + aw_haptic->trig[0].trig_brk = info.trig_cfg[6]; + break; + case AW_TRIG2: + aw_haptic->trig[1].trig_level = info.trig_cfg[7 + 0]; + aw_haptic->trig[1].trig_polar = info.trig_cfg[7 + 1]; + aw_haptic->trig[1].pos_enable = info.trig_cfg[7 + 2]; + aw_haptic->trig[1].pos_sequence = info.trig_cfg[7 + 3]; + aw_haptic->trig[1].neg_enable = info.trig_cfg[7 + 4]; + aw_haptic->trig[1].neg_sequence = info.trig_cfg[7 + 5]; + aw_haptic->trig[1].trig_brk = info.trig_cfg[7 + 6]; + break; + case AW_TRIG3: + aw_haptic->trig[2].trig_level = info.trig_cfg[14 + 0]; + aw_haptic->trig[2].trig_polar = info.trig_cfg[14 + 1]; + aw_haptic->trig[2].pos_enable = info.trig_cfg[14 + 2]; + aw_haptic->trig[2].pos_sequence = info.trig_cfg[14 + 3]; + aw_haptic->trig[2].neg_enable = info.trig_cfg[14 + 4]; + aw_haptic->trig[2].neg_sequence = info.trig_cfg[14 + 5]; + aw_haptic->trig[2].trig_brk = info.trig_cfg[14 + 6]; + break; + default: + break; + } +} + +static int aw862xx_haptic_trig_param_config(struct aw_haptic *aw_haptic, uint8_t pin) +{ + uint8_t trig_polar_lev_brk = 0x00; + uint8_t trig_pos_seq = 0x00; + uint8_t trig_neg_seq = 0x00; + + if ((aw_haptic->name == AW86224 || aw_haptic->name == AW86225) && + aw_haptic->is_used_irq_pin) { + aw862xx_haptic_trig_param_init(aw_haptic, AW_TRIG1); + aw862xx_haptic_select_pin(aw_haptic, AW_IRQ); + return -ERANGE; + } + switch (pin) { + case AW_TRIG1: + if (aw_haptic->name == AW86224 || aw_haptic->name == AW86225) + aw862xx_haptic_select_pin(aw_haptic, AW_TRIG1); + trig_polar_lev_brk = aw_haptic->trig[0].trig_polar << 2 | + aw_haptic->trig[0].trig_level << 1 | + aw_haptic->trig[0].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_TRGCFG7, + AW862XX_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 5); + trig_pos_seq = aw_haptic->trig[0].pos_enable << 7 | aw_haptic->trig[0].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG1, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[0].neg_enable << 7 | aw_haptic->trig[0].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG4, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig1 config ok!"); + break; + case AW_TRIG2: + trig_polar_lev_brk = aw_haptic->trig[1].trig_polar << 2 | + aw_haptic->trig[1].trig_level << 1 | + aw_haptic->trig[1].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_TRGCFG7, + AW862XX_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 1); + trig_pos_seq = aw_haptic->trig[1].pos_enable << 7 | aw_haptic->trig[1].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG2, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[1].neg_enable << 7 | aw_haptic->trig[1].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG5, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig2 config ok!"); + break; + case AW_TRIG3: + trig_polar_lev_brk = aw_haptic->trig[2].trig_polar << 2 | + aw_haptic->trig[2].trig_level << 1 | + aw_haptic->trig[2].trig_brk; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_TRGCFG8, + AW862XX_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK, + trig_polar_lev_brk << 5); + trig_pos_seq = aw_haptic->trig[2].pos_enable << 7 | aw_haptic->trig[2].pos_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG3, + &trig_pos_seq, AW_I2C_BYTE_ONE); + trig_neg_seq = aw_haptic->trig[2].neg_enable << 7 | aw_haptic->trig[2].neg_sequence; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_TRGCFG6, + &trig_neg_seq, AW_I2C_BYTE_ONE); + aw_info("trig3 config ok!"); + break; + default: + break; + } + + return 0; +} + +static void aw862xx_set_trig(struct aw_haptic *aw_haptic, uint8_t pin) +{ + aw_info("enter"); + aw862xx_haptic_trig_param_init(aw_haptic, pin); + aw862xx_haptic_trig_param_config(aw_haptic, pin); +} + +static void aw862xx_trig_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + switch (aw_haptic->name) { + case AW86223: + aw862xx_set_trig(aw_haptic, AW_TRIG1); + aw862xx_set_trig(aw_haptic, AW_TRIG2); + aw862xx_set_trig(aw_haptic, AW_TRIG3); + break; + case AW86214: + case AW86224: + case AW86225: + aw862xx_set_trig(aw_haptic, AW_TRIG1); + break; + default: + break; + } +} + +static void aw862xx_parse_dts(struct aw_haptic *aw_haptic, struct device_node *np) +{ + uint32_t duration_time[3]; + uint32_t trig_config_temp[21]; + uint32_t val = 0; + + val = of_property_read_u32(np, "aw862xx_gain_bypass", &aw_haptic->info.gain_bypass); + if (val != 0) + aw_info("aw862xx_gain_bypass not found"); + val = of_property_read_u32(np, "aw862xx_vib_lk_f0_cali", &aw_haptic->info.lk_f0_cali); + if (val != 0) + aw_info("aw862xx_vib_lk_f0_cali not found"); + val = of_property_read_u32(np, "aw862xx_vib_mode", &aw_haptic->info.mode); + if (val != 0) + aw_info("aw862xx_vib_mode not found"); + val = of_property_read_u32(np, "aw862xx_vib_f0_pre", &aw_haptic->info.f0_pre); + if (val != 0) + aw_info("vib_f0_pre not found"); + val = of_property_read_u32(np, "aw862xx_vib_f0_cali_percen", + &aw_haptic->info.f0_cali_percent); + if (val != 0) + aw_info("vib_f0_cali_percent not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_drv1_lvl", &aw_haptic->info.cont_drv1_lvl); + if (val != 0) + aw_info("vib_cont_drv1_lvl not found"); + val = of_property_read_u32(np, "aw862xx_vib_lra_vrms", &aw_haptic->info.lra_vrms); + if (val != 0) + aw_info("vib_cont_lra_vrms not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_brk_time", &aw_haptic->info.cont_brk_time); + if (val != 0) + aw_info("vib_cont_brk_time not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_brk_gain", &aw_haptic->info.cont_brk_gain); + if (val != 0) + aw_info("vib_cont_brk_gain not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_drv1_time", + &aw_haptic->info.cont_drv1_time); + if (val != 0) + aw_info("vib_cont_drv1_time not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_drv2_time", + &aw_haptic->info.cont_drv2_time); + if (val != 0) + aw_info("vib_cont_drv2_time not found"); + val = of_property_read_u32(np, "aw862xx_vib_cont_track_margin", + &aw_haptic->info.cont_track_margin); + if (val != 0) + aw_info("vib_cont_track_margin not found"); + val = of_property_read_u32(np, "aw862xx_vib_d2s_gain", &aw_haptic->info.d2s_gain); + if (val != 0) + aw_info("vib_d2s_gain not found"); + val = of_property_read_u32_array(np, "aw862xx_vib_trig_config", trig_config_temp, + ARRAY_SIZE(trig_config_temp)); + if (val != 0) + aw_info("vib_trig_config not found"); + else + memcpy(aw_haptic->info.trig_cfg, trig_config_temp, sizeof(trig_config_temp)); + val = of_property_read_u32_array(np, "aw862xx_vib_duration_time", duration_time, + ARRAY_SIZE(duration_time)); + if (val != 0) + aw_info("aw862xx_duration_time not found"); + else + memcpy(aw_haptic->info.duration_time, duration_time, sizeof(duration_time)); + aw_haptic->info.is_enabled_track_en = + of_property_read_bool(np, "aw862xx_vib_is_enabled_track_en"); + aw_info("aw_haptic->info.is_enabled_track_en = %d", aw_haptic->info.is_enabled_track_en); + aw_haptic->info.is_enabled_auto_brk = + of_property_read_bool(np, "aw862xx_vib_is_enabled_auto_brk"); + aw_info("aw_haptic->info.is_enabled_auto_brk = %d", + aw_haptic->info.is_enabled_auto_brk); +} + +static void aw862xx_get_wav_seq(struct aw_haptic *aw_haptic, uint32_t len) +{ + if (len > AW_SEQUENCER_SIZE) + len = AW_SEQUENCER_SIZE; + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_WAVCFG1, aw_haptic->seq, len); +} + +static void aw862xx_set_wav_seq(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t seq) +{ + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_WAVCFG1 + wav, &seq, AW_I2C_BYTE_ONE); +} + +static void aw862xx_set_wav_loop(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t loop) +{ + uint8_t tmp = 0; + + if (wav % 2) { + tmp = loop << 0; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_WAVCFG9 + (wav / 2), + AW862XX_BIT_WAVLOOP_SEQ_EVEN_MASK, tmp); + } else { + tmp = loop << 4; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_WAVCFG9 + (wav / 2), + AW862XX_BIT_WAVLOOP_SEQ_ODD_MASK, tmp); + } +} + +static void aw862xx_set_repeat_seq(struct aw_haptic *aw_haptic, uint8_t seq) +{ + aw862xx_set_wav_seq(aw_haptic, 0x00, seq); + aw862xx_set_wav_seq(aw_haptic, 0x01, 0x00); + aw862xx_set_wav_loop(aw_haptic, 0x00, AW862XX_BIT_WAVLOOP_INIFINITELY); +} + +static void aw862xx_get_gain(struct aw_haptic *aw_haptic, uint8_t *gain) +{ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_PLAYCFG2, gain, AW_I2C_BYTE_ONE); +} + +static void aw862xx_get_wav_loop(struct aw_haptic *aw_haptic, uint8_t *val) +{ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_WAVCFG9, val, AW_SEQUENCER_LOOP_SIZE); +} + +static void aw862xx_get_ram_data(struct aw_haptic *aw_haptic, uint8_t *ram_data, int size) +{ + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_RAMDATA, ram_data, size); +} + +static void aw862xx_get_lra_resistance(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint8_t d2s_gain_temp = 0; + uint32_t lra_code = 0; + uint32_t lra = 0; + int d2s_gain = 0; + + aw862xx_play_stop(aw_haptic); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSCTRL7, ®_val, AW_I2C_BYTE_ONE); + d2s_gain_temp = AW862XX_BIT_SYSCTRL7_GAIN & reg_val; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL7, + AW862XX_BIT_SYSCTRL7_D2S_GAIN_MASK, aw_haptic->info.d2s_gain); + d2s_gain = aw862xx_select_d2s_gain(aw_haptic->info.d2s_gain); + if (d2s_gain <= 0) { + aw_err("d2s_gain is error"); + return; + } + aw862xx_raminit(aw_haptic, true); + /* enter standby mode */ + aw862xx_play_stop(aw_haptic); + usleep_range(AW_STOP_DELAY_MIN, AW_STOP_DELAY_MAX); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL2, AW862XX_BIT_SYSCTRL2_STANDBY_MASK, + AW862XX_BIT_SYSCTRL2_STANDBY_OFF); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_DETCFG1, AW862XX_BIT_DETCFG1_RL_OS_MASK, + AW862XX_BIT_DETCFG1_RL); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_DETCFG2, AW862XX_BIT_DETCFG2_DIAG_GO_MASK, + AW862XX_BIT_DETCFG2_DIAG_GO_ON); + usleep_range(AW_RL_DELAY_MIN, AW_RL_DELAY_MAX); + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_RL, ®_val, AW_I2C_BYTE_ONE); + lra_code = (lra_code | reg_val) << 2; + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_DET_LO, ®_val, AW_I2C_BYTE_ONE); + lra_code = lra_code | (reg_val & AW862XX_BIT_DET_LO_RL); + /* 2num */ + lra = AW862XX_RL_FORMULA(lra_code, d2s_gain); + /* Keep up with aw8624 driver */ + aw_haptic->lra = lra * 10; + aw862xx_raminit(aw_haptic, false); + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_SYSCTRL7, + AW862XX_BIT_SYSCTRL7_D2S_GAIN_MASK, d2s_gain_temp); +} + +static uint8_t aw862xx_get_prctmode(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_PWMCFG3, ®_val, AW_I2C_BYTE_ONE); + reg_val >>= 7; + + return reg_val; +} + +static uint8_t aw862xx_judge_rtp_going(struct aw_haptic *aw_haptic) +{ + uint8_t glb_state = 0; + uint8_t rtp_state = 0; + + glb_state = aw862xx_get_glb_state(aw_haptic); + if (glb_state == AW_BIT_STATE_RTP_GO) { + rtp_state = 1; /*is going on */ + aw_info("rtp_routine_on"); + } + + return rtp_state; +} + +static uint64_t aw862xx_get_theory_time(struct aw_haptic *aw_haptic) +{ + uint8_t reg_val = 0; + uint32_t fre_val = 0; + uint64_t theory_time = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSCTRL2, ®_val, AW_I2C_BYTE_ONE); + fre_val = reg_val & AW862XX_BIT_SYSCTRL2_RATE; + if (fre_val == AW862XX_BIT_SYSCTRL2_RATE_48K) + theory_time = (aw_haptic->rtp_len / 48) * 1000; /*48K*/ + else if (fre_val == AW862XX_BIT_SYSCTRL2_RATE_24K) + theory_time = (aw_haptic->rtp_len / 24) * 1000; /*24K*/ + else + theory_time = (aw_haptic->rtp_len / 12) * 1000; /*12K*/ + aw_info("microsecond:%llu theory_time = %llu", aw_haptic->microsecond, theory_time); + + return theory_time; +} + +static uint8_t aw862xx_get_osc_status(struct aw_haptic *aw_haptic) +{ + uint8_t state = 0; + + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_SYSST2, &state, AW_I2C_BYTE_ONE); + state &= AW862XX_BIT_SYSST2_FF_EMPTY; + + return state; +} + +static int aw862xx_check_qualify(struct aw_haptic *aw_haptic) +{ + uint8_t reg = 0; + int ret = 0; + + aw_info("enter"); + ret = haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_EFRD9, ®, AW_I2C_BYTE_ONE); + if (ret < 0) + return ret; + if ((reg & 0x80) == 0x80) + return 0; + aw_err("register 0x64 error: 0x%02X", reg); + + return -ERANGE; +} + +static ssize_t cont_drv_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_lvl = 0x%02X, cont_drv2_lvl = 0x%02X\n", + aw_haptic->info.cont_drv1_lvl, aw_haptic->info.cont_drv2_lvl); + + return len; +} + +static ssize_t cont_drv_lvl_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_val = 0; + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_lvl = databuf[0]; + aw_haptic->info.cont_drv2_lvl = databuf[1]; + haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_CONTCFG6, + AW862XX_BIT_CONTCFG6_DRV1_LVL_MASK, + aw_haptic->info.cont_drv1_lvl); + reg_val = (uint8_t)aw_haptic->info.cont_drv2_lvl; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG7, ®_val, AW_I2C_BYTE_ONE); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_drv_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cont_drv1_time = 0x%02X, cont_drv2_time = 0x%02X\n", + aw_haptic->info.cont_drv1_time, aw_haptic->info.cont_drv2_time); + + return len; +} + +static ssize_t cont_drv_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_val[2] = {0}; + uint32_t databuf[2] = { 0, 0 }; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_haptic->info.cont_drv1_time = databuf[0]; + aw_haptic->info.cont_drv2_time = databuf[1]; + reg_val[0] = (uint8_t)aw_haptic->info.cont_drv1_time; + reg_val[1] = (uint8_t)aw_haptic->info.cont_drv2_time; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG8, reg_val, AW_I2C_BYTE_TWO); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t cont_brk_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "cont_brk_time = 0x%02X\n", + aw_haptic->info.cont_brk_time); + + return len; +} + +static ssize_t cont_brk_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint8_t reg_val = 0; + int err, val; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + err = kstrtoint(buf, 16, &val); + if (err != 0) { + aw_err("format not match!"); + return count; + } + mutex_lock(&aw_haptic->lock); + aw_haptic->info.cont_brk_time = val; + reg_val = aw_haptic->info.cont_brk_time; + haptic_nv_i2c_writes(aw_haptic, AW862XX_REG_CONTCFG10, ®_val, AW_I2C_BYTE_ONE); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int i = 0; + ssize_t len = 0; + uint8_t trig_num = 3; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (aw_haptic->name == AW86224 || aw_haptic->name == AW86225 || aw_haptic->name == AW86214) + trig_num = 1; + for (i = 0; i < trig_num; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, "trig%d: trig_level=%u, trig_polar=%u", + i + 1, aw_haptic->trig[i].trig_level, + aw_haptic->trig[i].trig_polar); + len += snprintf(buf + len, PAGE_SIZE - len, "pos_enable=%u, pos_sequence=%u,", + aw_haptic->trig[i].pos_enable, aw_haptic->trig[i].pos_sequence); + len += snprintf(buf + len, PAGE_SIZE - len, + "neg_enable=%u, neg_sequence=%u trig_brk=%u\n", + aw_haptic->trig[i].neg_enable, aw_haptic->trig[i].neg_sequence, + aw_haptic->trig[i].trig_brk); + } + + return len; +} + +static ssize_t trig_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[9] = { 0 }; + + if (sscanf(buf, "%u %u %u %u %u %u %u %u", &databuf[0], &databuf[1], &databuf[2], + &databuf[3], &databuf[4], &databuf[5], &databuf[6], &databuf[7]) == 8) { + aw_info("%u, %u, %u, %u, %u, %u, %u, %u", databuf[0], databuf[1], databuf[2], + databuf[3], databuf[4], databuf[5], databuf[6], databuf[7]); + if ((aw_haptic->name == AW86214 || aw_haptic->name == AW86224 || + aw_haptic->name == AW86225) && (databuf[0])) { + aw_err("input seq value out of range!"); + return count; + } + if (databuf[0] < 0 || databuf[0] > 2) { + aw_err("input seq value out of range!"); + return count; + } + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + if (databuf[4] > aw_haptic->ram.ram_num || databuf[6] > aw_haptic->ram.ram_num) { + aw_err("input seq value out of range!"); + return count; + } + aw_haptic->trig[databuf[0]].trig_level = databuf[1]; + aw_haptic->trig[databuf[0]].trig_polar = databuf[2]; + aw_haptic->trig[databuf[0]].pos_enable = databuf[3]; + aw_haptic->trig[databuf[0]].pos_sequence = databuf[4]; + aw_haptic->trig[databuf[0]].neg_enable = databuf[5]; + aw_haptic->trig[databuf[0]].neg_sequence = databuf[6]; + aw_haptic->trig[databuf[0]].trig_brk = databuf[7]; + mutex_lock(&aw_haptic->lock); + aw862xx_haptic_trig_param_config(aw_haptic, databuf[0]); + mutex_unlock(&aw_haptic->lock); + } else + aw_err("please input eight parameters"); + + return count; +} + +static DEVICE_ATTR_RW(cont_drv_lvl); +static DEVICE_ATTR_RW(cont_drv_time); +static DEVICE_ATTR_RW(cont_brk_time); +static DEVICE_ATTR_RW(trig); + +static struct attribute *aw862xx_vibrator_attributes[] = { + &dev_attr_cont_drv_lvl.attr, + &dev_attr_cont_drv_time.attr, + &dev_attr_cont_brk_time.attr, + &dev_attr_trig.attr, + NULL +}; + +static struct attribute_group aw862xx_vibrator_attribute_group = { + .attrs = aw862xx_vibrator_attributes +}; + +static void aw862xx_creat_node(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &aw862xx_vibrator_attribute_group); + if (ret < 0) + aw_err("error create aw862xx sysfs attr files"); +} + +struct aw_haptic_func aw862xx_func_list = { + .ram_init = aw862xx_raminit, + .parse_dts = aw862xx_parse_dts, + .trig_init = aw862xx_trig_init, + .play_mode = aw862xx_play_mode, + .play_stop = aw862xx_play_stop, + .irq_clear = aw862xx_irq_clear, + .creat_node = aw862xx_creat_node, + .cont_config = aw862xx_cont_config, + .offset_cali = aw862xx_offset_cali, + .haptic_start = aw862xx_haptic_start, + .read_cont_f0 = aw862xx_read_cont_f0, + .check_qualify = aw862xx_check_qualify, + .judge_rtp_going = aw862xx_judge_rtp_going, + .protect_config = aw862xx_protect_config, + .misc_para_init = aw862xx_misc_para_init, + .interrupt_setup = aw862xx_interrupt_setup, + .rtp_get_fifo_afs = aw862xx_rtp_get_fifo_afs, + .rtp_get_fifo_aes = aw862xx_rtp_get_fifo_aes, + .vbat_mode_config = aw862xx_vbat_mode_config, + .calculate_cali_data = aw862xx_calculate_cali_data, + .set_gain = aw862xx_set_gain, + .get_gain = aw862xx_get_gain, + .set_wav_seq = aw862xx_set_wav_seq, + .get_wav_seq = aw862xx_get_wav_seq, + .set_wav_loop = aw862xx_set_wav_loop, + .get_wav_loop = aw862xx_get_wav_loop, + .set_ram_data = aw862xx_set_ram_data, + .get_ram_data = aw862xx_get_ram_data, + .set_fifo_addr = aw862xx_set_fifo_addr, + .get_fifo_addr = aw862xx_get_fifo_addr, + .set_rtp_aei = aw862xx_set_rtp_aei, + .set_rtp_data = aw862xx_set_rtp_data, + .set_ram_addr = aw862xx_set_ram_addr, + .set_trim_lra = aw862xx_set_trim_lra, + .set_base_addr = aw862xx_set_base_addr, + .set_repeat_seq = aw862xx_set_repeat_seq, + .get_f0 = aw862xx_get_f0, + .get_reg = aw862xx_get_reg, + .get_vbat = aw862xx_get_vbat, + .get_prctmode = aw862xx_get_prctmode, + .get_irq_state = aw862xx_get_irq_state, + .get_glb_state = aw862xx_get_glb_state, + .get_osc_status = aw862xx_get_osc_status, + .get_theory_time = aw862xx_get_theory_time, + .get_lra_resistance = aw862xx_get_lra_resistance, + .get_first_wave_addr = aw862xx_get_first_wave_addr, +}; diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c new file mode 100644 index 000000000000..2d171062c3d4 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c @@ -0,0 +1,3813 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * File: haptic_nv.c + * + * Author: + * + * Copyright (c) 2021 AWINIC Technology CO., LTD + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "haptic_nv.h" +#include "haptic_nv_reg.h" + +#define HAPTIC_NV_DRIVER_VERSION "v1.12.0.10" + +static char aw_ram_name[][AW_NAME_MAX] = { + {"aw862x_haptic.bin"}, + {"aw862xx_haptic.bin"}, +}; + +static char aw_rtp_name[][AW_NAME_MAX] = { + {"haptic_nv_rtp_osc_24K_5s.bin"}, + {"haptic_nv_rtp.bin"}, + {"haptic_nv_rtp_lighthouse.bin"}, + {"haptic_nv_rtp_silk.bin"}, + {"haptic_nv_rtp_autosin.bin"}, +}; + +#ifdef AW_TIKTAP +static struct aw_haptic *g_aw_haptic; +#endif +#ifdef AW_DOUBLE +struct aw_haptic *left; +struct aw_haptic *right; +#endif + +/********************************************************* + * + * I2C Read/Write + * + *********************************************************/ +int haptic_nv_i2c_reads(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint8_t *buf, uint32_t len) +{ + int ret = -1; + struct i2c_msg msg[] = { + [0] = { + .addr = aw_haptic->i2c->addr, + .flags = 0, + .len = sizeof(uint8_t), + .buf = ®_addr, + }, + [1] = { + .addr = aw_haptic->i2c->addr, + .flags = I2C_M_RD, + .len = len, + .buf = buf, + }, + }; + + ret = i2c_transfer(aw_haptic->i2c->adapter, msg, ARRAY_SIZE(msg)); + if (ret < 0) { + aw_err("transfer failed. reg_addr=0x%02X", reg_addr); + return ret; + } else if (ret != AW_I2C_READ_MSG_NUM) { + aw_err("transfer failed(size error). reg_addr=0x%02X", reg_addr); + return -ENXIO; + } + + return ret; +} + +int haptic_nv_i2c_writes(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint8_t *buf, uint32_t len) +{ + uint8_t *data = NULL; + int ret = -1; + + data = kmalloc(len + 1, GFP_KERNEL); + data[0] = reg_addr; + memcpy(&data[1], buf, len); + ret = i2c_master_send(aw_haptic->i2c, data, len + 1); + if (ret < 0) + aw_err("i2c master send 0x%02X err", reg_addr); + kfree(data); + + return ret; +} + +int haptic_nv_i2c_write_bits(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint32_t mask, + uint8_t reg_data) +{ + uint8_t reg_val = 0; + int ret = -1; + + ret = haptic_nv_i2c_reads(aw_haptic, reg_addr, ®_val, AW_I2C_BYTE_ONE); + if (ret < 0) { + aw_err("i2c read error, ret=%d", ret); + return ret; + } + reg_val &= mask; + reg_val |= (reg_data & (~mask)); + ret = haptic_nv_i2c_writes(aw_haptic, reg_addr, ®_val, AW_I2C_BYTE_ONE); + if (ret < 0) { + aw_err("i2c write error, ret=%d", ret); + return ret; + } + + return 0; +} + +ssize_t haptic_nv_read_reg_array(struct aw_haptic *aw_haptic, char *buf, ssize_t len, + uint8_t head_reg_addr, uint8_t tail_reg_addr) +{ + int reg_num = 0; + int i = 0; + uint8_t reg_array[AW_REG_MAX] = {0}; + + reg_num = tail_reg_addr - head_reg_addr + 1; + haptic_nv_i2c_reads(aw_haptic, head_reg_addr, reg_array, reg_num); + for (i = 0 ; i < reg_num; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, "reg:0x%02X=0x%02X\n", + head_reg_addr + i, reg_array[i]); + } + + return len; +} + +static void pm_qos_enable(struct aw_haptic *aw_haptic, bool enable) +{ +#ifdef KERNEL_OVER_5_10 + if (enable) { + if (!cpu_latency_qos_request_active(&aw_haptic->aw_pm_qos_req_vb)) + cpu_latency_qos_add_request(&aw_haptic->aw_pm_qos_req_vb, + CPU_LATENCY_QOC_VALUE); + } else { + if (cpu_latency_qos_request_active(&aw_haptic->aw_pm_qos_req_vb)) + cpu_latency_qos_remove_request(&aw_haptic->aw_pm_qos_req_vb); + } +#else + if (enable) { + if (!pm_qos_request_active(&aw_haptic->aw_pm_qos_req_vb)) + pm_qos_add_request(&aw_haptic->aw_pm_qos_req_vb, PM_QOS_CPU_DMA_LATENCY, + AW_PM_QOS_VALUE_VB); + } else { + if (pm_qos_request_active(&aw_haptic->aw_pm_qos_req_vb)) + pm_qos_remove_request(&aw_haptic->aw_pm_qos_req_vb); + } +#endif +} + +#ifdef AW_CHECK_RAM_DATA +static int parse_ram_data(struct aw_haptic *aw_haptic, uint32_t len, uint8_t *cont_data, + uint8_t *ram_data) +{ + int i = 0; + + aw_info("enter"); + for (i = 0; i < len; i++) { + if (ram_data[i] != cont_data[i]) { + aw_err("check ramdata error, addr=0x%04X, ram_data=0x%02X, file_data=0x%02X", + i, ram_data[i], cont_data[i]); + return -ERANGE; + } + } + + return 0; +} + +static int check_ram_data(struct aw_haptic *aw_haptic, struct aw_haptic_container *aw_fw) +{ + int i = 0; + int len = 0; + int ret = 0; + uint8_t ram_data[AW_RAMDATA_RD_BUFFER_SIZE] = {0}; + + aw_haptic->func->set_ram_addr(aw_haptic); + i = aw_haptic->ram.ram_shift; + while (i < aw_fw->len) { + if ((aw_fw->len - i) < AW_RAMDATA_RD_BUFFER_SIZE) + len = aw_fw->len - i; + else + len = AW_RAMDATA_RD_BUFFER_SIZE; + + aw_haptic->func->get_ram_data(aw_haptic, ram_data, len); + ret = parse_ram_data(aw_haptic, len, &aw_fw->data[i], ram_data); + if (ret < 0) + break; + i += len; + } + + return ret; +} +#endif + +static void write_ram_data(struct aw_haptic *aw_haptic, struct aw_haptic_container *aw_fw) +{ + int i = 0; + int len = 0; + + aw_haptic->func->set_ram_addr(aw_haptic); + i = aw_haptic->ram.ram_shift; + while (i < aw_fw->len) { + if ((aw_fw->len - i) < AW_RAMDATA_WR_BUFFER_SIZE) + len = aw_fw->len - i; + else + len = AW_RAMDATA_WR_BUFFER_SIZE; + + aw_haptic->func->set_ram_data(aw_haptic, &aw_fw->data[i], len); + i += len; + } +} + +static int parse_dt_gpio(struct aw_haptic *aw_haptic, struct device *dev, struct device_node *np) +{ + aw_haptic->is_used_rst_pin = of_property_read_bool(np, "aw8624x_no_reset") ? 0 : 1; + if (aw_haptic->is_used_rst_pin) { + aw_haptic->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); + if (aw_haptic->reset_gpio < 0) { + aw_err("no reset gpio provide"); + return -EPERM; + } + aw_info("reset gpio provide ok %d", aw_haptic->reset_gpio); + } else { + aw_info("not use rst pin"); + } + + aw_haptic->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0); + if (aw_haptic->irq_gpio < 0) { + aw_err("no irq gpio provided."); + aw_haptic->is_used_irq_pin = false; + } else { + aw_info("irq gpio provide ok irq = %d.", aw_haptic->irq_gpio); + aw_haptic->is_used_irq_pin = true; + } +#ifdef AW_DOUBLE + if (of_device_is_compatible(np, "awinic,haptic_nv_l")) { + aw_info("compatible left vibrator."); + memcpy(aw_haptic->mark, "left", sizeof("left")); + left = NULL; + left = aw_haptic; + } else if (of_device_is_compatible(np, "awinic,haptic_nv_r")) { + aw_info("compatible right vibrator."); + memcpy(aw_haptic->mark, "right", sizeof("right")); + right = NULL; + right = aw_haptic; + } else { + aw_err("compatible failed."); + return -ERANGE; + } +#endif + + return 0; +} + +static void parse_dts_i2c_addr(struct aw_haptic *aw_haptic, struct device *dev, + struct device_node *np) +{ + uint32_t val = 0; + + val = of_property_read_u32(np, "aw862xx_i2c_addr", &aw_haptic->aw862xx_i2c_addr); + if (val) + aw_err("configure aw862xx_i2c_addr error"); + else + aw_info("configure aw862xx_i2c_addr ok"); +} + +static void hw_reset(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + if (aw_haptic->is_used_rst_pin) { + if (gpio_is_valid(aw_haptic->reset_gpio)) { + gpio_set_value_cansleep(aw_haptic->reset_gpio, 0); + usleep_range(1000, 2000); + gpio_set_value_cansleep(aw_haptic->reset_gpio, 1); + usleep_range(8000, 8500); + } else { + aw_err("failed"); + } + } else { + aw_info("aw_haptic->is_used_rst_pin is %d", aw_haptic->is_used_rst_pin); + } +} + +static void sw_reset(struct aw_haptic *aw_haptic) +{ + uint8_t reset = AW_BIT_RESET; + + aw_info("enter"); + haptic_nv_i2c_writes(aw_haptic, AW_REG_ID, &reset, AW_I2C_BYTE_ONE); + usleep_range(2000, 2500); +} + +static int read_chipid(struct aw_haptic *aw_haptic, uint32_t *reg_val, uint8_t type) +{ + uint8_t value[2] = {0}; + int cnt = 0; + int ret = -1; + + while (cnt < AW_I2C_RETRIES) { + ret = haptic_nv_i2c_reads(aw_haptic, AW_REG_CHIPIDH, &value[0], AW_I2C_BYTE_ONE); + if (value[0] == AW8623X_CHIP_ID_H) { + ret = haptic_nv_i2c_reads(aw_haptic, AW8623X_REG_CHIPIDL, &value[1], + AW_I2C_BYTE_ONE); + *reg_val = value[1] | value[0] << 8; + } else if (value[0] == AW8624X_CHIP_ID_H) { + ret = haptic_nv_i2c_reads(aw_haptic, AW8624X_REG_CHIPIDL, &value[1], + AW_I2C_BYTE_ONE); + *reg_val = value[1] | value[0] << 8; + } else { + ret = haptic_nv_i2c_reads(aw_haptic, AW_REG_ID, &value[0], AW_I2C_BYTE_ONE); + *reg_val = value[0]; + } + if (ret < 0) { + if (type == AW_FIRST_TRY) + aw_info("reading chip id"); + else if (type == AW_LAST_TRY) + aw_err("i2c_read cnt=%d error=%d", cnt, ret); + else + aw_err("type is error"); + } else { + break; + } + cnt++; + usleep_range(2000, 3000); + } + + return ret; +} + +static int parse_chipid(struct aw_haptic *aw_haptic) +{ + int ret = -1; + uint8_t cnt = 0; + uint8_t reg = 0; + uint32_t reg_val = 0; + + for (cnt = 0; cnt < AW_READ_CHIPID_RETRIES; cnt++) { + /* hardware reset */ + hw_reset(aw_haptic); + + ret = read_chipid(aw_haptic, ®_val, AW_FIRST_TRY); + if (ret < 0) { + aw_haptic->i2c->addr = (u16)aw_haptic->aw862xx_i2c_addr; + aw_info("try to replace i2c addr [(0x%02X)] to read chip id again", + aw_haptic->i2c->addr); + ret = read_chipid(aw_haptic, ®_val, AW_LAST_TRY); + if (ret < 0) + break; + } + + switch (reg_val) { +#ifdef AW862X_DRIVER + case AW8623_CHIP_ID: + aw_haptic->name = AW8623; + aw_info("detected aw8623."); + return 0; + case AW8624_CHIP_ID: + aw_haptic->name = AW8624; + aw_info("detected aw8624."); + return 0; +#endif + +#ifdef AW862XX_DRIVER + case AW8622X_CHIP_ID: + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_EFRD9, ®, AW_I2C_BYTE_ONE); + if ((reg & 0x41) == AW86223_EF_ID) { + aw_haptic->name = AW86223; + aw_info("aw86223 detected"); + return 0; + } + if ((reg & 0x41) == AW86224_EF_ID) { + aw_haptic->name = AW86224; + aw_info("aw86224 or aw86225 detected"); + return 0; + } + aw_info("unsupported ef_id = (0x%02X)", reg); + break; + case AW86214_CHIP_ID: + haptic_nv_i2c_reads(aw_haptic, AW862XX_REG_EFRD9, ®, AW_I2C_BYTE_ONE); + if ((reg & 0x41) == AW86214_EF_ID) { + aw_haptic->name = AW86214; + aw_info("aw86214 detected"); + return 0; + } + aw_info("unsupported ef_id = (0x%02X)", reg); + break; +#endif + +#ifdef AW8623X_DRIVER + case AW86233_CHIP_ID: + aw_haptic->name = AW86233; + aw_info("aw86233 detected"); + return 0; + case AW86234_CHIP_ID: + aw_haptic->name = AW86234; + aw_info("aw86234 detected"); + return 0; + case AW86235_CHIP_ID: + aw_haptic->name = AW86235; + aw_info("aw86235 detected"); + return 0; +#endif + +#ifdef AW8624X_DRIVER + case AW86243_CHIP_ID: + aw_haptic->name = AW86243; + aw_info("aw86243 detected"); + return 0; + case AW86245_CHIP_ID: + aw_haptic->name = AW86245; + aw_info("aw86245 detected"); + return 0; +#endif + default: + aw_info("unsupport device revision (0x%02X)", reg_val); + break; + } + usleep_range(AW_READ_CHIPID_RETRY_DELAY * 1000, + AW_READ_CHIPID_RETRY_DELAY * 1000 + 500); + } + + return -EINVAL; +} + +static int chip_private_init(struct aw_haptic *aw_haptic) +{ + switch (aw_haptic->name) { +#ifdef AW862X_DRIVER + case AW8623: + case AW8624: + aw_haptic->trim_lra_boundary = AW_TRIM_LRA_BOUNDARY; + aw_haptic->ram_file_num = AW862X_RAM_FILE; + break; +#endif + +#ifdef AW862XX_DRIVER + case AW86214: + case AW86223: + case AW86224: + case AW86225: + aw_haptic->trim_lra_boundary = AW_TRIM_LRA_BOUNDARY; + aw_haptic->ram_file_num = AW862XX_RAM_FILE; + break; +#endif + +#ifdef AW8623X_DRIVER + case AW86233: + case AW86234: + case AW86235: + aw_haptic->trim_lra_boundary = AW_TRIM_LRA_BOUNDARY; + aw_haptic->ram_file_num = AW862XX_RAM_FILE; + break; +#endif + +#ifdef AW8624X_DRIVER + case AW86243: + case AW86245: + aw_haptic->trim_lra_boundary = AW8624X_TRIM_LRA_BOUNDARY; + aw_haptic->ram_file_num = AW862XX_RAM_FILE; + break; +#endif + + default: + aw_info("unexpected chip!"); + return -EINVAL; + } + + return 0; +} + +static int func_ptr_init(struct aw_haptic *aw_haptic, struct device *dev) +{ + switch (aw_haptic->name) { +#ifdef AW862X_DRIVER + case AW8623: + case AW8624: + aw_haptic->func = &aw862x_func_list; + break; +#endif + +#ifdef AW862XX_DRIVER + case AW86214: + case AW86223: + case AW86224: + case AW86225: + aw_haptic->func = &aw862xx_func_list; + break; +#endif + +#ifdef AW8623X_DRIVER + case AW86233: + case AW86234: + case AW86235: + aw_haptic->func = &aw8623x_func_list; + break; +#endif + +#ifdef AW8624X_DRIVER + case AW86243: + case AW86245: + aw_haptic->func = &aw8624x_func_list; + break; +#endif + + default: + aw_info("unexpected chip!"); + return -EINVAL; + } + + return 0; +} + +static int write_rtp_data(struct aw_haptic *aw_haptic) +{ + uint32_t buf_len = 0; + int ret = -ERANGE; + struct aw_haptic_container *aw_rtp = aw_haptic->aw_rtp; + + if (!aw_rtp) { + aw_info("aw_rtp is null, break!"); + return ret; + } + + if (aw_haptic->rtp_cnt < (aw_haptic->ram.base_addr)) { + if ((aw_rtp->len - aw_haptic->rtp_cnt) < (aw_haptic->ram.base_addr)) + buf_len = aw_rtp->len - aw_haptic->rtp_cnt; + else + buf_len = aw_haptic->ram.base_addr; + } else if ((aw_rtp->len - aw_haptic->rtp_cnt) < (aw_haptic->ram.base_addr >> 2)) { + buf_len = aw_rtp->len - aw_haptic->rtp_cnt; + } else { + buf_len = aw_haptic->ram.base_addr >> 2; + } + +#ifdef AW_ENABLE_RTP_PRINT_LOG + aw_info("buf_len = %u", buf_len); +#endif +#ifdef AW_DOUBLE + if (aw_haptic->rtp_cnt == 0 && aw_haptic->dual_flag) { + aw_haptic->dual_flag = false; + if (down_trylock(&left->sema) == 0) { + ret = down_interruptible(&left->sema); + } else { + up(&left->sema); + up(&left->sema); + } + aw_info("dual rtp play start"); + } +#endif + aw_haptic->func->set_rtp_data(aw_haptic, &aw_rtp->data[aw_haptic->rtp_cnt], buf_len); + aw_haptic->rtp_cnt += buf_len; + + return 0; + +} + +static int judge_rtp_load_end(struct aw_haptic *aw_haptic) +{ + uint8_t glb_st = 0; + int ret = -ERANGE; + struct aw_haptic_container *aw_rtp = aw_haptic->aw_rtp; + + glb_st = aw_haptic->func->get_glb_state(aw_haptic); + + if ((aw_haptic->rtp_cnt == aw_rtp->len) || + ((glb_st & AW_BIT_GLBRD_STATE_MASK) == AW_BIT_STATE_STANDBY)) { + if (aw_haptic->rtp_cnt != aw_rtp->len) + aw_err("rtp play suspend!"); + else + aw_info("rtp update complete!,cnt=%u", aw_haptic->rtp_cnt); + aw_haptic->rtp_cnt = 0; + aw_haptic->rtp_init = false; + aw_haptic->func->set_rtp_aei(aw_haptic, false); + ret = 0; + } + + return ret; +} + +static void rtp_play(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + while ((!aw_haptic->func->rtp_get_fifo_afs(aw_haptic)) + && (aw_haptic->play_mode == AW_RTP_MODE)) { + +#ifdef AW_ENABLE_RTP_PRINT_LOG + aw_info("rtp cnt = %u", aw_haptic->rtp_cnt); +#endif + ret = write_rtp_data(aw_haptic); + if (ret != 0) + break; + ret = judge_rtp_load_end(aw_haptic); + if (ret == 0) + break; + } +} + +static irqreturn_t irq_handle(int irq, void *data) +{ + int irq_state = 0; + struct aw_haptic *aw_haptic = data; + + aw_info("enter"); + + do { + irq_state = aw_haptic->func->get_irq_state(aw_haptic); + + if (irq_state == AW_IRQ_ALMOST_EMPTY) { + if (aw_haptic->rtp_init) { + mutex_lock(&aw_haptic->rtp_lock); + rtp_play(aw_haptic); + mutex_unlock(&aw_haptic->rtp_lock); + } else { + aw_info("rtp_init: %d", aw_haptic->rtp_init); + } + } + + if (aw_haptic->play_mode != AW_RTP_MODE) + aw_haptic->func->set_rtp_aei(aw_haptic, false); + } while (irq_state); + + aw_info("exit"); + + return IRQ_HANDLED; +} + +static int irq_config(struct device *dev, struct aw_haptic *aw_haptic) +{ + int ret = -1; + int irq_flags = 0; + + aw_info("enter"); + if (gpio_is_valid(aw_haptic->irq_gpio) && !(aw_haptic->flags & AW_FLAG_SKIP_INTERRUPTS)) { + /* register irq handler */ + aw_haptic->func->interrupt_setup(aw_haptic); + irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + ret = devm_request_threaded_irq(dev, gpio_to_irq(aw_haptic->irq_gpio), NULL, + irq_handle, irq_flags, "aw_haptic", aw_haptic); + if (ret != 0) { + aw_err("failed to request IRQ %d: %d", + gpio_to_irq(aw_haptic->irq_gpio), ret); + return ret; + } + } else { + aw_info("skipping IRQ registration"); + /* disable feature support if gpio was invalid */ + aw_haptic->flags |= AW_FLAG_SKIP_INTERRUPTS; + } + + return 0; +} + +static int get_ram_num(struct aw_haptic *aw_haptic) +{ + uint32_t first_wave_addr = 0; + + aw_info("enter"); + if (!aw_haptic->ram_init) { + aw_err("ram init failed, ram_num = 0!"); + return -EPERM; + } + + mutex_lock(&aw_haptic->lock); + /* RAMINIT Enable */ + aw_haptic->func->play_stop(aw_haptic); + aw_haptic->func->ram_init(aw_haptic, true); + aw_haptic->func->set_ram_addr(aw_haptic); + aw_haptic->func->get_first_wave_addr(aw_haptic, &first_wave_addr); + aw_haptic->ram.ram_num = (first_wave_addr - aw_haptic->ram.base_addr - 1) / 4; + aw_info("first wave addr = 0x%04X, ram_num = %u", first_wave_addr, aw_haptic->ram.ram_num); + /* RAMINIT Disable */ + aw_haptic->func->ram_init(aw_haptic, false); + mutex_unlock(&aw_haptic->lock); + + return 0; +} + +static int container_update(struct aw_haptic *aw_haptic, struct aw_haptic_container *aw_fw) +{ + uint32_t shift = 0; + int ret = 0; + + aw_info("enter"); + + mutex_lock(&aw_haptic->lock); + aw_haptic->ram.baseaddr_shift = 2; + aw_haptic->ram.ram_shift = 4; + aw_haptic->func->play_stop(aw_haptic); + aw_haptic->func->ram_init(aw_haptic, true); + shift = aw_haptic->ram.baseaddr_shift; + aw_haptic->ram.base_addr = (uint32_t)((aw_fw->data[0 + shift] << 8) | + (aw_fw->data[1 + shift])); + aw_info("base_addr = %u", aw_haptic->ram.base_addr); + if (!aw_haptic->ram.base_addr) + aw_info("no set FIFO space for rtp play!"); + aw_haptic->func->set_base_addr(aw_haptic); + aw_haptic->func->set_fifo_addr(aw_haptic); + aw_haptic->func->get_fifo_addr(aw_haptic); + write_ram_data(aw_haptic, aw_fw); + +#ifdef AW_CHECK_RAM_DATA + ret = check_ram_data(aw_haptic, aw_fw); + if (ret) + aw_err("ram data check sum error"); + else + aw_info("ram data check sum pass"); +#endif + + aw_haptic->func->ram_init(aw_haptic, false); + mutex_unlock(&aw_haptic->lock); + + aw_info("exit"); + + return ret; +} + +static void ram_load(const struct firmware *cont, void *context) +{ + uint16_t check_sum = 0; + int i = 0; + int ret = 0; + struct aw_haptic *aw_haptic = context; + struct aw_haptic_container *aw_fw; + uint32_t ram_file_num = aw_haptic->ram_file_num; +#ifdef AW_READ_BIN_FLEXBALLY + static uint8_t load_cont; + int ram_timer_val = 1000; + + load_cont++; +#endif + + if (!cont) { + aw_err("failed to read %s", aw_ram_name[ram_file_num]); + release_firmware(cont); + +#ifdef AW_READ_BIN_FLEXBALLY + if (load_cont <= 20) { + schedule_delayed_work(&aw_haptic->ram_work, + msecs_to_jiffies(ram_timer_val)); + aw_info("start hrtimer:load_cont%u", load_cont); + } +#endif + return; + } + + aw_info("loaded %s - size: %zu", aw_ram_name[ram_file_num], cont ? cont->size : 0); + /* check sum */ + for (i = 2; i < cont->size; i++) + check_sum += cont->data[i]; + if (check_sum != (uint16_t)((cont->data[0] << 8) | (cont->data[1]))) { + aw_err("check sum err: check_sum=0x%04X", check_sum); + release_firmware(cont); + return; + } + aw_info("check sum pass."); + aw_haptic->ram.check_sum = check_sum; + + /* aw ram update */ + aw_fw = kzalloc(cont->size + sizeof(int), GFP_KERNEL); + if (!aw_fw) { + release_firmware(cont); + aw_err("Error allocating memory"); + return; + } + aw_fw->len = cont->size; + memcpy(aw_fw->data, cont->data, cont->size); + release_firmware(cont); + ret = container_update(aw_haptic, aw_fw); + if (ret) { + aw_err("ram firmware update failed!"); + } else { + aw_haptic->ram_init = true; + aw_haptic->ram.len = aw_fw->len - aw_haptic->ram.ram_shift; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->trig_init(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + aw_info("ram firmware update complete!"); + get_ram_num(aw_haptic); + } + kfree(aw_fw); + aw_fw = NULL; + +} + +static int ram_update(struct aw_haptic *aw_haptic) +{ + aw_haptic->ram_init = false; + aw_haptic->rtp_init = false; + + return request_firmware_nowait(THIS_MODULE, 1, aw_ram_name[aw_haptic->ram_file_num], + aw_haptic->dev, GFP_KERNEL, aw_haptic, ram_load); +} + +static void ram_play(struct aw_haptic *aw_haptic) +{ +#ifdef AW_DOUBLE + int ret = -1; + + if (aw_haptic->activate_mode == AW_RAM_MODE) + aw_haptic->func->set_wav_loop(aw_haptic, 0x00, 0x00); + aw_haptic->func->play_mode(aw_haptic, aw_haptic->activate_mode); + if (aw_haptic->dual_flag) { + aw_haptic->dual_flag = false; + if (down_trylock(&left->sema) == 0) { + ret = down_interruptible(&left->sema); + } else { + up(&left->sema); + up(&left->sema); + } + } +#else + aw_haptic->func->play_mode(aw_haptic, aw_haptic->activate_mode); +#endif + aw_haptic->func->haptic_start(aw_haptic); +} + +#ifdef AW_DURATION_DECIDE_WAVEFORM +static int analyse_duration_range(struct aw_haptic *aw_haptic) +{ + int i = 0; + int ret = 0; + int len = 0; + int *duration_time = NULL; + + aw_info("enter"); + len = ARRAY_SIZE(aw_haptic->info.duration_time); + duration_time = aw_haptic->info.duration_time; + if (len < 2) { + aw_err("duration time range error"); + return -ERANGE; + } + + for (i = (len - 1); i > 0; i--) { + if (duration_time[i] > duration_time[i-1]) + continue; + else + break; + + } + + if (i > 0) { + aw_err("duration time range error"); + ret = -ERANGE; + } + + return ret; +} + +static int ram_config(struct aw_haptic *aw_haptic, int duration) +{ + uint8_t wavseq = 0; + uint8_t wavloop = 0; + int ret = 0; + + aw_info("enter"); + ret = analyse_duration_range(aw_haptic); + if (ret < 0) + return ret; + + if ((duration > 0) && (duration < aw_haptic->info.duration_time[0])) { + wavseq = 3; + aw_haptic->activate_mode = AW_RAM_MODE; + } else if ((duration >= aw_haptic->info.duration_time[0]) && + (duration < aw_haptic->info.duration_time[1])) { + wavseq = 2; + aw_haptic->activate_mode = AW_RAM_MODE; + } else if ((duration >= aw_haptic->info.duration_time[1]) && + (duration < aw_haptic->info.duration_time[2])) { + wavseq = 1; + aw_haptic->activate_mode = AW_RAM_MODE; + } else if (duration >= aw_haptic->info.duration_time[2]) { + wavseq = 4; + wavloop = 15; + aw_haptic->activate_mode = AW_RAM_LOOP_MODE; + } else { + aw_err("duration time error, duration= %d", duration); + aw_haptic->activate_mode = AW_NULL; + return -ERANGE; + } + aw_info("duration %d, select index %u", aw_haptic->duration, wavseq); + aw_haptic->func->set_wav_seq(aw_haptic, 0, wavseq); + aw_haptic->func->set_wav_loop(aw_haptic, 0, wavloop); + aw_haptic->func->set_wav_seq(aw_haptic, 1, 0); + aw_haptic->func->set_wav_loop(aw_haptic, 1, 0); + + return 0; +} +#endif + +static void upload_lra(struct aw_haptic *aw_haptic, uint8_t flag) +{ + uint8_t reg_val; + + switch (flag) { + case AW_WRITE_ZERO: + aw_info("write zero to trim_lra!"); + reg_val = 0x00; + break; + case AW_F0_CALI_LRA: + aw_info("write f0_cali_data to trim_lra = 0x%02X", aw_haptic->f0_cali_data); + reg_val = (uint8_t)aw_haptic->f0_cali_data; + break; + case AW_OSC_CALI_LRA: + aw_info("write osc_cali_data to trim_lra = 0x%02X", aw_haptic->osc_cali_data); + reg_val = (uint8_t)aw_haptic->osc_cali_data; + break; + default: + aw_err("flag is error"); + reg_val = 0x00; + break; + } + aw_haptic->func->set_trim_lra(aw_haptic, reg_val); +} + +static int judge_within_cali_range(struct aw_haptic *aw_haptic) +{ + uint32_t f0_cali_min = 0; + uint32_t f0_cali_max = 0; + + aw_info("enter"); + f0_cali_min = aw_haptic->info.f0_pre * (100 - aw_haptic->info.f0_cali_percent) / 100; + f0_cali_max = aw_haptic->info.f0_pre * (100 + aw_haptic->info.f0_cali_percent) / 100; + + aw_info("f0_pre = %u, f0_cali_min = %u, f0_cali_max = %u, f0 = %u", + aw_haptic->info.f0_pre, f0_cali_min, f0_cali_max, aw_haptic->f0); + + if (aw_haptic->f0 < f0_cali_min) { + aw_err("lra f0 is too small, lra_f0 = %u!", aw_haptic->f0); +#ifdef AW_MAXIMUM_F0_CALI_DATA + aw_haptic->f0_cali_data = aw_haptic->trim_lra_boundary; + upload_lra(aw_haptic, AW_F0_CALI_LRA); +#endif + return -ERANGE; + } + + if (aw_haptic->f0 > f0_cali_max) { + aw_err("lra f0 is too large, lra_f0 = %u!", aw_haptic->f0); +#ifdef AW_MAXIMUM_F0_CALI_DATA + aw_haptic->f0_cali_data = aw_haptic->trim_lra_boundary - 1; + upload_lra(aw_haptic, AW_F0_CALI_LRA); +#endif + return -ERANGE; + } + + return 0; +} + +static int f0_cali(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + aw_info("enter"); + upload_lra(aw_haptic, AW_WRITE_ZERO); + if (aw_haptic->func->get_f0(aw_haptic)) { + aw_err("get f0 failed"); + } else { + /* max and min limit */ + ret = judge_within_cali_range(aw_haptic); + if (ret < 0) + return -ERANGE; + /* calculate cali step */ + aw_haptic->func->calculate_cali_data(aw_haptic); + upload_lra(aw_haptic, AW_F0_CALI_LRA); + } + aw_haptic->func->play_stop(aw_haptic); + + return ret; +} + +static void ram_vbat_comp(struct aw_haptic *aw_haptic, bool flag) +{ + int temp_gain = 0; + + aw_info("enter"); + if (flag) { + if (aw_haptic->ram_vbat_comp == AW_RAM_VBAT_COMP_ENABLE) { + aw_haptic->func->get_vbat(aw_haptic); + temp_gain = aw_haptic->gain * AW_VBAT_REFER / aw_haptic->vbat; + if (temp_gain > (AW_DEFAULT_GAIN * AW_VBAT_REFER / AW_VBAT_MIN)) { + temp_gain = AW_DEFAULT_GAIN * AW_VBAT_REFER / AW_VBAT_MIN; + aw_info("gain limit=%d", temp_gain); + } + aw_haptic->func->set_gain(aw_haptic, temp_gain); + aw_info("ram vbat comp open, set_gain 0x%02X", temp_gain); + } else { + aw_haptic->func->set_gain(aw_haptic, aw_haptic->gain); + aw_info("ram vbat comp close, set_gain 0x%02X", aw_haptic->gain); + } + } else { + aw_haptic->func->set_gain(aw_haptic, aw_haptic->gain); + aw_info("ram vbat comp close, set_gain 0x%02X", aw_haptic->gain); + } +} + +static int osc_calculation_time(struct aw_haptic *aw_haptic) +{ + uint32_t base_addr = aw_haptic->ram.base_addr; + uint32_t buf_len = 0; + struct aw_haptic_container *aw_rtp = aw_haptic->aw_rtp; + + if (!aw_haptic->func->rtp_get_fifo_afs(aw_haptic)) { + aw_dbg("haptic_rtp_get_fifo_afi, rtp_cnt= %u", aw_haptic->rtp_cnt); + + mutex_lock(&aw_haptic->rtp_lock); + pm_qos_enable(aw_haptic, true); + if ((aw_rtp->len - aw_haptic->rtp_cnt) < (base_addr >> 2)) + buf_len = aw_rtp->len - aw_haptic->rtp_cnt; + else + buf_len = (base_addr >> 2); + + if (aw_haptic->rtp_cnt != aw_rtp->len) { + if (aw_haptic->timeval_flags == 1) { + aw_haptic->kstart = ktime_get(); + aw_haptic->timeval_flags = 0; + } + aw_haptic->func->set_rtp_data(aw_haptic, &aw_rtp->data[aw_haptic->rtp_cnt], + buf_len); + aw_haptic->rtp_cnt += buf_len; + } + pm_qos_enable(aw_haptic, false); + mutex_unlock(&aw_haptic->rtp_lock); + } + + if (aw_haptic->func->get_osc_status(aw_haptic)) { + aw_haptic->kend = ktime_get(); + aw_info("osc trim playback done aw_haptic->rtp_cnt= %u", aw_haptic->rtp_cnt); + return 0; + } + aw_haptic->kend = ktime_get(); + aw_haptic->microsecond = ktime_to_us(ktime_sub(aw_haptic->kend, aw_haptic->kstart)); + if (aw_haptic->microsecond > AW_OSC_CALI_MAX_LENGTH) { + aw_info("osc trim time out! aw_haptic->rtp_cnt %u", aw_haptic->rtp_cnt); + return 0; + } + + return -ERANGE; +} + +static int rtp_fw_load(struct aw_haptic *aw_haptic, uint32_t file_num) +{ + int ret = 0; + const struct firmware *rtp_file; + + ret = request_firmware(&rtp_file, aw_rtp_name[file_num], aw_haptic->dev); + if (ret < 0) { + aw_err("failed to read %s", aw_rtp_name[file_num]); + return ret; + } + + vfree(aw_haptic->aw_rtp); + aw_haptic->aw_rtp = NULL; + aw_haptic->aw_rtp = vmalloc(rtp_file->size + sizeof(int)); + if (!aw_haptic->aw_rtp) { + release_firmware(rtp_file); + aw_err("error allocating memory"); + return -ENOMEM; + } + aw_haptic->aw_rtp->len = rtp_file->size; + aw_haptic->rtp_len = rtp_file->size; + aw_info("rtp file:[%s] size = %dbytes", aw_rtp_name[file_num], aw_haptic->aw_rtp->len); + memcpy(aw_haptic->aw_rtp->data, rtp_file->data, rtp_file->size); + release_firmware(rtp_file); + + return 0; +} + +static int rtp_osc_cali(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + aw_info("enter"); + /*aw_haptic add stop,for irq interrupt during calibrate */ + aw_haptic->func->play_stop(aw_haptic); + + mutex_lock(&aw_haptic->rtp_lock); + ret = rtp_fw_load(aw_haptic, 0); + if (ret < 0) { + mutex_unlock(&aw_haptic->rtp_lock); + return ret; + } + mutex_unlock(&aw_haptic->rtp_lock); + + aw_haptic->rtp_init = false; + aw_haptic->rtp_cnt = 0; + aw_haptic->timeval_flags = 1; + + ram_vbat_comp(aw_haptic, false); + aw_haptic->func->play_mode(aw_haptic, AW_RTP_MODE); + disable_irq(gpio_to_irq(aw_haptic->irq_gpio)); + aw_haptic->func->haptic_start(aw_haptic); + while (1) { + ret = osc_calculation_time(aw_haptic); + if (!ret) + break; + } + enable_irq(gpio_to_irq(aw_haptic->irq_gpio)); + aw_haptic->microsecond = ktime_to_us(ktime_sub(aw_haptic->kend, aw_haptic->kstart)); + /*calibration osc */ + aw_info("microsecond: %llu", aw_haptic->microsecond); + + return 0; +} + +static void rtp_trim_lra_cali(struct aw_haptic *aw_haptic) +{ + uint32_t lra_trim_code = 0; + /*0.1 percent below no need to calibrate */ + uint32_t osc_cali_threshold = 10; + uint32_t code = 0; + unsigned long real_time = 0; + unsigned long theory_time = 0; + + upload_lra(aw_haptic, AW_WRITE_ZERO); + if (rtp_osc_cali(aw_haptic)) + return; + real_time = aw_haptic->microsecond; + theory_time = aw_haptic->func->get_theory_time(aw_haptic); + if (theory_time == real_time) { + aw_info("theory_time == real_time: %ld, no need to calibrate!", real_time); + return; + } else if (theory_time < real_time) { + if ((real_time - theory_time) > (theory_time / AW_OSC_TRIM_PARAM)) { + aw_info("(real_time - theory_time) > (theory_time/50), can't calibrate!"); + return; + } + + if ((real_time - theory_time) < (osc_cali_threshold * theory_time / 10000)) { + aw_info("real_time: %ld, theory_time: %ld, no need to calibrate!", + real_time, theory_time); + return; + } + + code = ((real_time - theory_time) * 4) / (theory_time / 1000); + code = ((code % 10 < 5) ? 0 : 1) + code / 10; + code = aw_haptic->trim_lra_boundary + code; + } else if (theory_time > real_time) { + if ((theory_time - real_time) > (theory_time / AW_OSC_TRIM_PARAM)) { + aw_info("(theory_time - real_time) > (theory_time / 50), can't calibrate!"); + return; + } + if ((theory_time - real_time) < (osc_cali_threshold * theory_time / 10000)) { + aw_info("real_time: %ld, theory_time: %ld, no need to calibrate!", + real_time, theory_time); + return; + } + + code = ((theory_time - real_time) * 4) / (theory_time / 1000); + code = ((code % 10 < 5) ? 0 : 1) + code / 10; + code = aw_haptic->trim_lra_boundary - code; + } + if (code >= aw_haptic->trim_lra_boundary) + lra_trim_code = code - aw_haptic->trim_lra_boundary; + else + lra_trim_code = code + aw_haptic->trim_lra_boundary; + + aw_haptic->osc_cali_data = lra_trim_code; + upload_lra(aw_haptic, AW_OSC_CALI_LRA); + aw_info("real_time: %lu, theory_time: %lu", real_time, theory_time); + aw_info("code: %u, trim_lra: 0x%02X", code, lra_trim_code); +} + +static int parse_awrw_data(struct aw_haptic *aw_haptic, const char *buf) +{ + uint8_t i = 0; + uint8_t reg_num = aw_haptic->i2c_info.reg_num; + const char *temp_buf = NULL; + char data_buf[AWRW_CMD_UNIT] = { 0 }; + uint32_t value = 0; + int ret = 0; + int len = strlen(buf) - (AWRW_CMD_UNIT * 3); + + if (len < 0) { + aw_err("parse data error"); + return -ERANGE; + } + temp_buf = &buf[AWRW_CMD_UNIT * 3]; + for (i = 0; i < reg_num; i++) { + if (((i + 1) * AWRW_CMD_UNIT) > len) { + aw_err("parse data error"); + return -ERANGE; + } + memcpy(data_buf, &temp_buf[i * AWRW_CMD_UNIT], 4); + data_buf[4] = '\0'; + ret = kstrtouint(data_buf, 0, &value); + if (ret < 0) { + aw_err("kstrtouint error"); + return ret; + } + aw_haptic->i2c_info.reg_data[i] = (uint8_t)value; + } + + return 0; +} + +static int haptic_audio_ctr_list_insert(struct aw_haptic *aw_haptic, + struct aw_haptic_ctr *haptic_ctr) +{ + struct aw_haptic_ctr *p_new = NULL; + struct aw_haptic_audio *haptic_audio = &aw_haptic->haptic_audio; + + aw_info("enter"); + p_new = kzalloc(sizeof(struct aw_haptic_ctr), GFP_KERNEL); + if (p_new == NULL) + return -ENOMEM; + + /* update new list info */ + p_new->cnt = haptic_ctr->cnt; + p_new->cmd = haptic_ctr->cmd; + p_new->play = haptic_ctr->play; + p_new->wavseq = haptic_ctr->wavseq; + p_new->loop = haptic_ctr->loop; + p_new->gain = haptic_ctr->gain; + INIT_LIST_HEAD(&(p_new->list)); + list_add(&(p_new->list), &(haptic_audio->ctr_list)); + aw_info("exit"); + + return 0; +} + +static void haptic_audio_ctrl_list_clr(struct aw_haptic_audio *haptic_audio) +{ + struct aw_haptic_ctr *p_ctr = NULL; + struct aw_haptic_ctr *p_ctr_bak = NULL; + + list_for_each_entry_safe_reverse(p_ctr, p_ctr_bak, &(haptic_audio->ctr_list), list) { + list_del(&p_ctr->list); + kfree(p_ctr); + p_ctr = NULL; + } +} + +static void haptic_audio_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter!"); + aw_haptic->func->set_wav_seq(aw_haptic, 0x01, 0x00); +} + +static void haptic_audio_off(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->set_gain(aw_haptic, 0x80); + aw_haptic->func->play_stop(aw_haptic); + haptic_audio_ctrl_list_clr(&aw_haptic->haptic_audio); + mutex_unlock(&aw_haptic->lock); +} + +static void haptic_ctr_list_config(struct aw_haptic *aw_haptic, struct aw_haptic_ctr *p_ctr, + struct aw_haptic_ctr *p_ctr_bak, + struct aw_haptic_audio *haptic_audio) +{ + uint32_t list_input_cnt = 0; + uint32_t list_output_cnt = 0; + uint32_t list_diff_cnt = 0; + uint32_t list_del_cnt = 0; + + list_for_each_entry_safe(p_ctr, p_ctr_bak, &(haptic_audio->ctr_list), list) { + list_input_cnt = p_ctr->cnt; + break; + } + list_for_each_entry_safe_reverse(p_ctr, p_ctr_bak, &(haptic_audio->ctr_list), list) { + list_output_cnt = p_ctr->cnt; + break; + } + + if (list_input_cnt > list_output_cnt) + list_diff_cnt = list_input_cnt - list_output_cnt; + + if (list_input_cnt < list_output_cnt) + list_diff_cnt = 32 + list_input_cnt - list_output_cnt; + + if (list_diff_cnt > 2) { + list_for_each_entry_safe_reverse(p_ctr, p_ctr_bak, + &(haptic_audio->ctr_list), list) { + if ((p_ctr->play == 0) && (AW_CMD_ENABLE == (AW_CMD_ENABLE & p_ctr->cmd))) { + list_del(&p_ctr->list); + kfree(p_ctr); + list_del_cnt++; + } + if (list_del_cnt == list_diff_cnt) + break; + } + } +} + +static void parse_haptic_audio_data(struct aw_haptic *aw_haptic) +{ + bool ctr_list_flag = false; + struct aw_haptic_ctr *p_ctr = NULL; + struct aw_haptic_ctr *p_ctr_bak = NULL; + struct aw_haptic_audio *haptic_audio = &(aw_haptic->haptic_audio); + + memset(&(haptic_audio->ctr), 0, sizeof(struct aw_haptic_ctr)); + list_for_each_entry_safe_reverse(p_ctr, p_ctr_bak, &(haptic_audio->ctr_list), list) { + ctr_list_flag = true; + break; + } + + if (ctr_list_flag == false) + aw_dbg("ctr list empty"); + if (ctr_list_flag == true) + haptic_ctr_list_config(aw_haptic, p_ctr, p_ctr_bak, haptic_audio); + + /* get the last data from list */ + list_for_each_entry_safe_reverse(p_ctr, p_ctr_bak, &(haptic_audio->ctr_list), list) { + haptic_audio->ctr.cnt = p_ctr->cnt; + haptic_audio->ctr.cmd = p_ctr->cmd; + haptic_audio->ctr.play = p_ctr->play; + haptic_audio->ctr.wavseq = p_ctr->wavseq; + haptic_audio->ctr.loop = p_ctr->loop; + haptic_audio->ctr.gain = p_ctr->gain; + list_del(&p_ctr->list); + kfree(p_ctr); + p_ctr = NULL; + break; + } + + if (haptic_audio->ctr.play) { + aw_info("cnt=%u, cmd=%u, play=%u, wavseq=%u, loop=%u, gain=%u", + haptic_audio->ctr.cnt, haptic_audio->ctr.cmd, haptic_audio->ctr.play, + haptic_audio->ctr.wavseq, haptic_audio->ctr.loop, haptic_audio->ctr.gain); + } + +} + +static void haptic_audio_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, haptic_audio.work); + + int rtp_is_going_on = 0; + + aw_dbg("enter"); + + mutex_lock(&aw_haptic->haptic_audio.lock); + parse_haptic_audio_data(aw_haptic); + /* rtp mode jump */ + rtp_is_going_on = aw_haptic->func->judge_rtp_going(aw_haptic); + if (rtp_is_going_on) { + mutex_unlock(&aw_haptic->haptic_audio.lock); + return; + } + mutex_unlock(&aw_haptic->haptic_audio.lock); + +#ifdef AW_DOUBLE + if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_ENABLE) { + mutex_lock(&aw_haptic->lock); + /* haptic config */ + if (aw_haptic->haptic_audio.ctr.cmd & AW_CMD_L_EN) { + left->func->play_stop(left); + left->func->play_mode(left, AW_RAM_MODE); + left->func->set_wav_seq(left, 0x00, aw_haptic->haptic_audio.ctr.wavseq); + left->func->set_wav_seq(left, 0x01, 0x00); + left->func->set_wav_loop(left, 0x00, aw_haptic->haptic_audio.ctr.loop); + left->func->set_gain(left, aw_haptic->haptic_audio.ctr.gain); + } + if (aw_haptic->haptic_audio.ctr.cmd & AW_CMD_R_EN) { + right->func->play_stop(right); + right->func->play_mode(right, AW_RAM_MODE); + right->func->set_wav_seq(right, 0x00, aw_haptic->haptic_audio.ctr.wavseq); + right->func->set_wav_seq(right, 0x01, 0x00); + right->func->set_wav_loop(right, 0x00, aw_haptic->haptic_audio.ctr.loop); + right->func->set_gain(right, aw_haptic->haptic_audio.ctr.gain); + } + /* play go */ + if (aw_haptic->haptic_audio.ctr.cmd & AW_CMD_L_EN) + left->func->haptic_start(left); + if (aw_haptic->haptic_audio.ctr.cmd & AW_CMD_R_EN) + right->func->haptic_start(right); + mutex_unlock(&aw_haptic->lock); + } else if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_STOP) { + mutex_lock(&aw_haptic->lock); + left->func->play_stop(left); + right->func->play_stop(right); + mutex_unlock(&aw_haptic->lock); + } else if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_GAIN) { + mutex_lock(&aw_haptic->lock); + left->func->set_gain(left, aw_haptic->haptic_audio.ctr.gain); + right->func->set_gain(right, aw_haptic->haptic_audio.ctr.gain); + mutex_unlock(&aw_haptic->lock); + } +#else + if ((AW_CMD_HAPTIC & aw_haptic->haptic_audio.ctr.cmd) == AW_CMD_ENABLE) { + if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_ENABLE) { + aw_info("haptic audio play start"); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + aw_haptic->func->play_mode(aw_haptic, AW_RAM_MODE); + aw_haptic->func->set_wav_seq(aw_haptic, 0x00, + aw_haptic->haptic_audio.ctr.wavseq); + aw_haptic->func->set_wav_loop(aw_haptic, 0x00, + aw_haptic->haptic_audio.ctr.loop); + aw_haptic->func->set_gain(aw_haptic, aw_haptic->haptic_audio.ctr.gain); + aw_haptic->func->haptic_start(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + } else if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_STOP) { + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + } else if (aw_haptic->haptic_audio.ctr.play == AW_PLAY_GAIN) { + mutex_lock(&aw_haptic->lock); + aw_haptic->func->set_gain(aw_haptic, aw_haptic->haptic_audio.ctr.gain); + mutex_unlock(&aw_haptic->lock); + } + } +#endif +} + +static enum hrtimer_restart haptic_audio_timer_func(struct hrtimer *timer) +{ + struct aw_haptic *aw_haptic = container_of(timer, struct aw_haptic, haptic_audio.timer); + int time = aw_haptic->haptic_audio.timer_val; + + queue_work(aw_haptic->work_queue, &aw_haptic->haptic_audio.work); + hrtimer_start(&aw_haptic->haptic_audio.timer, + ktime_set(time / 1000000, (time % 1000000) * 1000), HRTIMER_MODE_REL); + + return HRTIMER_NORESTART; +} + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", aw_haptic->state); +} + +static ssize_t state_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + return count; +} + +static ssize_t duration_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ktime_t time_rem; + s64 time_ms = 0; + + if (hrtimer_active(&aw_haptic->timer)) { + time_rem = hrtimer_get_remaining(&aw_haptic->timer); + time_ms = ktime_to_ms(time_rem); + } + + return snprintf(buf, PAGE_SIZE, "%lld\n", time_ms); +} + +static ssize_t duration_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + + /* setting 0 on duration is NOP for now */ + if (val <= 0) + return count; + + aw_haptic->duration = val; + aw_info("duration=%d", aw_haptic->duration); + + return count; +} + +static ssize_t activate_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + /* For now nothing to show */ + return snprintf(buf, PAGE_SIZE, "activate = %d\n", aw_haptic->state); +} + +static ssize_t activate_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + int rc = 0; + uint32_t val = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + + if (val != 0 && val != 1) + return count; + + aw_info("value=%u", val); + + mutex_lock(&aw_haptic->lock); + hrtimer_cancel(&aw_haptic->timer); + aw_haptic->state = val; + aw_haptic->activate_mode = aw_haptic->info.mode; + mutex_unlock(&aw_haptic->lock); + queue_work(aw_haptic->work_queue, &aw_haptic->vibrator_work); + + return count; +} + +static ssize_t activate_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", aw_haptic->activate_mode); +} + +static ssize_t activate_mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + + mutex_lock(&aw_haptic->lock); + aw_haptic->activate_mode = val; + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t index_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + aw_haptic->func->get_wav_seq(aw_haptic, 1); + aw_haptic->index = aw_haptic->seq[0]; + + return snprintf(buf, PAGE_SIZE, "index = %d\n", aw_haptic->index); +} + +static ssize_t index_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + + if (val > aw_haptic->ram.ram_num) { + aw_err("input value out of range!"); + return count; + } + + aw_info("value=%u", val); + + mutex_lock(&aw_haptic->lock); + aw_haptic->index = val; + aw_haptic->func->set_repeat_seq(aw_haptic, aw_haptic->index); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t gain_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t gain = 0; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->get_gain(aw_haptic, &gain); + mutex_unlock(&aw_haptic->lock); + + return snprintf(buf, PAGE_SIZE, "gain = 0x%02X\n", gain); +} + +static ssize_t gain_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + aw_info("value=0x%02X", val); + + mutex_lock(&aw_haptic->lock); + aw_haptic->gain = val; + aw_haptic->func->set_gain(aw_haptic, aw_haptic->gain); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t seq_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + uint8_t i = 0; + size_t count = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->get_wav_seq(aw_haptic, AW_SEQUENCER_SIZE); + for (i = 0; i < AW_SEQUENCER_SIZE; i++) + count += snprintf(buf + count, PAGE_SIZE - count, "seq%d = %u\n", i + 1, + aw_haptic->seq[i]); + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t seq_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0, 0 }; + + if (sscanf(buf, "%X %X", &databuf[0], &databuf[1]) == 2) { + if (databuf[0] >= AW_SEQUENCER_SIZE || databuf[1] > aw_haptic->ram.ram_num) { + aw_err("input value out of range!"); + return count; + } + aw_info("seq%u=0x%02X", databuf[0], databuf[1]); + + mutex_lock(&aw_haptic->lock); + aw_haptic->seq[databuf[0]] = (uint8_t)databuf[1]; + aw_haptic->func->set_wav_seq(aw_haptic, (uint8_t)databuf[0], + aw_haptic->seq[databuf[0]]); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t loop_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + uint8_t i = 0; + size_t count = 0; + cdev_t *cdev = dev_get_drvdata(dev); + uint8_t reg_val[AW_SEQUENCER_LOOP_SIZE] = {0}; + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->get_wav_loop(aw_haptic, reg_val); + for (i = 0; i < AW_SEQUENCER_LOOP_SIZE; i++) { + aw_haptic->loop[i * 2 + 0] = (reg_val[i] >> 4) & 0x0F; + aw_haptic->loop[i * 2 + 1] = (reg_val[i] >> 0) & 0x0F; + + count += snprintf(buf + count, PAGE_SIZE - count, "seq%d loop: 0x%02X\n", i * 2 + 1, + aw_haptic->loop[i * 2 + 0]); + count += snprintf(buf + count, PAGE_SIZE - count, "seq%d loop: 0x%02X\n", i * 2 + 2, + aw_haptic->loop[i * 2 + 1]); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t loop_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0, 0 }; + + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + aw_info("seq%u loop=0x%02X", databuf[0], databuf[1]); + + mutex_lock(&aw_haptic->lock); + aw_haptic->loop[databuf[0]] = (uint8_t)databuf[1]; + aw_haptic->func->set_wav_loop(aw_haptic, (uint8_t)databuf[0], + aw_haptic->loop[databuf[0]]); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t reg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + len = aw_haptic->func->get_reg(aw_haptic, len, buf); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t reg_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint8_t val = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0, 0 }; + + if (sscanf(buf, "%X %X", &databuf[0], &databuf[1]) == 2) { + val = (uint8_t)databuf[1]; + mutex_lock(&aw_haptic->lock); + haptic_nv_i2c_writes(aw_haptic, (uint8_t)databuf[0], &val, AW_I2C_BYTE_ONE); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t ram_update_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + int i = 0; + int j = 0; + int size = 0; + ssize_t len = 0; + uint8_t ram_data[AW_RAMDATA_RD_BUFFER_SIZE] = {0}; + uint8_t buffer[AW_RAMDATA_SHOW_LINE_BUFFER_SZIE] = {0}; + uint8_t unit[AW_RAMDATA_SHOW_UINT_SIZE] = {0}; + + mutex_lock(&aw_haptic->lock); + len += snprintf(buf + len, PAGE_SIZE - len, "Please cat log\n"); + /* RAMINIT Enable */ + aw_haptic->func->ram_init(aw_haptic, true); + aw_haptic->func->play_stop(aw_haptic); + aw_haptic->func->set_ram_addr(aw_haptic); + while (i < aw_haptic->ram.len) { + if ((aw_haptic->ram.len - i) < AW_RAMDATA_RD_BUFFER_SIZE) + size = aw_haptic->ram.len - i; + else + size = AW_RAMDATA_RD_BUFFER_SIZE; + + aw_haptic->func->get_ram_data(aw_haptic, ram_data, size); + for (j = 0; j < size; j++) { + sprintf(unit, "0x%02X ", ram_data[j]); + strcat(buffer, unit); + if ((j + 1) % AW_RAMDATA_SHOW_COLUMN == 0 || j == size - 1) { + aw_info("[ram_data]:%s", buffer); + memset(buffer, 0, AW_RAMDATA_SHOW_LINE_BUFFER_SZIE); + } + } + i += size; + } + /* RAMINIT Disable */ + aw_haptic->func->ram_init(aw_haptic, false); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t ram_update_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + if (val) + ram_update(aw_haptic); + + return count; +} + +static ssize_t f0_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + upload_lra(aw_haptic, AW_WRITE_ZERO); + aw_haptic->func->get_f0(aw_haptic); + upload_lra(aw_haptic, AW_F0_CALI_LRA); + mutex_unlock(&aw_haptic->lock); + + len += snprintf(buf + len, PAGE_SIZE - len, "%u\n", aw_haptic->f0); + + return len; +} + +static ssize_t f0_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + return count; +} + + +static ssize_t cali_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + upload_lra(aw_haptic, AW_F0_CALI_LRA); + aw_haptic->func->get_f0(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + len += snprintf(buf + len, PAGE_SIZE - len, "%u\n", aw_haptic->f0); + + return len; +} + +static ssize_t cali_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + if (val) { + mutex_lock(&aw_haptic->lock); + f0_cali(aw_haptic); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + + +static ssize_t f0_save_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "f0_cali_data = 0x%02X\n", + aw_haptic->f0_cali_data); + + return len; +} + +static ssize_t f0_save_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + aw_haptic->f0_cali_data = val; + + return count; +} + +static ssize_t cont_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->read_cont_f0(aw_haptic); + len += snprintf(buf + len, PAGE_SIZE - len, "%u\n", aw_haptic->cont_f0); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t cont_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + if (val) + aw_haptic->func->cont_config(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + return count; +} + + +static ssize_t vbat_monitor_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->get_vbat(aw_haptic); + len += snprintf(buf + len, PAGE_SIZE - len, "vbat_monitor = %u\n", aw_haptic->vbat); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t vbat_monitor_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + + +static ssize_t lra_resistance_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->get_lra_resistance(aw_haptic); + len += snprintf(buf + len, PAGE_SIZE - len, "lra_resistance = %u\n", aw_haptic->lra); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t lra_resistance_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + +static ssize_t prctmode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + uint8_t reg_val = 0; + + mutex_lock(&aw_haptic->lock); + reg_val = aw_haptic->func->get_prctmode(aw_haptic); + len += snprintf(buf + len, PAGE_SIZE - len, "prctmode = %u\n", reg_val); + mutex_unlock(&aw_haptic->lock); + + return len; +} + +static ssize_t prctmode_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0, 0 }; + uint32_t prtime = 0; + uint32_t prlvl = 0; + + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) == 2) { + prtime = databuf[0]; + prlvl = databuf[1]; + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->protect_config(aw_haptic, prtime, prlvl); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t ram_vbat_comp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "ram_vbat_comp = %u\n", + aw_haptic->ram_vbat_comp); + + return len; +} + +static ssize_t ram_vbat_comp_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw_haptic->lock); + if (val) + aw_haptic->ram_vbat_comp = AW_RAM_VBAT_COMP_ENABLE; + else + aw_haptic->ram_vbat_comp = AW_RAM_VBAT_COMP_DISABLE; + mutex_unlock(&aw_haptic->lock); + + return count; +} + + +static ssize_t ram_num_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + get_ram_num(aw_haptic); + len += snprintf(buf + len, PAGE_SIZE - len, "ram_num = %u\n", aw_haptic->ram.ram_num); + + return len; +} + + +static ssize_t awrw_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint8_t reg_num = aw_haptic->i2c_info.reg_num; + uint8_t flag = aw_haptic->i2c_info.flag; + uint8_t *reg_data = aw_haptic->i2c_info.reg_data; + uint8_t i = 0; + ssize_t len = 0; + + if (!reg_num) { + aw_err("awrw parameter error"); + return len; + } + if (flag == AW_READ) { + for (i = 0; i < reg_num; i++) + len += snprintf(buf + len, PAGE_SIZE - len, "0x%02X,", reg_data[i]); + len += snprintf(buf + len - 1, PAGE_SIZE - len, "\n"); + } + + return len; +} + +static ssize_t awrw_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t datatype[3] = { 0 }; + int ret = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (sscanf(buf, "%x %x %x", &datatype[0], &datatype[1], &datatype[2]) == 3) { + if (!datatype[1]) { + aw_err("awrw parameter error"); + return count; + } + aw_haptic->i2c_info.flag = (uint8_t)datatype[0]; + aw_haptic->i2c_info.reg_num = (uint8_t)datatype[1]; + aw_haptic->i2c_info.first_addr = (uint8_t)datatype[2]; + + mutex_lock(&aw_haptic->lock); + if (aw_haptic->i2c_info.flag == AW_WRITE) { + ret = parse_awrw_data(aw_haptic, buf); + if (ret < 0) { + mutex_unlock(&aw_haptic->lock); + return count; + } + haptic_nv_i2c_writes(aw_haptic, aw_haptic->i2c_info.first_addr, + aw_haptic->i2c_info.reg_data, + aw_haptic->i2c_info.reg_num); + } else if (aw_haptic->i2c_info.flag == AW_READ) { + haptic_nv_i2c_reads(aw_haptic, aw_haptic->i2c_info.first_addr, + aw_haptic->i2c_info.reg_data, + aw_haptic->i2c_info.reg_num); + } else { + aw_err("flag is error"); + } + mutex_unlock(&aw_haptic->lock); + + } else + aw_err("missing number of parameters"); + + return count; +} + +static ssize_t gun_type_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "0x%02X\n", aw_haptic->gun_type); +} + +static ssize_t gun_type_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + aw_info("value=%u", val); + + mutex_lock(&aw_haptic->lock); + aw_haptic->gun_type = val; + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t bullet_nr_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "0x%02X\n", aw_haptic->bullet_nr); +} + +static ssize_t bullet_nr_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + aw_info("value=%u", val); + + mutex_lock(&aw_haptic->lock); + aw_haptic->bullet_nr = val; + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t haptic_audio_time_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "haptic_audio.delay_val=%dus\n", + aw_haptic->haptic_audio.delay_val); + len += snprintf(buf + len, PAGE_SIZE - len, "haptic_audio.timer_val=%dus\n", + aw_haptic->haptic_audio.timer_val); + + return len; +} + +static ssize_t haptic_audio_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[2] = { 0 }; + + if (sscanf(buf, "%u %u", &databuf[0], &databuf[1]) == 2) { + aw_haptic->haptic_audio.delay_val = databuf[0]; + aw_haptic->haptic_audio.timer_val = databuf[1]; + } + + return count; +} + +static ssize_t haptic_audio_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf+len, PAGE_SIZE-len, "%u\n", aw_haptic->haptic_audio.ctr.cnt); + + return len; +} + +static int haptic_audio_config(struct aw_haptic *aw_haptic, uint32_t databuf[]) +{ + struct aw_haptic_ctr *hap_ctr = NULL; + int delay = aw_haptic->haptic_audio.delay_val; + + aw_info("enter"); + hap_ctr = kzalloc(sizeof(struct aw_haptic_ctr), GFP_KERNEL); + if (hap_ctr == NULL) + return -ENOMEM; + + mutex_lock(&aw_haptic->haptic_audio.lock); + hap_ctr->cnt = (uint8_t)databuf[0]; + hap_ctr->cmd = (uint8_t)databuf[1]; + hap_ctr->play = (uint8_t)databuf[2]; + hap_ctr->wavseq = (uint8_t)databuf[3]; + hap_ctr->loop = (uint8_t)databuf[4]; + hap_ctr->gain = (uint8_t)databuf[5]; + + haptic_audio_ctr_list_insert(aw_haptic, hap_ctr); + + if (hap_ctr->cmd == 0xff) { + aw_info("haptic_audio stop"); + if (hrtimer_active(&aw_haptic->haptic_audio.timer)) { + aw_info("cancel haptic_audio_timer"); + hrtimer_cancel(&aw_haptic->haptic_audio.timer); + aw_haptic->haptic_audio.ctr.cnt = 0; + haptic_audio_off(aw_haptic); + } + } else { + if (hrtimer_active(&aw_haptic->haptic_audio.timer)) { + /* */ + } else { + aw_info("start haptic_audio_timer"); + haptic_audio_init(aw_haptic); + hrtimer_start(&aw_haptic->haptic_audio.timer, + ktime_set(delay / 1000000, (delay % 1000000) * 1000), + HRTIMER_MODE_REL); + } + } + kfree(hap_ctr); + mutex_unlock(&aw_haptic->haptic_audio.lock); + + return 0; +} + +static ssize_t haptic_audio_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t databuf[6] = { 0 }; + int rtp_is_going_on = 0; + + rtp_is_going_on = aw_haptic->func->judge_rtp_going(aw_haptic); + + if (rtp_is_going_on) { + aw_info("RTP is running, stop audio haptic"); + return count; + } + + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + + if (sscanf(buf, "%u %u %u %u %u %u", &databuf[0], &databuf[1], + &databuf[2], &databuf[3], &databuf[4], &databuf[5]) == 6) { + if (databuf[2]) { + aw_info("cnt=%u, cmd=%u, play=%u", databuf[0], databuf[1], databuf[2]); + aw_info("wavseq=%u, loop=%u, gain=%u", databuf[3], databuf[4], databuf[5]); + haptic_audio_config(aw_haptic, databuf); + } + } + + return count; +} + +#ifdef AW_DOUBLE +static ssize_t dual_cont_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + right->func->play_stop(right); + left->func->play_stop(left); + if (val) { + upload_lra(right, AW_F0_CALI_LRA); + upload_lra(left, AW_F0_CALI_LRA); + right->func->cont_config(right); + left->func->cont_config(left); + } + + return count; +} + +static ssize_t dual_index_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "%d %d\n", left->index, right->index); + + return len; +} + +static ssize_t dual_index_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + int index_l = 0; + int index_r = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (sscanf(buf, "%d %d", &index_l, &index_r) == 2) { + aw_info("index_l=%d index_r=%d", index_l, index_r); + if (index_l > aw_haptic->ram.ram_num || index_r > aw_haptic->ram.ram_num) { + aw_err("input value out of range!"); + return count; + } + mutex_lock(&aw_haptic->lock); + left->index = index_l; + left->func->set_repeat_seq(left, left->index); + right->index = index_r; + right->func->set_repeat_seq(right, right->index); + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t dual_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "dual_mode = %u\n", aw_haptic->activate_mode); +} + +static ssize_t dual_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + mutex_lock(&aw_haptic->lock); + left->activate_mode = val; + right->activate_mode = val; + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t dual_duration_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ktime_t time_rem; + s64 time_ms = 0; + + if (hrtimer_active(&aw_haptic->timer)) { + time_rem = hrtimer_get_remaining(&aw_haptic->timer); + time_ms = ktime_to_ms(time_rem); + } + + return snprintf(buf, PAGE_SIZE, "duration = %lldms\n", time_ms); +} + +static ssize_t dual_duration_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int duration_l = 0; + int duration_r = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + if (sscanf(buf, "%d %d", &duration_l, &duration_r) == 2) { + mutex_lock(&aw_haptic->lock); + left->duration = duration_l; + right->duration = duration_r; + mutex_unlock(&aw_haptic->lock); + } + + return count; +} + +static ssize_t dual_activate_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return snprintf(buf, PAGE_SIZE, "activate = %d\n", aw_haptic->state); +} + +static ssize_t dual_activate_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + aw_info("value=%u", val); + if (!left->ram_init || !right->ram_init) { + aw_err("ram init failed, not allow to play!"); + return count; + } + mutex_lock(&aw_haptic->lock); + left->state = val; + right->state = val; + left->dual_flag = true; + right->dual_flag = true; + mutex_unlock(&aw_haptic->lock); + queue_work(left->work_queue, &left->vibrator_work); + queue_work(right->work_queue, &right->vibrator_work); + + return count; +} +#endif + +static DEVICE_ATTR_RW(state); +static DEVICE_ATTR_RW(reg); +static DEVICE_ATTR_RW(duration); +static DEVICE_ATTR_RW(activate); +static DEVICE_ATTR_RW(activate_mode); +static DEVICE_ATTR_RW(index); +static DEVICE_ATTR_RW(gain); +static DEVICE_ATTR_RW(seq); +static DEVICE_ATTR_RW(loop); +static DEVICE_ATTR_RW(ram_update); +static DEVICE_ATTR_RW(f0); +static DEVICE_ATTR_RW(cali); +static DEVICE_ATTR_RW(f0_save); +static DEVICE_ATTR_RW(cont); +static DEVICE_ATTR_RW(vbat_monitor); +static DEVICE_ATTR_RW(lra_resistance); +static DEVICE_ATTR_RW(prctmode); +static DEVICE_ATTR_RW(ram_vbat_comp); +static DEVICE_ATTR_RO(ram_num); +static DEVICE_ATTR_RW(awrw); +static DEVICE_ATTR_RW(gun_type); +static DEVICE_ATTR_RW(bullet_nr); +static DEVICE_ATTR_RW(haptic_audio_time); +static DEVICE_ATTR_RW(haptic_audio); +#ifdef AW_DOUBLE +static DEVICE_ATTR_WO(dual_cont); +static DEVICE_ATTR_RW(dual_index); +static DEVICE_ATTR_RW(dual_mode); +static DEVICE_ATTR_RW(dual_duration); +static DEVICE_ATTR_RW(dual_activate); +#endif + +static struct attribute *vibrator_attributes[] = { + &dev_attr_state.attr, + &dev_attr_duration.attr, + &dev_attr_activate.attr, + &dev_attr_activate_mode.attr, + &dev_attr_index.attr, + &dev_attr_gain.attr, + &dev_attr_seq.attr, + &dev_attr_loop.attr, + &dev_attr_reg.attr, + &dev_attr_ram_update.attr, + &dev_attr_f0.attr, + &dev_attr_cali.attr, + &dev_attr_f0_save.attr, + &dev_attr_cont.attr, + &dev_attr_vbat_monitor.attr, + &dev_attr_lra_resistance.attr, + &dev_attr_prctmode.attr, + &dev_attr_ram_vbat_comp.attr, + &dev_attr_ram_num.attr, + &dev_attr_awrw.attr, + &dev_attr_gun_type.attr, + &dev_attr_bullet_nr.attr, + &dev_attr_haptic_audio_time.attr, + &dev_attr_haptic_audio.attr, +#ifdef AW_DOUBLE + &dev_attr_dual_cont.attr, + &dev_attr_dual_index.attr, + &dev_attr_dual_mode.attr, + &dev_attr_dual_duration.attr, + &dev_attr_dual_activate.attr, +#endif + NULL +}; + +static struct attribute_group vibrator_attribute_group = { + .attrs = vibrator_attributes +}; + +static ssize_t rtp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "rtp_cnt = %u", aw_haptic->rtp_cnt); + + return len; +} + +static ssize_t rtp_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) { + aw_err("kstrtouint fail"); + return count; + } + + if (!aw_haptic->ram.base_addr) { + aw_err("no set FIFO space for rtp play!"); + return count; + } + + mutex_lock(&aw_haptic->lock); + if ((val > 0) && (val < aw_haptic->rtp_num_max)) { + aw_haptic->state = 1; + aw_haptic->rtp_file_num = val; + } else if (val == 0) { + aw_haptic->state = 0; + } else { + aw_haptic->state = 0; + aw_err("input number error:%u", val); + } + mutex_unlock(&aw_haptic->lock); + queue_work(aw_haptic->work_queue, &aw_haptic->rtp_work); + + return count; +} + +static ssize_t osc_cali_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "osc_cali_data = 0x%02X\n", + aw_haptic->osc_cali_data); + + return len; +} + +static ssize_t osc_cali_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + uint32_t val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw_haptic->lock); + if (val == 1) { + rtp_trim_lra_cali(aw_haptic); + } else if (val == 2) { + upload_lra(aw_haptic, AW_OSC_CALI_LRA); + rtp_osc_cali(aw_haptic); + } + mutex_unlock(&aw_haptic->lock); + + return count; +} + +static ssize_t osc_save_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + len += snprintf(buf + len, PAGE_SIZE - len, "osc_cali_data = 0x%02X\n", + aw_haptic->osc_cali_data); + + return len; +} + +static ssize_t osc_save_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + uint32_t val = 0; + int rc = 0; + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return count; + aw_haptic->osc_cali_data = val; + + return count; +} + +#ifdef AW_DOUBLE +static ssize_t dual_rtp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "left_rtp_cnt = %u\n", left->rtp_cnt); + len += snprintf(buf + len, PAGE_SIZE - len, "right_rtp_cnt = %u\n", right->rtp_cnt); + + return len; +} + +static ssize_t dual_rtp_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + cdev_t *cdev = dev_get_drvdata(dev); + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + int rtp_l = 0; + int rtp_r = 0; + + mutex_lock(&aw_haptic->lock); + if (sscanf(buf, "%d %d", &rtp_l, &rtp_r) == 2) { + if (rtp_l > 0 && rtp_l < aw_haptic->rtp_num_max) { + left->state = 1; + left->rtp_file_num = rtp_l; + } else if (rtp_l == 0) { + left->state = 0; + } else { + left->state = 0; + aw_err("input number error:%d", rtp_l); + } + if (rtp_r > 0 && rtp_r < aw_haptic->rtp_num_max) { + right->state = 1; + right->rtp_file_num = rtp_r; + } else if (rtp_r == 0) { + right->state = 0; + } else { + right->state = 0; + aw_err("input number error:%d", rtp_r); + } + } + left->dual_flag = true; + right->dual_flag = true; + mutex_unlock(&aw_haptic->lock); + queue_work(left->work_queue, &left->rtp_work); + queue_work(right->work_queue, &right->rtp_work); + + return count; +} +#endif + +static DEVICE_ATTR_RW(rtp); +static DEVICE_ATTR_RW(osc_cali); +static DEVICE_ATTR_RW(osc_save); +#ifdef AW_DOUBLE +static DEVICE_ATTR_RW(dual_rtp); +#endif + +static struct attribute *rtp_attributes[] = { + &dev_attr_rtp.attr, + &dev_attr_osc_cali.attr, + &dev_attr_osc_save.attr, +#ifdef AW_DOUBLE + &dev_attr_dual_rtp.attr, +#endif + NULL +}; + +static struct attribute_group rtp_attribute_group = { + .attrs = rtp_attributes +}; + +#ifdef AW_TIKTAP +static inline unsigned int tiktap_get_sys_msecs(void) +{ +#if (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE) + struct timespec64 ts64; + + ktime_get_coarse_real_ts64(&ts64); +#else + struct timespec64 ts64 = current_kernel_time64(); +#endif + + return jiffies_to_msecs(timespec64_to_jiffies(&ts64)); +} + +static void tiktap_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, tiktap_work); + struct mmap_buf_format *tiktap_buf = aw_haptic->start_buf; + int count = 100; + unsigned char reg_val = 0x10; + unsigned char glb_state_val = 0; + unsigned int write_start; + unsigned int buf_cnt = 0; + + mutex_lock(&aw_haptic->lock); + aw_haptic->tiktap_stop_flag = false; + aw_haptic->func->play_mode(aw_haptic, AW_RTP_MODE); + upload_lra(aw_haptic, AW_OSC_CALI_LRA); + while (true && count--) { + if (tiktap_buf->status == MMAP_BUF_DATA_VALID) { + aw_haptic->func->haptic_start(aw_haptic); + mdelay(1); + break; + } else if (aw_haptic->tiktap_stop_flag == true) { + mutex_unlock(&aw_haptic->lock); + return; + } + mdelay(1); + } + if (count <= 0) { + aw_err("wait 100 ms but start_buf->status != VALID! status = 0x%02x", + tiktap_buf->status); + aw_haptic->tiktap_stop_flag = true; + mutex_unlock(&aw_haptic->lock); + return; + } + aw_haptic->tiktap_ready = true; + mutex_unlock(&aw_haptic->lock); + + mutex_lock(&aw_haptic->rtp_lock); + pm_qos_enable(aw_haptic, true); + write_start = tiktap_get_sys_msecs(); + while (true) { + if (tiktap_get_sys_msecs() > (write_start + 800)) { + aw_err("Failed! tiktap endless loop"); + break; + } + reg_val = aw_haptic->func->rtp_get_fifo_aes(aw_haptic); + glb_state_val = aw_haptic->func->get_glb_state(aw_haptic); + if ((glb_state_val & AW_BIT_GLBRD_STATE_MASK) != AW_BIT_STATE_RTP_GO) { + aw_err("tiktap glb_state != RTP_GO!, glb_state = 0x%02x", glb_state_val); + break; + } + if ((aw_haptic->tiktap_stop_flag == true) || + (tiktap_buf->status == MMAP_BUF_DATA_FINISHED) || + (tiktap_buf->status == MMAP_BUF_DATA_INVALID)) { + aw_info("tiktap exit! tiktap_buf->status = 0x%02x", tiktap_buf->status); + break; + } else if ((tiktap_buf->status == MMAP_BUF_DATA_VALID) && (reg_val & 0x01)) { + aw_info("buf_cnt = %u, bit = %u, length = %d!", + buf_cnt, tiktap_buf->bit, tiktap_buf->length); + + aw_haptic->func->set_rtp_data(aw_haptic, tiktap_buf->data, tiktap_buf->length); + tiktap_buf->status = MMAP_BUF_DATA_FINISHED; + + tiktap_buf = tiktap_buf->kernel_next; + write_start = tiktap_get_sys_msecs(); + buf_cnt++; + } else { + mdelay(1); + } + } + pm_qos_enable(aw_haptic, false); + aw_haptic->tiktap_stop_flag = true; + mutex_unlock(&aw_haptic->rtp_lock); +} + +static void tiktap_clean_buf(struct aw_haptic *aw_haptic, int status) +{ + struct mmap_buf_format *tiktap_buf = aw_haptic->start_buf; + int i = 0; + + for (i = 0; i < AW_TIKTAP_MMAP_BUF_SUM; i++) { + tiktap_buf->status = status; + tiktap_buf = tiktap_buf->kernel_next; + } +} + +static long tiktap_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int tmp = 0; + int ret = 0; + struct aw_haptic *aw_haptic = (struct aw_haptic *)file->private_data; + + switch (cmd) { + case TIKTAP_GET_HWINFO: + aw_info("cmd = TIKTAP_GET_HWINFO!"); + tmp = aw_haptic->name; + if (copy_to_user((void __user *)arg, &tmp, sizeof(unsigned int))) + ret = -EFAULT; + break; + case TIKTAP_GET_F0: + aw_info("cmd = TIKTAP_GET_F0!"); + tmp = aw_haptic->f0; + if (copy_to_user((void __user *)arg, &tmp, sizeof(unsigned int))) + ret = -EFAULT; + break; + case TIKTAP_STOP_MODE: + aw_info("cmd = TIKTAP_STOP_MODE!"); + tiktap_clean_buf(aw_haptic, MMAP_BUF_DATA_INVALID); + aw_haptic->tiktap_stop_flag = true; + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + mutex_unlock(&aw_haptic->lock); + break; + case TIKTAP_RTP_MODE: + /* aw_info("cmd = TIKTAP_RTP_MODE!"); */ + tiktap_clean_buf(aw_haptic, MMAP_BUF_DATA_INVALID); + aw_haptic->tiktap_stop_flag = true; + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + mutex_unlock(&aw_haptic->lock); + queue_work(aw_haptic->work_queue, &aw_haptic->tiktap_work); + break; + case TIKTAP_SETTING_GAIN: + aw_info("cmd = TIKTAP_SETTING_GAIN!"); + if (arg > 0x80) + arg = 0x80; + mutex_lock(&aw_haptic->lock); + aw_haptic->func->set_gain(aw_haptic, (uint8_t)arg); + mutex_unlock(&aw_haptic->lock); + break; + default: + aw_info("unknown cmd = %u", cmd); + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long tiktap_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + ret = tiktap_unlocked_ioctl(file, cmd, arg); + + return ret; +} +#endif + +static int tiktap_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long phys; + struct aw_haptic *aw_haptic = (struct aw_haptic *)file->private_data; + int ret = 0; + +#if KERNEL_VERSION(4, 7, 0) < LINUX_VERSION_CODE + vm_flags_t vm_flags = calc_vm_prot_bits(PROT_READ|PROT_WRITE, 0) | + calc_vm_flag_bits(MAP_SHARED); + + vm_flags |= current->mm->def_flags | VM_MAYREAD | VM_MAYWRITE | + VM_MAYEXEC | VM_SHARED | VM_MAYSHARE; + + if (!vma || (pgprot_val(vma->vm_page_prot) != pgprot_val(vm_get_page_prot(vm_flags)))) { + aw_err("vm_page_prot error!"); + return -EPERM; + } + + if (!vma || ((vma->vm_end - vma->vm_start) != (PAGE_SIZE << AW_TIKTAP_MMAP_PAGE_ORDER))) { + aw_err("mmap size check err!"); + return -EPERM; + } +#endif + phys = virt_to_phys(aw_haptic->start_buf); + + ret = remap_pfn_range(vma, vma->vm_start, (phys >> PAGE_SHIFT), + (vma->vm_end - vma->vm_start), vma->vm_page_prot); + if (ret) { + aw_err("mmap failed!"); + return ret; + } + + aw_info("success!"); + + return ret; +} + +static int tiktap_file_open(struct inode *inode, struct file *file) +{ +#ifdef AW_DOUBLE + file->private_data = (void *)left; +#else + file->private_data = (void *)g_aw_haptic; +#endif + return 0; +} + +#ifdef AW_DOUBLE +static int tiktap_file_open_r(struct inode *inode, struct file *file) +{ + file->private_data = (void *)right; + return 0; +} +#endif + +#ifdef KERNEL_OVER_5_10 +static const struct proc_ops tiktap_proc_ops = { + .proc_mmap = tiktap_file_mmap, + .proc_open = tiktap_file_open, + .proc_ioctl = tiktap_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl = tiktap_compat_ioctl, +#endif +}; +#ifdef AW_DOUBLE +static const struct proc_ops tiktap_proc_ops_r = { + .proc_mmap = tiktap_file_mmap, + .proc_open = tiktap_file_open_r, + .proc_ioctl = tiktap_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl = tiktap_compat_ioctl, +#endif +}; +#endif +#else +static const struct file_operations tiktap_proc_ops = { + .owner = THIS_MODULE, + .mmap = tiktap_file_mmap, + .open = tiktap_file_open, + .unlocked_ioctl = tiktap_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tiktap_compat_ioctl, +#endif +}; +#ifdef AW_DOUBLE +static const struct file_operations tiktap_proc_ops_r = { + .owner = THIS_MODULE, + .mmap = tiktap_file_mmap, + .open = tiktap_file_open_r, + .unlocked_ioctl = tiktap_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tiktap_compat_ioctl, +#endif +}; +#endif +#endif + +static int tiktap_init(struct aw_haptic *aw_haptic) +{ + struct mmap_buf_format *tiktap_start_buf; + struct proc_dir_entry *tiktap_config_proc = NULL; + + /* Create proc file node */ +#ifdef AW_DOUBLE + if (of_device_is_compatible(aw_haptic->i2c->dev.of_node, "awinic,haptic_nv_l")) + tiktap_config_proc = proc_create(AW_TIKTAP_PROCNAME, 0664, NULL, &tiktap_proc_ops); + + if (of_device_is_compatible(aw_haptic->i2c->dev.of_node, "awinic,haptic_nv_r")) + tiktap_config_proc = proc_create(AW_TIKTAP_PROCNAME_R, 0664, NULL, &tiktap_proc_ops_r); +#else + tiktap_config_proc = proc_create(AW_TIKTAP_PROCNAME, 0664, NULL, &tiktap_proc_ops); +#endif + if (tiktap_config_proc == NULL) { + aw_err("create proc file failed!"); + return -EPERM; + } + aw_info("create proc file success!"); + + /* Construct shared memory */ + tiktap_start_buf = (struct mmap_buf_format *)__get_free_pages(GFP_KERNEL, AW_TIKTAP_MMAP_PAGE_ORDER); + if (tiktap_start_buf == NULL) { + aw_err("Error __get_free_pages failed"); + return -ENOMEM; + } + SetPageReserved(virt_to_page(tiktap_start_buf)); + { + struct mmap_buf_format *temp; + unsigned int i = 0; + + temp = tiktap_start_buf; + for (i = 1; i < AW_TIKTAP_MMAP_BUF_SUM; i++) { + temp->kernel_next = (tiktap_start_buf + i); + temp = temp->kernel_next; + } + temp->kernel_next = tiktap_start_buf; + + temp = tiktap_start_buf; + for (i = 0; i < AW_TIKTAP_MMAP_BUF_SUM; i++) { + temp->bit = i; + temp = temp->kernel_next; + } + } + + aw_haptic->aw_config_proc = tiktap_config_proc; + aw_haptic->start_buf = tiktap_start_buf; + /* init flag and work */ + aw_haptic->tiktap_stop_flag = true; + aw_haptic->tiktap_ready = false; + INIT_WORK(&aw_haptic->tiktap_work, tiktap_work_routine); + + return 0; +} +#endif + +static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer) +{ + struct aw_haptic *aw_haptic = container_of(timer, struct aw_haptic, timer); + + aw_info("enter"); + aw_haptic->state = 0; + queue_work(aw_haptic->work_queue, &aw_haptic->vibrator_work); + + return HRTIMER_NORESTART; +} + +static void vibrator_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, vibrator_work); + + aw_info("enter"); + + mutex_lock(&aw_haptic->lock); + /* Enter standby mode */ + aw_haptic->func->play_stop(aw_haptic); + if (aw_haptic->state) { +#ifdef AW_DURATION_DECIDE_WAVEFORM + if (ram_config(aw_haptic, aw_haptic->duration) < 0) { + mutex_unlock(&aw_haptic->lock); + return; + } +#endif + upload_lra(aw_haptic, AW_F0_CALI_LRA); + if (aw_haptic->activate_mode == AW_RAM_MODE) { + ram_vbat_comp(aw_haptic, false); + ram_play(aw_haptic); + } else if (aw_haptic->activate_mode == AW_RAM_LOOP_MODE) { + ram_vbat_comp(aw_haptic, true); + ram_play(aw_haptic); + /* run ms timer */ + hrtimer_start(&aw_haptic->timer, ktime_set(aw_haptic->duration / 1000, + (aw_haptic->duration % 1000) * 1000000), HRTIMER_MODE_REL); + } else if (aw_haptic->activate_mode == AW_CONT_MODE) { + aw_haptic->func->cont_config(aw_haptic); + /* run ms timer */ + hrtimer_start(&aw_haptic->timer, ktime_set(aw_haptic->duration / 1000, + (aw_haptic->duration % 1000) * 1000000), HRTIMER_MODE_REL); + } else { + aw_err("activate_mode error"); + } + } + mutex_unlock(&aw_haptic->lock); +} + +static int wait_enter_rtp_mode(struct aw_haptic *aw_haptic, int cnt) +{ + bool rtp_work_flag = false; + uint8_t ret = 0; + + while (cnt) { + ret = aw_haptic->func->judge_rtp_going(aw_haptic); + if (ret) { + rtp_work_flag = true; + aw_info("RTP_GO!"); + break; + } + cnt--; + aw_info("wait for RTP_GO, glb_state=0x%02X", ret); + usleep_range(AW_RTP_DELAY_MIN, AW_RTP_DELAY_MAX); + } + if (!rtp_work_flag) { + aw_haptic->func->play_stop(aw_haptic); + aw_err("failed to enter RTP_GO status!"); + return -ERANGE; + } + + return 0; +} + +static void rtp_work_routine(struct work_struct *work) +{ + int ret = 0; + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, rtp_work); + + aw_info("enter"); + + mutex_lock(&aw_haptic->lock); + if (hrtimer_active(&aw_haptic->timer)) + hrtimer_cancel(&aw_haptic->timer); + aw_haptic->func->play_stop(aw_haptic); + aw_haptic->func->set_rtp_aei(aw_haptic, false); + aw_haptic->func->irq_clear(aw_haptic); + if (!aw_haptic->state) { + mutex_unlock(&aw_haptic->lock); + return; + } + mutex_unlock(&aw_haptic->lock); + + /* fw loaded */ + mutex_lock(&aw_haptic->rtp_lock); + ret = rtp_fw_load(aw_haptic, aw_haptic->rtp_file_num); + if (ret < 0) { + mutex_unlock(&aw_haptic->rtp_lock); + return; + } + mutex_unlock(&aw_haptic->rtp_lock); + + /* rtp config */ + mutex_lock(&aw_haptic->lock); + aw_haptic->rtp_init = true; + upload_lra(aw_haptic, AW_OSC_CALI_LRA); + aw_haptic->func->play_mode(aw_haptic, AW_RTP_MODE); + aw_haptic->func->haptic_start(aw_haptic); + usleep_range(AW_RTP_DELAY_MIN, AW_RTP_DELAY_MAX); + ret = wait_enter_rtp_mode(aw_haptic, 200); + if (ret < 0) { + mutex_unlock(&aw_haptic->lock); + return; + } + mutex_unlock(&aw_haptic->lock); + + mutex_lock(&aw_haptic->rtp_lock); + pm_qos_enable(aw_haptic, true); + aw_haptic->rtp_cnt = 0; + rtp_play(aw_haptic); + if (aw_haptic->play_mode == AW_RTP_MODE) + aw_haptic->func->set_rtp_aei(aw_haptic, true); + pm_qos_enable(aw_haptic, false); + mutex_unlock(&aw_haptic->rtp_lock); +} + +#ifdef TIMED_OUTPUT +static int vibrator_get_time(struct timed_output_dev *dev) +{ + struct aw_haptic *aw_haptic = container_of(dev, struct aw_haptic, vib_dev); + + if (hrtimer_active(&aw_haptic->timer)) { + ktime_t r = hrtimer_get_remaining(&aw_haptic->timer); + + return ktime_to_ms(r); + } + + return 0; +} + +static void vibrator_enable(struct timed_output_dev *dev, int value) +{ + struct aw_haptic *aw_haptic = container_of(dev, struct aw_haptic, vib_dev); + + aw_info("enter"); + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return; + } + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + if (value > 0) { + upload_lra(aw_haptic, AW_F0_CALI_LRA); + ram_vbat_comp(aw_haptic, false); + aw_haptic->func->play_mode(aw_haptic, AW_RAM_MODE); + aw_haptic->func->haptic_start(aw_haptic); + } + mutex_unlock(&aw_haptic->lock); + + aw_info("exit"); +} +#else +static enum led_brightness brightness_get(struct led_classdev *cdev) +{ + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + return aw_haptic->amplitude; +} + +static void brightness_set(struct led_classdev *cdev, enum led_brightness level) +{ + struct aw_haptic *aw_haptic = container_of(cdev, struct aw_haptic, vib_dev); + + aw_info("enter"); + if (!aw_haptic->ram_init) { + aw_err("ram init failed, not allow to play!"); + return; + } + aw_haptic->amplitude = level; + + mutex_lock(&aw_haptic->lock); + aw_haptic->state = aw_haptic->amplitude; + aw_haptic->activate_mode = AW_RAM_MODE; + mutex_unlock(&aw_haptic->lock); + queue_work(aw_haptic->work_queue, &aw_haptic->vibrator_work); +} +#endif + +static int vibrator_init(struct aw_haptic *aw_haptic) +{ + int ret = 0; + + aw_info("enter"); + +#ifdef TIMED_OUTPUT + aw_info("TIMED_OUT FRAMEWORK!"); +#ifdef AW_DOUBLE + ret = memcmp(aw_haptic->mark, "left", sizeof("left")); + if (!ret) + aw_haptic->vib_dev.name = "vibrator_l"; + ret = memcmp(aw_haptic->mark, "right", sizeof("right")); + if (!ret) + aw_haptic->vib_dev.name = "vibrator_r"; +#else + aw_haptic->vib_dev.name = "vibrator"; +#endif + aw_haptic->vib_dev.get_time = vibrator_get_time; + aw_haptic->vib_dev.enable = vibrator_enable; + + ret = timed_output_dev_register(&(aw_haptic->vib_dev)); + if (ret < 0) { + aw_err("fail to create timed output dev"); + return ret; + } +#else + aw_info("loaded in leds_cdev framework!"); +#ifdef AW_DOUBLE + ret = memcmp(aw_haptic->mark, "left", sizeof("left")); + if (!ret) + aw_haptic->vib_dev.name = "vibrator_l"; + ret = memcmp(aw_haptic->mark, "right", sizeof("right")); + if (!ret) + aw_haptic->vib_dev.name = "vibrator_r"; +#else +#ifdef KERNEL_OVER_5_10 + aw_haptic->vib_dev.name = "aw_vibrator"; +#else + aw_haptic->vib_dev.name = "vibrator"; +#endif +#endif + aw_haptic->vib_dev.brightness_get = brightness_get; + aw_haptic->vib_dev.brightness_set = brightness_set; + ret = devm_led_classdev_register(&aw_haptic->i2c->dev, &aw_haptic->vib_dev); + if (ret < 0) { + aw_err("fail to create led dev"); + return ret; + } +#endif + + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &vibrator_attribute_group); + if (ret < 0) { + aw_err("error creating sysfs common attr files"); + return ret; + } + if (aw_haptic->is_used_irq_pin) { + ret = sysfs_create_group(&aw_haptic->vib_dev.dev->kobj, &rtp_attribute_group); + if (ret < 0) { + aw_err("error creating sysfs rtp attr files"); + return ret; + } + } + hrtimer_init(&aw_haptic->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + aw_haptic->timer.function = vibrator_timer_func; + INIT_WORK(&aw_haptic->vibrator_work, vibrator_work_routine); + INIT_WORK(&aw_haptic->rtp_work, rtp_work_routine); + mutex_init(&aw_haptic->lock); + mutex_init(&aw_haptic->rtp_lock); + sema_init(&aw_haptic->sema, 1); + + return 0; +} + +static void haptic_init(struct aw_haptic *aw_haptic) +{ + aw_info("enter"); + aw_haptic->haptic_audio.delay_val = 1; + aw_haptic->haptic_audio.timer_val = 21318; + INIT_LIST_HEAD(&(aw_haptic->haptic_audio.ctr_list)); + hrtimer_init(&aw_haptic->haptic_audio.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + aw_haptic->haptic_audio.timer.function = haptic_audio_timer_func; + INIT_WORK(&aw_haptic->haptic_audio.work, haptic_audio_work_routine); + mutex_init(&aw_haptic->haptic_audio.lock); + + mutex_lock(&aw_haptic->lock); + aw_haptic->rtp_num_max = sizeof(aw_rtp_name) / AW_NAME_MAX; + aw_haptic->activate_mode = aw_haptic->info.mode; + aw_haptic->f0_pre = aw_haptic->info.f0_pre; + aw_haptic->gun_type = AW_GUN_TYPE_DEF_VAL; + aw_haptic->bullet_nr = AW_BULLET_NR_DEF_VAL; + aw_haptic->func->play_mode(aw_haptic, AW_STANDBY_MODE); + aw_haptic->func->misc_para_init(aw_haptic); + aw_haptic->func->vbat_mode_config(aw_haptic, AW_CONT_VBAT_HW_COMP_MODE); + aw_haptic->ram_vbat_comp = AW_RAM_VBAT_COMP_ENABLE; + + if (aw_haptic->info.lk_f0_cali) { + aw_haptic->f0_cali_data = aw_haptic->info.lk_f0_cali; + upload_lra(aw_haptic, AW_F0_CALI_LRA); + } else { + f0_cali(aw_haptic); + } + mutex_unlock(&aw_haptic->lock); + + aw_info("exit"); +} + +static void ram_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, ram_work.work); + + ram_update(aw_haptic); +} + +static void ram_work_init(struct aw_haptic *aw_haptic) +{ + int ram_timer_val = AW_RAM_WORK_DELAY_INTERVAL; + + INIT_DELAYED_WORK(&aw_haptic->ram_work, ram_work_routine); + schedule_delayed_work(&aw_haptic->ram_work, msecs_to_jiffies(ram_timer_val)); +} + +#ifdef AW_INPUT_FRAMEWORK +static void input_stop_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, stop_work); + + mutex_lock(&aw_haptic->lock); + hrtimer_cancel(&aw_haptic->timer); + aw_haptic->func->play_stop(aw_haptic); + mutex_unlock(&aw_haptic->lock); +} + +static void input_gain_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, input_gain_work); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->set_gain(aw_haptic, aw_haptic->gain); + mutex_unlock(&aw_haptic->lock); +} + +static void input_vib_work_routine(struct work_struct *work) +{ + struct aw_haptic *aw_haptic = container_of(work, struct aw_haptic, input_vib_work); + + mutex_lock(&aw_haptic->lock); + /* Enter standby mode */ + hrtimer_cancel(&aw_haptic->timer); + aw_haptic->func->play_stop(aw_haptic); + if (aw_haptic->state) { + upload_lra(aw_haptic, AW_F0_CALI_LRA); + if (aw_haptic->activate_mode == AW_RAM_MODE) { + ram_vbat_comp(aw_haptic, false); + aw_haptic->func->set_wav_seq(aw_haptic, 0x00, aw_haptic->index); + aw_haptic->func->set_wav_seq(aw_haptic, 0x01, 0x00); + aw_haptic->func->set_wav_loop(aw_haptic, 0x00, 0x00); + ram_play(aw_haptic); + } else if (aw_haptic->activate_mode == AW_RAM_LOOP_MODE) { + ram_vbat_comp(aw_haptic, true); + aw_haptic->func->set_repeat_seq(aw_haptic, aw_haptic->index); + ram_play(aw_haptic); + /* run ms timer */ + hrtimer_start(&aw_haptic->timer, ktime_set(aw_haptic->duration / 1000, + (aw_haptic->duration % 1000) * 1000000), HRTIMER_MODE_REL); + } else { + aw_err("activate_mode error"); + } + } + mutex_unlock(&aw_haptic->lock); +} + +static int input_upload_effect(struct input_dev *dev, struct ff_effect *effect, + struct ff_effect *old) +{ + struct aw_haptic *aw_haptic = input_get_drvdata(dev); + short wav_id = 0; + int wav_id_max = 0; + int ret = 0; + + mutex_lock(&aw_haptic->lock); + switch (effect->type) { + case FF_CONSTANT: + aw_haptic->activate_mode = AW_RAM_LOOP_MODE; + aw_haptic->duration = effect->replay.length; + aw_haptic->index = aw_haptic->ram.ram_num; + aw_info("waveform id = %d", aw_haptic->index); + break; + case FF_PERIODIC: + ret = copy_from_user(&wav_id, effect->u.periodic.custom_data, sizeof(short)); + if (ret) { + aw_err("copy from user error %d!!", ret); + mutex_unlock(&aw_haptic->lock); + return -ERANGE; + } + aw_info("waveform id = %d", wav_id); + wav_id_max = sizeof(aw_rtp_name) / sizeof(*aw_rtp_name) + + aw_haptic->ram.ram_num - 1; + if (wav_id > 0 && wav_id < aw_haptic->ram.ram_num) { + aw_haptic->activate_mode = AW_RAM_MODE; + aw_haptic->index = wav_id; + } else if (wav_id > aw_haptic->ram.ram_num && wav_id <= wav_id_max) { + aw_haptic->activate_mode = AW_RTP_MODE; + aw_haptic->rtp_file_num = wav_id - aw_haptic->ram.ram_num; + } else { + aw_haptic->activate_mode = AW_STANDBY_MODE; + aw_err("waveform id is error"); + mutex_unlock(&aw_haptic->lock); + return -ERANGE; + } + break; + default: + aw_err("Unsupported effect type: %u", effect->type); + break; + } + mutex_unlock(&aw_haptic->lock); + + return 0; +} + +static int input_playback(struct input_dev *dev, int effect_id, int val) +{ + struct aw_haptic *aw_haptic = input_get_drvdata(dev); + + if (val > 0) { + aw_haptic->state = 1; + } else { + queue_work(aw_haptic->work_queue, &aw_haptic->stop_work); + return 0; + } + + switch (aw_haptic->activate_mode) { + case AW_RAM_MODE: + queue_work(aw_haptic->work_queue, &aw_haptic->input_vib_work); + break; + case AW_RAM_LOOP_MODE: + queue_work(aw_haptic->work_queue, &aw_haptic->input_vib_work); + break; + case AW_RTP_MODE: + queue_work(aw_haptic->work_queue, &aw_haptic->rtp_work); + break; + default: + aw_err("Unsupported mode: %d", aw_haptic->activate_mode); + break; + } + + return 0; +} + +static int input_erase(struct input_dev *dev, int effect_id) +{ + struct aw_haptic *aw_haptic = input_get_drvdata(dev); + + aw_haptic->duration = 0; + + return 0; +} + +static void input_set_gain(struct input_dev *dev, uint16_t gain) +{ + struct aw_haptic *aw_haptic = input_get_drvdata(dev); + + if (gain > 0x7fff) + gain = 0x7fff; + aw_haptic->gain = gain * 0x80 / 0x7fff; + queue_work(aw_haptic->work_queue, &aw_haptic->input_gain_work); + aw_info("aw_haptic->gain = 0x%02x", aw_haptic->gain); +} + +static int input_framework_init(struct aw_haptic *aw_haptic) +{ + struct input_dev *input_dev; + int ret = 0; + + input_dev = devm_input_allocate_device(aw_haptic->dev); + if (input_dev == NULL) + return -ENOMEM; + input_dev->name = "aw-haptic-nv"; + input_set_drvdata(input_dev, aw_haptic); + aw_haptic->input_dev = input_dev; + input_set_capability(input_dev, EV_FF, FF_GAIN); + input_set_capability(input_dev, EV_FF, FF_CONSTANT); + input_set_capability(input_dev, EV_FF, FF_PERIODIC); + input_set_capability(input_dev, EV_FF, FF_CUSTOM); + ret = input_ff_create(input_dev, AW_EFFECT_NUMBER); + if (ret < 0) { + aw_err("create input FF device failed, rc=%d\n", ret); + return ret; + } + input_dev->ff->upload = input_upload_effect; + input_dev->ff->playback = input_playback; + input_dev->ff->erase = input_erase; + input_dev->ff->set_gain = input_set_gain; + INIT_WORK(&aw_haptic->input_gain_work, input_gain_work_routine); + INIT_WORK(&aw_haptic->stop_work, input_stop_work_routine); + INIT_WORK(&aw_haptic->input_vib_work, input_vib_work_routine); + ret = input_register_device(input_dev); + if (ret < 0) { + aw_err("register input device failed, rc=%d\n", ret); + input_ff_destroy(aw_haptic->input_dev); + return ret; + } + + return ret; +} +#endif + +static int aw_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + int ret = 0; + struct aw_haptic *aw_haptic; + struct device_node *np = i2c->dev.of_node; + + pr_info("<%s>%s: enter\n", AW_I2C_NAME, __func__); + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { + pr_err("<%s>%s: check_functionality failed\n", AW_I2C_NAME, __func__); + return -EIO; + } + + aw_haptic = devm_kzalloc(&i2c->dev, sizeof(struct aw_haptic), GFP_KERNEL); + if (aw_haptic == NULL) + return -ENOMEM; + + aw_haptic->dev = &i2c->dev; + aw_haptic->i2c = i2c; + + i2c_set_clientdata(i2c, aw_haptic); +#ifdef AW_INPUT_FRAMEWORK + ret = input_framework_init(aw_haptic); + if (ret < 0) + goto err_input_config; +#endif + /* aw_haptic rst & int */ + if (np) { + ret = parse_dt_gpio(aw_haptic, &i2c->dev, np); + if (ret) { + aw_err("failed to parse gpio"); + goto err_parse_dt; + } + } else { + aw_haptic->reset_gpio = -1; + aw_haptic->irq_gpio = -1; + } + + if (aw_haptic->is_used_rst_pin) { + if (gpio_is_valid(aw_haptic->reset_gpio)) { + ret = devm_gpio_request_one(&i2c->dev, aw_haptic->reset_gpio, + GPIOF_OUT_INIT_LOW, "awinic_rst"); + if (ret) { + aw_err("rst request failed"); + goto err_reset_gpio_request; + } + } + } + + if (gpio_is_valid(aw_haptic->irq_gpio)) { + ret = devm_gpio_request_one(&i2c->dev, aw_haptic->irq_gpio, + GPIOF_DIR_IN, "awinic_int"); + if (ret) { + aw_err("int request failed"); + goto err_irq_gpio_request; + } + } + + parse_dts_i2c_addr(aw_haptic, &i2c->dev, np); + /* aw_haptic chip id */ + ret = parse_chipid(aw_haptic); + if (ret < 0) { + aw_err("read_chipid failed ret=%d", ret); + goto err_id; + } + + ret = chip_private_init(aw_haptic); + if (ret < 0) { + aw_err("chip_private_init failed ret=%d", ret); + goto err_chip_private_init; + } + + ret = func_ptr_init(aw_haptic, &i2c->dev); + if (ret < 0) { + aw_err("ctrl_init failed ret=%d", ret); + goto err_ctrl_init; + } + + ret = aw_haptic->func->check_qualify(aw_haptic); + if (ret < 0) { + aw_err("qualify check failed ret=%d", ret); + goto err_ctrl_init; + } + + sw_reset(aw_haptic); + ret = aw_haptic->func->offset_cali(aw_haptic); + if (ret < 0) + sw_reset(aw_haptic); + + aw_haptic->func->parse_dts(aw_haptic, np); + + ret = irq_config(&i2c->dev, aw_haptic); + if (ret != 0) { + aw_err("irq_config failed ret=%d", ret); + goto err_irq_config; + } + +#ifdef AW_TIKTAP + g_aw_haptic = aw_haptic; + ret = tiktap_init(aw_haptic); + if (ret) { + aw_err("tiktap_init failed ret = %d", ret); + goto err_irq_config; + } +#endif + vibrator_init(aw_haptic); + haptic_init(aw_haptic); + aw_haptic->work_queue = create_singlethread_workqueue("aw_haptic_vibrator_work_queue"); + if (!aw_haptic->work_queue) { + aw_err("Error creating aw_haptic_vibrator_work_queue"); + goto err_irq_config; + } + aw_haptic->func->creat_node(aw_haptic); + ram_work_init(aw_haptic); + dev_set_drvdata(&i2c->dev, aw_haptic); + aw_info("probe completed successfully!"); + return 0; + +err_irq_config: +err_ctrl_init: +err_chip_private_init: +err_irq_gpio_request: +err_reset_gpio_request: +err_parse_dt: +err_id: +err_input_config: + devm_kfree(&i2c->dev, aw_haptic); + aw_haptic = NULL; + return ret; +} + +#ifdef KERNEL_OVER_6_1 +static void aw_i2c_remove(struct i2c_client *i2c) +{ + struct aw_haptic *aw_haptic = i2c_get_clientdata(i2c); + + aw_info("enter"); +#ifdef TIMED_OUTPUT + timed_output_dev_unregister(&aw_haptic->vib_dev); +#else + sysfs_remove_group(&aw_haptic->vib_dev.dev->kobj, &vibrator_attribute_group); + devm_led_classdev_unregister(&aw_haptic->i2c->dev, &aw_haptic->vib_dev); +#endif +#ifdef AW_INPUT_FRAMEWORK + cancel_work_sync(&aw_haptic->input_gain_work); + cancel_work_sync(&aw_haptic->stop_work); + cancel_work_sync(&aw_haptic->input_vib_work); + input_unregister_device(aw_haptic->input_dev); + input_ff_destroy(aw_haptic->input_dev); +#endif + cancel_delayed_work_sync(&aw_haptic->ram_work); + cancel_work_sync(&aw_haptic->haptic_audio.work); + hrtimer_cancel(&aw_haptic->haptic_audio.timer); + cancel_work_sync(&aw_haptic->rtp_work); + cancel_work_sync(&aw_haptic->vibrator_work); + hrtimer_cancel(&aw_haptic->timer); + mutex_destroy(&aw_haptic->lock); + mutex_destroy(&aw_haptic->rtp_lock); + mutex_destroy(&aw_haptic->haptic_audio.lock); +#ifdef AW_TIKTAP + cancel_work_sync(&aw_haptic->tiktap_work); + ClearPageReserved(virt_to_page(aw_haptic->start_buf)); + free_pages((unsigned long)aw_haptic->start_buf, AW_TIKTAP_MMAP_PAGE_ORDER); + aw_haptic->start_buf = NULL; + proc_remove(aw_haptic->aw_config_proc); + aw_haptic->aw_config_proc = NULL; +#endif + devm_free_irq(&i2c->dev, gpio_to_irq(aw_haptic->irq_gpio), aw_haptic); +} +#else +static int aw_i2c_remove(struct i2c_client *i2c) +{ + struct aw_haptic *aw_haptic = i2c_get_clientdata(i2c); + + aw_info("enter"); +#ifdef TIMED_OUTPUT + timed_output_dev_unregister(&aw_haptic->vib_dev); +#else + sysfs_remove_group(&aw_haptic->vib_dev.dev->kobj, &vibrator_attribute_group); + devm_led_classdev_unregister(&aw_haptic->i2c->dev, &aw_haptic->vib_dev); +#endif +#ifdef AW_INPUT_FRAMEWORK + cancel_work_sync(&aw_haptic->input_gain_work); + cancel_work_sync(&aw_haptic->stop_work); + cancel_work_sync(&aw_haptic->input_vib_work); + input_unregister_device(aw_haptic->input_dev); + input_ff_destroy(aw_haptic->input_dev); +#endif + cancel_delayed_work_sync(&aw_haptic->ram_work); + cancel_work_sync(&aw_haptic->haptic_audio.work); + hrtimer_cancel(&aw_haptic->haptic_audio.timer); + cancel_work_sync(&aw_haptic->rtp_work); + cancel_work_sync(&aw_haptic->vibrator_work); + hrtimer_cancel(&aw_haptic->timer); + mutex_destroy(&aw_haptic->lock); + mutex_destroy(&aw_haptic->rtp_lock); + mutex_destroy(&aw_haptic->haptic_audio.lock); +#ifdef AW_TIKTAP + cancel_work_sync(&aw_haptic->tiktap_work); + ClearPageReserved(virt_to_page(aw_haptic->start_buf)); + free_pages((unsigned long)aw_haptic->start_buf, AW_TIKTAP_MMAP_PAGE_ORDER); + aw_haptic->start_buf = NULL; + proc_remove(aw_haptic->aw_config_proc); + aw_haptic->aw_config_proc = NULL; +#endif + devm_free_irq(&i2c->dev, gpio_to_irq(aw_haptic->irq_gpio), aw_haptic); + + return 0; +} +#endif + +static int aw_i2c_suspend(struct device *dev) +{ + int ret = 0; + struct aw_haptic *aw_haptic = dev_get_drvdata(dev); + + aw_info("enter"); + + mutex_lock(&aw_haptic->lock); + aw_haptic->func->play_stop(aw_haptic); + mutex_unlock(&aw_haptic->lock); + + return ret; +} + +static int aw_i2c_resume(struct device *dev) +{ + pr_info("<%s>%s enter\n", AW_I2C_NAME, __func__); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(aw_pm_ops, aw_i2c_suspend, aw_i2c_resume); + +static const struct i2c_device_id aw_i2c_id[] = { + {AW_I2C_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, aw_i2c_id); + +static const struct of_device_id aw_dt_match[] = { +#ifdef AW_DOUBLE + {.compatible = "awinic,haptic_nv_r"}, + {.compatible = "awinic,haptic_nv_l"}, +#else + {.compatible = "awinic,haptic_nv"}, +#endif + {}, +}; + +static struct i2c_driver aw_i2c_driver = { + .driver = { + .name = AW_I2C_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(aw_dt_match), +#ifdef CONFIG_PM_SLEEP + .pm = &aw_pm_ops, +#endif + }, + .probe = aw_i2c_probe, + .remove = aw_i2c_remove, + .id_table = aw_i2c_id, +}; + +static int __init aw_i2c_init(void) +{ + int ret = 0; + + pr_info("<%s>%s: aw_haptic driver version %s\n", AW_I2C_NAME, __func__, + HAPTIC_NV_DRIVER_VERSION); + ret = i2c_add_driver(&aw_i2c_driver); + if (ret) { + pr_err("<%s>%s: fail to add aw_haptic device into i2c\n", AW_I2C_NAME, __func__); + return ret; + } + return 0; +} +module_init(aw_i2c_init); + +static void __exit aw_i2c_exit(void) +{ + i2c_del_driver(&aw_i2c_driver); +} +module_exit(aw_i2c_exit); + +MODULE_DESCRIPTION("AWINIC Haptic Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.h b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.h new file mode 100644 index 000000000000..30a8c3c8369c --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.h @@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _HAPTIC_NV_H_ +#define _HAPTIC_NV_H_ +/********************************************************* + * + * Macro Control + * + *********************************************************/ +#define AW_CHECK_RAM_DATA +#define AW_READ_BIN_FLEXBALLY +#define AW_INPUT_FRAMEWORK +#define AW_TIKTAP +/* #define AW_DOUBLE */ +/* #define AW_DURATION_DECIDE_WAVEFORM */ +/* #define AW_ENABLE_RTP_PRINT_LOG */ +/* #define AW862X_MUL_GET_F0 */ +/* #define AW_MAXIMUM_F0_CALI_DATA */ +#define AW862X_DRIVER +#define AW862XX_DRIVER +#define AW8623X_DRIVER +#define AW8624X_DRIVER +/********************************************************* + * + * Haptic_NV CHIPID + * + *********************************************************/ +#define AW8623_CHIP_ID (0x23) +#define AW8624_CHIP_ID (0x24) +#define AW8622X_CHIP_ID (0x00) +#define AW86214_CHIP_ID (0x01) +#define AW8623X_CHIP_ID_H (0x23) +#define AW86233_CHIP_ID (0x2330) +#define AW86234_CHIP_ID (0x2340) +#define AW86235_CHIP_ID (0x2350) +#define AW8624X_CHIP_ID_H (0x24) +#define AW86243_CHIP_ID (0x2430) +#define AW86245_CHIP_ID (0x2450) +/********************************************************* + * + * Marco + * + *********************************************************/ +#define AW_I2C_NAME "haptic_nv" +#define AW_I2C_RETRIES (5) +#define AW_I2C_READ_MSG_NUM (2) +#define AW_I2C_BYTE_ONE (1) +#define AW_I2C_BYTE_TWO (2) +#define AW_I2C_BYTE_THREE (3) +#define AW_I2C_BYTE_FOUR (4) +#define AW_I2C_BYTE_FIVE (5) +#define AW_I2C_BYTE_SIX (6) +#define AW_I2C_BYTE_SEVEN (7) +#define AW_I2C_BYTE_EIGHT (8) + +#define AWRW_SIZE (220) +#define AW_REG_MAX (0xFF) +#define AW_NAME_MAX (64) +#define AW_VBAT_MIN (3000) +#define AW_VBAT_MAX (4500) +#define AW_TRIG_NUM (3) +#define AWRW_CMD_UNIT (5) +#define AW_VBAT_REFER (4200) +#define AW_DEFAULT_GAIN (0x80) +#define AW_SEQUENCER_SIZE (8) +#define AW_PM_QOS_VALUE_VB (400) +#define AW_GUN_TYPE_DEF_VAL (0xFF) +#define AW_DRV_WIDTH_MIN (0) +#define AW_DRV_WIDTH_MAX (255) +#define AW_BULLET_NR_DEF_VAL (0) +#define CPU_LATENCY_QOC_VALUE (0) +#define AW_SEQUENCER_LOOP_SIZE (4) +#define AW_RAMDATA_SHOW_COLUMN (16) +#define AW_READ_CHIPID_RETRIES (5) +#define AW_RAMDATA_RD_BUFFER_SIZE (1024) +#define AW_RAMDATA_WR_BUFFER_SIZE (2048) +#define AW_RAMDATA_SHOW_UINT_SIZE (6) +#define AW_READ_CHIPID_RETRY_DELAY (2) +#define AW_EFFECT_NUMBER (3) +#define AW_RAM_WORK_DELAY_INTERVAL (8000) +#define AW_RAMDATA_SHOW_LINE_BUFFER_SZIE (100) + +#define AW_RL_DELAY_MIN (3000) +#define AW_RL_DELAY_MAX (3500) +#define AW_F0_DELAY_MIN (10000) +#define AW_F0_DELAY_MAX (10500) +#define AW_RTP_DELAY_MIN (2000) +#define AW_RTP_DELAY_MAX (2500) +#define AW_PLAY_DELAY_MIN (2000) +#define AW_PLAY_DELAY_MAX (2500) +#define AW_STOP_DELAY_MIN (2000) +#define AW_STOP_DELAY_MAX (2500) +#define AW_VBAT_DELAY_MIN (2000) +#define AW_VBAT_DELAY_MAX (2500) +#define AW_OSC_TRIM_PARAM (50) +#define AW_OSC_CALI_MAX_LENGTH (5100000) + +#define AW_SET_RAMADDR_H(addr) ((addr) >> 8) +#define AW_SET_RAMADDR_L(addr) ((addr) & 0x00FF) +#define AW_SET_BASEADDR_H(addr) ((addr) >> 8) +#define AW_SET_BASEADDR_L(addr) ((addr) & 0x00FF) +/********************************************************* + * + * aw862x marco + * + ********************************************************/ +#define AW862X_F0_CALI_ACCURACY (25) +#define AW862X_MUL_GET_F0_RANGE (150) +#define AW862X_MUL_GET_F0_NUM (3) + +#define AW862X_VBAT_FORMULA(code) (6100 * (code) / 256) +#define AW862X_F0_FORMULA(reg, coeff) (1000000000 / ((reg) * (coeff))) +#define AW862X_RL_FORMULA(reg_val) (298 * (reg_val)) +#define AW862X_SET_AEADDR_H(addr) ((((addr) >> 1) >> 8)) +#define AW862X_SET_AEADDR_L(addr) (((addr) >> 1) & 0x00FF) +#define AW862X_SET_AFADDR_H(addr) (((addr) - ((addr) >> 2)) >> 8) +#define AW862X_SET_AFADDR_L(addr) (((addr) - ((addr) >> 2)) & 0x00FF) +/********************************************************* + * + * aw862xx marco + * + ********************************************************/ +#define AW862XX_DRV2_LVL_MAX (127) +#define AW862XX_F0_CALI_ACCURACY (24) +#define AW862XX_VBAT_FORMULA(code) (6100 * (code) / 1024) +#define AW862XX_OS_FORMULA(os_code, d2s_gain) (2440 * ((os_code) - 512) / (1024 * ((d2s_gain) + 1))) +#define AW862XX_F0_FORMULA(code) (384000 * 10 / (code)) +#define AW862XX_RL_FORMULA(code, d2s_gain) (((code) * 678 * 100) / (1024 * (d2s_gain))) +#define AW862XX_SET_AEADDR_H(addr) ((((addr) >> 1) >> 4) & 0xF0) +#define AW862XX_SET_AEADDR_L(addr) (((addr) >> 1) & 0x00FF) +#define AW862XX_SET_AFADDR_H(addr) ((((addr) - ((addr) >> 2)) >> 8) & 0x0F) +#define AW862XX_SET_AFADDR_L(addr) (((addr) - ((addr) >> 2)) & 0x00FF) +#define AW862XX_DRV2_LVL_FORMULA(f0, vrms) ((((f0) < 1800) ? 1809920 : 1990912) / 1000 * (vrms) / 61000) +#define AW862XX_DRV_WIDTH_FORMULA(f0, margin, brk_gain) \ + ((240000 / (f0)) - (margin) - (brk_gain) - 8) + +/********************************************************* + * + * aw8623x marco + * + ********************************************************/ +#define AW8623X_DRV2_LVL_MAX (127) +#define AW8623X_F0_CALI_ACCURACY (24) + +#define AW8623X_VBAT_FORMULA(code) (6100 * (code) / 1023) +#define AW8623X_F0_FORMULA(code) (384000 * 10 / (code)) +#define AW8623X_RL_FORMULA(code, d2s_gain) (((code) * 678 * 1000) / (1023 * (d2s_gain))) +#define AW8623X_OS_FORMULA(code, d2s_gain) (2440 * ((code) - 512) / (1023 * (1 + d2s_gain))) +#define AW8623X_SET_AEADDR_H(addr) ((((addr) >> 1) >> 4) & 0xF0) +#define AW8623X_SET_AEADDR_L(addr) (((addr) >> 1) & 0x00FF) +#define AW8623X_SET_AFADDR_H(addr) ((((addr) - ((addr) >> 2)) >> 8) & 0x0F) +#define AW8623X_SET_AFADDR_L(addr) (((addr) - ((addr) >> 2)) & 0x00FF) +#define AW8623X_DRV2_LVL_FORMULA(f0, vrms) ((((f0) < 1800) ? 1809920 : 1990912) / 1000 * (vrms) / 40000) +#define AW8623X_DRV_WIDTH_FORMULA(f0, margin, brk_gain) \ + ((240000 / (f0)) - (margin) - (brk_gain) - 8) + +/********************************************************* + * + * aw8624x marco + * + ********************************************************/ +#define AW8624X_DRV2_LVL_MAX (127) +#define AW8624X_F0_CALI_ACCURACY (24) + +#define AW8624X_VBAT_FORMULA(code) (6100 * (code) / 1023) +#define AW8624X_F0_FORMULA(code) (384000 * 10 / (code)) +#define AW8624X_RL_FORMULA(code, d2s_gain) (((code) * 610 * 1000) / (1023 * (d2s_gain))) +#define AW8624X_OS_FORMULA(code, d2s_gain) (2440 * ((code) - 512) / (1023 * (1 + d2s_gain))) +#define AW8624X_SET_AEADDR_H(addr) ((((addr) >> 1) >> 4) & 0xF0) +#define AW8624X_SET_AEADDR_L(addr) (((addr) >> 1) & 0x00FF) +#define AW8624X_SET_AFADDR_H(addr) ((((addr) - ((addr) >> 2)) >> 8) & 0x0F) +#define AW8624X_SET_AFADDR_L(addr) (((addr) - ((addr) >> 2)) & 0x00FF) +#define AW8624X_DRV2_LVL_FORMULA(f0, vrms) ((((f0) < 1800) ? 1809920 : 1990912) / 1000 * (vrms) / 61000) +#define AW8624X_DRV_WIDTH_FORMULA(f0, margin, brk_gain) \ + ((240000 / (f0)) - (margin) - (brk_gain) - 8) + +/********************************************************* + * + * Conditional Marco + * + *********************************************************/ + +#ifdef AW_TIKTAP +#define AW_TIKTAP_PROCNAME "tiktap_buf" +#define AW_TIKTAP_PROCNAME_R "tiktap_buf_r" +#define AW_TIKTAP_MMAP_PAGE_ORDER (2) +#define AW_TIKTAP_MMAP_BUF_SUM (16) +#define AW_TIKTAP_MMAP_BUF_SIZE (1000) + +#pragma pack(4) +struct mmap_buf_format { + uint8_t status; + uint8_t bit; + int16_t length; + + struct mmap_buf_format *kernel_next; + struct mmap_buf_format *user_next; + uint8_t reg_addr; + int8_t data[AW_TIKTAP_MMAP_BUF_SIZE]; +}; /* 1024 byte */ +#pragma pack() + +#define TIKTAP_IOCTL_GROUP 0xFF +#define TIKTAP_GET_F0 _IO(TIKTAP_IOCTL_GROUP, 0x01) +#define TIKTAP_GET_HWINFO _IO(TIKTAP_IOCTL_GROUP, 0x02) +#define TIKTAP_SET_FREQ _IO(TIKTAP_IOCTL_GROUP, 0x03) +#define TIKTAP_SETTING_GAIN _IO(TIKTAP_IOCTL_GROUP, 0x04) +#define TIKTAP_SETTING_SPEED _IO(TIKTAP_IOCTL_GROUP, 0x05) +#define TIKTAP_SETTING_BSTVOL _IO(TIKTAP_IOCTL_GROUP, 0x06) +#define TIKTAP_ON_MODE _IO(TIKTAP_IOCTL_GROUP, 0x07) +#define TIKTAP_OFF_MODE _IO(TIKTAP_IOCTL_GROUP, 0x08) +#define TIKTAP_RTP_MODE _IO(TIKTAP_IOCTL_GROUP, 0x09) +#define TIKTAP_RTP_IRQ_MODE _IO(TIKTAP_IOCTL_GROUP, 0x0A) +#define TIKTAP_STOP_MODE _IO(TIKTAP_IOCTL_GROUP, 0x0B) +#define TIKTAP_STOP_RTP_MODE _IO(TIKTAP_IOCTL_GROUP, 0x0C) +#define TIKTAP_WRITE_REG _IO(TIKTAP_IOCTL_GROUP, 0x0D) +#define TIKTAP_READ_REG _IO(TIKTAP_IOCTL_GROUP, 0x0E) +#define TIKTAP_BST_SWITCH _IO(TIKTAP_IOCTL_GROUP, 0x0F) +#define TIKTAP_GET_SPEED _IO(TIKTAP_IOCTL_GROUP, 0x10) + +enum { + MMAP_BUF_DATA_VALID = 0x55, + MMAP_BUF_DATA_FINISHED = 0xAA, + MMAP_BUF_DATA_INVALID = 0xFF, +}; +#endif + +#if KERNEL_VERSION(4, 4, 1) >= LINUX_VERSION_CODE +#define TIMED_OUTPUT +#endif + +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE +#define KERNEL_OVER_5_10 +#endif + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +#define KERNEL_OVER_6_1 +#endif + +#ifdef TIMED_OUTPUT +#include <../../../drivers/staging/android/timed_output.h> +typedef struct timed_output_dev cdev_t; +#else +typedef struct led_classdev cdev_t; +#endif +/********************************************************* + * + * Log Format + * + *********************************************************/ +#ifdef AW_DOUBLE +#define aw_err(format, ...) \ + pr_err("[haptic_nv]<%s>%s: " format "\n", aw_haptic->mark, __func__, ##__VA_ARGS__) + +#define aw_info(format, ...) \ + pr_info("[haptic_nv]<%s>%s: " format "\n", aw_haptic->mark, __func__, ##__VA_ARGS__) + +#define aw_dbg(format, ...) \ + pr_debug("[haptic_nv]<%s>%s: " format "\n", aw_haptic->mark, __func__, ##__VA_ARGS__) +#else +#define aw_err(format, ...) \ + pr_err("[%s][%04d]%s: " format "\n", AW_I2C_NAME, __LINE__, __func__, ##__VA_ARGS__) + +#define aw_info(format, ...) \ + pr_info("[%s][%04d]%s: " format "\n", AW_I2C_NAME, __LINE__, __func__, ##__VA_ARGS__) + +#define aw_dbg(format, ...) \ + pr_debug("[%s][%04d]%s: " format "\n", AW_I2C_NAME, __LINE__, __func__, ##__VA_ARGS__) +#endif +/********************************************************* + * + * Enum Define + * + *********************************************************/ +enum awrw_flag { + AW_WRITE = 0, + AW_READ = 1, +}; + +enum aw_haptic_flags { + AW_FLAG_NONR = 0, + AW_FLAG_SKIP_INTERRUPTS = 1, +}; + +enum aw_haptic_work_mode { + AW_STANDBY_MODE = 0, + AW_RAM_MODE = 1, + AW_RAM_LOOP_MODE = 2, + AW_CONT_MODE = 3, + AW_RTP_MODE = 4, + AW_TRIG_MODE = 5, + AW_NULL = 6, +}; + +enum aw_haptic_cont_vbat_comp_mode { + AW_CONT_VBAT_SW_COMP_MODE = 0, + AW_CONT_VBAT_HW_COMP_MODE = 1, +}; + +enum aw_haptic_ram_vbat_comp_mode { + AW_RAM_VBAT_COMP_DISABLE = 0, + AW_RAM_VBAT_COMP_ENABLE = 1, +}; + +enum aw_haptic_pwm_mode { + AW_PWM_48K = 0, + AW_PWM_24K = 1, + AW_PWM_12K = 2, +}; + +enum aw_haptic_play { + AW_PLAY_NULL = 0, + AW_PLAY_ENABLE = 1, + AW_PLAY_STOP = 2, + AW_PLAY_GAIN = 8, +}; + +enum aw_haptic_cmd { + AW_CMD_NULL = 0, + AW_CMD_ENABLE = 1, + AW_CMD_HAPTIC = 0x0F, + AW_CMD_TP = 0x10, + AW_CMD_R_EN = 0x40, + AW_CMD_L_EN = 0x80, + AW_CMD_SYS = 0xF0, + AW_CMD_STOP = 255, +}; + +enum aw_haptic_cali_lra { + AW_WRITE_ZERO = 0, + AW_F0_CALI_LRA = 1, + AW_OSC_CALI_LRA = 2, +}; + +enum aw_haptic_awrw_flag { + AW_SEQ_WRITE = 0, + AW_SEQ_READ = 1, +}; + +enum aw_trim_lra { + AW_TRIM_LRA_BOUNDARY = 0x20, + AW8624X_TRIM_LRA_BOUNDARY = 0x40, +}; + +enum aw_haptic_read_chip_type { + AW_FIRST_TRY = 0, + AW_LAST_TRY = 1, +}; + +enum aw_haptic_chip_name { + AW_CHIP_NULL = 0, + AW86223 = 1, + AW86224 = 2, + AW86225 = 3, + AW86214 = 4, + AW8623 = 5, + AW8624 = 6, + AW86233 = 7, + AW86234 = 8, + AW86235 = 9, + AW86243 = 10, + AW86245 = 11, +}; + +enum aw_haptic_irq_state { + AW_IRQ_ALMOST_EMPTY = 1, +}; + +enum aw_haptic_dts_data_type { + AW_DTS_NULL = 0, + AW_DTS_DATA_U32 = 1, + AW_DTS_DATA_ARRAY = 2, + AW_DTS_DATA_BOOL = 3, +}; + +enum aw_haptic_protect_config { + AW_PROTECT_OFF = 0, + AW_PROTECT_EN = 1, + AW_PROTECT_CFG_1 = 0x2D, + AW_PROTECT_CFG_2 = 0x3E, + AW_PROTECT_CFG_3 = 0X3F, +}; + +enum aw_haptic_ram_file_num { + AW862X_RAM_FILE = 0, + AW862XX_RAM_FILE = 1, +}; + +enum aw_haptic_pin { + AW_TRIG1 = 0, + AW_TRIG2 = 1, + AW_TRIG3 = 2, + AW_IRQ = 3, +}; + +/********************************************************* + * + * Enum aw8623x + * + *********************************************************/ +enum aw8623x_sram_size_flag { + AW8623X_HAPTIC_SRAM_1K = 0, + AW8623X_HAPTIC_SRAM_2K = 1, + AW8623X_HAPTIC_SRAM_3K = 2, +}; + +/********************************************************* + * + * Enum aw862xx + * + *********************************************************/ +enum aw862xx_ef_id { + AW86223_EF_ID = 0x01, + AW86224_EF_ID = 0x00, + AW86225_EF_ID = 0x00, + AW86214_EF_ID = 0x41, +}; + +enum aw862xx_sram_size_flag { + AW862XX_HAPTIC_SRAM_1K = 0, + AW862XX_HAPTIC_SRAM_2K = 1, + AW862XX_HAPTIC_SRAM_3K = 2, +}; +/********************************************************* + * + * Enum aw862x + * + *********************************************************/ +enum aw862x_pwm_clk { + AW862X_CLK_24K = 2, + AW862X_CLK_12K = 3, +}; +/********************************************************* + * + * Struct Define + * + *********************************************************/ +struct trig { + uint8_t enable; + uint8_t trig_edge; + uint8_t trig_brk; + uint8_t trig_level; + uint8_t trig_polar; + uint8_t pos_enable; + uint8_t neg_enable; + uint8_t pos_sequence; + uint8_t neg_sequence; +}; + +struct aw_haptic_ram { + uint8_t ram_num; + uint8_t version; + uint8_t ram_shift; + uint8_t baseaddr_shift; + + uint32_t len; + uint32_t check_sum; + uint32_t base_addr; +}; + +struct aw_haptic_ctr { + uint8_t cnt; + uint8_t cmd; + uint8_t play; + uint8_t loop; + uint8_t gain; + uint8_t wavseq; + struct list_head list; +}; + +struct aw_i2c_info { + uint8_t flag; + uint8_t reg_num; + uint8_t first_addr; + uint8_t reg_data[AWRW_SIZE]; +}; + +struct aw_haptic_audio { + int delay_val; + int timer_val; + struct mutex lock; + struct hrtimer timer; + struct list_head list; + struct work_struct work; + struct aw_haptic_ctr ctr; + struct list_head ctr_list; +}; + +struct aw_haptic_dts_data { + void *dts_val; + uint8_t type; + uint32_t len; +}; + +struct aw_haptic_dts_info { + bool is_enabled_auto_brk; + bool is_enabled_track_en; + /* aw8624x */ + bool is_enabled_smart_loop; + bool is_enabled_inter_brake; + + uint32_t mode; + uint32_t f0_cali_percent; + uint32_t f0_pre; + uint32_t lra_vrms; + uint32_t lk_f0_cali; + uint32_t cont_tset; + uint32_t cont_drv1_lvl; + uint32_t cont_drv2_lvl; + uint32_t duration_time[3]; + uint32_t trig_cfg[21]; + /* aw862x */ + uint32_t cont_td; + uint32_t cont_zc_thr; + uint32_t cont_num_brk; + uint32_t f0_coeff; + uint32_t cont_brake[24]; + uint32_t bemf_config[4]; + uint32_t sw_brake[2]; + uint32_t wavseq[16]; + uint32_t wavloop[10]; + uint32_t td_brake[3]; + uint32_t f0_trace_parameter[4]; + /* aw862xx */ + uint32_t gain_bypass; + uint32_t cont_drv1_time; + uint32_t cont_drv2_time; + uint32_t cont_brk_time; + uint32_t cont_track_margin; + uint32_t cont_brk_gain; + uint32_t d2s_gain; + uint32_t prctmode[3]; + /* aw8624x */ + uint32_t f0_d2s_gain; +}; + +struct aw_haptic { + bool rtp_init; + bool ram_init; + bool dual_flag; + bool is_used_irq_pin; + bool is_used_rst_pin; + + uint8_t flags; + uint8_t play_mode; + uint8_t chipid_flag; + uint8_t max_pos_beme; + uint8_t max_neg_beme; + uint8_t activate_mode; + uint8_t ram_vbat_comp; + uint8_t seq[AW_SEQUENCER_SIZE]; + uint8_t loop[AW_SEQUENCER_SIZE]; + uint8_t trim_lra_boundary; +#ifdef AW_DOUBLE + uint8_t mark[15]; +#endif + + int name; + int gain; + int state; + int index; + int irq_gpio; + int duration; + int effect_id; + int amplitude; + int reset_gpio; + + uint32_t f0; + uint32_t lra; + uint32_t vbat; + uint32_t level; + uint32_t f0_pre; + uint32_t cont_f0; + uint32_t rtp_cnt; + uint32_t rtp_len; + uint32_t gun_type; + uint32_t bullet_nr; + uint32_t theory_time; + uint32_t interval_us; + uint32_t f0_cali_data; + uint32_t rtp_file_num; + uint32_t rtp_num_max; + uint32_t ram_file_num; + uint32_t timeval_flags; + uint32_t osc_cali_data; + uint32_t aw862xx_i2c_addr; + uint64_t microsecond; + + cdev_t vib_dev; + + ktime_t kend; + ktime_t kstart; + ktime_t current_t; + ktime_t pre_enter_t; +#ifdef AW_TIKTAP + bool tiktap_ready; + bool vib_stop_flag; + bool tiktap_stop_flag; + struct work_struct tiktap_work; + struct proc_dir_entry *aw_config_proc; + struct mmap_buf_format *start_buf; +#endif + struct mutex lock; + struct device *dev; + struct hrtimer timer; + struct mutex rtp_lock; + struct i2c_client *i2c; + struct aw_haptic_ram ram; + struct aw_haptic_func *func; + struct aw_i2c_info i2c_info; + struct input_dev *input_dev; + struct semaphore sema; + struct work_struct rtp_work; + struct work_struct stop_work; + struct delayed_work ram_work; + struct trig trig[AW_TRIG_NUM]; + struct aw_haptic_dts_info info; + struct work_struct vibrator_work; + struct work_struct input_gain_work; + struct work_struct input_vib_work; + struct aw_haptic_container *aw_rtp; + struct aw_haptic_audio haptic_audio; + struct workqueue_struct *work_queue; + struct pm_qos_request aw_pm_qos_req_vb; +}; + +struct aw_haptic_container { + int len; + uint8_t data[]; +}; + +struct aw_haptic_func { + int (*check_qualify)(struct aw_haptic *aw_haptic); + int (*get_irq_state)(struct aw_haptic *aw_haptic); + int (*get_f0)(struct aw_haptic *aw_haptic); + int (*offset_cali)(struct aw_haptic *aw_haptic); + void (*creat_node)(struct aw_haptic *aw_haptic); + void (*read_cont_f0)(struct aw_haptic *aw_haptic); + void (*parse_dts)(struct aw_haptic *aw_haptic, struct device_node *np); + void (*trig_init)(struct aw_haptic *aw_haptic); + void (*irq_clear)(struct aw_haptic *aw_haptic); + void (*haptic_start)(struct aw_haptic *aw_haptic); + void (*play_stop)(struct aw_haptic *aw_haptic); + void (*play_mode)(struct aw_haptic *aw_haptic, uint8_t play_mode); + void (*cont_config)(struct aw_haptic *aw_haptic); + void (*ram_init)(struct aw_haptic *aw_haptic, bool flag); + void (*misc_para_init)(struct aw_haptic *aw_haptic); + void (*interrupt_setup)(struct aw_haptic *aw_haptic); + void (*vbat_mode_config)(struct aw_haptic *aw_haptic, uint8_t flag); + void (*protect_config)(struct aw_haptic *aw_haptic, uint8_t prtime, uint8_t prlvl); + void (*calculate_cali_data)(struct aw_haptic *aw_haptic); + void (*set_gain)(struct aw_haptic *aw_haptic, uint8_t gain); + void (*get_gain)(struct aw_haptic *aw_haptic, uint8_t *gain); + void (*set_wav_seq)(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t seq); + void (*get_wav_seq)(struct aw_haptic *aw_haptic, uint32_t len); + void (*set_wav_loop)(struct aw_haptic *aw_haptic, uint8_t wav, uint8_t loop); + void (*get_wav_loop)(struct aw_haptic *aw_haptic, uint8_t *val); + void (*set_rtp_data)(struct aw_haptic *aw_haptic, uint8_t *data, uint32_t len); + void (*set_fifo_addr)(struct aw_haptic *aw_haptic); + void (*get_fifo_addr)(struct aw_haptic *aw_haptic); + void (*set_ram_data)(struct aw_haptic *aw_haptic, uint8_t *data, int len); + void (*get_ram_data)(struct aw_haptic *aw_haptic, uint8_t *ram_data, int size); + void (*set_ram_addr)(struct aw_haptic *aw_haptic); + void (*set_repeat_seq)(struct aw_haptic *aw_haptic, uint8_t seq); + void (*set_base_addr)(struct aw_haptic *aw_haptic); + void (*set_trim_lra)(struct aw_haptic *aw_haptic, uint8_t val); + void (*set_rtp_aei)(struct aw_haptic *aw_haptic, bool flag); + void (*get_vbat)(struct aw_haptic *aw_haptic); + void (*get_lra_resistance)(struct aw_haptic *aw_haptic); + void (*get_first_wave_addr)(struct aw_haptic *aw_haptic, uint32_t *first_wave_addr); + ssize_t (*get_reg)(struct aw_haptic *aw_haptic, ssize_t len, char *buf); + uint8_t (*get_prctmode)(struct aw_haptic *aw_haptic); + uint8_t (*get_glb_state)(struct aw_haptic *aw_haptic); + uint8_t (*get_osc_status)(struct aw_haptic *aw_haptic); + uint8_t (*judge_rtp_going)(struct aw_haptic *aw_haptic); + uint8_t (*rtp_get_fifo_afs)(struct aw_haptic *aw_haptic); + uint8_t (*rtp_get_fifo_aes)(struct aw_haptic *aw_haptic); + uint64_t (*get_theory_time)(struct aw_haptic *aw_haptic); +}; +/********************************************************* + * + * Function Call + * + *********************************************************/ +#ifdef AW862X_DRIVER +extern struct aw_haptic_func aw862x_func_list; +#endif + +#ifdef AW862XX_DRIVER +extern struct aw_haptic_func aw862xx_func_list; +#endif + +#ifdef AW8623X_DRIVER +extern struct aw_haptic_func aw8623x_func_list; +#endif + +#ifdef AW8624X_DRIVER +extern struct aw_haptic_func aw8624x_func_list; +#endif + +extern int haptic_nv_i2c_reads(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint8_t *buf, uint32_t len); +extern int haptic_nv_i2c_writes(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint8_t *buf, uint32_t len); +extern int haptic_nv_i2c_write_bits(struct aw_haptic *aw_haptic, uint8_t reg_addr, uint32_t mask, uint8_t reg_data); +extern ssize_t haptic_nv_read_reg_array(struct aw_haptic *aw_haptic, char *buf, ssize_t len, + uint8_t head_reg_addr, uint8_t tail_reg_addr); +#endif diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv_reg.h b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv_reg.h new file mode 100644 index 000000000000..3665dbbec2e5 --- /dev/null +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv_reg.h @@ -0,0 +1,1990 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _HAPTIC_NV_REG_H_ +#define _HAPTIC_NV_REG_H_ +/******************************************** + * common Register List + *******************************************/ +#define AW_REG_ID (0x00) +#define AW_REG_CHIPIDH (0x57) /* AW8623X AW8624X*/ +/******************************************** + * AW862XX Register List + *******************************************/ +#define AW862XX_REG_ID (0x00) +#define AW862XX_REG_SYSST (0x01) +#define AW862XX_REG_SYSINT (0x02) +#define AW862XX_REG_SYSINTM (0x03) +#define AW862XX_REG_SYSST2 (0x04) +#define AW862XX_REG_SYSER (0x05) +#define AW862XX_REG_PLAYCFG2 (0x07) +#define AW862XX_REG_PLAYCFG3 (0x08) +#define AW862XX_REG_PLAYCFG4 (0x09) +#define AW862XX_REG_WAVCFG1 (0x0A) +#define AW862XX_REG_WAVCFG2 (0x0B) +#define AW862XX_REG_WAVCFG3 (0x0C) +#define AW862XX_REG_WAVCFG4 (0x0D) +#define AW862XX_REG_WAVCFG5 (0x0E) +#define AW862XX_REG_WAVCFG6 (0x0F) +#define AW862XX_REG_WAVCFG7 (0x10) +#define AW862XX_REG_WAVCFG8 (0x11) +#define AW862XX_REG_WAVCFG9 (0x12) +#define AW862XX_REG_WAVCFG10 (0x13) +#define AW862XX_REG_WAVCFG11 (0x14) +#define AW862XX_REG_WAVCFG12 (0x15) +#define AW862XX_REG_WAVCFG13 (0x16) +#define AW862XX_REG_CONTCFG1 (0x18) +#define AW862XX_REG_CONTCFG2 (0x19) +#define AW862XX_REG_CONTCFG3 (0x1A) +#define AW862XX_REG_CONTCFG4 (0x1B) +#define AW862XX_REG_CONTCFG5 (0x1C) +#define AW862XX_REG_CONTCFG6 (0x1D) +#define AW862XX_REG_CONTCFG7 (0x1E) +#define AW862XX_REG_CONTCFG8 (0x1F) +#define AW862XX_REG_CONTCFG9 (0x20) +#define AW862XX_REG_CONTCFG10 (0x21) +#define AW862XX_REG_CONTCFG11 (0x22) +#define AW862XX_REG_CONTCFG12 (0x23) +#define AW862XX_REG_CONTCFG13 (0x24) +#define AW862XX_REG_CONTRD14 (0x25) +#define AW862XX_REG_CONTRD15 (0x26) +#define AW862XX_REG_CONTRD16 (0x27) +#define AW862XX_REG_CONTRD17 (0x28) +#define AW862XX_REG_CONTRD18 (0x29) +#define AW862XX_REG_CONTRD19 (0x2A) +#define AW862XX_REG_CONTRD20 (0x2B) +#define AW862XX_REG_CONTRD21 (0x2C) +#define AW862XX_REG_RTPCFG1 (0x2D) +#define AW862XX_REG_RTPCFG2 (0x2E) +#define AW862XX_REG_RTPCFG3 (0x2F) +#define AW862XX_REG_RTPCFG4 (0x30) +#define AW862XX_REG_RTPCFG5 (0x31) +#define AW862XX_REG_RTPDATA (0x32) +#define AW862XX_REG_TRGCFG1 (0x33) +#define AW862XX_REG_TRGCFG2 (0x34) +#define AW862XX_REG_TRGCFG3 (0x35) +#define AW862XX_REG_TRGCFG4 (0x36) +#define AW862XX_REG_TRGCFG5 (0x37) +#define AW862XX_REG_TRGCFG6 (0x38) +#define AW862XX_REG_TRGCFG7 (0x39) +#define AW862XX_REG_TRGCFG8 (0x3A) +#define AW862XX_REG_GLBCFG2 (0x3C) +#define AW862XX_REG_GLBCFG4 (0x3E) +#define AW862XX_REG_GLBRD5 (0x3F) +#define AW862XX_REG_RAMADDRH (0x40) +#define AW862XX_REG_RAMADDRL (0x41) +#define AW862XX_REG_RAMDATA (0x42) +#define AW862XX_REG_SYSCTRL1 (0x43) +#define AW862XX_REG_SYSCTRL2 (0x44) +#define AW862XX_REG_SYSCTRL3 (0x45) +#define AW862XX_REG_SYSCTRL4 (0x46) +#define AW862XX_REG_SYSCTRL5 (0x47) +#define AW862XX_REG_SYSCTRL6 (0x48) +#define AW862XX_REG_SYSCTRL7 (0x49) +#define AW862XX_REG_PWMCFG1 (0x4C) +#define AW862XX_REG_PWMCFG3 (0x4E) +#define AW862XX_REG_PWMCFG4 (0x4F) +#define AW862XX_REG_DETCFG1 (0x51) +#define AW862XX_REG_DETCFG2 (0x52) +#define AW862XX_REG_DET_RL (0x53) +#define AW862XX_REG_DET_OS (0x54) +#define AW862XX_REG_DET_VBAT (0x55) +#define AW862XX_REG_DET_LO (0x57) +#define AW862XX_REG_TRIMCFG1 (0x58) +#define AW862XX_REG_TRIMCFG3 (0x5A) +#define AW862XX_REG_EFRD9 (0x64) +#define AW862XX_REG_ANACFG8 (0x77) +/******************************************** + * AW862X Register List + *******************************************/ +#define AW862X_REG_ID (0x00) +#define AW862X_REG_SYSST (0x01) +#define AW862X_REG_SYSINT (0x02) +#define AW862X_REG_SYSINTM (0x03) +#define AW862X_REG_SYSCTRL (0x04) +#define AW862X_REG_GO (0x05) +#define AW862X_REG_RTP_DATA (0x06) +#define AW862X_REG_WAVSEQ1 (0x07) +#define AW862X_REG_WAVSEQ2 (0x08) +#define AW862X_REG_WAVSEQ3 (0x09) +#define AW862X_REG_WAVSEQ4 (0x0a) +#define AW862X_REG_WAVSEQ5 (0x0b) +#define AW862X_REG_WAVSEQ6 (0x0c) +#define AW862X_REG_WAVSEQ7 (0x0d) +#define AW862X_REG_WAVSEQ8 (0x0e) +#define AW862X_REG_WAVLOOP1 (0x0f) +#define AW862X_REG_WAVLOOP2 (0x10) +#define AW862X_REG_WAVLOOP3 (0x11) +#define AW862X_REG_WAVLOOP4 (0x12) +#define AW862X_REG_MANLOOP (0x13) +#define AW862X_REG_TRG1_SEQP (0x14) +#define AW862X_REG_TRG1_SEQN (0x17) +#define AW862X_REG_TRG_CFG1 (0x1b) +#define AW862X_REG_TRG_CFG2 (0x1c) +#define AW862X_REG_DBGCTRL (0x20) +#define AW862X_REG_BASE_ADDRH (0x21) +#define AW862X_REG_BASE_ADDRL (0x22) +#define AW862X_REG_FIFO_AEH (0x23) +#define AW862X_REG_FIFO_AEL (0x24) +#define AW862X_REG_FIFO_AFH (0x25) +#define AW862X_REG_FIFO_AFL (0x26) +#define AW862X_REG_DATCTRL (0x2b) +#define AW862X_REG_PWMPRC (0x2d) +#define AW862X_REG_PWMDBG (0x2e) +#define AW862X_REG_DBGSTAT (0x30) +#define AW862X_REG_WAVECTRL (0x31) +#define AW862X_REG_BRAKE0_CTRL (0x32) +#define AW862X_REG_BRAKE1_CTRL (0x33) +#define AW862X_REG_BRAKE2_CTRL (0x34) +#define AW862X_REG_BRAKE_NUM (0x35) +#define AW862X_REG_ANACTRL (0x38) +#define AW862X_REG_SW_BRAKE (0x39) +#define AW862X_REG_DATDBG (0x3b) +#define AW862X_REG_PRLVL (0x3e) +#define AW862X_REG_PRTIME (0x3f) +#define AW862X_REG_RAMADDRH (0x40) +#define AW862X_REG_RAMADDRL (0x41) +#define AW862X_REG_RAMDATA (0x42) +#define AW862X_REG_BRA_MAX_NUM (0x44) +#define AW862X_REG_GLB_STATE (0x47) +#define AW862X_REG_CONT_CTRL (0x48) +#define AW862X_REG_F_PRE_H (0x49) +#define AW862X_REG_F_PRE_L (0x4a) +#define AW862X_REG_TD_H (0x4b) +#define AW862X_REG_TD_L (0x4c) +#define AW862X_REG_TSET (0x4d) +#define AW862X_REG_THRS_BRA_END (0x4f) +#define AW862X_REG_EF_RDATAH (0x55) +#define AW862X_REG_TRIM_LRA (0x5b) +#define AW862X_REG_R_SPARE (0x5d) +#define AW862X_REG_D2SCFG (0x5e) +#define AW862X_REG_DETCTRL (0x5f) +#define AW862X_REG_RLDET (0x60) +#define AW862X_REG_OSDET (0x61) +#define AW862X_REG_VBATDET (0x62) +#define AW862X_REG_ADCTEST (0x66) +#define AW862X_REG_F_LRA_F0_H (0x68) +#define AW862X_REG_F_LRA_F0_L (0x69) +#define AW862X_REG_F_LRA_CONT_H (0x6a) +#define AW862X_REG_F_LRA_CONT_L (0x6b) +#define AW862X_REG_WAIT_VOL_MP (0x6e) +#define AW862X_REG_WAIT_VOL_MN (0x6f) +#define AW862X_REG_ZC_THRSH_H (0x72) +#define AW862X_REG_ZC_THRSH_L (0x73) +#define AW862X_REG_BEMF_VTHH_H (0x74) +#define AW862X_REG_BEMF_VTHH_L (0x75) +#define AW862X_REG_BEMF_VTHL_H (0x76) +#define AW862X_REG_BEMF_VTHL_L (0x77) +#define AW862X_REG_BEMF_NUM (0x78) +#define AW862X_REG_DRV_TIME (0x79) +#define AW862X_REG_TIME_NZC (0x7a) +#define AW862X_REG_DRV_LVL (0x7b) +#define AW862X_REG_DRV_LVL_OV (0x7c) +#define AW862X_REG_NUM_F0_1 (0x7d) +#define AW862X_REG_NUM_F0_2 (0x7e) +#define AW862X_REG_NUM_F0_3 (0x7f) +/******************************************** + * AW8623X Register List + *******************************************/ +#define AW8623X_REG_RSTCFG (0x00) +#define AW8623X_REG_SYSST (0x01) +#define AW8623X_REG_SYSINT (0x02) +#define AW8623X_REG_SYSINTM (0x03) +#define AW8623X_REG_SYSST2 (0x04) +#define AW8623X_REG_SYSER (0x05) +#define AW8623X_REG_PLAYCFG2 (0x07) +#define AW8623X_REG_PLAYCFG3 (0x08) +#define AW8623X_REG_PLAYCFG4 (0x09) +#define AW8623X_REG_WAVCFG1 (0x0A) +#define AW8623X_REG_WAVCFG2 (0x0B) +#define AW8623X_REG_WAVCFG3 (0x0C) +#define AW8623X_REG_WAVCFG4 (0x0D) +#define AW8623X_REG_WAVCFG5 (0x0E) +#define AW8623X_REG_WAVCFG6 (0x0F) +#define AW8623X_REG_WAVCFG7 (0x10) +#define AW8623X_REG_WAVCFG8 (0x11) +#define AW8623X_REG_WAVCFG9 (0x12) +#define AW8623X_REG_WAVCFG10 (0x13) +#define AW8623X_REG_WAVCFG11 (0x14) +#define AW8623X_REG_WAVCFG12 (0x15) +#define AW8623X_REG_WAVCFG13 (0x16) +#define AW8623X_REG_CONTCFG1 (0x17) +#define AW8623X_REG_CONTCFG2 (0x18) +#define AW8623X_REG_CONTCFG3 (0x19) +#define AW8623X_REG_CONTCFG4 (0x1A) +#define AW8623X_REG_CONTCFG5 (0x1B) +#define AW8623X_REG_CONTCFG6 (0x1C) +#define AW8623X_REG_CONTCFG7 (0x1D) +#define AW8623X_REG_CONTCFG8 (0x1E) +#define AW8623X_REG_CONTCFG9 (0x1F) +#define AW8623X_REG_CONTCFG10 (0x20) +#define AW8623X_REG_CONTCFG11 (0x21) +#define AW8623X_REG_CONTCFG12 (0x22) +#define AW8623X_REG_CONTCFG13 (0x23) +#define AW8623X_REG_CONTRD14 (0x24) +#define AW8623X_REG_CONTRD15 (0x25) +#define AW8623X_REG_CONTRD16 (0x26) +#define AW8623X_REG_CONTRD17 (0x27) +#define AW8623X_REG_CONTRD18 (0x28) +#define AW8623X_REG_CONTRD19 (0x29) +#define AW8623X_REG_CONTRD20 (0x2A) +#define AW8623X_REG_CONTRD21 (0x2B) +#define AW8623X_REG_RTPCFG1 (0x2C) +#define AW8623X_REG_RTPCFG2 (0x2D) +#define AW8623X_REG_RTPCFG3 (0x2E) +#define AW8623X_REG_RTPCFG4 (0x2F) +#define AW8623X_REG_RTPCFG5 (0x30) +#define AW8623X_REG_RTPCFG6 (0x31) +#define AW8623X_REG_RTPDATA (0x32) +#define AW8623X_REG_TRGCFG1 (0x33) +#define AW8623X_REG_TRGCFG2 (0x34) +#define AW8623X_REG_TRGCFG3 (0x35) +#define AW8623X_REG_TRGCFG4 (0x36) +#define AW8623X_REG_TRGCFG5 (0x37) +#define AW8623X_REG_TRGCFG6 (0x38) +#define AW8623X_REG_TRGCFG7 (0x39) +#define AW8623X_REG_TRGCFG8 (0x3A) +#define AW8623X_REG_GLBCFG2 (0x3C) +#define AW8623X_REG_GLBCFG4 (0x3E) +#define AW8623X_REG_GLBRD5 (0x3F) +#define AW8623X_REG_RAMADDRH (0x40) +#define AW8623X_REG_RAMADDRL (0x41) +#define AW8623X_REG_RAMDATA (0x42) +#define AW8623X_REG_TRGCFG9 (0x43) +#define AW8623X_REG_I2SCFG1 (0x44) +#define AW8623X_REG_SYSCTRL1 (0x45) +#define AW8623X_REG_SYSCTRL2 (0x46) +#define AW8623X_REG_SYSCTRL3 (0x47) +#define AW8623X_REG_SYSCTRL4 (0x48) +#define AW8623X_REG_SYSCTRL5 (0x49) +#define AW8623X_REG_PWMCFG1 (0x4A) +#define AW8623X_REG_PWMCFG3 (0x4C) +#define AW8623X_REG_PWMCFG4 (0x4D) +#define AW8623X_REG_VBATCTRL (0x4E) +#define AW8623X_REG_DETCFG1 (0x4F) +#define AW8623X_REG_DETCFG2 (0x50) +#define AW8623X_REG_DETRD1 (0x51) +#define AW8623X_REG_DETRD2 (0x52) +#define AW8623X_REG_DETRD3 (0x53) +#define AW8623X_REG_IDH (0x57) +#define AW8623X_REG_IDL (0x58) +#define AW8623X_REG_TRIMCFG1 (0x59) +#define AW8623X_REG_TRIMCFG2 (0x5A) +#define AW8623X_REG_TRIMCFG3 (0x5B) +#define AW8623X_REG_AUTOSIN1 (0x5C) +#define AW8623X_REG_AUTOSIN2 (0x5D) +#define AW8623X_REG_EFCFG6 (0x64) +#define AW8623X_REG_CHIPIDL (0x69) +#define AW8623X_REG_EFCFG12 (0x6A) +#define AW8623X_REG_ANACFG3 (0x70) +#define AW8623X_REG_ANACFG4 (0x71) +#define AW8623X_REG_ANACFG10 (0x77) +/******************************************** + * AW8624X Register List + *******************************************/ +#define AW8624X_REG_ID (0x00) +#define AW8624X_REG_SYSST (0x01) +#define AW8624X_REG_SYSINT (0x02) +#define AW8624X_REG_SYSINTM (0x03) +#define AW8624X_REG_SYSST2 (0x04) +#define AW8624X_REG_SYSER (0x05) +#define AW8624X_REG_PLAYCFG2 (0x07) +#define AW8624X_REG_PLAYCFG3 (0x08) +#define AW8624X_REG_PLAYCFG4 (0x09) +#define AW8624X_REG_WAVCFG1 (0x0A) +#define AW8624X_REG_WAVCFG2 (0x0B) +#define AW8624X_REG_WAVCFG3 (0x0C) +#define AW8624X_REG_WAVCFG4 (0x0D) +#define AW8624X_REG_WAVCFG5 (0x0E) +#define AW8624X_REG_WAVCFG6 (0x0F) +#define AW8624X_REG_WAVCFG7 (0x10) +#define AW8624X_REG_WAVCFG8 (0x11) +#define AW8624X_REG_WAVCFG9 (0x12) +#define AW8624X_REG_WAVCFG10 (0x13) +#define AW8624X_REG_WAVCFG11 (0x14) +#define AW8624X_REG_WAVCFG12 (0x15) +#define AW8624X_REG_WAVCFG13 (0x16) +#define AW8624X_REG_CONTCFG1 (0x18) +#define AW8624X_REG_CONTCFG2 (0x19) +#define AW8624X_REG_CONTCFG3 (0x1A) +#define AW8624X_REG_CONTCFG4 (0x1B) +#define AW8624X_REG_CONTCFG5 (0x1C) +#define AW8624X_REG_CONTCFG6 (0x1D) +#define AW8624X_REG_CONTCFG7 (0x1E) +#define AW8624X_REG_CONTCFG8 (0x1F) +#define AW8624X_REG_CONTCFG9 (0x20) +#define AW8624X_REG_CONTCFG10 (0x21) +#define AW8624X_REG_CONTCFG11 (0x22) +#define AW8624X_REG_CONTCFG12 (0x23) +#define AW8624X_REG_CONTCFG13 (0x24) +#define AW8624X_REG_CONTRD14 (0x25) +#define AW8624X_REG_CONTRD15 (0x26) +#define AW8624X_REG_CONTRD16 (0x27) +#define AW8624X_REG_CONTRD17 (0x28) +#define AW8624X_REG_CONTRD18 (0x29) +#define AW8624X_REG_CONTRD19 (0x2A) +#define AW8624X_REG_CONTRD20 (0x2B) +#define AW8624X_REG_CONTRD21 (0x2C) +#define AW8624X_REG_RTPCFG1 (0x2D) +#define AW8624X_REG_RTPCFG2 (0x2E) +#define AW8624X_REG_RTPCFG3 (0x2F) +#define AW8624X_REG_RTPCFG4 (0x30) +#define AW8624X_REG_RTPCFG5 (0x31) +#define AW8624X_REG_RTPDATA (0x32) +#define AW8624X_REG_TRGCFG1 (0x33) +#define AW8624X_REG_TRGCFG2 (0x34) +#define AW8624X_REG_TRGCFG3 (0x35) +#define AW8624X_REG_TRGCFG4 (0x36) +#define AW8624X_REG_TRGCFG5 (0x37) +#define AW8624X_REG_TRGCFG6 (0x38) +#define AW8624X_REG_TRGCFG7 (0x39) +#define AW8624X_REG_TRGCFG8 (0x3A) +#define AW8624X_REG_GLBCFG2 (0x3C) +#define AW8624X_REG_GLBCFG4 (0x3E) +#define AW8624X_REG_GLBRD5 (0x3F) +#define AW8624X_REG_RAMADDRH (0x40) +#define AW8624X_REG_RAMADDRL (0x41) +#define AW8624X_REG_RAMDATA (0x42) +#define AW8624X_REG_SYSCTRL1 (0x43) +#define AW8624X_REG_SYSCTRL2 (0x44) +#define AW8624X_REG_SYSCTRL3 (0x45) +#define AW8624X_REG_SYSCTRL4 (0x46) +#define AW8624X_REG_SYSCTRL5 (0x49) +#define AW8624X_REG_SYSCTRL6 (0x4A) +#define AW8624X_REG_PWMCFG1 (0x4C) +#define AW8624X_REG_PWMCFG3 (0x4E) +#define AW8624X_REG_PWMCFG4 (0x4F) +#define AW8624X_REG_DET_LO (0x50) +#define AW8624X_REG_DETCFG1 (0x51) +#define AW8624X_REG_DETCFG2 (0x52) +#define AW8624X_REG_DET_RL (0x53) +#define AW8624X_REG_DET_OS (0x54) +#define AW8624X_REG_DET_VBAT (0x55) +#define AW8624X_REG_CHIPIDH (0x57) +#define AW8624X_REG_CHIPIDL (0x58) +#define AW8624X_REG_TRIMCFG1 (0x59) +#define AW8624X_REG_TRIMCFG3 (0x5A) +#define AW8624X_REG_EFRD9 (0x64) +#define AW8624X_REG_ANACFG8 (0x77) +/****************************************************** + * Common Register Detail + *****************************************************/ +#define AW_BIT_RESET (0xAA) +/* GLB_STATE */ +#define AW_BIT_GLBRD_STATE_MASK (15<<0) +#define AW_BIT_STATE_STANDBY (0<<0) +#define AW_BIT_STATE_WAKEUP (1<<0) +#define AW_BIT_STATE_STARTUP (2<<0) +#define AW_BIT_STATE_WAIT (3<<0) +#define AW_BIT_STATE_CONT_GO (6<<0) +#define AW_BIT_STATE_RAM_GO (7<<0) +#define AW_BIT_STATE_RTP_GO (8<<0) +#define AW_BIT_STATE_TRIG_GO (9<<0) +#define AW_BIT_STATE_BRAKE (11<<0) +#define AW_BIT_STATE_END (12<<0) +/****************************************************** + * AW862XX Register Detail + *****************************************************/ +/* SYSST: reg 0x01 RO */ +#define AW862XX_BIT_SYSST_UVLS (1<<5) +#define AW862XX_BIT_SYSST_FF_AES (1<<4) +#define AW862XX_BIT_SYSST_FF_AFS (1<<3) +#define AW862XX_BIT_SYSST_OCDS (1<<2) +#define AW862XX_BIT_SYSST_OTS (1<<1) +#define AW862XX_BIT_SYSST_DONES (1<<0) + +/* SYSINT: reg 0x02 RC */ +#define AW862XX_BIT_SYSINT_UVLI (1<<5) +#define AW862XX_BIT_SYSINT_FF_AEI (1<<4) +#define AW862XX_BIT_SYSINT_FF_AFI (1<<3) +#define AW862XX_BIT_SYSINT_OCDI (1<<2) +#define AW862XX_BIT_SYSINT_OTI (1<<1) +#define AW862XX_BIT_SYSINT_DONEI (1<<0) + +/* SYSINTM: reg 0x03 RW */ +#define AW862XX_BIT_SYSINTM_UVLM_MASK (~(1<<5)) +#define AW862XX_BIT_SYSINTM_UVLM_OFF (1<<5) +#define AW862XX_BIT_SYSINTM_UVLM_ON (0<<5) +#define AW862XX_BIT_SYSINTM_FF_AEM_MASK (~(1<<4)) +#define AW862XX_BIT_SYSINTM_FF_AEM_OFF (1<<4) +#define AW862XX_BIT_SYSINTM_FF_AEM_ON (0<<4) +#define AW862XX_BIT_SYSINTM_FF_AFM_MASK (~(1<<3)) +#define AW862XX_BIT_SYSINTM_FF_AFM_OFF (1<<3) +#define AW862XX_BIT_SYSINTM_FF_AFM_ON (0<<3) +#define AW862XX_BIT_SYSINTM_OCDM_MASK (~(1<<2)) +#define AW862XX_BIT_SYSINTM_OCDM_OFF (1<<2) +#define AW862XX_BIT_SYSINTM_OCDM_ON (0<<2) +#define AW862XX_BIT_SYSINTM_OTM_MASK (~(1<<1)) +#define AW862XX_BIT_SYSINTM_OTM_OFF (1<<1) +#define AW862XX_BIT_SYSINTM_OTM_ON (0<<1) +#define AW862XX_BIT_SYSINTM_DONEM_MASK (~(1<<0)) +#define AW862XX_BIT_SYSINTM_DONEM_OFF (1<<0) +#define AW862XX_BIT_SYSINTM_DONEM_ON (0<<0) + +/* SYSST2: reg 0x04 RO */ +#define AW862XX_BIT_SYSST2_RAM_ADDR_ER (1<<7) +#define AW862XX_BIT_SYSST2_TRG_ADDR_ER (1<<6) +#define AW862XX_BIT_SYSST2_VBG_OK (1<<3) +#define AW862XX_BIT_SYSST2_LDO_OK (1<<2) +#define AW862XX_BIT_SYSST2_FF_FULL (1<<1) +#define AW862XX_BIT_SYSST2_FF_EMPTY (1<<0) + +/* SYSER: reg 0x05 RC */ +#define AW862XX_BIT_SYSER_I2S_ERR (1<<7) +#define AW862XX_BIT_SYSER_TRIG1_EVENT (1<<6) +#define AW862XX_BIT_SYSER_TRIG2_EVENT (1<<5) +#define AW862XX_BIT_SYSER_TRIG3_EVENT (1<<4) +#define AW862XX_BIT_SYSER_OV (1<<3) +#define AW862XX_BIT_SYSER_ADDR_ER (1<<2) +#define AW862XX_BIT_SYSER_FF_ER (1<<1) +#define AW862XX_BIT_SYSER_PLL_REF_ER (1<<0) + +/* PLAYCFG3: reg 0x08 RW */ +#define AW862XX_BIT_PLAYCFG3_STOP_MODE_MASK (~(1<<5)) +#define AW862XX_BIT_PLAYCFG3_STOP_MODE_NOW (1<<5) +#define AW862XX_BIT_PLAYCFG3_STOP_MODE_LATER (0<<5) +#define AW862XX_BIT_PLAYCFG3_BRK_EN_MASK (~(1<<2)) +#define AW862XX_BIT_PLAYCFG3_BRK (1<<2) +#define AW862XX_BIT_PLAYCFG3_BRK_ENABLE (1<<2) +#define AW862XX_BIT_PLAYCFG3_BRK_DISABLE (0<<2) +#define AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK (~(3<<0)) +#define AW862XX_BIT_PLAYCFG3_PLAY_MODE_STOP (3<<0) +#define AW862XX_BIT_PLAYCFG3_PLAY_MODE_CONT (2<<0) +#define AW862XX_BIT_PLAYCFG3_PLAY_MODE_RTP (1<<0) +#define AW862XX_BIT_PLAYCFG3_PLAY_MODE_RAM (0<<0) + +/* PLAYCFG4: reg 0x09 RW */ +#define AW862XX_BIT_PLAYCFG4_STOP_MASK (~(1<<1)) +#define AW862XX_BIT_PLAYCFG4_STOP_ON (1<<1) +#define AW862XX_BIT_PLAYCFG4_STOP_OFF (0<<1) +#define AW862XX_BIT_PLAYCFG4_GO_MASK (~(1<<0)) +#define AW862XX_BIT_PLAYCFG4_GO_ON (1<<0) +#define AW862XX_BIT_PLAYCFG4_GO_OFF (0<<0) + +/* WAVCFG1-8: reg 0x0A - reg 0x11 RW */ +#define AW862XX_BIT_WAVCFG_SEQWAIT_MASK (~(1<<7)) +#define AW862XX_BIT_WAVCFG_SEQWAIT_TIME (1<<7) +#define AW862XX_BIT_WAVCFG_SEQWAIT_NUMBER (0<<7) +#define AW862XX_BIT_WAVCFG_SEQ (0x7F) + +/* WAVCFG9-12: reg 0x12 - reg 0x15 RW */ +#define AW862XX_BIT_WAVLOOP_SEQ_ODD_MASK (~(0x0F<<4)) +#define AW862XX_BIT_WAVLOOP_SEQ_ODD_INIFINITELY (0x0F<<4) +#define AW862XX_BIT_WAVLOOP_SEQ_EVEN_MASK (~(0x0F<<0)) +#define AW862XX_BIT_WAVLOOP_SEQ_EVEN_INIFINITELY (0x0F<<0) +#define AW862XX_BIT_WAVLOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG9: reg 0x12 RW */ +#define AW862XX_BIT_WAVCFG9_SEQ1LOOP_MASK (~(0x0F<<4)) +#define AW862XX_BIT_WAVCFG9_SEQ1LOOP_INIFINITELY (0x0F<<4) +#define AW862XX_BIT_WAVCFG9_SEQ2LOOP_MASK (~(0x0F<<0)) +#define AW862XX_BIT_WAVCFG9_SEQ2LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG10: reg 0x13 RW */ +#define AW862XX_BIT_WAVCFG10_SEQ3LOOP_MASK (~(0x0F<<4)) +#define AW862XX_BIT_WAVCFG10_SEQ3LOOP_INIFINITELY (0x0F<<4) +#define AW862XX_BIT_WAVCFG10_SEQ4LOOP_MASK (~(0x0F<<0)) +#define AW862XX_BIT_WAVCFG10_SEQ4LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG11: reg 0x14 RW */ +#define AW862XX_BIT_WAVCFG11_SEQ5LOOP_MASK (~(0x0F<<4)) +#define AW862XX_BIT_WAVCFG11_SEQ5LOOP_INIFINITELY (0x0F<<4) +#define AW862XX_BIT_WAVCFG11_SEQ6LOOP_MASK (~(0x0F<<0)) +#define AW862XX_BIT_WAVCFG11_SEQ6LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG12: reg 0x15 RW */ +#define AW862XX_BIT_WAVCFG12_SEQ7LOOP_MASK (~(0x0F<<4)) +#define AW862XX_BIT_WAVCFG12_SEQ7LOOP_INIFINITELY (0x0F<<4) +#define AW862XX_BIT_WAVCFG12_SEQ8LOOP_MASK (~(0x0F<<0)) +#define AW862XX_BIT_WAVCFG12_SEQ8LOOP_INIFINITELY (0x0F<<0) + +/***************** CONT *****************/ +/* CONTCFG1: reg 0x18 RW */ +#define AW862XX_BIT_CONTCFG1_EDGE_FRE_MASK (~(0x0F<<4)) +#define AW862XX_BIT_CONTCFG1_EN_F0_DET_MASK (~(1<<3)) +#define AW862XX_BIT_CONTCFG1_F0_DET_ENABLE (1<<3) +#define AW862XX_BIT_CONTCFG1_F0_DET_DISABLE (0<<3) +#define AW862XX_BIT_CONTCFG1_SIN_MODE_MASK (~(1<<0)) +#define AW862XX_BIT_CONTCFG1_SIN_MODE_COS (1<<0) +#define AW862XX_BIT_CONTCFG1_SIN_MODE_SINE (0<<0) + +/* CONTCFG5: reg 0x1C RW */ +#define AW862XX_BIT_CONTCFG5_BRK_GAIN_MASK (~(0x0F<<0)) + +/* CONTCFG6: reg 0x1D RW */ +#define AW862XX_BIT_CONTCFG6_TRACK_EN_MASK (~(1<<7)) +#define AW862XX_BIT_CONTCFG6_TRACK_ENABLE (1<<7) +#define AW862XX_BIT_CONTCFG6_TRACK_DISABLE (0<<7) +#define AW862XX_BIT_CONTCFG6_DRV1_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG7: reg 0x1E RW */ +#define AW862XX_BIT_CONTCFG7_DRV2_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG13: reg 0x24 RW */ +#define AW862XX_BIT_CONTCFG13_TSET_MASK (~(0x0F<<4)) +#define AW862XX_BIT_CONTCFG13_BEME_SET_MASK (~(0x0F<<0)) + +/***************** RTP *****************/ +/* RTPCFG1: reg 0x2D RW */ +#define AW862XX_BIT_RTPCFG1_ADDRH_MASK (~(0x0F<<0)) + +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_MASK (~(1<<5)) +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_EN (1<<5) +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_2K_DIS (0<<5) + +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_MASK (~(1<<4)) +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_EN (1<<4) +#define AW862XX_BIT_RTPCFG1_SRAM_SIZE_1K_DIS (0<<4) + +/* RTPCFG3: reg 0x2F RW */ +#define AW862XX_BIT_RTPCFG3_FIFO_AEH_MASK (~(0x0F<<4)) +#define AW862XX_BIT_RTPCFG3_FIFO_AFH_MASK (~(0x0F<<0)) +#define AW862XX_BIT_RTPCFG3_FIFO_AEH (0x0F<<4) +#define AW862XX_BIT_RTPCFG3_FIFO_AFH (0x0F<<0) + +/***************** TRIGGER *****************/ +#define AW862XX_BIT_TRG_ENABLE_MASK (~(1<<7)) +#define AW862XX_BIT_TRG_ENABLE (1<<7) +#define AW862XX_BIT_TRG_DISABLE (0<<7) +#define AW862XX_BIT_TRG_SEQ_MASK (~(0x7F<<0)) + +/* TRGCFG1: reg 0x33 RW */ +#define AW862XX_BIT_TRGCFG1_TRG1_POS_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG1_TRG1_POS_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG1_TRG1_POS_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG1_TRG1SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG2: reg 0x34 RW */ +#define AW862XX_BIT_TRGCFG2_TRG2_POS_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG2_TRG2_POS_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG2_TRG2_POS_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG2_TRG2SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG3: reg 0x35 RW */ +#define AW862XX_BIT_TRGCFG3_TRG3_POS_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG3_TRG3_POS_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG3_TRG3_POS_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG3_TRG3SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG4: reg 0x36 RW */ +#define AW862XX_BIT_TRGCFG4_TRG1_NEG_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG4_TRG1_NEG_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG4_TRG1_NEG_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG4_TRG1SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG5: reg 0x37 RW */ +#define AW862XX_BIT_TRGCFG5_TRG2_NEG_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG5_TRG2_NEG_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG5_TRG2_NEG_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG5_TRG2SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG6: reg 0x38 RW */ +#define AW862XX_BIT_TRGCFG6_TRG3_NEG_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG6_TRG3_NEG_ENABLE (1<<7) +#define AW862XX_BIT_TRGCFG6_TRG3_NEG_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG6_TRG3SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG7: reg 0x39 RW */ +#define AW862XX_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK (~(7<<5)) +#define AW862XX_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK (~(7<<1)) +#define AW862XX_BIT_TRGCFG7_TRG1_POLAR_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG7_TRG1_POLAR_NEG (1<<7) +#define AW862XX_BIT_TRGCFG7_TRG1_POLAR_POS (0<<7) +#define AW862XX_BIT_TRGCFG7_TRG1_MODE_MASK (~(1<<6)) +#define AW862XX_BIT_TRGCFG7_TRG1_MODE_LEVEL (1<<6) +#define AW862XX_BIT_TRGCFG7_TRG1_MODE_EDGE (0<<6) +#define AW862XX_BIT_TRGCFG7_TRG1_AUTO_BRK_MASK (~(1<<5)) +#define AW862XX_BIT_TRGCFG7_TRG1_AUTO_BRK_ENABLE (1<<5) +#define AW862XX_BIT_TRGCFG7_TRG1_AUTO_BRK_DISABLE (0<<5) +#define AW862XX_BIT_TRGCFG7_TRG2_POLAR_MASK (~(1<<3)) +#define AW862XX_BIT_TRGCFG7_TRG2_POLAR_NEG (1<<3) +#define AW862XX_BIT_TRGCFG7_TRG2_POLAR_POS (0<<3) +#define AW862XX_BIT_TRGCFG7_TRG2_MODE_MASK (~(1<<2)) +#define AW862XX_BIT_TRGCFG7_TRG2_MODE_LEVEL (1<<2) +#define AW862XX_BIT_TRGCFG7_TRG2_MODE_EDGE (0<<2) +#define AW862XX_BIT_TRGCFG7_TRG2_AUTO_BRK_MASK (~(1<<1)) +#define AW862XX_BIT_TRGCFG7_TRG2_AUTO_BRK_ENABLE (1<<1) +#define AW862XX_BIT_TRGCFG7_TRG2_AUTO_BRK_DISABLE (0<<1) + +/* TRGCFG8: reg 0x3A RW */ +#define AW862XX_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK (~(7<<5)) +#define AW862XX_BIT_TRGCFG8_TRG3_POLAR_MASK (~(1<<7)) +#define AW862XX_BIT_TRGCFG8_TRG3_POLAR_NEG (1<<7) +#define AW862XX_BIT_TRGCFG8_TRG3_POLAR_POS (0<<7) +#define AW862XX_BIT_TRGCFG8_TRG3_MODE_MASK (~(1<<6)) +#define AW862XX_BIT_TRGCFG8_TRG3_MODE_LEVEL (1<<6) +#define AW862XX_BIT_TRGCFG8_TRG3_MODE_EDGE (0<<6) +#define AW862XX_BIT_TRGCFG8_TRG3_AUTO_BRK_MASK (~(1<<5)) +#define AW862XX_BIT_TRGCFG8_TRG3_AUTO_BRK_ENABLE (1<<5) +#define AW862XX_BIT_TRGCFG8_TRG3_AUTO_BRK_DISABLE (0<<5) +#define AW862XX_BIT_TRGCFG8_TRG_TRIG1_MODE_MASK (~(3<<3)) +#define AW862XX_BIT_TRGCFG8_PWM_LRA (0<<3) +#define AW862XX_BIT_TRGCFG8_PWM_ERA (1<<3) +#define AW862XX_BIT_TRGCFG8_TRIG1 (2<<3) +#define AW862XX_BIT_TRGCFG8_DISABLE (3<<3) +#define AW862XX_BIT_TRGCFG8_TRG1_STOP_MASK (~(1<<2)) +#define AW862XX_BIT_TRGCFG8_TRG1_STOP (1<<2) +#define AW862XX_BIT_TRGCFG8_TRG2_STOP_MASK (~(1<<1)) +#define AW862XX_BIT_TRGCFG8_TRG2_STOP (1<<1) +#define AW862XX_BIT_TRGCFG8_TRG3_STOP_MASK (~(1<<0)) +#define AW862XX_BIT_TRGCFG8_TRG3_STOP (1<<0) + +/* GLBCFG2: reg 0x3C RW */ +/* START_DLY */ +#define AW862XX_BIT_GLBCFG2_START_DLY_250US (0x0C) + +/* GLBCFG4: reg 0x3E RW */ +#define AW862XX_BIT_GLBCFG4_GO_PRIO_MASK (~(3<<6)) +#define AW862XX_BIT_GLBCFG4_TRG3_PRIO_MASK (~(3<<4)) +#define AW862XX_BIT_GLBCFG4_TRG2_PRIO_MASK (~(3<<2)) +#define AW862XX_BIT_GLBCFG4_TRG1_PRIO_MASK (~(3<<0)) + +/* GLBRD5: reg 0x3F R0 */ +/* GLB_STATE */ +#define AW862XX_BIT_GLBRD5_STATE (15<<0) +#define AW862XX_BIT_GLBRD5_STATE_STANDBY (0<<0) +#define AW862XX_BIT_GLBRD5_STATE_WAKEUP (1<<0) +#define AW862XX_BIT_GLBRD5_STATE_STARTUP (2<<0) +#define AW862XX_BIT_GLBRD5_STATE_WAIT (3<<0) +#define AW862XX_BIT_GLBRD5_STATE_CONT_GO (6<<0) +#define AW862XX_BIT_GLBRD5_STATE_RAM_GO (7<<0) +#define AW862XX_BIT_GLBRD5_STATE_RTP_GO (8<<0) +#define AW862XX_BIT_GLBRD5_STATE_TRIG_GO (9<<0) +#define AW862XX_BIT_GLBRD5_STATE_I2S_GO (10<<0) +#define AW862XX_BIT_GLBRD5_STATE_BRAKE (11<<0) +#define AW862XX_BIT_GLBRD5_STATE_END (12<<0) +/* RAMADDRH: reg 0x40 RWS */ +#define AW862XX_BIT_RAMADDRH_MASK (~(63<<0)) + +/***************** SYSCTRL *****************/ +/* SYSCTRL1: reg 0x43 RW */ +#define AW862XX_BIT_SYSCTRL1_VBAT_MODE_MASK (~(1<<7)) +#define AW862XX_BIT_SYSCTRL1_VBAT_MODE_HW (1<<7) +#define AW862XX_BIT_SYSCTRL1_VBAT_MODE_SW (0<<7) +#define AW862XX_BIT_SYSCTRL1_PERP_MASK (~(1<<6)) +#define AW862XX_BIT_SYSCTRL1_PERP_ON (1<<6) +#define AW862XX_BIT_SYSCTRL1_PERP_OFF (0<<6) +#define AW862XX_BIT_SYSCTRL1_CLK_SEL_MASK (~(3<<4)) +#define AW862XX_BIT_SYSCTRL1_CLK_SEL_OSC (1<<4) +#define AW862XX_BIT_SYSCTRL1_CLK_SEL_AUTO (0<<4) +#define AW862XX_BIT_SYSCTRL1_RAMINIT_MASK (~(1<<3)) +#define AW862XX_BIT_SYSCTRL1_RAMINIT_ON (1<<3) +#define AW862XX_BIT_SYSCTRL1_RAMINIT_OFF (0<<3) +#define AW862XX_BIT_SYSCTRL1_EN_FIR_MASK (~(1<<2)) +#define AW862XX_BIT_SYSCTRL1_FIR_ENABLE (0<<2) +#define AW862XX_BIT_SYSCTRL1_WAKE_MODE_MASK (~(1<<1)) +#define AW862XX_BIT_SYSCTRL1_WAKE_MODE_WAKEUP (1<<1) +#define AW862XX_BIT_SYSCTRL1_WAKE_MODE_BST (0<<1) +#define AW862XX_BIT_SYSCTRL1_RTP_CLK_MASK (~(1<<0)) +#define AW862XX_BIT_SYSCTRL1_RTP_PLL (1<<0) +#define AW862XX_BIT_SYSCTRL1_RTP_OSC (0<<0) + +/* SYSCTRL2: reg 0x44 RW */ +#define AW862XX_BIT_SYSCTRL2_WAKE_MASK (~(1<<7)) +#define AW862XX_BIT_SYSCTRL2_WAKE_ON (1<<7) +#define AW862XX_BIT_SYSCTRL2_WAKE_OFF (0<<7) +#define AW862XX_BIT_SYSCTRL2_STANDBY_MASK (~(1<<6)) +#define AW862XX_BIT_SYSCTRL2_STANDBY_ON (1<<6) +#define AW862XX_BIT_SYSCTRL2_STANDBY_OFF (0<<6) +#define AW862XX_BIT_SYSCTRL2_RTP_DLY_MASK (~(3<<4)) +#define AW862XX_BIT_SYSCTRL2_INTN_PIN_MASK (~(1<<3)) +#define AW862XX_BIT_SYSCTRL2_INTN (1<<3) +#define AW862XX_BIT_SYSCTRL2_TRIG1 (0<<3) +#define AW862XX_BIT_SYSCTRL2_WCK_PIN_MASK (~(1<<2)) +#define AW862XX_BIT_SYSCTRL2_ENABLE_TRIG2 (1<<2) +#define AW862XX_BIT_SYSCTRL2_DISENABLE_TRIG2 (0<<2) +#define AW862XX_BIT_SYSCTRL2_WAVDAT_MODE_MASK (~(3<<0)) +#define AW862XX_BIT_SYSCTRL2_RATE (3<<0) +#define AW862XX_BIT_SYSCTRL2_RATE_12K (2<<0) +#define AW862XX_BIT_SYSCTRL2_RATE_24K (0<<0) +#define AW862XX_BIT_SYSCTRL2_RATE_48K (1<<0) + +/* SYSCTRL7: reg 0x49 RW */ +#define AW862XX_BIT_SYSCTRL7_GAIN_BYPASS_MASK (~(1<<6)) +#define AW862XX_BIT_SYSCTRL7_GAIN_CHANGEABLE (1<<6) +#define AW862XX_BIT_SYSCTRL7_GAIN_FIXED (0<<6) +#define AW862XX_BIT_SYSCTRL7_GAIN (0x07) + +#define AW862XX_BIT_SYSCTRL7_INT_EDGE_MODE_MASK (~(1<<5)) +#define AW862XX_BIT_SYSCTRL7_INT_EDGE_MODE_POS (0<<5) +#define AW862XX_BIT_SYSCTRL7_INT_EDGE_MODE_BOTH (1<<5) +#define AW862XX_BIT_SYSCTRL7_INT_MODE_MASK (~(1<<4)) +#define AW862XX_BIT_SYSCTRL7_INT_MODE_EDGE (1<<4) +#define AW862XX_BIT_SYSCTRL7_INT_MODE_LEVEL (0<<4) + +#define AW862XX_BIT_SYSCTRL7_INTP_MASK (~(1<<3)) +#define AW862XX_BIT_SYSCTRL7_INTP_HIGH (1<<3) +#define AW862XX_BIT_SYSCTRL7_INTP_LOW (0<<3) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_MASK (~(7<<0)) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_1 (0<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_2 (1<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_4 (2<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_5 (3<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_8 (4<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_10 (5<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_20 (6<<0) +#define AW862XX_BIT_SYSCTRL7_D2S_GAIN_40 (7<<0) + +/* PWMCFG1: reg 0x4C RW */ +#define AW862XX_BIT_PWMCFG1_PRC_EN_MASK (~(1<<7)) +#define AW862XX_BIT_PWMCFG1_PRC_ENABLE (1<<7) +#define AW862XX_BIT_PWMCFG1_PRC_DISABLE (0<<7) +#define AW862XX_BIT_PWMCFG1_PRCTIME_MASK (~(0x7F<<0)) + +/* PWMCFG2: reg 0x4D RW */ +#define AW862XX_BIT_PWMCFG2_REF_SEL_MASK (~(1<<5)) +#define AW862XX_BIT_PWMCFG2_REF_SEL_TRIANGLE (1<<5) +#define AW862XX_BIT_PWMCFG2_REF_SEL_SAWTOOTH (0<<5) +#define AW862XX_BIT_PWMCFG2_PD_HWM_MASK (~(1<<4)) +#define AW862XX_BIT_PWMCFG2_PD_HWM_ON (1<<4) +#define AW862XX_BIT_PWMCFG2_PWMOE_MASK (~(1<<3)) +#define AW862XX_BIT_PWMCFG2_PWMOE_ON (1<<3) +#define AW862XX_BIT_PWMCFG2_PWMFRC_MASK (~(7<<0)) + +/* PWMCFG3: reg 0x4E RW */ +#define AW862XX_BIT_PWMCFG3_PR_EN_MASK (~(1<<7)) +#define AW862XX_BIT_PWMCFG3_PR_ENABLE (1<<7) +#define AW862XX_BIT_PWMCFG3_PR_DISABLE (0<<7) +#define AW862XX_BIT_PWMCFG3_PRLVL_MASK (~(0x7F<<0)) +#define AW862XX_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE (0x3F) + +/* PWMCFG4: reg 0x4F RW */ +/* PRTIME */ +#define AW862XX_PWMCFG4_PRTIME_DEFAULT_VALUE (0x32) + +/* DETCFG1: reg 0x51 RW */ +#define AW862XX_BIT_DETCFG1_FTS_GO_MASK (~(1<<7)) +#define AW862XX_BIT_DETCFG1_FTS_GO_ENABLE (1<<7) +#define AW862XX_BIT_DETCFG1_TEST_GO_MASK (~(1<<6)) +#define AW862XX_BIT_DETCFG1_TEST_GO_ENABLE (1<<6) +#define AW862XX_BIT_DETCFG1_ADO_SLOT_MODE_MASK (~(1<<5)) +#define AW862XX_BIT_DETCFG1_ADO_SLOT_ADC_32 (1<<5) +#define AW862XX_BIT_DETCFG1_ADO_SLOT_ADC_256 (0<<5) +#define AW862XX_BIT_DETCFG1_RL_OS_MASK (~(1<<4)) +#define AW862XX_BIT_DETCFG1_RL (1<<4) +#define AW862XX_BIT_DETCFG1_OS (0<<4) +#define AW862XX_BIT_DETCFG1_PRCT_MODE_MASK (~(1<<3)) +#define AW862XX_BIT_DETCFG1_PRCT_MODE_INVALID (1<<3) +#define AW862XX_BIT_DETCFG1_PRCT_MODE_VALID (0<<3) +#define AW862XX_BIT_DETCFG1_CLK_ADC_MASK (~(7<<0)) +#define AW862XX_BIT_DETCFG1_CLK_ADC_12M (0<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_6M (1<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_3M (2<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_1M5 (3<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_M75 (4<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_M37 (5<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_M18 (6<<0) +#define AW862XX_BIT_DETCFG1_CLK_ADC_M09 (7<<0) + +/* DETCFG2: reg 0x52 RW */ +#define AW862XX_BIT_DETCFG2_VBAT_GO_MASK (~(1<<1)) +#define AW862XX_BIT_DETCFG2_VABT_GO_ON (1<<1) +#define AW862XX_BIT_DETCFG2_DIAG_GO_MASK (~(1<<0)) +#define AW862XX_BIT_DETCFG2_DIAG_GO_ON (1<<0) + +/* DET_LO: reg 0x57 RW */ +#define AW862XX_BIT_DET_LO_TEST_MASK (~(3<<6)) +#define AW862XX_BIT_DET_LO_VBAT_MASK (~(3<<4)) +#define AW862XX_BIT_DET_LO_VBAT (3<<4) +#define AW862XX_BIT_DET_LO_OS_MASK (~(3<<2)) +#define AW862XX_BIT_DET_LO_RL_MASK (~(3<<0)) +#define AW862XX_BIT_DET_LO_RL (3<<0) + +/* TRIMCFG1: reg:0x58 RW */ +#define AW862XX_BIT_TRIMCFG1_RL_TRIM_SRC_MASK (~(1<<6)) +#define AW862XX_BIT_TRIMCFG1_RL_TRIM_SRC_REG (1<<6) +#define AW862XX_BIT_TRIMCFG1_RL_TRIM_SRC_EFUSE (0<<6) +#define AW862XX_BIT_TRIMCFG1_TRIM_RL_MASK (~(63<<0)) + +/* TRIMCFG3: reg:0x5A RW */ +#define AW862XX_BIT_TRIMCFG3_OSC_TRIM_SRC_MASK (~(1<<7)) +#define AW862XX_BIT_TRIMCFG3_OSC_TRIM_SRC_REG (1<<7) +#define AW862XX_BIT_TRIMCFG3_OSC_TRIM_SRC_EFUSE (0<<7) +#define AW862XX_BIT_TRIMCFG3_TRIM_LRA_MASK (~(63<<0)) + +/* TRIMCFG4: reg:0x5B RW */ +/* TRIM_OSC */ + +/* ANACFG8: reg:0x77 RW */ +#define AW862XX_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK (~(3<<6)) +#define AW862XX_BIT_ANACFG8_TRTF_CTRL_HDRV (3<<6) + +/****************************************************** + * AW862X Register Detail + *****************************************************/ + /* SYSST 0x01 */ +#define AW862X_BIT_SYSST_OVS (1<<6) +#define AW862X_BIT_SYSST_UVLS (1<<5) +#define AW862X_BIT_SYSST_FF_AES (1<<4) +#define AW862X_BIT_SYSST_FF_AFS (1<<3) +#define AW862X_BIT_SYSST_OCDS (1<<2) +#define AW862X_BIT_SYSST_OTS (1<<1) +#define AW862X_BIT_SYSST_DONES (1<<0) + + /* SYSINT 0x02 */ +#define AW862X_BIT_SYSINT_OVI (1<<6) +#define AW862X_BIT_SYSINT_UVLI (1<<5) +#define AW862X_BIT_SYSINT_FF_AEI (1<<4) +#define AW862X_BIT_SYSINT_FF_AFI (1<<3) +#define AW862X_BIT_SYSINT_OCDI (1<<2) +#define AW862X_BIT_SYSINT_OTI (1<<1) +#define AW862X_BIT_SYSINT_DONEI (1<<0) + + /* SYSINTM 0x03 */ +#define AW862X_BIT_SYSINTM_OV_MASK (~(1<<6)) +#define AW862X_BIT_SYSINTM_OV_OFF (1<<6) +#define AW862X_BIT_SYSINTM_OV_EN (0<<6) +#define AW862X_BIT_SYSINTM_UVLO_MASK (~(1<<5)) +#define AW862X_BIT_SYSINTM_UVLO_OFF (1<<5) +#define AW862X_BIT_SYSINTM_UVLO_EN (0<<5) +#define AW862X_BIT_SYSINTM_FF_AE_MASK (~(1<<4)) +#define AW862X_BIT_SYSINTM_FF_AE_OFF (1<<4) +#define AW862X_BIT_SYSINTM_FF_AE_EN (0<<4) +#define AW862X_BIT_SYSINTM_FF_AF_MASK (~(1<<3)) +#define AW862X_BIT_SYSINTM_FF_AF_OFF (1<<3) +#define AW862X_BIT_SYSINTM_FF_AF_EN (0<<3) +#define AW862X_BIT_SYSINTM_OCD_MASK (~(1<<2)) +#define AW862X_BIT_SYSINTM_OCD_OFF (1<<2) +#define AW862X_BIT_SYSINTM_OCD_EN (0<<2) +#define AW862X_BIT_SYSINTM_OT_MASK (~(1<<1)) +#define AW862X_BIT_SYSINTM_OT_OFF (1<<1) +#define AW862X_BIT_SYSINTM_OT_EN (0<<1) +#define AW862X_BIT_SYSINTM_DONE_MASK (~(1<<0)) +#define AW862X_BIT_SYSINTM_DONE_OFF (1<<0) +#define AW862X_BIT_SYSINTM_DONE_EN (0<<0) + + /* SYSCTRL 0x04 */ +#define AW862X_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6)) +#define AW862X_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6) +#define AW862X_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6) +#define AW862X_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6) +#define AW862X_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5)) +#define AW862X_BIT_SYSCTRL_RAMINIT_EN (1<<5) +#define AW862X_BIT_SYSCTRL_RAMINIT_OFF (0<<5) +#define AW862X_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2)) +#define AW862X_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2) +#define AW862X_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2) +#define AW862X_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2) +#define AW862X_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0)) +#define AW862X_BIT_SYSCTRL_STANDBY (1<<0) +#define AW862X_BIT_SYSCTRL_ACTIVE (0<<0) + + /* GO 0x05 */ +#define AW862X_BIT_GO_MASK (~(1<<0)) +#define AW862X_BIT_GO_ENABLE (1<<0) +#define AW862X_BIT_GO_DISABLE (0<<0) + + /* WAVSEQ1 0x07 */ +#define AW862X_BIT_WAVSEQ1_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0)) + + /* WAVSEQ2 0x08 */ +#define AW862X_BIT_WAVSEQ2_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0)) + + /* WAVSEQ3 0x09 */ +#define AW862X_BIT_WAVSEQ3_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0)) + + /* WAVSEQ4 0x0A */ +#define AW862X_BIT_WAVSEQ4_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0)) + + /* WAVSEQ5 0X0B */ +#define AW862X_BIT_WAVSEQ5_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0)) + + /* WAVSEQ6 0X0C */ +#define AW862X_BIT_WAVSEQ6_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0)) + + /* WAVSEQ7 */ +#define AW862X_BIT_WAVSEQ7_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0)) + + /* WAVSEQ8 */ +#define AW862X_BIT_WAVSEQ8_WAIT (1<<7) +#define AW862X_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0)) + + /* WAVLOOP */ +#define AW862X_BIT_WAVLOOP_SEQN_MASK (~(15<<4)) +#define AW862X_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0)) +#define AW862X_BIT_WAVLOOP_INIFINITELY (15<<0) + + /* WAVLOOP1 */ +#define AW862X_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4)) +#define AW862X_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0)) + + /* WAVLOOP2 */ +#define AW862X_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4)) +#define AW862X_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0)) + + /* WAVLOOP3 */ +#define AW862X_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4)) +#define AW862X_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0)) + + /* WAVLOOP4 */ +#define AW862X_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4)) +#define AW862X_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0)) + + /* TRGCFG1 */ +#define AW862X_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1)) +#define AW862X_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1) +#define AW862X_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1) +#define AW862X_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0)) +#define AW862X_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0) +#define AW862X_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0) + + /* TRGCFG2 */ +#define AW862X_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0)) +#define AW862X_BIT_TRGCFG2_TRG1_ENABLE (1<<0) +#define AW862X_BIT_TRGCFG2_TRG1_DISABLE (0<<0) + + /*DBGCTRL 0X20 */ +#define AW862X_BIT_DBGCTRL_INTN_TRG_SEL_MASK (~(1<<5)) +#define AW862X_BIT_DBGCTRL_INTN_SEL_ENABLE (1<<5) +#define AW862X_BIT_DBGCTRL_TRG_SEL_ENABLE (0<<5) +#define AW862X_BIT_DBGCTRL_INT_MODE_MASK (~(3<<2)) +#define AW862X_BIT_DBGCTRL_INTN_LEVEL_MODE (0<<2) +#define AW862X_BIT_DBGCTRL_INT_MODE_EDGE (1<<2) +#define AW862X_BIT_DBGCTRL_INTN_POSEDGE_MODE (2<<2) +#define AW862X_BIT_DBGCTRL_INTN_BOTH_EDGE_MODE (3<<2) + + /* DATCTRL */ +#define AW862X_BIT_DATCTRL_FC_MASK (~(3<<6)) +#define AW862X_BIT_DATCTRL_FC_1000HZ (3<<6) +#define AW862X_BIT_DATCTRL_FC_800HZ (3<<6) +#define AW862X_BIT_DATCTRL_FC_600HZ (1<<6) +#define AW862X_BIT_DATCTRL_FC_400HZ (0<<6) +#define AW862X_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5)) +#define AW862X_BIT_DATCTRL_LPF_ENABLE (1<<5) +#define AW862X_BIT_DATCTRL_LPF_DISABLE (0<<5) + + /*PWMPRC 0X2D */ +#define AW862X_BIT_PWMPRC_PRC_EN_MASK (~(1<<7)) +#define AW862X_BIT_PWMPRC_PRC_ENABLE (1<<7) +#define AW862X_BIT_PWMPRC_PRC_DISABLE (0<<7) +#define AW862X_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0)) + + /* PWMDBG */ +#define AW862X_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5)) +#define AW862X_BIT_PWMDBG_PWM_12K (3<<5) +#define AW862X_BIT_PWMDBG_PWM_24K (2<<5) +#define AW862X_BIT_PWMDBG_PWM_48K (0<<5) + +/* GLB_STATE 0x47*/ +#define AW862X_BIT_GLBRD5_STATE_MASK (~(15<<0)) +#define AW862X_BIT_GLBRD5_STATE (15<<0) +#define AW862X_BIT_GLBRD5_STATE_STANDBY (0<<0) +#define AW862X_BIT_GLBRD5_STATE_WAKEUP (1<<0) +#define AW862X_BIT_GLBRD5_STATE_STARTUP (2<<0) +#define AW862X_BIT_GLBRD5_STATE_WAIT (3<<0) +#define AW862X_BIT_GLBRD5_STATE_CONT_GO (6<<0) +#define AW862X_BIT_GLBRD5_STATE_RAM_GO (7<<0) +#define AW862X_BIT_GLBRD5_STATE_RTP_GO (8<<0) +#define AW862X_BIT_GLBRD5_STATE_TRIG_GO (9<<0) +#define AW862X_BIT_GLBRD5_STATE_I2S_GO (10<<0) +#define AW862X_BIT_GLBRD5_STATE_BRAKE (11<<0) +#define AW862X_BIT_GLBRD5_STATE_END (12<<0) + + /* WAVECTRL */ +#define AW862X_BIT_WAVECTRL_NUM_OV_DRIVER_MASK (~(0xF<<4)) +#define AW862X_BIT_WAVECTRL_NUM_OV_DRIVER (0<<4) + + /* CONT_CTRL */ +#define AW862X_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7)) +#define AW862X_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7) +#define AW862X_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7) +#define AW862X_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5)) +#define AW862X_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5) +#define AW862X_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5) +#define AW862X_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5) +#define AW862X_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5) +#define AW862X_BIT_CONT_CTRL_MODE_MASK (~(1<<4)) +#define AW862X_BIT_CONT_CTRL_BY_DRV_TIME (1<<4) +#define AW862X_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4) +#define AW862X_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3)) +#define AW862X_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3) +#define AW862X_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3) +#define AW862X_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2)) +#define AW862X_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2) +#define AW862X_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2) +#define AW862X_BIT_CONT_CTRL_O2C_MASK (~(1<<1)) +#define AW862X_BIT_CONT_CTRL_O2C_ENABLE (1<<1) +#define AW862X_BIT_CONT_CTRL_O2C_DISABLE (0<<1) +#define AW862X_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0)) +#define AW862X_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0) +#define AW862X_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0) + +#define AW862X_BIT_D2SCFG_CLK_ADC_MASK (~(7<<5)) +#define AW862X_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<5) + +#define AW862X_BIT_D2SCFG_GAIN_MASK (~(7<<0)) +#define AW862X_BIT_D2SCFG_GAIN_40 (7<<0) + /* DETCTRL */ +#define AW862X_BIT_DETCTRL_RL_OS_MASK (~(1<<6)) +#define AW862X_BIT_DETCTRL_RL_DETECT (1<<6) +#define AW862X_BIT_DETCTRL_OS_DETECT (0<<6) +#define AW862X_BIT_DETCTRL_PROTECT_MASK (~(1<<5)) +#define AW862X_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5) +#define AW862X_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5) +#define AW862X_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1)) +#define AW862X_BIT_DETCTRL_VABT_GO_ENABLE (1<<1) +#define AW862X_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1) +#define AW862X_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0)) +#define AW862X_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0) +#define AW862X_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0) + + +#define AW862X_BIT_RAMADDRH_MASK (~(63<<0)) + + /* VBAT MODE */ +#define AW862X_BIT_DETCTRL_VBAT_MODE_MASK (~(1<<6)) +#define AW862X_BIT_DETCTRL_VBAT_HW_COMP (1<<6) +#define AW862X_BIT_DETCTRL_VBAT_SW_COMP (0<<6) + + + /* ANACTRL */ +#define AW862X_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5)) +#define AW862X_BIT_ANACTRL_LRA_SRC_REG (1<<5) +#define AW862X_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5) +#define AW862X_BIT_ANACTRL_EN_IO_PD1_MASK (~(1<<0)) +#define AW862X_BIT_ANACTRL_EN_IO_PD1_HIGH (1<<0) +#define AW862X_BIT_ANACTRL_EN_IO_PD1_LOW (0<<0) + +/* PRLVL */ +#define AW862X_BIT_PRLVL_PR_EN_MASK (~(1<<7)) +#define AW862X_BIT_PRLVL_PR_ENABLE (1<<7) +#define AW862X_BIT_PRLVL_PR_DISABLE (0<<7) +#define AW862X_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0)) +#define AW862X_BIT_PRLVL_PRLVL_DEFAULT_VALUE (0x3F) + +/* PRTIME */ +#define AW862X_REG_PRTIME_DEFAULT_VALUE (0x12) + +#define AW862X_BIT_BEMF_NUM_BRK_MASK (~(0xf<<0)) + +/* TD_H 0x4b TD_brake */ +#define AW862X_BIT_R_SPARE_MASK (~(1<<7)) +#define AW862X_BIT_R_SPARE_ENABLE (1<<7) + +/* TIME_NZC */ +#define AW862X_BIT_TIME_NZC_DEF_VAL (0x1f) + +/* TRIM_LRA */ +#define AW862X_BIT_TRIM_LRA (0x3f<<0) +/****************************************************** + * AW8623X Register Detail + *****************************************************/ +/* SYSST: reg 0x01 RO */ +#define AW8623X_BIT_SYSST_UVLS (1<<5) +#define AW8623X_BIT_SYSST_FF_AES (1<<4) +#define AW8623X_BIT_SYSST_FF_AFS (1<<3) +#define AW8623X_BIT_SYSST_OCDS (1<<2) +#define AW8623X_BIT_SYSST_OTS (1<<1) +#define AW8623X_BIT_SYSST_DONES (1<<0) + +/* SYSINT: reg 0x02 RC */ +#define AW8623X_BIT_SYSINT_UVLI (1<<5) +#define AW8623X_BIT_SYSINT_FF_AEI (1<<4) +#define AW8623X_BIT_SYSINT_FF_AFI (1<<3) +#define AW8623X_BIT_SYSINT_OCDI (1<<2) +#define AW8623X_BIT_SYSINT_OTI (1<<1) +#define AW8623X_BIT_SYSINT_DONEI (1<<0) + +/* SYSINTM: reg 0x03 RW */ +#define AW8623X_BIT_SYSINTM_UVLM_MASK (~(1<<5)) +#define AW8623X_BIT_SYSINTM_UVLM_OFF (1<<5) +#define AW8623X_BIT_SYSINTM_UVLM_ON (0<<5) +#define AW8623X_BIT_SYSINTM_FF_AEM_MASK (~(1<<4)) +#define AW8623X_BIT_SYSINTM_FF_AEM_OFF (1<<4) +#define AW8623X_BIT_SYSINTM_FF_AEM_ON (0<<4) +#define AW8623X_BIT_SYSINTM_FF_AFM_MASK (~(1<<3)) +#define AW8623X_BIT_SYSINTM_FF_AFM_OFF (1<<3) +#define AW8623X_BIT_SYSINTM_FF_AFM_ON (0<<3) +#define AW8623X_BIT_SYSINTM_OCDM_MASK (~(1<<2)) +#define AW8623X_BIT_SYSINTM_OCDM_OFF (1<<2) +#define AW8623X_BIT_SYSINTM_OCDM_ON (0<<2) +#define AW8623X_BIT_SYSINTM_OTM_MASK (~(1<<1)) +#define AW8623X_BIT_SYSINTM_OTM_OFF (1<<1) +#define AW8623X_BIT_SYSINTM_OTM_ON (0<<1) +#define AW8623X_BIT_SYSINTM_DONEM_MASK (~(1<<0)) +#define AW8623X_BIT_SYSINTM_DONEM_OFF (1<<0) +#define AW8623X_BIT_SYSINTM_DONEM_ON (0<<0) + +/* SYSST2: reg 0x04 RO */ +#define AW8623X_BIT_SYSST2_WCK_OK (1<<5) +#define AW8623X_BIT_SYSST2_BCK_OK (1<<4) +#define AW8623X_BIT_SYSST2_LDO_OK (1<<3) +#define AW8623X_BIT_SYSST2_VBG_OK (1<<2) +#define AW8623X_BIT_SYSST2_FF_FULL (1<<1) +#define AW8623X_BIT_SYSST2_FF_EMPTY (1<<0) + +/* SYSER: reg 0x05 RC */ +#define AW8623X_BIT_SYSER_TRIG1_EVENT (1<<5) +#define AW8623X_BIT_SYSER_TRIG2_EVENT (1<<4) +#define AW8623X_BIT_SYSER_TRIG3_EVENT (1<<3) +#define AW8623X_BIT_SYSER_OV (1<<2) +#define AW8623X_BIT_SYSER_ADDR_ER (1<<1) +#define AW8623X_BIT_SYSER_FF_ER (1<<0) + +/* PLAYCFG3: reg 0x08 RW */ +#define AW8623X_BIT_PLAYCFG3_ONEWIRE_COMP_MASK (~(1<<4)) +#define AW8623X_BIT_PLAYCFG3_ONEWIRE_1908_MODE (1<<4) +#define AW8623X_BIT_PLAYCFG3_ONEWIRE_2102_MODE (0<<4) +#define AW8623X_BIT_PLAYCFG3_STOP_MODE_MASK (~(1<<3)) +#define AW8623X_BIT_PLAYCFG3_STOP_MODE_NOW (1<<3) +#define AW8623X_BIT_PLAYCFG3_STOP_MODE_LATER (0<<3) +#define AW8623X_BIT_PLAYCFG3_BRK_EN_MASK (~(1<<2)) +#define AW8623X_BIT_PLAYCFG3_BRK (1<<2) +#define AW8623X_BIT_PLAYCFG3_BRK_ENABLE (1<<2) +#define AW8623X_BIT_PLAYCFG3_BRK_DISABLE (0<<2) +#define AW8623X_BIT_PLAYCFG3_PLAY_MODE_MASK (~(3<<0)) +#define AW8623X_BIT_PLAYCFG3_PLAY_MODE_STOP (3<<0) +#define AW8623X_BIT_PLAYCFG3_PLAY_MODE_CONT (2<<0) +#define AW8623X_BIT_PLAYCFG3_PLAY_MODE_RTP (1<<0) +#define AW8623X_BIT_PLAYCFG3_PLAY_MODE_RAM (0<<0) + +/* PLAYCFG4: reg 0x09 WC */ +#define AW8623X_BIT_PLAYCFG4_STOP_MASK (~(1<<1)) +#define AW8623X_BIT_PLAYCFG4_STOP_ON (1<<1) +#define AW8623X_BIT_PLAYCFG4_STOP_OFF (0<<1) +#define AW8623X_BIT_PLAYCFG4_GO_MASK (~(1<<0)) +#define AW8623X_BIT_PLAYCFG4_GO_ON (1<<0) +#define AW8623X_BIT_PLAYCFG4_GO_OFF (0<<0) + +/* WAVCFG1-8: reg 0x0A - reg 0x11 RW */ +#define AW8623X_BIT_WAVCFG_SEQWAIT_MASK (~(1<<7)) +#define AW8623X_BIT_WAVCFG_SEQWAIT_TIME (1<<7) +#define AW8623X_BIT_WAVCFG_SEQWAIT_NUMBER (0<<7) +#define AW8623X_BIT_WAVCFG_SEQ (0x7F) + +/* WAVCFG9-12: reg 0x12 - reg 0x15 RW */ +#define AW8623X_BIT_WAVLOOP_SEQ_ODD_MASK (~(0x0F<<4)) +#define AW8623X_BIT_WAVLOOP_SEQ_ODD_INIFINITELY (0x0F<<4) +#define AW8623X_BIT_WAVLOOP_SEQ_EVEN_MASK (~(0x0F<<0)) +#define AW8623X_BIT_WAVLOOP_SEQ_EVEN_INIFINITELY (0x0F<<0) +#define AW8623X_BIT_WAVLOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG9: reg 0x12 RW */ +#define AW8623X_BIT_WAVCFG9_SEQ1LOOP_MASK (~(0x0F<<4)) +#define AW8623X_BIT_WAVCFG9_SEQ1LOOP_INIFINITELY (0x0F<<4) +#define AW8623X_BIT_WAVCFG9_SEQ2LOOP_MASK (~(0x0F<<0)) +#define AW8623X_BIT_WAVCFG9_SEQ2LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG10: reg 0x13 RW */ +#define AW8623X_BIT_WAVCFG10_SEQ3LOOP_MASK (~(0x0F<<4)) +#define AW8623X_BIT_WAVCFG10_SEQ3LOOP_INIFINITELY (0x0F<<4) +#define AW8623X_BIT_WAVCFG10_SEQ4LOOP_MASK (~(0x0F<<0)) +#define AW8623X_BIT_WAVCFG10_SEQ4LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG11: reg 0x14 RW */ +#define AW8623X_BIT_WAVCFG11_SEQ5LOOP_MASK (~(0x0F<<4)) +#define AW8623X_BIT_WAVCFG11_SEQ5LOOP_INIFINITELY (0x0F<<4) +#define AW8623X_BIT_WAVCFG11_SEQ6LOOP_MASK (~(0x0F<<0)) +#define AW8623X_BIT_WAVCFG11_SEQ6LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG12: reg 0x15 RW */ +#define AW8623X_BIT_WAVCFG12_SEQ7LOOP_MASK (~(0x0F<<4)) +#define AW8623X_BIT_WAVCFG12_SEQ7LOOP_INIFINITELY (0x0F<<4) +#define AW8623X_BIT_WAVCFG12_SEQ8LOOP_MASK (~(0x0F<<0)) +#define AW8623X_BIT_WAVCFG12_SEQ8LOOP_INIFINITELY (0x0F<<0) + +/***************** CONT *****************/ +/* CONTCFG1: reg 0x17 RW */ +#define AW8623X_BIT_CONTCFG1_EDGE_FRE_MASK (~(0x0F<<0)) +#define AW8623X_BIT_CONTCFG1_EN_F0_DET_MASK (~(1<<5)) +#define AW8623X_BIT_CONTCFG1_F0_DET_ENABLE (1<<5) +#define AW8623X_BIT_CONTCFG1_F0_DET_DISABLE (0<<5) +#define AW8623X_BIT_CONTCFG1_SIN_MODE_MASK (~(1<<4)) +#define AW8623X_BIT_CONTCFG1_SIN_MODE_COS (1<<0) +#define AW8623X_BIT_CONTCFG1_SIN_MODE_SINE (0<<0) + +/* CONTCFG5: reg 0x1B RW */ +#define AW8623X_BIT_CONTCFG5_BRK_GAIN_MASK (~(0x0F<<0)) + +/* CONTCFG6: reg 0x1C RW */ +#define AW8623X_BIT_CONTCFG6_TRACK_EN_MASK (~(1<<7)) +#define AW8623X_BIT_CONTCFG6_TRACK_ENABLE (1<<7) +#define AW8623X_BIT_CONTCFG6_TRACK_DISABLE (0<<7) +#define AW8623X_BIT_CONTCFG6_DRV1_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG7: reg 0x1D RW */ +#define AW8623X_BIT_CONTCFG7_WAITHZ_EN_MASK (~(1<<7)) +#define AW8623X_BIT_CONTCFG7_WAITHZ_ENABLE (1<<7) +#define AW8623X_BIT_CONTCFG7_WAITHZ_DISABLE (0<<7) +#define AW8623X_BIT_CONTCFG7_DRV2_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG13: reg 0x23 RW */ +#define AW8623X_BIT_CONTCFG13_TSET_MASK (~(0x0F<<4)) +#define AW8623X_BIT_CONTCFG13_BEME_SET_MASK (~(0x0F<<0)) + +/***************** RTP *****************/ +/* RTPCFG1: reg 0x2C RW */ +#define AW8623X_BIT_RTPCFG1_ADDRH_MASK (~(0x0F<<0)) + +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_MASK (~(1<<5)) +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_EN (1<<5) +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_2K_DIS (0<<5) + +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_MASK (~(1<<4)) +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_EN (1<<4) +#define AW8623X_BIT_RTPCFG1_SRAM_SIZE_1K_DIS (0<<4) + +/* RTPCFG3: reg 0x2E RW */ +#define AW8623X_BIT_RTPCFG3_FIFO_AEH_MASK (~(0x0F<<4)) +#define AW8623X_BIT_RTPCFG3_FIFO_AFH_MASK (~(0x0F<<0)) +#define AW8623X_BIT_RTPCFG3_FIFO_AEH (0x0F<<4) +#define AW8623X_BIT_RTPCFG3_FIFO_AFH (0x0F<<0) + +/* RTPCFG6: reg 0x31 RW */ +#define AW8623X_BIT_RTPCFG6_EN_AUTO_SIN_96K_MASK (~(1<<3)) +#define AW8623X_BIT_RTPCFG6_EN_AUTO_SIN_96K_ENABLE (1<<3) +#define AW8623X_BIT_RTPCFG6_EN_AUTO_SIN_96K_DISABLE (0<<3) +#define AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_MASK (~(1<<2)) +#define AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_ENABLE (1<<2) +#define AW8623X_BIT_RTPCFG6_EN_RTP_AUTO_SIN_DISABLE (0<<2) +#define AW8623X_BIT_RTPCFG6_EN_TWORTP_MASK (~(1<<1)) +#define AW8623X_BIT_RTPCFG6_EN_TWORTP_ENABLE (1<<1) +#define AW8623X_BIT_RTPCFG6_EN_TWORTP_DISABLE (0<<1) +#define AW8623X_BIT_RTPCFG6_WCK_PIN_MASK (~(1<<0)) +#define AW8623X_BIT_RTPCFG6_WCK_PIN_ENABLE (1<<0) +#define AW8623X_BIT_RTPCFG6_WCK_PIN_DISABLE (0<<0) + +/***************** TRIGGER *****************/ +#define AW8623X_BIT_TRG_ENABLE_MASK (~(1<<7)) +#define AW8623X_BIT_TRG_ENABLE (1<<7) +#define AW8623X_BIT_TRG_DISABLE (0<<7) +#define AW8623X_BIT_TRG_SEQ_MASK (~(0x7F<<0)) + +/* TRGCFG1: reg 0x33 RW */ +#define AW8623X_BIT_TRGCFG1_TRG1_POS_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG1_TRG1_POS_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG1_TRG1_POS_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG1_TRG1SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG2: reg 0x34 RW */ +#define AW8623X_BIT_TRGCFG2_TRG2_POS_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG2_TRG2_POS_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG2_TRG2_POS_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG2_TRG2SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG3: r3g 0x35 RW */ +#define AW8623X_BIT_TRGCFG3_TRG3_POS_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG3_TRG3_POS_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG3_TRG3_POS_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG3_TRG3SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG4: r3g 0x36 RW */ +#define AW8623X_BIT_TRGCFG4_TRG1_NEG_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG4_TRG1_NEG_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG4_TRG1_NEG_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG4_TRG1SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG5: r3g 0x37 RW */ +#define AW8623X_BIT_TRGCFG5_TRG2_NEG_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG5_TRG2_NEG_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG5_TRG2_NEG_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG5_TRG2SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG6: r3g 0x38 RW */ +#define AW8623X_BIT_TRGCFG6_TRG3_NEG_MASK (~(1<<7)) +#define AW8623X_BIT_TRGCFG6_TRG3_NEG_ENABLE (1<<7) +#define AW8623X_BIT_TRGCFG6_TRG3_NEG_DISABLE (0<<7) +#define AW8623X_BIT_TRGCFG6_TRG3SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG7: reg 0x39 RW */ +#define AW8623X_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK (~(7<<3)) +#define AW8623X_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK (~(7<<0)) +#define AW8623X_BIT_TRGCFG7_TRG1_POLAR_MASK (~(1<<5)) +#define AW8623X_BIT_TRGCFG7_TRG1_POLAR_NEG (1<<5) +#define AW8623X_BIT_TRGCFG7_TRG1_POLAR_POS (0<<5) +#define AW8623X_BIT_TRGCFG7_TRG1_MODE_MASK (~(1<<4)) +#define AW8623X_BIT_TRGCFG7_TRG1_MODE_LEVEL (1<<4) +#define AW8623X_BIT_TRGCFG7_TRG1_MODE_EDGE (0<<4) +#define AW8623X_BIT_TRGCFG7_TRG1_AUTO_BRK_MASK (~(1<<3)) +#define AW8623X_BIT_TRGCFG7_TRG1_AUTO_BRK_ENABLE (1<<3) +#define AW8623X_BIT_TRGCFG7_TRG1_AUTO_BRK_DISABLE (0<<3) +#define AW8623X_BIT_TRGCFG7_TRG2_POLAR_MASK (~(1<<2)) +#define AW8623X_BIT_TRGCFG7_TRG2_POLAR_NEG (1<<2) +#define AW8623X_BIT_TRGCFG7_TRG2_POLAR_POS (0<<2) +#define AW8623X_BIT_TRGCFG7_TRG2_MODE_MASK (~(1<<1)) +#define AW8623X_BIT_TRGCFG7_TRG2_MODE_LEVEL (1<<1) +#define AW8623X_BIT_TRGCFG7_TRG2_MODE_EDGE (0<<1) +#define AW8623X_BIT_TRGCFG7_TRG2_AUTO_BRK_MASK (~(1<<0)) +#define AW8623X_BIT_TRGCFG7_TRG2_AUTO_BRK_ENABLE (1<<0) +#define AW8623X_BIT_TRGCFG7_TRG2_AUTO_BRK_DISABLE (0<<0) + +/* TRGCFG8: reg 0x3A RW */ +#define AW8623X_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK (~(7<<3)) +#define AW8623X_BIT_TRGCFG8_TRG3_POLAR_MASK (~(1<<5)) +#define AW8623X_BIT_TRGCFG8_TRG3_POLAR_NEG (1<<5) +#define AW8623X_BIT_TRGCFG8_TRG3_POLAR_POS (0<<5) +#define AW8623X_BIT_TRGCFG8_TRG3_MODE_MASK (~(1<<4)) +#define AW8623X_BIT_TRGCFG8_TRG3_MODE_LEVEL (1<<4) +#define AW8623X_BIT_TRGCFG8_TRG3_MODE_EDGE (0<<4) +#define AW8623X_BIT_TRGCFG8_TRG3_AUTO_BRK_MASK (~(1<<3)) +#define AW8623X_BIT_TRGCFG8_TRG3_AUTO_BRK_ENABLE (1<<3) +#define AW8623X_BIT_TRGCFG8_TRG3_AUTO_BRK_DISABLE (0<<3) +#define AW8623X_BIT_TRGCFG8_TRG1_STOP_MASK (~(1<<2)) +#define AW8623X_BIT_TRGCFG8_TRG1_STOP (1<<2) +#define AW8623X_BIT_TRGCFG8_TRG2_STOP_MASK (~(1<<1)) +#define AW8623X_BIT_TRGCFG8_TRG2_STOP (1<<1) +#define AW8623X_BIT_TRGCFG8_TRG3_STOP_MASK (~(1<<0)) +#define AW8623X_BIT_TRGCFG8_TRG3_STOP (1<<0) + +/* GLBCFG4: reg 0x3E RW */ +#define AW8623X_BIT_GLBCFG4_GO_PRIO_MASK (~(3<<6)) +#define AW8623X_BIT_GLBCFG4_TRG3_PRIO_MASK (~(3<<4)) +#define AW8623X_BIT_GLBCFG4_TRG2_PRIO_MASK (~(3<<2)) +#define AW8623X_BIT_GLBCFG4_TRG1_PRIO_MASK (~(3<<0)) + +/* GLBRD5: reg 0x3F R0 */ +/* GLB_STATE */ +#define AW8623X_BIT_GLBRD5_STATE (15<<0) +#define AW8623X_BIT_GLBRD5_STATE_STANDBY (0<<0) +#define AW8623X_BIT_GLBRD5_STATE_WAKEUP (1<<0) +#define AW8623X_BIT_GLBRD5_STATE_STARTUP (2<<0) +#define AW8623X_BIT_GLBRD5_STATE_WAIT (3<<0) +#define AW8623X_BIT_GLBRD5_STATE_CONT_GO (6<<0) +#define AW8623X_BIT_GLBRD5_STATE_RAM_GO (7<<0) +#define AW8623X_BIT_GLBRD5_STATE_RTP_GO (8<<0) +#define AW8623X_BIT_GLBRD5_STATE_TRIG_GO (9<<0) +#define AW8623X_BIT_GLBRD5_STATE_I2S_GO (10<<0) +#define AW8623X_BIT_GLBRD5_STATE_BRAKE (11<<0) +#define AW8623X_BIT_GLBRD5_STATE_END (12<<0) +/* RAMADDRH: reg 0x40 RWS */ +#define AW8623X_BIT_RAMADDRH_MASK (~(63<<0)) + +/* I2SCFG1: reg 0x44 RW */ +#define AW8623X_BIT_I2SCFG1_I2S_EN_MASK (~(1<<2)) +#define AW8623X_BIT_I2SCFG1_I2S_ENABLE (1<<2) +#define AW8623X_BIT_I2SCFG1_I2S_DISABLE (0<<2) +#define AW8623X_BIT_I2SCFG1_I2S_MD_MASK (~(1<<1)) +#define AW8623X_BIT_I2SCFG1_I2S_MD_MSB (1<<1) +#define AW8623X_BIT_I2SCFG1_I2S_MD_PHILIP (0<<1) +#define AW8623X_BIT_I2SCFG1_I2S_SLOT_CHSEL_MASK (~(1<<0)) +#define AW8623X_BIT_I2SCFG1_I2S_SLOT_CHSEL_R_BEHIND (1<<0) +#define AW8623X_BIT_I2SCFG1_I2S_SLOT_CHSEL_L_BEYOND (0<<0) + +/***************** SYSCTRL *****************/ +/* SYSCTRL1: reg 0x45 RW */ +#define AW8623X_BIT_SYSCTRL1_TRIG1_MODE_MASK (~(7<<4)) +#define AW8623X_BIT_SYSCTRL1_TRIG1_NONE (7<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_AD (6<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_RCK (5<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_BCK (4<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_TRIG (3<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_ONE_WIRE (2<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_PWM_ERM (1<<4) +#define AW8623X_BIT_SYSCTRL1_TRIG1_PWM_LRA (0<<4) +#define AW8623X_BIT_SYSCTRL1_GAIN_BYPASS_MASK (~(1<<3)) +#define AW8623X_BIT_SYSCTRL1_GAIN_CHANGE_ENABLE (1<<3) +#define AW8623X_BIT_SYSCTRL1_GAIN_CHANGE_DISABLE (0<<3) +#define AW8623X_BIT_SYSCTRL1_RAMINIT_MASK (~(1<<2)) +#define AW8623X_BIT_SYSCTRL1_RAMINIT_ON (1<<2) +#define AW8623X_BIT_SYSCTRL1_RAMINIT_OFF (0<<2) +#define AW8623X_BIT_SYSCTRL1_EN_FIR_MASK (~(1<<1)) +#define AW8623X_BIT_SYSCTRL1_FIR_ENABLE (0<<1) +#define AW8623X_BIT_SYSCTRL1_INTN_PIN_MASK (~(1<<0)) +#define AW8623X_BIT_SYSCTRL1_INTN (1<<0) +#define AW8623X_BIT_SYSCTRL1_TRIG1 (0<<0) + +/* SYSCTRL2: reg 0x46 RW */ +#define AW8623X_BIT_SYSCTRL2_WAKE_MASK (~(1<<7)) +#define AW8623X_BIT_SYSCTRL2_WAKE_ON (1<<7) +#define AW8623X_BIT_SYSCTRL2_WAKE_OFF (0<<7) +#define AW8623X_BIT_SYSCTRL2_STANDBY_MASK (~(1<<6)) +#define AW8623X_BIT_SYSCTRL2_STANDBY_ON (1<<6) +#define AW8623X_BIT_SYSCTRL2_STANDBY_OFF (0<<6) +#define AW8623X_BIT_SYSCTRL2_EN_DLL_MASK (~(1<<5)) +#define AW8623X_BIT_SYSCTRL2_EN_DLL (1<<5) +#define AW8623X_BIT_SYSCTRL2_DISENABLE_DLL (0<<5) +#define AW8623X_BIT_SYSCTRL2_RCK_FRE_MASK (~(3<<3)) +#define AW8623X_BIT_SYSCTRL2_RCK_FRE_96K (3<<3) +#define AW8623X_BIT_SYSCTRL2_RCK_FRE_48K (2<<3) +#define AW8623X_BIT_SYSCTRL2_RCK_FRE_32_768K (1<<3) +#define AW8623X_BIT_SYSCTRL2_RCK_FRE_24K (0<<3) +#define AW8623X_BIT_SYSCTRL2_EN_INTN_CLKOUT_MASK (~(1<<2)) +#define AW8623X_BIT_SYSCTRL2_EN_INTN_CLKOUT (1<<2) +#define AW8623X_BIT_SYSCTRL2_DISENABLE_INTN_CLKOUT (0<<2) +#define AW8623X_BIT_SYSCTRL2_WAVDAT_MODE_MASK (~(3<<0)) +#define AW8623X_BIT_SYSCTRL2_RATE (3<<0) +#define AW8623X_BIT_SYSCTRL2_RATE_12K (2<<0) +#define AW8623X_BIT_SYSCTRL2_RATE_24K (0<<0) +#define AW8623X_BIT_SYSCTRL2_RATE_48K (1<<0) + +/* SYSCTRL3: reg 0x47 RW */ +#define AW8623X_BIT_SYSCTRL3_EN_TRIG1_PD_MASK (~(1<<6)) +#define AW8623X_BIT_SYSCTRL3_EN_TRIG1_PD (1<<6) +#define AW8623X_BIT_SYSCTRL3_DISENABLE_TRIG1_PD (0<<6) +#define AW8623X_BIT_SYSCTRL3_RTP_DLY_MASK (~(3<<4)) +#define AW8623X_BIT_SYSCTRL3_RTP_DLY_FIFO_AE (3<<4) +#define AW8623X_BIT_SYSCTRL3_RTP_DLY_FIFO_8 (2<<4) +#define AW8623X_BIT_SYSCTRL3_RTP_DLY_FIFO_5 (1<<4) +#define AW8623X_BIT_SYSCTRL3_RTP_DLY_FIFO_1 (0<<4) +#define AW8623X_BIT_SYSCTRL3_INTMODE_MASK (~(3<<2)) +#define AW8623X_BIT_SYSCTRL3_INTMODE_BOTH_EDGE (3<<2) +#define AW8623X_BIT_SYSCTRL3_INTMODE_LEVEL_1 (2<<2) +#define AW8623X_BIT_SYSCTRL3_INTMODE_POS_EDGE (1<<2) +#define AW8623X_BIT_SYSCTRL3_INTMODE_LEVEL_2 (0<<2) +#define AW8623X_BIT_SYSCTRL3_INTP_MASK (~(1<<1)) +#define AW8623X_BIT_SYSCTRL3_INTP_ACTIVE_HIGH (1<<1) +#define AW8623X_BIT_SYSCTRL3_INTP_ACTIVE_LOW (0<<1) +#define AW8623X_BIT_SYSCTRL3_WAKE_MODE_MASK (~(1<<0)) +#define AW8623X_BIT_SYSCTRL3_WAKE_MODE_WAKEUP (1<<0) +#define AW8623X_BIT_SYSCTRL3_WAKE_MODE_BST (0<<0) + +/* SYSCTRL5: reg 0x49 RW */ +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_MASK (~(7<<2)) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_VBAT_CTRL (5<<2) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_TRIG_ENG (4<<2) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_CONT_ENG (3<<2) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_RTP_ENG (2<<2) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_RAM_ENG (1<<2) +#define AW8623X_BIT_SYSCTRL5_MODULE_SEL_EFUSE_ENG (0<<2) +#define AW8623X_BIT_SYSCTRL5_DEV_ADDR_CTR_MASK (~(3<<0)) +#define AW8623X_BIT_SYSCTRL5_DEV_ADDR_CTR_HW_IRSW (3<<0) +#define AW8623X_BIT_SYSCTRL5_DEV_ADDR_CTR_HW_1 (2<<0) +#define AW8623X_BIT_SYSCTRL5_DEV_ADDR_CTR_IRSW (1<<0) +#define AW8623X_BIT_SYSCTRL5_DEV_ADDR_CTR_HW_2 (0<<0) + +/* PWMCFG1: reg 0x4A RW */ +#define AW8623X_BIT_PWMCFG1_PRC_EN_MASK (~(1<<7)) +#define AW8623X_BIT_PWMCFG1_PRC_ENABLE (1<<7) +#define AW8623X_BIT_PWMCFG1_PRC_DISABLE (0<<7) +#define AW8623X_BIT_PWMCFG1_PRCTIME_MASK (~(0x7F<<0)) + +/* PWMCFG2: reg 0x4B RW */ +#define AW8623X_BIT_PWMCFG2_PRCT_MODE_MASK (~(1<<6)) +#define AW8623X_BIT_PWMCFG2_PRCT_MODE_VALID (1<<6) +#define AW8623X_BIT_PWMCFG2_PRCT_MODE_INVALID (0<<6) +#define AW8623X_BIT_PWMCFG2_REF_SEL_MASK (~(1<<5)) +#define AW8623X_BIT_PWMCFG2_REF_SEL_TRIANGLE (1<<5) +#define AW8623X_BIT_PWMCFG2_REF_SEL_SAWTOOTH (0<<5) +#define AW8623X_BIT_PWMCFG2_PD_HWM_MASK (~(1<<4)) +#define AW8623X_BIT_PWMCFG2_PD_HWM_FULL (1<<4) +#define AW8623X_BIT_PWMCFG2_PD_HWM_HALF (0<<4) +#define AW8623X_BIT_PWMCFG2_PWMOE_MASK (~(1<<3)) +#define AW8623X_BIT_PWMCFG2_PWMOE_ON (1<<3) +#define AW8623X_BIT_PWMCFG2_PWMOE_OFF (0<<3) +#define AW8623X_BIT_PWMCFG2_PWMFRC_MASK (~(7<<0)) + +/* PWMCFG3: reg 0x4C RW */ +#define AW8623X_BIT_PWMCFG3_PR_EN_MASK (~(1<<7)) +#define AW8623X_BIT_PWMCFG3_PR_ENABLE (1<<7) +#define AW8623X_BIT_PWMCFG3_PR_DISABLE (0<<7) +#define AW8623X_BIT_PWMCFG3_PRLVL_MASK (~(0x7F<<0)) +#define AW8623X_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE (0x3F) + +/* PWMCFG4: reg 0x4D RW */ +/* PRTIME */ +#define AW8623X_PWMCFG4_PRTIME_DEFAULT_VALUE (0x32) + +/* VBATCTRL: reg 0x4E RW */ +#define AW8623X_BIT_VBATCTRL_VBAT_PRO_MASK (~(1<<7)) +#define AW8623X_BIT_VBATCTRL_VBAT_PRO_ENABLE (1<<7) +#define AW8623X_BIT_VBATCTRL_VBAT_PRO_DISABLE (0<<7) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_MASK (~(1<<6)) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_HW (1<<6) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_SW (0<<6) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_CON_MASK (~(1<<5)) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_CON_DURING (1<<5) +#define AW8623X_BIT_VBATCTRL_VBAT_MODE_CON_BEFORE (0<<5) +#define AW8623X_BIT_VBATCTRL_DELTA_VBAT_MASK (~(1<<4)) +#define AW8623X_BIT_VBATCTRL_DELTA_VBAT_0_2 (1<<4) +#define AW8623X_BIT_VBATCTRL_DELTA_VBAT_0_1 (0<<4) +#define AW8623X_BIT_VBATCTRL_REL_VBAT_MASK (~(3<<2)) +#define AW8623X_BIT_VBATCTRL_REL_VBAT_100 (3<<2) +#define AW8623X_BIT_VBATCTRL_REL_VBAT_50 (2<<2) +#define AW8623X_BIT_VBATCTRL_REL_VBAT_25 (1<<2) +#define AW8623X_BIT_VBATCTRL_REL_VBAT_10 (0<<2) +#define AW8623X_BIT_VBATCTRL_ABS_VBAT_MASK (~(3<<0)) +#define AW8623X_BIT_VBATCTRL_ABS_VBAT_3_5 (3<<0) +#define AW8623X_BIT_VBATCTRL_ABS_VBAT_3_4 (2<<0) +#define AW8623X_BIT_VBATCTRL_ABS_VBAT_3_3 (1<<0) +#define AW8623X_BIT_VBATCTRL_ABS_VBAT_3_2 (0<<0) + +/* DETCFG1: reg 0x4F RW */ +#define AW8623X_BIT_DETCFG1_EN_VBAT_AVG_MASK (~(1<<7)) +#define AW8623X_BIT_DETCFG1_EN_VBAT_AVG_16_TIMES (1<<7) +#define AW8623X_BIT_DETCFG1_VBAT_REF_MASK (~(7<<4)) +#define AW8623X_BIT_DETCFG1_VBAT_REF_5_5 (7<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_5_0 (6<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_4_8 (5<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_4_5 (4<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_4_2 (3<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_4_0 (2<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_3_6 (1<<4) +#define AW8623X_BIT_DETCFG1_VBAT_REF_3_3 (0<<4) +#define AW8623X_BIT_DETCFG1_ADC_FS_MASK (~(3<<2)) +#define AW8623X_BIT_DETCFG1_ADC_FS_24K (3<<2) +#define AW8623X_BIT_DETCFG1_ADC_FS_48K (2<<2) +#define AW8623X_BIT_DETCFG1_ADC_FS_96K (1<<2) +#define AW8623X_BIT_DETCFG1_ADC_FS_192K (0<<2) +#define AW8623X_BIT_DETCFG1_DET_GO_MASK (~(3<<0)) +#define AW8623X_BIT_DETCFG1_DET_GO_ON (1<<0) +#define AW8623X_BIT_DETCFG1_DET_GO_OFF (0<<0) + +/* DETCFG2: reg 0x50 RW */ +#define AW8623X_BIT_DETCFG2_DET_SEQ0_MASK (~(0X0F<<3)) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_HDN_1 (0x0E<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_HDN_2 (0x0A<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_HDP_1 (0x0D<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_HDP_2 (9<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_FTS (6<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_VOUT (5<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_OS (4<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_RL (3<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_TRIG1 (2<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_PVDD (1<<3) +#define AW8623X_BIT_DETCFG2_DET_SEQ0_VBAT (0<<3) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_MASK (~(7<<0)) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_40 (7<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_20 (6<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_10 (5<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_8 (4<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_5 (3<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_4 (2<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_2 (1<<0) +#define AW8623X_BIT_DETCFG2_D2S_GAIN_1 (0<<0) + +/* DETRD1: reg 0x51 RO */ +#define AW8623X_BIT_DETRD1_AVG_DATA_H_MASK (~(3<<0)) + +/* TRIMCFG1: reg 0x59 RW */ +#define AW8623X_BIT_TRIMCFG1_RL_TRIM_SRC_MASK (~(1<<7)) +#define AW8623X_BIT_TRIMCFG1_RL_TRIM_SRC_REG (1<<7) +#define AW8623X_BIT_TRIMCFG1_RL_TRIM_SRC_EFUSE (0<<7) +#define AW8623X_BIT_TRIMCFG1_TRIM_RL_MASK (~(0x7F<<0)) + +/* TRIMCFG2: reg 0x5A RW */ +#define AW8623X_BIT_TRIMCFG2_OSC_TRIM_SRC_MASK (~(1<<6)) +#define AW8623X_BIT_TRIMCFG2_OSC_TRIM_SRC_REG (1<<6) +#define AW8623X_BIT_TRIMCFG2_OSC_TRIM_SRC_EFUSE (0<<6) +#define AW8623X_BIT_TRIMCFG2_TRIM_LRA_MASK (~(0x3F<<0)) + +/* ANACFG4: reg:0x70 RW */ +#define AW8623X_BIT_ANACFG3_EN_OVP_SAR_MASK (~(1<<7)) +#define AW8623X_BIT_ANACFG3_EN_OVP_SAR_ENABLE (1<<7) +#define AW8623X_BIT_ANACFG3_EN_OVP_SAR_DISABLE (0<<7) + +/* ANACFG4: reg:0x71 RW */ +#define AW8623X_BIT_ANACFG4_PRO_HDRV_MASK (~(1<<7)) +#define AW8623X_BIT_ANACFG4_PRO_HDRV_ENABLE (1<<7) +#define AW8623X_BIT_ANACFG4_PRO_HDRV_DISABLE (0<<7) + +/****************************************************** + * AW8624X Register Detail + *****************************************************/ +/* SYSST: reg 0x01 RO */ +#define AW8624X_BIT_SYSST_UVLS (1<<5) +#define AW8624X_BIT_SYSST_FF_AES (1<<4) +#define AW8624X_BIT_SYSST_FF_AFS (1<<3) +#define AW8624X_BIT_SYSST_OCDS (1<<2) +#define AW8624X_BIT_SYSST_OTS (1<<1) +#define AW8624X_BIT_SYSST_DONES (1<<0) + +/* SYSINT: reg 0x02 RC */ +#define AW8624X_BIT_SYSINT_UVLI (1<<5) +#define AW8624X_BIT_SYSINT_FF_AEI (1<<4) +#define AW8624X_BIT_SYSINT_FF_AFI (1<<3) +#define AW8624X_BIT_SYSINT_OCDI (1<<2) +#define AW8624X_BIT_SYSINT_OTI (1<<1) +#define AW8624X_BIT_SYSINT_DONEI (1<<0) + +/* SYSINTM: reg 0x03 RW */ +#define AW8624X_BIT_SYSINTM_UVLM_MASK (~(1<<5)) +#define AW8624X_BIT_SYSINTM_UVLM_OFF (1<<5) +#define AW8624X_BIT_SYSINTM_UVLM_ON (0<<5) +#define AW8624X_BIT_SYSINTM_FF_AEM_MASK (~(1<<4)) +#define AW8624X_BIT_SYSINTM_FF_AEM_OFF (1<<4) +#define AW8624X_BIT_SYSINTM_FF_AEM_ON (0<<4) +#define AW8624X_BIT_SYSINTM_FF_AFM_MASK (~(1<<3)) +#define AW8624X_BIT_SYSINTM_FF_AFM_OFF (1<<3) +#define AW8624X_BIT_SYSINTM_FF_AFM_ON (0<<3) +#define AW8624X_BIT_SYSINTM_OCDM_MASK (~(1<<2)) +#define AW8624X_BIT_SYSINTM_OCDM_OFF (1<<2) +#define AW8624X_BIT_SYSINTM_OCDM_ON (0<<2) +#define AW8624X_BIT_SYSINTM_OTM_MASK (~(1<<1)) +#define AW8624X_BIT_SYSINTM_OTM_OFF (1<<1) +#define AW8624X_BIT_SYSINTM_OTM_ON (0<<1) +#define AW8624X_BIT_SYSINTM_DONEM_MASK (~(1<<0)) +#define AW8624X_BIT_SYSINTM_DONEM_OFF (1<<0) +#define AW8624X_BIT_SYSINTM_DONEM_ON (0<<0) + +/* SYSST2: reg 0x04 RO */ +#define AW8624X_BIT_SYSST2_RAM_ADDR_ER (1<<5) +#define AW8624X_BIT_SYSST2_TRG_ADDR_ER (1<<4) +#define AW8624X_BIT_SYSST2_DVDD_PORN (1<<3) +#define AW8624X_BIT_SYSST2_VBG_OK (1<<2) +#define AW8624X_BIT_SYSST2_FF_FULL (1<<1) +#define AW8624X_BIT_SYSST2_FF_EMPTY (1<<0) + +/* SYSER: reg 0x05 RC */ +#define AW8624X_BIT_SYSER_TRIG1_EVENT (1<<6) +#define AW8624X_BIT_SYSER_TRIG2_EVENT (1<<5) +#define AW8624X_BIT_SYSER_TRIG3_EVENT (1<<4) +#define AW8624X_BIT_SYSER_OV (1<<3) +#define AW8624X_BIT_SYSER_ADDR_ER (1<<2) +#define AW8624X_BIT_SYSER_FF_ER (1<<1) +#define AW8624X_BIT_SYSER_PLL_REF_ER (1<<0) + +/* PLAYCFG3: reg 0x08 RW */ +#define AW8624X_BIT_PLAYCFG3_STOP_MODE_MASK (~(1<<5)) +#define AW8624X_BIT_PLAYCFG3_STOP_MODE_NOW (1<<5) +#define AW8624X_BIT_PLAYCFG3_STOP_MODE_LATER (0<<5) +#define AW8624X_BIT_PLAYCFG3_BRK_EN_MASK (~(1<<2)) +#define AW8624X_BIT_PLAYCFG3_BRK (1<<2) +#define AW8624X_BIT_PLAYCFG3_BRK_ENABLE (1<<2) +#define AW8624X_BIT_PLAYCFG3_BRK_DISABLE (0<<2) +#define AW8624X_BIT_PLAYCFG3_PLAY_MODE_MASK (~(3<<0)) +#define AW8624X_BIT_PLAYCFG3_PLAY_MODE_STOP (3<<0) +#define AW8624X_BIT_PLAYCFG3_PLAY_MODE_CONT (2<<0) +#define AW8624X_BIT_PLAYCFG3_PLAY_MODE_RTP (1<<0) +#define AW8624X_BIT_PLAYCFG3_PLAY_MODE_RAM (0<<0) + +/* PLAYCFG4: reg 0x09 RW */ +#define AW8624X_BIT_PLAYCFG4_STOP_MASK (~(1<<1)) +#define AW8624X_BIT_PLAYCFG4_STOP_ON (1<<1) +#define AW8624X_BIT_PLAYCFG4_STOP_OFF (0<<1) +#define AW8624X_BIT_PLAYCFG4_GO_MASK (~(1<<0)) +#define AW8624X_BIT_PLAYCFG4_GO_ON (1<<0) +#define AW8624X_BIT_PLAYCFG4_GO_OFF (0<<0) + +/* WAVCFG1-8: reg 0x0A - reg 0x11 RW */ +#define AW8624X_BIT_WAVCFG_SEQWAIT_MASK (~(1<<7)) +#define AW8624X_BIT_WAVCFG_SEQWAIT_TIME (1<<7) +#define AW8624X_BIT_WAVCFG_SEQWAIT_NUMBER (0<<7) +#define AW8624X_BIT_WAVCFG_SEQ (0x7F) + +/* WAVCFG9-12: reg 0x12 - reg 0x15 RW */ +#define AW8624X_BIT_WAVLOOP_SEQ_ODD_MASK (~(0x0F<<4)) +#define AW8624X_BIT_WAVLOOP_SEQ_ODD_INIFINITELY (0x0F<<4) +#define AW8624X_BIT_WAVLOOP_SEQ_EVEN_MASK (~(0x0F<<0)) +#define AW8624X_BIT_WAVLOOP_SEQ_EVEN_INIFINITELY (0x0F<<0) +#define AW8624X_BIT_WAVLOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG9: reg 0x12 RW */ +#define AW8624X_BIT_WAVCFG9_SEQ1LOOP_MASK (~(0x0F<<4)) +#define AW8624X_BIT_WAVCFG9_SEQ1LOOP_INIFINITELY (0x0F<<4) +#define AW8624X_BIT_WAVCFG9_SEQ2LOOP_MASK (~(0x0F<<0)) +#define AW8624X_BIT_WAVCFG9_SEQ2LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG10: reg 0x13 RW */ +#define AW8624X_BIT_WAVCFG10_SEQ3LOOP_MASK (~(0x0F<<4)) +#define AW8624X_BIT_WAVCFG10_SEQ3LOOP_INIFINITELY (0x0F<<4) +#define AW8624X_BIT_WAVCFG10_SEQ4LOOP_MASK (~(0x0F<<0)) +#define AW8624X_BIT_WAVCFG10_SEQ4LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG11: reg 0x14 RW */ +#define AW8624X_BIT_WAVCFG11_SEQ5LOOP_MASK (~(0x0F<<4)) +#define AW8624X_BIT_WAVCFG11_SEQ5LOOP_INIFINITELY (0x0F<<4) +#define AW8624X_BIT_WAVCFG11_SEQ6LOOP_MASK (~(0x0F<<0)) +#define AW8624X_BIT_WAVCFG11_SEQ6LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG12: reg 0x15 RW */ +#define AW8624X_BIT_WAVCFG12_SEQ7LOOP_MASK (~(0x0F<<4)) +#define AW8624X_BIT_WAVCFG12_SEQ7LOOP_INIFINITELY (0x0F<<4) +#define AW8624X_BIT_WAVCFG12_SEQ8LOOP_MASK (~(0x0F<<0)) +#define AW8624X_BIT_WAVCFG12_SEQ8LOOP_INIFINITELY (0x0F<<0) + +/***************** CONT *****************/ +/* CONTCFG1: reg 0x18 RW */ +#define AW8624X_BIT_CONTCFG1_EDGE_FRE_MASK (~(0x0F<<4)) +#define AW8624X_BIT_CONTCFG1_PEAK_NUM_MASK (~(3<<1)) +#define AW8624X_BIT_CONTCFG1_PEAK_NUM_NO_F0_DET (0<<1) +#define AW8624X_BIT_CONTCFG1_PEAK_NUM_1 (1<<1) +#define AW8624X_BIT_CONTCFG1_PEAK_NUM_2 (2<<1) +#define AW8624X_BIT_CONTCFG1_PEAK_NUM_3 (3<<1) +#define AW8624X_BIT_CONTCFG1_SIN_MODE_MASK (~(1<<0)) +#define AW8624X_BIT_CONTCFG1_SIN_MODE_COS (1<<0) +#define AW8624X_BIT_CONTCFG1_SIN_MODE_SINE (0<<0) + +/* CONTCFG5: reg 0x1C RW */ +#define AW8624X_BIT_CONTCFG5_OPEN_LOOP_NUM_MASK (~(7<<5)) +#define AW8624X_BIT_CONTCFG5_SMART_LOOP_MASK (~(1<<4)) +#define AW8624X_BIT_CONTCFG5_SMART_LOOP_ON (1<<4) +#define AW8624X_BIT_CONTCFG5_SMART_LOOP_OFF (0<<4) +#define AW8624X_BIT_CONTCFG5_BRK_GAIN_MASK (~(0x0F<<0)) + +/* CONTCFG6: reg 0x1D RW */ +#define AW8624X_BIT_CONTCFG6_TRACK_EN_MASK (~(1<<7)) +#define AW8624X_BIT_CONTCFG6_TRACK_ENABLE (1<<7) +#define AW8624X_BIT_CONTCFG6_TRACK_DISABLE (0<<7) +#define AW8624X_BIT_CONTCFG6_DRV1_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG7: reg 0x1E RW */ +#define AW8624X_BIT_CONTCFG7_DRV_SWITCH_MASK (~(1<<7)) +#define AW8624X_BIT_CONTCFG7_DRV_SWITCH_ENABLE (1<<7) +#define AW8624X_BIT_CONTCFG7_DRV_SWITCH_DISABLE (0<<7) +#define AW8624X_BIT_CONTCFG7_DRV2_LVL_MASK (~(0x7F<<0)) + +/* CONTRD20: reg 0x2B RO */ +#define AW8624X_BIT_CONTRD20_BEMF_PEAK4_L_MASK (~(3<<6)) +#define AW8624X_BIT_CONTRD20_BEMF_PEAK3_L_MASK (~(3<<4)) +#define AW8624X_BIT_CONTRD20_BEMF_PEAK2_L_MASK (~(3<<2)) +#define AW8624X_BIT_CONTRD20_BEMF_PEAK1_L_MASK (~(3<<0)) + +/* CONTRD21: reg 0x2C RO */ +#define AW8624X_BIT_CONTRD21_BEMF_PEAK5_L_MASK (~(3<<0)) + +/***************** RTP *****************/ +/* RTPCFG1: reg 0x2D RW */ +#define AW8624X_BIT_RTPCFG1_ADDRH_MASK (~(0x0F<<0)) + +/* RTPCFG3: reg 0x2F RW */ +#define AW8624X_BIT_RTPCFG3_FIFO_AEH_MASK (~(0x0F<<4)) +#define AW8624X_BIT_RTPCFG3_FIFO_AFH_MASK (~(0x0F<<0)) +#define AW8624X_BIT_RTPCFG3_FIFO_AEH (0x0F<<4) +#define AW8624X_BIT_RTPCFG3_FIFO_AFH (0x0F<<0) + +/***************** TRIGGER *****************/ +#define AW8624X_BIT_TRG_ENABLE_MASK (~(1<<7)) +#define AW8624X_BIT_TRG_ENABLE (1<<7) +#define AW8624X_BIT_TRG_DISABLE (0<<7) +#define AW8624X_BIT_TRG_SEQ_MASK (~(0x7F<<0)) + +/* TRGCFG1: reg 0x33 RW */ +#define AW8624X_BIT_TRGCFG1_TRG1_POS_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG1_TRG1_POS_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG1_TRG1_POS_DISABLE (0<<7) +#define AW8624X_BIT_TRGCFG1_TRG1SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG2: reg 0x34 RW */ +#define AW8624X_BIT_TRGCFG2_TRG2_POS_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG2_TRG2_POS_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG2_TRG2_POS_DISABLE (0<<7) +#define AW8624X_BIT_TRGCFG2_TRG2SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG3: reg 0x35 RW */ +#define AW8624X_BIT_TRGCFG3_TRG3_POS_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG3_TRG3_POS_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG3_TRG3_POS_DISABLE (0<<7) +#define AW8624X_BIT_TRGCFG3_TRG3SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG4: reg 0x36 RW */ +#define AW8624X_BIT_TRGCFG4_TRG1_NEG_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG4_TRG1_NEG_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG4_TRG1_NEG_DISABLE (0<<7) +#define AW8624X_BIT_TRGCFG4_TRG1SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG5: reg 0x37 RW */ +#define AW8624X_BIT_TRGCFG5_TRG2_NEG_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG5_TRG2_NEG_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG5_TRG2_NEG_DISABLE (0<<7) +#define AW8624X_BIT_TRGCFG5_TRG2SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG6: reg 0x38 RW */ +#define AW8624X_BIT_TRGCFG6_TRG3_NEG_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG6_TRG3_NEG_ENABLE (1<<7) +#define AW8624X_BIT_TRGCFG6_TRG3_NEG_DISABLE (0<<7) +#define AW862XX_BIT_TRGCFG6_TRG3SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG7: reg 0x39 RW */ +#define AW8624X_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK (~(7<<5)) +#define AW8624X_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK (~(7<<1)) +#define AW8624X_BIT_TRGCFG7_TRG1_POLAR_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG7_TRG1_POLAR_NEG (1<<7) +#define AW8624X_BIT_TRGCFG7_TRG1_POLAR_POS (0<<7) +#define AW8624X_BIT_TRGCFG7_TRG1_MODE_MASK (~(1<<6)) +#define AW8624X_BIT_TRGCFG7_TRG1_MODE_LEVEL (1<<6) +#define AW8624X_BIT_TRGCFG7_TRG1_MODE_EDGE (0<<6) +#define AW8624X_BIT_TRGCFG7_TRG1_AUTO_BRK_MASK (~(1<<5)) +#define AW8624X_BIT_TRGCFG7_TRG1_AUTO_BRK_ENABLE (1<<5) +#define AW8624X_BIT_TRGCFG7_TRG1_AUTO_BRK_DISABLE (0<<5) +#define AW8624X_BIT_TRGCFG7_TRG2_POLAR_MASK (~(1<<3)) +#define AW8624X_BIT_TRGCFG7_TRG2_POLAR_NEG (1<<3) +#define AW8624X_BIT_TRGCFG7_TRG2_POLAR_POS (0<<3) +#define AW8624X_BIT_TRGCFG7_TRG2_MODE_MASK (~(1<<2)) +#define AW8624X_BIT_TRGCFG7_TRG2_MODE_LEVEL (1<<2) +#define AW8624X_BIT_TRGCFG7_TRG2_MODE_EDGE (0<<2) +#define AW8624X_BIT_TRGCFG7_TRG2_AUTO_BRK_MASK (~(1<<1)) +#define AW8624X_BIT_TRGCFG7_TRG2_AUTO_BRK_ENABLE (1<<1) +#define AW8624X_BIT_TRGCFG7_TRG2_AUTO_BRK_DISABLE (0<<1) + +/* TRGCFG8: reg 0x3A RW */ +#define AW8624X_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK (~(7<<5)) +#define AW8624X_BIT_TRGCFG8_TRG3_POLAR_MASK (~(1<<7)) +#define AW8624X_BIT_TRGCFG8_TRG3_POLAR_NEG (1<<7) +#define AW8624X_BIT_TRGCFG8_TRG3_POLAR_POS (0<<7) +#define AW8624X_BIT_TRGCFG8_TRG3_MODE_MASK (~(1<<6)) +#define AW8624X_BIT_TRGCFG8_TRG3_MODE_LEVEL (1<<6) +#define AW8624X_BIT_TRGCFG8_TRG3_MODE_EDGE (0<<6) +#define AW8624X_BIT_TRGCFG8_TRG3_AUTO_BRK_MASK (~(1<<5)) +#define AW8624X_BIT_TRGCFG8_TRG3_AUTO_BRK_ENABLE (1<<5) +#define AW8624X_BIT_TRGCFG8_TRG3_AUTO_BRK_DISABLE (0<<5) +#define AW8624X_BIT_TRGCFG8_TRG1_STOP_MASK (~(1<<2)) +#define AW8624X_BIT_TRGCFG8_TRG1_STOP (1<<2) +#define AW8624X_BIT_TRGCFG8_TRG2_STOP_MASK (~(1<<1)) +#define AW8624X_BIT_TRGCFG8_TRG2_STOP (1<<1) +#define AW8624X_BIT_TRGCFG8_TRG3_STOP_MASK (~(1<<0)) +#define AW8624X_BIT_TRGCFG8_TRG3_STOP (1<<0) + +/* GLBCFG2: reg 0x3C RW */ +/* START_DLY */ +#define AW8624X_BIT_GLBCFG2_START_DLY_250US (0x0C) + +/* GLBCFG4: reg 0x3E RW */ +#define AW8624X_BIT_GLBCFG4_GO_PRIO_MASK (~(3<<6)) +#define AW8624X_BIT_GLBCFG4_TRG3_PRIO_MASK (~(3<<4)) +#define AW8624X_BIT_GLBCFG4_TRG2_PRIO_MASK (~(3<<2)) +#define AW8624X_BIT_GLBCFG4_TRG1_PRIO_MASK (~(3<<0)) + +/* SYSCTRL1: reg 0x43 RW */ +#define AW8624X_BIT_SYSCTRL1_VBAT_MODE_MASK (~(1<<7)) +#define AW8624X_BIT_SYSCTRL1_VBAT_MODE_HW (1<<7) +#define AW8624X_BIT_SYSCTRL1_VBAT_MODE_SW (0<<7) +#define AW8624X_BIT_SYSCTRL1_INT_BRK_MASK (~(1<<6)) +#define AW8624X_BIT_SYSCTRL1_INT_BRK_ON (1<<6) +#define AW8624X_BIT_SYSCTRL1_INT_BRK_OFF (0<<6) +#define AW8624X_BIT_SYSCTRL1_RCK_FRE_MASK (~(3<<4)) +#define AW8624X_BIT_SYSCTRL1_RCK_FRE_127 (3<<4) +#define AW8624X_BIT_SYSCTRL1_RCK_FRE_255 (2<<4) +#define AW8624X_BIT_SYSCTRL1_RCK_FRE_374 (1<<4) +#define AW8624X_BIT_SYSCTRL1_RCK_FRE_511 (0<<4) +#define AW8624X_BIT_SYSCTRL1_RAMINIT_MASK (~(1<<3)) +#define AW8624X_BIT_SYSCTRL1_RAMINIT_ON (1<<3) +#define AW8624X_BIT_SYSCTRL1_RAMINIT_OFF (0<<3) +#define AW8624X_BIT_SYSCTRL1_EN_FIR_MASK (~(1<<2)) +#define AW8624X_BIT_SYSCTRL1_FIR_ENABLE (0<<2) +#define AW8624X_BIT_SYSCTRL1_WAKE_MODE_MASK (~(1<<1)) +#define AW8624X_BIT_SYSCTRL1_WAKE_MODE_WAKEUP (1<<1) +#define AW8624X_BIT_SYSCTRL1_WAKE_MODE_BST (0<<1) +#define AW8624X_BIT_SYSCTRL1_RTP_CLK_MASK (~(1<<0)) +#define AW8624X_BIT_SYSCTRL1_RTP_PLL (1<<0) +#define AW8624X_BIT_SYSCTRL1_RTP_OSC (0<<0) + +/* SYSCTRL2: reg 0x44 RW */ +#define AW8624X_BIT_SYSCTRL2_WAKE_MASK (~(1<<7)) +#define AW8624X_BIT_SYSCTRL2_WAKE_ON (1<<7) +#define AW8624X_BIT_SYSCTRL2_WAKE_OFF (0<<7) +#define AW8624X_BIT_SYSCTRL2_STANDBY_MASK (~(1<<6)) +#define AW8624X_BIT_SYSCTRL2_STANDBY_ON (1<<6) +#define AW8624X_BIT_SYSCTRL2_STANDBY_OFF (0<<6) +#define AW8624X_BIT_SYSCTRL2_RTP_DLY_MASK (~(3<<4)) +#define AW8624X_BIT_SYSCTRL2_WAIT_NHZ_MASK (~(1<<3)) +#define AW8624X_BIT_SYSCTRL2_WAIT_NHZ_ENABLE (0<<3) +#define AW8624X_BIT_SYSCTRL2_WAIT_NHZ_DISABLE (1<<3) +#define AW8624X_BIT_SYSCTRL2_WCK_PIN_MASK (~(1<<2)) +#define AW8624X_BIT_SYSCTRL2_ENABLE_TRIG1 (1<<2) +#define AW8624X_BIT_SYSCTRL2_DISENABLE_TRIG1 (0<<2) +#define AW8624X_BIT_SYSCTRL2_WAVDAT_MODE_MASK (~(3<<0)) +#define AW8624X_BIT_SYSCTRL2_RATE (3<<0) +#define AW8624X_BIT_SYSCTRL2_RATE_12K (2<<0) +#define AW8624X_BIT_SYSCTRL2_RATE_48K (1<<0) +#define AW8624X_BIT_SYSCTRL2_RATE_24K (0<<0) + +/* SYSCTRL3: reg 0x45 RW */ +#define AW8624X_BIT_SYSCTRL3_TSET_MASK (~(0x0F<<4)) +#define AW8624X_BIT_SYSCTRL3_BEMF_SET_MASK (~(0x0F<<0)) + +/* SYSCTRL5: reg 0x49 RW */ +#define AW8624X_BIT_SYSCTRL5_INTBRK_MD_MASK (~(1<<7)) +#define AW8624X_BIT_SYSCTRL5_INTBRK_MD_ENABLE (1<<7) +#define AW8624X_BIT_SYSCTRL5_INTBRK_MD_DISABLE (0<<7) +#define AW8624X_BIT_SYSCTRL5_GAIN_BYPASS_MASK (~(1<<6)) +#define AW8624X_BIT_SYSCTRL5_GAIN_CHANGEABLE (1<<6) +#define AW8624X_BIT_SYSCTRL5_GAIN_FIXED (0<<6) +#define AW8624X_BIT_SYSCTRL5_INT_EDGE_MODE_MASK (~(1<<5)) +#define AW8624X_BIT_SYSCTRL5_INT_EDGE_MODE_POS (0<<5) +#define AW8624X_BIT_SYSCTRL5_INT_EDGE_MODE_BOTH (1<<5) +#define AW8624X_BIT_SYSCTRL5_INT_MODE_MASK (~(1<<4)) +#define AW8624X_BIT_SYSCTRL5_INT_MODE_EDGE (1<<4) +#define AW8624X_BIT_SYSCTRL5_INT_MODE_LEVEL (0<<4) +#define AW8624X_BIT_SYSCTRL5_INTP_MASK (~(1<<3)) +#define AW8624X_BIT_SYSCTRL5_INTP_HIGH (1<<3) +#define AW8624X_BIT_SYSCTRL5_INTP_LOW (0<<3) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_MASK (~(7<<0)) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_1 (0<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_2 (1<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_4 (2<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_5 (3<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_8 (4<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_10 (5<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_20 (6<<0) +#define AW8624X_BIT_SYSCTRL5_D2S_GAIN_40 (7<<0) + +/* SYSCTRL6: reg 0x4A RW */ +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_MASK (~(7<<0)) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_1 (0<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_2 (1<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_4 (2<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_5 (3<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_8 (4<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_10 (5<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_20 (6<<0) +#define AW8624X_BIT_SYSCTRL6_F0_D2S_GAIN_40 (7<<0) + +/* PWMCFG1: reg 0x4C RW */ +#define AW8624X_BIT_PWMCFG1_PRC_EN_MASK (~(1<<7)) +#define AW8624X_BIT_PWMCFG1_PRC_ENABLE (1<<7) +#define AW8624X_BIT_PWMCFG1_PRC_DISABLE (0<<7) +#define AW8624X_BIT_PWMCFG1_PRCTIME_MASK (~(0x7F<<0)) + +/* PWMCFG3: reg 0x4E RW */ +#define AW8624X_BIT_PWMCFG3_PR_EN_MASK (~(1<<7)) +#define AW8624X_BIT_PWMCFG3_PR_ENABLE (1<<7) +#define AW8624X_BIT_PWMCFG3_PR_DISABLE (0<<7) +#define AW8624X_BIT_PWMCFG3_PRLVL_MASK (~(0x7F<<0)) +#define AW8624X_BIT_PWMCFG3_PRLVL_DEFAULT_VALUE (0x3F) + +/* PWMCFG4: reg 0x4F RW */ +/* PRTIME */ +#define AW8624X_PWMCFG4_PRTIME_DEFAULT_VALUE (0x32) + +/* DET_LO: reg 0x50 RO */ +#define AW8624X_BIT_DET_LO_TEST_LO_MASK (~(3<<6)) +#define AW8624X_BIT_DET_LO_VBAT_LO_MASK (~(3<<4)) +#define AW8624X_BIT_DET_LO_VBAT (3<<4) +#define AW8624X_BIT_DET_LO_OS_MASK (~(3<<2)) +#define AW8624X_BIT_DET_LO_RL_MASK (~(3<<0)) +#define AW8624X_BIT_DET_LO_RL (3<<0) + +/* DETCFG1: reg 0x51 RW */ +#define AW8624X_BIT_DETCFG1_FTS_GO_MASK (~(1<<7)) +#define AW8624X_BIT_DETCFG1_FTS_GO_ENABLE (1<<7) +#define AW8624X_BIT_DETCFG1_TEST_GO_MASK (~(1<<6)) +#define AW8624X_BIT_DETCFG1_TEST_GO_ENABLE (1<<6) +#define AW8624X_BIT_DETCFG1_ADO_SLOT_MODE_MASK (~(1<<5)) +#define AW8624X_BIT_DETCFG1_ADO_SLOT_ADC_32 (1<<5) +#define AW8624X_BIT_DETCFG1_ADO_SLOT_ADC_256 (0<<5) +#define AW8624X_BIT_DETCFG1_RL_OS_MASK (~(1<<4)) +#define AW8624X_BIT_DETCFG1_RL (1<<4) +#define AW8624X_BIT_DETCFG1_OS (0<<4) +#define AW8624X_BIT_DETCFG1_PRCT_MODE_MASK (~(1<<3)) +#define AW8624X_BIT_DETCFG1_PRCT_MODE_INVALID (0<<3) +#define AW8624X_BIT_DETCFG1_PRCT_MODE_VALID (1<<3) +#define AW8624X_BIT_DETCFG1_CLK_ADC_MASK (~(7<<0)) +#define AW8624X_BIT_DETCFG1_CLK_ADC_12M (0<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_6M (1<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_3M (2<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_1M5 (3<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_M75 (4<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_M37 (5<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_M18 (6<<0) +#define AW8624X_BIT_DETCFG1_CLK_ADC_M09 (7<<0) + +/* DETCFG2: reg 0x52 RW */ +#define AW8624X_BIT_DETCFG2_VBAT_GO_MASK (~(1<<1)) +#define AW8624X_BIT_DETCFG2_VABT_GO_ON (1<<1) +#define AW8624X_BIT_DETCFG2_DIAG_GO_MASK (~(1<<0)) +#define AW8624X_BIT_DETCFG2_DIAG_GO_ON (1<<0) + +/* TRIMCFG1: reg:0x59 RW */ +#define AW8624X_BIT_TRIMCFG1_RL_TRIM_SRC_MASK (~(1<<6)) +#define AW8624X_BIT_TRIMCFG1_RL_TRIM_SRC_REG (1<<6) +#define AW8624X_BIT_TRIMCFG1_RL_TRIM_SRC_EFUSE (0<<6) +#define AW8624X_BIT_TRIMCFG1_TRIM_RL_MASK (~(63<<0)) + +/* TRIMCFG3: reg:0x5A RW */ +#define AW8624X_BIT_TRIMCFG3_OSC_TRIM_SRC_MASK (~(1<<7)) +#define AW8624X_BIT_TRIMCFG3_OSC_TRIM_SRC_REG (1<<7) +#define AW8624X_BIT_TRIMCFG3_OSC_TRIM_SRC_EFUSE (0<<7) +#define AW8624X_BIT_TRIMCFG3_TRIM_LRA_MASK (~(0x7F<<0)) + +/* EFRD9: reg:0x64 RO */ + +/* ANACFG8: reg:0x77 RW */ +#define AW8624X_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK (~(3<<6)) +#define AW8624X_BIT_ANACFG8_TRTF_CTRL_HDRV (3<<6) + +#endif