From 84b3b1daa05b465d890812576f82d8167503a9ce Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sun, 8 Sep 2024 22:12:25 +0800 Subject: [PATCH] ff/aw86225: implement aw86225 vibrator driver base on ff Signed-off-by: dongjiuzhu1 --- drivers/input/CMakeLists.txt | 4 + drivers/input/Kconfig | 17 + drivers/input/Make.defs | 4 + drivers/input/aw86225.c | 2520 ++++++++++++++++++++++++++++++ drivers/input/aw86225_internal.h | 293 ++++ drivers/input/aw86225_reg.h | 707 +++++++++ include/nuttx/input/aw86225.h | 161 ++ 7 files changed, 3706 insertions(+) create mode 100644 drivers/input/aw86225.c create mode 100644 drivers/input/aw86225_internal.h create mode 100644 drivers/input/aw86225_reg.h create mode 100644 include/nuttx/input/aw86225.h diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index ade587aa55..4beb158f01 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -31,6 +31,10 @@ if(CONFIG_INPUT) list(APPEND SRCS ff_upper.c) endif() + if(CONFIG_FF_AW86225) + list(APPEND SRCS aw86225.c) + endif() + if(CONFIG_INPUT_MOUSE) list(APPEND SRCS mouse_upper.c) endif() diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 81667f13e7..3d59d24a3d 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -32,6 +32,23 @@ config INPUT_FF Enable support for force feedback devices. The doc link: https://www.kernel.org/doc/html/v4.19/input/ff.html. +if INPUT_FF + +config FF_AW86225 + bool "Enable aw86225 driver" + default n + ---help--- + Enable aw86225 haptic controller chip. + +config FF_RTP_FILE_PATH + string "Path of aw86225 rtp file" + default "/etc" + depends on FF_AW86225 + ---help--- + File path depend on the opening of FF_AW86225. + +endif # INPUT_FF + config INPUT_MOUSE bool default n diff --git a/drivers/input/Make.defs b/drivers/input/Make.defs index 7be5294633..980eb7c022 100644 --- a/drivers/input/Make.defs +++ b/drivers/input/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_INPUT_FF),y) CSRCS += ff_upper.c endif +ifeq ($(CONFIG_FF_AW86225),y) + CSRCS += aw86225.c +endif + ifeq ($(CONFIG_INPUT_MOUSE),y) CSRCS += mouse_upper.c endif diff --git a/drivers/input/aw86225.c b/drivers/input/aw86225.c new file mode 100644 index 0000000000..788a5d50b3 --- /dev/null +++ b/drivers/input/aw86225.c @@ -0,0 +1,2520 @@ +/**************************************************************************** + * drivers/input/aw86225.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aw86225_reg.h" +#include "aw86225_internal.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void aw86225_long_vibrate_work_routine(FAR void *arg); +static void aw86225_ram_work_routine(FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static FAR const char *g_aw86225_ram_name = "aw86225_haptic.bin"; +static FAR const char g_aw86225_rtp_name[][AW86225_RTP_NAME_MAX] = +{ + {"door_open_RTP.bin"}, + {"Guitar_RTP.bin"}, + {"aw86225_osc_rtp_24K_5s.bin"}, + {"AcousticGuitar_RTP.bin"}, + {"Carousel_RTP.bin"}, + {"Celesta_RTP.bin"}, + {"Childhood_RTP.bin"}, + {"Country_RTP.bin"}, + {"Cowboy_RTP.bin"}, + {"Echo_RTP.bin"}, + {"Fairyland_RTP.bin"}, + {"Fantasy_RTP.bin"}, + {"Field_Trip_RTP.bin"}, + {"Glee_RTP.bin"}, + {"Glockenspiel_RTP.bin"}, + {"Ice_Latte_RTP.bin"}, + {"Kung_Fu_RTP.bin"}, + {"Leisure_RTP.bin"}, + {"Lollipop_RTP.bin"}, + {"MiMix2_RTP.bin"}, + {"Mi_RTP.bin"}, + {"MiHouse_RTP.bin"}, + {"MiJazz_RTP.bin"}, + {"MiRemix_RTP.bin"}, + {"Mountain_Spring_RTP.bin"}, + {"Orange_RTP.bin"}, + {"WindChime_RTP.bin"}, + {"Space_Age_RTP.bin"}, + {"ToyRobot_RTP.bin"}, + {"Vigor_RTP.bin"}, + {"Bottle_RTP.bin"}, + {"Bubble_RTP.bin"}, + {"Bullfrog_RTP.bin"}, + {"Burst_RTP.bin"}, + {"Chirp_RTP.bin"}, + {"Clank_RTP.bin"}, + {"Crystal_RTP.bin"}, + {"FadeIn_RTP.bin"}, + {"FadeOut_RTP.bin"}, + {"Flute_RTP.bin"}, + {"Fresh_RTP.bin"}, + {"Frog_RTP.bin"}, + {"Guitar_RTP.bin"}, + {"Harp_RTP.bin"}, + {"IncomingMessage_RTP.bin"}, + {"MessageSent_RTP.bin"}, + {"Moment_RTP.bin"}, + {"NotificationXylophone_RTP.bin"}, + {"Potion_RTP.bin"}, + {"Radar_RTP.bin"}, + {"Spring_RTP.bin"}, + {"Swoosh_RTP.bin"}, + {"Gesture_UpSlide_RTP.bin"}, + {"Gesture_UpHold_RTP.bin"}, + {"Charge_Wire_RTP.bin"}, + {"Charge_Wireless_RTP.bin"}, + {"Unlock_Failed_RTP.bin"}, + {"FOD_Motion1_RTP.bin"}, + {"FOD_Motion2_RTP.bin"}, + {"FOD_Motion3_RTP.bin"}, + {"FOD_Motion4_RTP.bin"}, + {"FaceID_Wrong1_RTP.bin"}, + {"FaceID_Wrong2_RTP.bin"}, + {"uninstall_animation_rtp.bin"}, + {"uninstall_dialog_rtp.bin"}, + {"screenshot_rtp.bin"}, + {"lockscreen_camera_entry_rtp.bin"}, + {"launcher_edit_rtp.bin"}, + {"launcher_icon_selection_rtp.bin"}, + {"taskcard_remove_rtp.bin"}, + {"task_cleanall_rtp.bin"}, + {"new_iconfolder_rtp.bin"}, + {"notification_remove_rtp.bin"}, + {"notification_cleanall_rtp.bin"}, + {"notification_setting_rtp.bin"}, + {"game_turbo_rtp.bin"}, + {"NFC_card_rtp.bin"}, + {"wakeup_voice_assistant_rtp.bin"}, + {"NFC_card_slow_rtp.bin"}, + {"POCO_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"offline_countdown_RTP.bin"}, + {"scene_bomb_injury_RTP.bin"}, + {"scene_bomb_RTP.bin"}, + {"door_open_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"scene_step_RTP.bin"}, + {"crawl_RTP.bin"}, + {"scope_on_RTP.bin"}, + {"scope_off_RTP.bin"}, + {"magazine_quick_RTP.bin"}, + {"grenade_RTP.bin"}, + {"scene_getshot_RTP.bin"}, + {"grenade_explosion_RTP.bin"}, + {"punch_RTP.bin"}, + {"pan_RTP.bin"}, + {"bandage_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"scene_jump_RTP.bin"}, + {"vehicle_plane_RTP.bin"}, + {"scene_openparachute_RTP.bin"}, + {"scene_closeparachute_RTP.bin"}, + {"vehicle_collision_RTP.bin"}, + {"vehicle_buggy_RTP.bin"}, + {"vehicle_dacia_RTP.bin"}, + {"vehicle_moto_RTP.bin"}, + {"firearms_akm_RTP.bin"}, + {"firearms_m16a4_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"firearms_awm_RTP.bin"}, + {"firearms_mini14_RTP.bin"}, + {"firearms_vss_RTP.bin"}, + {"firearms_qbz_RTP.bin"}, + {"firearms_ump9_RTP.bin"}, + {"firearms_dp28_RTP.bin"}, + {"firearms_s1897_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"firearms_p18c_RTP.bin"}, + {"aw86225_rtp.bin"}, + {"aw86225_rtp.bin"}, + {"CFM_KillOne_RTP.bin"}, + {"CFM_Headshot_RTP.bin"}, + {"CFM_MultiKill_RTP.bin"}, + {"CFM_KillOne_Strong_RTP.bin"}, + {"CFM_Headshot_Strong_RTP.bin"}, + {"CFM_MultiKill_Strong_RTP.bin"}, + {"CFM_Weapon_Grenade_Explode_RTP.bin"}, + {"CFM_Weapon_Grenade_KillOne_RTP.bin"}, + {"CFM_ImpactFlesh_Normal_RTP.bin"}, + {"CFM_Weapon_C4_Installed_RTP.bin"}, + {"CFM_Hero_Appear_RTP.bin"}, + {"CFM_UI_Reward_OpenBox_RTP.bin"}, + {"CFM_UI_Reward_Task_RTP.bin"}, + {"CFM_Weapon_BLT_Shoot_RTP.bin"}, + {"Atlantis_RTP.bin"}, + {"DigitalUniverse_RTP.bin"}, + {"Reveries_RTP.bin"}, + {"FOD_Motion_Triang_RTP.bin"}, + {"FOD_Motion_Flare_RTP.bin"}, + {"FOD_Motion_Ripple_RTP.bin"}, + {"FOD_Motion_Spiral_RTP.bin"}, + {"gamebox_launch_rtp.bin"}, + {"Gesture_Back_Pull_RTP.bin"}, + {"Gesture_Back_Release_RTP.bin"}, + {"alert_rtp.bin"}, + {"feedback_negative_light_rtp.bin"}, + {"feedback_neutral_rtp.bin"}, + {"feedback_positive_rtp.bin"}, + {"fingerprint_record_rtp.bin"}, + {"lockdown_rtp.bin"}, + {"sliding_damping_rtp.bin"}, + {"todo_alldone_rtp.bin"}, + {"uninstall_animation_icon_rtp.bin"}, + {"signal_button_highlight_rtp.bin"}, + {"signal_button_negative_rtp.bin"}, + {"signal_button_rtp.bin"}, + {"signal_clock_high_rtp.bin"}, + {"signal_clock_rtp.bin"}, + {"signal_clock_unit_rtp.bin"}, + {"signal_inputbox_rtp.bin"}, + {"signal_key_high_rtp.bin"}, + {"signal_key_unit_rtp.bin"}, + {"signal_list_highlight_rtp.bin"}, + {"signal_list_rtp.bin"}, + {"signal_picker_rtp.bin"}, + {"signal_popup_rtp.bin"}, + {"signal_seekbar_rtp.bin"}, + {"signal_switch_rtp.bin"}, + {"signal_tab_rtp.bin"}, + {"signal_text_rtp.bin"}, + {"signal_transition_light_rtp.bin"}, + {"signal_transition_rtp.bin"}, + {"haptics_video_rtp.bin"}, +}; + +static const unsigned char g_aw86225_reg_access[AW86225_REG_MAX] = +{ + [AW86225_REG_ID] = REG_RD_ACCESS, + [AW86225_REG_SYSST] = REG_RD_ACCESS, + [AW86225_REG_SYSINT] = REG_RD_ACCESS, + [AW86225_REG_SYSINTM] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSST2] = REG_RD_ACCESS, + [AW86225_REG_SYSER] = REG_RD_ACCESS, + [AW86225_REG_PLAYCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PLAYCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PLAYCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG5] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG6] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG7] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG8] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG9] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG10] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG11] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG12] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG13] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_WAVCFG14] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG5] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG6] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG7] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG8] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG9] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG10] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG11] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG12] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTCFG13] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_CONTRD14] = REG_RD_ACCESS, + [AW86225_REG_CONTRD15] = REG_RD_ACCESS, + [AW86225_REG_CONTRD16] = REG_RD_ACCESS, + [AW86225_REG_CONTRD17] = REG_RD_ACCESS, + [AW86225_REG_CONTRD18] = REG_RD_ACCESS, + [AW86225_REG_CONTRD19] = REG_RD_ACCESS, + [AW86225_REG_CONTRD20] = REG_RD_ACCESS, + [AW86225_REG_CONTRD21] = REG_RD_ACCESS, + [AW86225_REG_RTPCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RTPCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RTPCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RTPCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RTPCFG5] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RTPDATA] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG5] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG6] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG7] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRGCFG8] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_GLBCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_GLBCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_GLBCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_GLBCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_GLBRD5] = REG_RD_ACCESS, + [AW86225_REG_RAMADDRH] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RAMADDRL] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_RAMDATA] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL5] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL6] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_SYSCTRL7] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PWMCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PWMCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PWMCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_PWMCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_DETCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_DETCFG2] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_DET_RL] = REG_RD_ACCESS, + [AW86225_REG_DET_OS] = REG_RD_ACCESS, + [AW86225_REG_DET_VBAT] = REG_RD_ACCESS, + [AW86225_REG_DET_TEST] = REG_RD_ACCESS, + [AW86225_REG_DET_LO] = REG_RD_ACCESS, + [AW86225_REG_TRIMCFG1] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRIMCFG3] = REG_RD_ACCESS | REG_WR_ACCESS, + [AW86225_REG_TRIMCFG4] = REG_RD_ACCESS | REG_WR_ACCESS, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int aw86225_i2c_write_cnt(FAR struct aw86225 *aw86225, + uint8_t reg_addr, + FAR const uint8_t *reg_data, uint32_t cnt) +{ + struct i2c_msg_s msg[2]; + int ret = -1; + int retries = 0; + + msg[0].frequency = aw86225->freq; + msg[0].addr = aw86225->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®_addr; + msg[0].length = 1; + + msg[1].frequency = aw86225->freq; + msg[1].addr = aw86225->addr; + msg[1].flags = I2C_M_NOSTART; + msg[1].buffer = (uint8_t *)reg_data; + msg[1].length = cnt; + + while (retries < AW86225_I2C_RETRIES) + { + ret = I2C_TRANSFER(aw86225->i2c, msg, 2); + if (ret < 0) + { + ierr("ERROR: I2C_TRANSFER failed: %d\n", ret); + } + else + { + break; + } + + retries++; + } + + return ret; +} + +static int aw86225_i2c_write(FAR struct aw86225 *aw86225, + uint8_t reg_addr, uint8_t reg_data) +{ + return aw86225_i2c_write_cnt(aw86225, reg_addr, ®_data, 1); +} + +static int aw86225_i2c_read_cnt(FAR struct aw86225 *aw86225, + uint8_t reg_addr, + FAR const uint8_t *reg_data, + uint32_t cnt) +{ + struct i2c_msg_s msg[2]; + int ret = -1; + int retries = 0; + + msg[0].frequency = aw86225->freq; + msg[0].addr = aw86225->addr; + msg[0].flags = 0; + msg[0].buffer = ®_addr; + msg[0].length = 1; + + msg[1].frequency = aw86225->freq; + msg[1].addr = aw86225->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = (uint8_t *)reg_data; + msg[1].length = cnt; + + while (retries < AW86225_I2C_RETRIES) + { + ret = I2C_TRANSFER(aw86225->i2c, msg, 2); + if (ret < 0) + { + ierr("ERROR: I2C_TRANSFER failed: %d\n", ret); + } + else + { + break; + } + + retries++; + } + + return ret; +} + +static int aw86225_i2c_read(FAR struct aw86225 *aw86225, uint8_t reg_addr, + FAR uint8_t *reg_data) +{ + return aw86225_i2c_read_cnt(aw86225, reg_addr, reg_data, 1); +} + +static int aw86225_i2c_writes(FAR struct aw86225 *aw86225, + unsigned char reg_addr, + FAR unsigned char *buf, + unsigned int len) +{ + return aw86225_i2c_write_cnt(aw86225, reg_addr, buf, len); +} + +static int aw86225_i2c_write_bits(FAR struct aw86225 *aw86225, + unsigned char reg_addr, unsigned int mask, + unsigned char reg_data) +{ + int ret; + uint8_t reg_val = 0; + + ret = aw86225_i2c_read(aw86225, reg_addr, ®_val); + if (ret < 0) + { + ierr("i2c read error, ret: %d\n", ret); + return ret; + } + + reg_val &= mask; + reg_val |= reg_data; + ret = aw86225_i2c_write(aw86225, reg_addr, reg_val); + if (ret < 0) + { + ierr("i2c write error, ret: %d\n", ret); + } + + return ret; +} + +static int aw86225_request_firmware(FAR struct aw86225_firmware *fw, + FAR const char *filename) +{ + char file_path[PATH_MAX]; + struct file file; + size_t file_size; + int ret; + + snprintf(file_path, sizeof(file_path), "%s/%s", CONFIG_FF_RTP_FILE_PATH, + filename); + ret = file_open(&file, file_path, O_RDONLY); + if (ret < 0) + { + ierr("open file failed"); + return ret; + } + + file_size = file_seek(&file, 0, SEEK_END); + file_seek(&file, 0, SEEK_SET); + + fw->data = kmm_malloc(file_size); + if (fw->data != NULL) + { + fw->size = file_read(&file, (void *)fw->data, file_size); + } + + file_close(&file); + + if (fw->data == NULL || fw->size <= 0) + { + kmm_free((void *)fw->data); + return -1; + } + + return 0; +} + +static void aw86225_release_firmware(FAR struct aw86225_firmware *fw) +{ + kmm_free((void *)fw->data); + fw->data = NULL; + fw->size = 0; +} + +static uint8_t aw86225_haptic_rtp_get_fifo_afs(FAR struct aw86225 *aw86225) +{ + uint8_t reg_val = 0; + + aw86225_i2c_read(aw86225, AW86225_REG_SYSST, ®_val); + reg_val &= AW86225_BIT_SYSST_FF_AFS; + return reg_val >> 3; +} + +static void aw86225_haptic_set_rtp_aei(FAR struct aw86225 *aw86225, + bool flag) +{ + if (flag) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, + AW86225_BIT_SYSINTM_FF_AEM_MASK, + AW86225_BIT_SYSINTM_FF_AEM_ON); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, + AW86225_BIT_SYSINTM_FF_AEM_MASK, + AW86225_BIT_SYSINTM_FF_AEM_OFF); + } +} + +static void aw86225_haptic_upload_lra(FAR struct aw86225 *aw86225, + unsigned int flag) +{ + switch (flag) + { + case AW86225_WRITE_ZERO: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_TRIMCFG3, + AW86225_BIT_TRIMCFG3_TRIM_LRA_MASK, + 0x00); + break; + } + + case AW86225_F0_CALI: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_TRIMCFG3, + AW86225_BIT_TRIMCFG3_TRIM_LRA_MASK, + (char)aw86225->f0_cali_data); + break; + } + + case AW86225_OSC_CALI: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_TRIMCFG3, + AW86225_BIT_TRIMCFG3_TRIM_LRA_MASK, + (char)aw86225->osc_cali_data); + break; + } + + default: + ierr("%s write trim_lra error !\n", __func__); + break; + } +} + +static void aw86225_sram_size(FAR struct aw86225 *aw86225, + int size_flag) +{ + if (size_flag == AW86225_HAPTIC_SRAM_2K) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_DIS); + } + else if (size_flag == AW86225_HAPTIC_SRAM_1K) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_DIS); + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + } + else if (size_flag == AW86225_HAPTIC_SRAM_3K) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_EN); + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_MASK, + AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_EN); + } +} + +static void aw86225_haptic_stop(FAR struct aw86225 *aw86225) +{ + unsigned char cnt = 40; + unsigned char reg_val = 0; + bool force_flag = true; + + aw86225->play_mode = AW86225_HAPTIC_STANDBY_MODE; + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG4, 0x02); + while (cnt) + { + aw86225_i2c_read(aw86225, AW86225_REG_GLBRD5, ®_val); + if ((reg_val & 0x0f) == 0x00 || (reg_val & 0x0f) == 0x0a) + { + cnt = 0; + force_flag = false; + iinfo("entered standby! glb_state=0x%02X\n", reg_val); + } + else + { + cnt--; + iinfo("wait for standby, glb_state=0x%02X\n", reg_val); + } + + usleep(2000); + } + + if (force_flag) + { + iinfo("%s force to enter standby mode!\n", __func__); + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_STANDBY_MASK, + AW86225_BIT_SYSCTRL2_STANDBY_ON); + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_STANDBY_MASK, + AW86225_BIT_SYSCTRL2_STANDBY_OFF); + } +} + +static void aw86225_haptic_raminit(FAR struct aw86225 *aw86225, + bool flag) +{ + if (flag) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL1, + AW86225_BIT_SYSCTRL1_RAMINIT_MASK, + AW86225_BIT_SYSCTRL1_RAMINIT_ON); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL1, + AW86225_BIT_SYSCTRL1_RAMINIT_MASK, + AW86225_BIT_SYSCTRL1_RAMINIT_OFF); + } +} + +static void aw86225_haptic_get_vbat(FAR struct aw86225 *aw86225) +{ + unsigned char reg_val = 0; + unsigned int vbat_code = 0; + + /* unsigned int cont = 2000; */ + + aw86225_haptic_stop(aw86225); + aw86225_haptic_raminit(aw86225, true); + aw86225_i2c_write_bits(aw86225, AW86225_REG_DETCFG2, + AW86225_BIT_DETCFG2_VBAT_GO_MASK, + AW86225_BIT_DETCFG2_VABT_GO_ON); + usleep(22500); + aw86225_i2c_read(aw86225, AW86225_REG_DET_VBAT, ®_val); + vbat_code = (vbat_code | reg_val) << 2; + aw86225_i2c_read(aw86225, AW86225_REG_DET_LO, ®_val); + vbat_code = vbat_code | ((reg_val & 0x30) >> 4); + aw86225->vbat = 6100 * vbat_code / 1024; + if (aw86225->vbat > AW86225_VBAT_MAX) + { + aw86225->vbat = AW86225_VBAT_MAX; + } + + if (aw86225->vbat < AW86225_VBAT_MIN) + { + aw86225->vbat = AW86225_VBAT_MIN; + } + + iinfo("%s aw86225->vbat=%dmV, vbat_code=0x%02X\n", __func__, + aw86225->vbat, vbat_code); + aw86225_haptic_raminit(aw86225, false); +} + +static void aw86225_interrupt_clear(FAR struct aw86225 *aw86225) +{ + unsigned char reg_val = 0; + aw86225_i2c_read(aw86225, AW86225_REG_SYSINT, ®_val); +} + +static int aw86225_haptic_set_gain(FAR struct aw86225 *aw86225, + unsigned char gain) +{ + unsigned char comp_gain = 0; + if (aw86225->ram_vbat_compensate == AW86225_HAPTIC_RAM_VBAT_COMP_ENABLE) + { + aw86225_haptic_get_vbat(aw86225); + comp_gain = aw86225->gain * AW86225_VBAT_REFER / aw86225->vbat; + if (comp_gain > (128 * AW86225_VBAT_REFER / AW86225_VBAT_MIN)) + { + comp_gain = 128 * AW86225_VBAT_REFER / AW86225_VBAT_MIN; + } + + iinfo("%s: enable vbat comp, level = %x comp level = %x", __func__, + gain, comp_gain); + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG2, comp_gain); + } + else + { + iinfo("%s: disable compsensation, vbat=%d, vbat_min=%d, vbat_ref=%d", + __func__, aw86225->vbat, AW86225_VBAT_MIN, AW86225_VBAT_REFER); + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG2, gain); + } + + return 0; +} + +static int aw86225_haptic_ram_vbat_compensate(FAR struct aw86225 *aw86225, + bool flag) +{ + if (flag) + { + aw86225->ram_vbat_compensate = AW86225_HAPTIC_RAM_VBAT_COMP_ENABLE; + } + else + { + aw86225->ram_vbat_compensate = AW86225_HAPTIC_RAM_VBAT_COMP_DISABLE; + } + + return 0; +} + +static int aw86225_haptic_play_mode(FAR struct aw86225 *aw86225, + unsigned char play_mode) +{ + switch (play_mode) + { + case AW86225_HAPTIC_STANDBY_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_STANDBY_MODE; + aw86225_haptic_stop(aw86225); + break; + } + + case AW86225_HAPTIC_RAM_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_RAM_MODE; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW86225_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + } + + case AW86225_HAPTIC_RAM_LOOP_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_RAM_LOOP_MODE; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW86225_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + } + + case AW86225_HAPTIC_RTP_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_RTP_MODE; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW86225_BIT_PLAYCFG3_PLAY_MODE_RTP); + break; + } + + case AW86225_HAPTIC_TRIG_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_TRIG_MODE; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW86225_BIT_PLAYCFG3_PLAY_MODE_RAM); + break; + } + + case AW86225_HAPTIC_CONT_MODE: + { + aw86225->play_mode = AW86225_HAPTIC_CONT_MODE; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK, + AW86225_BIT_PLAYCFG3_PLAY_MODE_CONT); + break; + } + + default: + ierr("%s: play mode %d error", __func__, play_mode); + break; + } + + return 0; +} + +static int aw86225_haptic_play_go(FAR struct aw86225 *aw86225, bool flag) +{ + unsigned char reg_val = 0; + + if (flag == true) + { + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG4, 0x01); + usleep(2000); + } + else + { + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG4, 0x02); + } + + aw86225_i2c_read(aw86225, AW86225_REG_GLBRD5, ®_val); + return 0; +} + +static int aw86225_haptic_set_wav_seq(FAR struct aw86225 *aw86225, + unsigned char wav, unsigned char seq) +{ + aw86225_i2c_write(aw86225, AW86225_REG_WAVCFG1 + wav, seq); + return 0; +} + +static int aw86225_haptic_set_wav_loop(FAR struct aw86225 *aw86225, + unsigned char wav, unsigned char loop) +{ + unsigned char tmp = 0; + + if (wav % 2) + { + tmp = loop << 0; + aw86225_i2c_write_bits(aw86225, AW86225_REG_WAVCFG9 + (wav / 2), + AW86225_BIT_WAVLOOP_SEQ_EVEN_MASK, tmp); + } + else + { + tmp = loop << 4; + aw86225_i2c_write_bits(aw86225, AW86225_REG_WAVCFG9 + (wav / 2), + AW86225_BIT_WAVLOOP_SEQ_ODD_MASK, tmp); + } + + return 0; +} + +static int aw86225_haptic_read_lra_f0(FAR struct aw86225 *aw86225) +{ + unsigned char reg_val = 0; + unsigned int f0_reg = 0; + unsigned long f0_tmp = 0; + + /* F_LRA_F0_H */ + + aw86225_i2c_read(aw86225, AW86225_REG_CONTRD14, ®_val); + f0_reg = (f0_reg | reg_val) << 8; + + /* F_LRA_F0_L */ + + aw86225_i2c_read(aw86225, AW86225_REG_CONTRD15, ®_val); + f0_reg |= (reg_val << 0); + if (!f0_reg) + { + ierr("%s didn't get cont f0 because f0_reg value is 0!\n", __func__); + aw86225->f0 = aw86225->config->f0_ref; + return -1; + } + else + { + f0_tmp = 384000 * 10 / f0_reg; + aw86225->f0 = (unsigned int)f0_tmp; + iinfo("%s lra_f0=%d\n", __func__, aw86225->f0); + } + + return 0; +} + +static int aw86225_haptic_read_cont_f0(FAR struct aw86225 *aw86225) +{ + unsigned char reg_val = 0; + unsigned int f0_reg = 0; + unsigned long f0_tmp = 0; + + aw86225_i2c_read(aw86225, AW86225_REG_CONTRD16, ®_val); + f0_reg = (f0_reg | reg_val) << 8; + aw86225_i2c_read(aw86225, AW86225_REG_CONTRD17, ®_val); + f0_reg |= (reg_val << 0); + if (!f0_reg) + { + ierr("%s didn't get cont f0 because f0_reg value is 0!\n", __func__); + aw86225->cont_f0 = aw86225->config->f0_ref; + return -1; + } + else + { + f0_tmp = 384000 * 10 / f0_reg; + aw86225->cont_f0 = (unsigned int)f0_tmp; + iinfo("%s cont_f0=%d\n", __func__, aw86225->cont_f0); + } + + return 0; +} + +static int aw86225_haptic_cont_get_f0(FAR struct aw86225 *aw86225) +{ + int ret = 0; + unsigned char reg_val = 0; + unsigned int cnt = 200; + bool get_f0_flag = false; + unsigned char brk_en_temp = 0; + + aw86225->f0 = aw86225->config->f0_ref; + + /* enter standby mode */ + + aw86225_haptic_stop(aw86225); + + /* f0 calibrate work mode */ + + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_CONT_MODE); + + /* enable f0 detect */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG1, + AW86225_BIT_CONTCFG1_EN_F0_DET_MASK, + AW86225_BIT_CONTCFG1_F0_DET_ENABLE); + + /* cont config */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG6, + AW86225_BIT_CONTCFG6_TRACK_EN_MASK, + AW86225_BIT_CONTCFG6_TRACK_ENABLE); + + /* enable auto brake */ + + aw86225_i2c_read(aw86225, AW86225_REG_PLAYCFG3, ®_val); + brk_en_temp = 0x04 & reg_val; + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_BRK_EN_MASK, + AW86225_BIT_PLAYCFG3_BRK_ENABLE); + + /* f0 driver level */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG6, + AW86225_BIT_CONTCFG6_DRV1_LVL_MASK, + aw86225->config->cont_drv1_lvl_dt); + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG7, + aw86225->config->cont_drv2_lvl_dt); + + /* DRV1_TIME */ + + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG8, + aw86225->config->cont_drv1_time_dt); + + /* DRV2_TIME */ + + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG9, + aw86225->config->cont_drv2_time_dt); + + /* TRACK_MARGIN */ + + if (!aw86225->config->cont_track_margin) + { + ierr("%s aw86225->config->cont_track_margin = 0!\n", __func__); + } + else + { + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG11, + (unsigned char)aw86225->config->cont_track_margin); + } + + /* cont play go */ + + aw86225_haptic_play_go(aw86225, true); + + /* 300ms */ + + while (cnt) + { + aw86225_i2c_read(aw86225, AW86225_REG_GLBRD5, ®_val); + if ((reg_val & 0x0f) == 0x00) + { + cnt = 0; + get_f0_flag = true; + iinfo("%s entered standby mode! glb_state=0x%02X\n", + __func__, reg_val); + } + else + { + cnt--; + iinfo("%s waitting for standby, glb_state=0x%02X\n", + __func__, reg_val); + } + + usleep(10000); + } + + if (get_f0_flag) + { + aw86225_haptic_read_lra_f0(aw86225); + aw86225_haptic_read_cont_f0(aw86225); + } + else + { + ierr("%s enter standby mode failed, stop reading f0!\n", __func__); + } + + /* restore default config */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG1, + AW86225_BIT_CONTCFG1_EN_F0_DET_MASK, + AW86225_BIT_CONTCFG1_F0_DET_DISABLE); + + /* recover auto break config */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_BRK_EN_MASK, + brk_en_temp); + + return ret; +} + +static int aw86225_haptic_rtp_init(FAR struct aw86225 *aw86225) +{ + unsigned int buf_len = 0; + unsigned char glb_state_val = 0; + + aw86225->rtp_cnt = 0; + nxmutex_lock(&aw86225->rtp_lock); + while ((!aw86225_haptic_rtp_get_fifo_afs(aw86225)) + && (aw86225->play_mode == AW86225_HAPTIC_RTP_MODE) + && !atomic_load(&aw86225->exit_in_rtp_loop)) + { + if (!aw86225->rtp_container) + { + ierr("%s:aw86225->rtp_container is null\n", __func__); + break; + } + + if (aw86225->rtp_cnt < aw86225->ram.base_addr) + { + if ((aw86225->rtp_container->len - aw86225->rtp_cnt) < + aw86225->ram.base_addr) + { + buf_len = aw86225->rtp_container->len - aw86225->rtp_cnt; + } + else + { + buf_len = aw86225->ram.base_addr; + } + } + else if ((aw86225->rtp_container->len - aw86225->rtp_cnt) < + (aw86225->ram.base_addr >> 2)) + { + buf_len = aw86225->rtp_container->len - aw86225->rtp_cnt; + } + else + { + buf_len = aw86225->ram.base_addr >> 2; + } + + aw86225_i2c_writes(aw86225, AW86225_REG_RTPDATA, + &aw86225->rtp_container->data[aw86225->rtp_cnt], + buf_len); + aw86225->rtp_cnt += buf_len; + aw86225_i2c_read(aw86225, AW86225_REG_GLBRD5, &glb_state_val); + if ((aw86225->rtp_cnt == aw86225->rtp_container->len) + || ((glb_state_val & 0x0f) == 0x00)) + { + if (aw86225->rtp_cnt == aw86225->rtp_container->len) + { + iinfo("%s: rtp load completely! glb_state_val=0x%02x \ + aw86225->rtp_cnt=%d\n", \ + __func__, glb_state_val, aw86225->rtp_cnt); + } + else + { + iinfo("%s rtp load failed!! glb_state_val=0x%02x \ + aw86225->rtp_cnt=%d\n", __func__, glb_state_val, \ + aw86225->rtp_cnt); + aw86225->rtp_cnt = 0; + nxmutex_unlock(&aw86225->rtp_lock); + return 0; + } + } + } + + nxmutex_unlock(&aw86225->rtp_lock); + if (aw86225->play_mode == AW86225_HAPTIC_RTP_MODE + && !atomic_load(&aw86225->exit_in_rtp_loop)) + { + aw86225_haptic_set_rtp_aei(aw86225, true); + } + + iinfo("%s exit\n", __func__); + return 0; +} + +static int aw86225_haptic_set_repeat_wav_seq(FAR struct aw86225 *aw86225, + unsigned char seq) +{ + aw86225_haptic_set_wav_seq(aw86225, 0x00, seq); + aw86225_haptic_set_wav_loop(aw86225, 0x00, + AW86225_BIT_WAVLOOP_INIFINITELY); + return 0; +} + +static void aw86225_haptic_set_pwm(FAR struct aw86225 *aw86225, + unsigned char mode) +{ + switch (mode) + { + case AW86225_PWM_48K: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW86225_BIT_SYSCTRL2_RATE_48K); + break; + } + + case AW86225_PWM_24K: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW86225_BIT_SYSCTRL2_RATE_24K); + break; + } + + case AW86225_PWM_12K: + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_WAVDAT_MODE_MASK, + AW86225_BIT_SYSCTRL2_RATE_12K); + break; + } + + default: + break; + } +} + +static int16_t +aw86225_haptic_effect_strength(FAR struct aw86225 *aw86225) +{ + iinfo("aw86225->play.vmax_mv =0x%x\n", aw86225->play.vmax_mv); + + if (aw86225->play.vmax_mv >= 0x7fff) + { + aw86225->level = 0x80; + } + else if (aw86225->play.vmax_mv <= 0x3fff) + { + aw86225->level = 0x1e; + } + else + { + aw86225->level = (aw86225->play.vmax_mv - 16383) / 128; + } + + if (aw86225->level < 0x1e) + { + aw86225->level = 0x1e; + } + + iinfo("%s: aw86225->level =0x%x\n", __func__, aw86225->level); + return 0; +} + +static void aw86225_rtp_work_routine(FAR void *arg) +{ + FAR struct aw86225 *aw86225 = arg; + struct aw86225_firmware rtp_file; + int ret = -1; + unsigned int cnt = 200; + unsigned char reg_val = 0; + bool rtp_work_flag = false; + + iinfo("%s enter\n", __func__); + + if ((aw86225->effect_id < aw86225->config->effect_id_boundary) && + (aw86225->effect_id > aw86225->config->effect_max)) + { + return; + } + + iinfo("%s: effect_id =%d state = %d\n", __func__, aw86225->effect_id, + aw86225->state); + nxmutex_lock(&aw86225->lock); + aw86225_haptic_upload_lra(aw86225, AW86225_OSC_CALI); + aw86225_haptic_set_rtp_aei(aw86225, false); + aw86225_interrupt_clear(aw86225); + + /* wait for irq to exit */ + + atomic_store(&aw86225->exit_in_rtp_loop, 1); + while (atomic_load(&aw86225->is_in_rtp_loop)) + { + iinfo("%s: goint to waiting irq exit\n", __func__); + + ret = nxsem_wait(&aw86225->wait_q); + + if (ret == -ERESTART) + { + atomic_store(&aw86225->exit_in_rtp_loop, 0); + nxsem_post(&aw86225->stop_wait_q); + nxmutex_unlock(&aw86225->lock); + ierr("%s: wake up by signal return erro\n", __func__); + return; + } + } + + atomic_store(&aw86225->exit_in_rtp_loop, 0); + nxsem_post(&aw86225->stop_wait_q); + aw86225_haptic_stop(aw86225); + + if (aw86225->state) + { + aw86225->wk_lock_flag = 1; + aw86225_haptic_effect_strength(aw86225); + aw86225->rtp_file_num = aw86225->effect_id - + aw86225->config->effect_id_boundary; + iinfo("aw86225->rtp_file_num =%d\n", aw86225->rtp_file_num); + if (aw86225->rtp_file_num < 0) + { + aw86225->rtp_file_num = 0; + } + + if (aw86225->rtp_file_num > + ((sizeof(g_aw86225_rtp_name) / AW86225_RTP_NAME_MAX) - 1)) + { + aw86225->rtp_file_num = + (sizeof(g_aw86225_rtp_name) / AW86225_RTP_NAME_MAX) - 1; + } + + /* fw loaded */ + + ret = aw86225_request_firmware(&rtp_file, + g_aw86225_rtp_name[aw86225->rtp_file_num]); + if (ret < 0) + { + ierr("%s: failed to read %s\n", __func__, + g_aw86225_rtp_name[aw86225->rtp_file_num]); + if (aw86225->wk_lock_flag == 1) + { + aw86225->wk_lock_flag = 0; + } + + nxmutex_unlock(&aw86225->lock); + return; + } + + aw86225->rtp_init = 0; + kmm_free(aw86225->rtp_container); + aw86225->rtp_container = kmm_malloc(rtp_file.size + sizeof(int)); + if (!aw86225->rtp_container) + { + aw86225_release_firmware(&rtp_file); + ierr("%s: error allocating memory\n", __func__); + if (aw86225->wk_lock_flag == 1) + { + aw86225->wk_lock_flag = 0; + } + + nxmutex_unlock(&aw86225->lock); + return; + } + + aw86225->rtp_container->len = rtp_file.size; + iinfo("%s: rtp file:[%s] size = %dbytes\n", + __func__, g_aw86225_rtp_name[aw86225->rtp_file_num], + aw86225->rtp_container->len); + memcpy(aw86225->rtp_container->data, rtp_file.data, rtp_file.size); + aw86225_release_firmware(&rtp_file); + aw86225->rtp_init = 1; + aw86225_haptic_upload_lra(aw86225, AW86225_OSC_CALI); + aw86225_haptic_set_pwm(aw86225, AW86225_PWM_24K); + + /* gain */ + + aw86225_haptic_ram_vbat_compensate(aw86225, false); + aw86225_haptic_set_gain(aw86225, aw86225->level); + + /* rtp mode config */ + + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_RTP_MODE); + + /* haptic go */ + + aw86225_haptic_play_go(aw86225, true); + nxmutex_unlock(&aw86225->lock); + usleep(2000); + while (cnt) + { + aw86225_i2c_read(aw86225, AW86225_REG_GLBRD5, ®_val); + if ((reg_val & 0x0f) == 0x08) + { + cnt = 0; + rtp_work_flag = true; + iinfo("%s RTP_GO! glb_state=0x08\n", __func__); + } + else + { + cnt--; + iinfo("wait for RTP_GO, glb_state=0x%02X\n", reg_val); + } + + usleep(2000); + } + + if (rtp_work_flag) + { + aw86225_haptic_rtp_init(aw86225); + } + else + { + aw86225_haptic_stop(aw86225); + ierr("%s failed to enter RTP_GO status!\n", __func__); + } + } + else + { + if (aw86225->wk_lock_flag == 1) + { + aw86225->wk_lock_flag = 0; + } + + aw86225->rtp_cnt = 0; + aw86225->rtp_init = 0; + nxmutex_unlock(&aw86225->lock); + } +} + +static int aw86225_container_update(FAR struct aw86225 *aw86225, + FAR struct aw86225_container *aw86225_cont) +{ + unsigned char reg_val = 0; + unsigned int shift = 0; + unsigned int temp = 0; + int i = 0; + int ret = 0; +#ifdef AW_CHECK_RAM_DATA + unsigned short check_sum = 0; +#endif + + iinfo("%s enter\n", __func__); + nxmutex_lock(&aw86225->lock); + aw86225->ram.baseaddr_shift = 2; + aw86225->ram.ram_shift = 4; + + /* RAMINIT Enable */ + + aw86225_haptic_raminit(aw86225, true); + + /* Enter standby mode */ + + aw86225_haptic_stop(aw86225); + + /* base addr */ + + shift = aw86225->ram.baseaddr_shift; + aw86225->ram.base_addr = (unsigned int) + ((aw86225_cont->data[0 + shift] << 8) | + (aw86225_cont->data[1 + shift])); + + /* default 3k SRAM */ + + aw86225_sram_size(aw86225, AW86225_HAPTIC_SRAM_3K); + + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG1, + AW86225_BIT_RTPCFG1_ADDRH_MASK, + aw86225_cont->data[0 + shift]); + + aw86225_i2c_write(aw86225, AW86225_REG_RTPCFG2, + aw86225_cont->data[1 + shift]); + + /* FIFO_AEH */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG3, + AW86225_BIT_RTPCFG3_FIFO_AEH_MASK, + (unsigned char) + (((aw86225->ram.base_addr >> 1) >> 4) & 0xf0)); + + /* FIFO AEL */ + + aw86225_i2c_write(aw86225, AW86225_REG_RTPCFG4, + (unsigned char) + (((aw86225->ram.base_addr >> 1) & 0x00ff))); + + /* FIFO_AFH */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_RTPCFG3, + AW86225_BIT_RTPCFG3_FIFO_AFH_MASK, + (unsigned char)(((aw86225->ram.base_addr - + (aw86225->ram.base_addr >> 2)) >> 8) & 0x0f)); + + /* FIFO_AFL */ + + aw86225_i2c_write(aw86225, AW86225_REG_RTPCFG5, + (unsigned char)(((aw86225->ram.base_addr - + (aw86225->ram.base_addr >> 2)) & 0x00ff))); + + aw86225_i2c_read(aw86225, AW86225_REG_RTPCFG3, ®_val); + temp = ((reg_val & 0x0f) << 24) | ((reg_val & 0xf0) << 4); + aw86225_i2c_read(aw86225, AW86225_REG_RTPCFG4, ®_val); + temp = temp | reg_val; + iinfo("almost_empty_threshold = %d", (unsigned short)temp); + aw86225_i2c_read(aw86225, AW86225_REG_RTPCFG5, ®_val); + temp = temp | (reg_val << 16); + iinfo("almost_full_threshold = %d\n", temp >> 16); + + shift = aw86225->ram.baseaddr_shift; + + aw86225_i2c_write_bits(aw86225, AW86225_REG_RAMADDRH, + AW86225_BIT_RAMADDRH_MASK, + aw86225_cont->data[0 + shift]); + aw86225_i2c_write(aw86225, AW86225_REG_RAMADDRL, + aw86225_cont->data[1 + shift]); + shift = aw86225->ram.ram_shift; + iinfo("%s: ram_len = %d\n", __func__, aw86225_cont->len - shift); + for (i = shift; i < aw86225_cont->len; i++) + { + aw86225->ram_update_flag = aw86225_i2c_write(aw86225, + AW86225_REG_RAMDATA, + aw86225_cont->data[i]); + } + +#ifdef AW_CHECK_RAM_DATA + shift = aw86225->ram.baseaddr_shift; + aw86225_i2c_write_bits(aw86225, AW86225_REG_RAMADDRH, + AW86225_BIT_RAMADDRH_MASK, + aw86225_cont->data[0 + shift]); + aw86225_i2c_write(aw86225, AW86225_REG_RAMADDRL, + aw86225_cont->data[1 + shift]); + shift = aw86225->ram.ram_shift; + for (i = shift; i < aw86225_cont->len; i++) + { + aw86225_i2c_read(aw86225, AW86225_REG_RAMDATA, ®_val); + if (reg_val != aw86225_cont->data[i]) + { + iinfo("%s: ram check error addr=0x%04x, file_data=0x%02X, \ + ram_data=0x%02X\n", \ + __func__, i, aw86225_cont->data[i], reg_val); + ret = -1; + break; + } + + check_sum += reg_val; + } + + if (!ret) + { + aw86225_i2c_read(aw86225, AW86225_REG_RTPCFG1, ®_val); + check_sum += reg_val & 0x0f; + aw86225_i2c_read(aw86225, AW86225_REG_RTPCFG2, ®_val); + check_sum += reg_val; + + if (check_sum != aw86225->ram.check_sum) + { + ierr("ram data check sum error, check_sum=0x%04x\n", check_sum); + ret = -1; + } + else + { + iinfo("ram data check sum pass, check_sum=0x%04x\n", check_sum); + } + } +#endif + + /* RAMINIT Disable */ + + aw86225_haptic_raminit(aw86225, false); + nxmutex_unlock(&aw86225->lock); + iinfo("%s exit\n", __func__); + return ret; +} + +static void aw86225_ram_loaded(FAR struct aw86225_firmware *cont, + FAR struct aw86225 *aw86225) +{ + struct aw86225_container *aw86225_fw; + unsigned short check_sum = 0; + int i = 0; + int ret = 0; +#ifdef AW_READ_BIN_FLEXBALLY + static unsigned char load_cont; + int ram_timer_val = 1000; + + load_cont++; +#endif + ierr("%s enter\n", __func__); + aw86225_request_firmware(cont, g_aw86225_ram_name); + + if (!cont) + { + ierr("%s: failed to read %s\n", __func__, g_aw86225_ram_name); + aw86225_release_firmware(cont); +#ifdef AW_READ_BIN_FLEXBALLY + if (load_cont <= 20) + { + work_queue(HPWORK, &aw86225->ram_work, + aw86225_ram_work_routine, + aw86225, MSEC2TICK(ram_timer_val)); + ierr("%s:start hrtimer: load_cont=%d\n", __func__, load_cont); + } + +#endif + return; + } + + /* check sum */ + + for (i = 2; i < cont->size; i++) + { + check_sum += cont->data[i]; + } + + if (check_sum != (unsigned short)((cont->data[0] << 8) | (cont->data[1]))) + { + ierr("%s: check sum err: check_sum=0x%04x\n", __func__, check_sum); + return; + } + else + { + iinfo("%s: check sum pass: 0x%04x\n", __func__, check_sum); + aw86225->ram.check_sum = check_sum; + } + + /* aw86225 ram update less then 128kB */ + + aw86225_fw = kmm_zalloc(cont->size + sizeof(int)); + if (!aw86225_fw) + { + aw86225_release_firmware(cont); + ierr("%s: Error allocating memory\n", __func__); + return; + } + + aw86225_fw->len = cont->size; + memcpy(aw86225_fw->data, cont->data, cont->size); + aw86225_release_firmware(cont); + ret = aw86225_container_update(aw86225, aw86225_fw); + if (ret) + { + kmm_free(aw86225_fw); + aw86225->ram.len = 0; + ierr("%s: ram firmware update failed!\n", __func__); + } + else + { + aw86225->ram_init = 1; + aw86225->ram.len = aw86225_fw->len; + kmm_free(aw86225_fw); + iinfo("%s: ram firmware update complete!\n", __func__); + } +} + +static void aw86225_vibrator_timer_func(wdparm_t arg) +{ + struct aw86225 *aw86225 = (struct aw86225 *)arg; + iinfo("%s enter\n", __func__); + aw86225->state = 0; + work_queue(HPWORK, &aw86225->long_vibrate_work, + aw86225_long_vibrate_work_routine, aw86225, 0); +} + +static void +aw86225_haptic_play_repeat_seq(FAR struct aw86225 *aw86225, + unsigned char flag) +{ + if (flag) + { + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_RAM_LOOP_MODE); + aw86225_haptic_play_go(aw86225, true); + } +} + +static void aw86225_haptic_trig_config(FAR struct aw86225 *aw86225) +{ + if (aw86225->is_used_irq == false) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_INTN_PIN_MASK, + AW86225_BIT_SYSCTRL2_TRIG1); + } +} + +static void +aw86225_haptic_swicth_motor_protect_config(FAR struct aw86225 *aw86225, + unsigned char addr, + unsigned char val) +{ + if (addr == 1) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_DETCFG1, + AW86225_BIT_DETCFG1_PRCT_MODE_MASK, + AW86225_BIT_DETCFG1_PRCT_MODE_VALID); + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG1, + AW86225_BIT_PWMCFG1_PRC_EN_MASK, + AW86225_BIT_PWMCFG1_PRC_ENABLE); + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG3, + AW86225_BIT_PWMCFG3_PR_EN_MASK, + AW86225_BIT_PWMCFG3_PR_ENABLE); + } + else if (addr == 0) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_DETCFG1, + AW86225_BIT_DETCFG1_PRCT_MODE_MASK, + AW86225_BIT_DETCFG1_PRCT_MODE_INVALID); + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG1, + AW86225_BIT_PWMCFG1_PRC_EN_MASK, + AW86225_BIT_PWMCFG1_PRC_DISABLE); + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG3, + AW86225_BIT_PWMCFG3_PR_EN_MASK, + AW86225_BIT_PWMCFG3_PR_DISABLE); + } + else if (addr == 0x2d) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG1, + AW86225_BIT_PWMCFG1_PRCTIME_MASK, val); + } + else if (addr == 0x3e) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_PWMCFG3, + AW86225_BIT_PWMCFG3_PRLVL_MASK, val); + } + else if (addr == 0x3f) + { + aw86225_i2c_write(aw86225, AW86225_REG_PWMCFG4, val); + } +} + +static void aw86225_haptic_f0_calibration(FAR struct aw86225 *aw86225) +{ + unsigned char reg_val = 0; + unsigned int f0_limit = 0; + char f0_cali_lra = 0; + int f0_cali_step = 0; + unsigned int f0_cali_min = aw86225->config->f0_ref * + (100 - aw86225->config->f0_cali_percent) / 100; + unsigned int f0_cali_max = aw86225->config->f0_ref * + (100 + aw86225->config->f0_cali_percent) / 100; + + if (aw86225_haptic_cont_get_f0(aw86225)) + { + ierr("%s get f0 error, user defafult f0\n", __func__); + } + else + { + /* max and min limit */ + + f0_limit = aw86225->f0; + iinfo("%s f0_ref = %d, f0_cali_min = %d, f0_cali_max = %d, f0 = %d\n", + __func__, aw86225->config->f0_ref, + f0_cali_min, f0_cali_max, aw86225->f0); + + if ((aw86225->f0 < f0_cali_min) || aw86225->f0 > f0_cali_max) + { + ierr("f0 calibration out of range = %d!\n", aw86225->f0); + f0_limit = aw86225->config->f0_ref; + return; + } + + /* calculate cali step */ + + f0_cali_step = 100000 * ((int)f0_limit - + (int)aw86225->config->f0_ref) / ((int)f0_limit * 24); + iinfo("%s f0_cali_step = %d\n", __func__, 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 */ + + aw86225->f0_cali_data = (int)f0_cali_lra; + aw86225_haptic_upload_lra(aw86225, AW86225_F0_CALI); + aw86225_i2c_read(aw86225, AW86225_REG_TRIMCFG3, ®_val); + iinfo("%s final trim_lra=0x%02x\n", __func__, reg_val); + } + + /* restore standby work mode */ + + aw86225_haptic_stop(aw86225); +} + +/**************************************************************************** + * Name: haptic cont + ****************************************************************************/ + +static int aw86225_haptic_cont_config(FAR struct aw86225 *aw86225) +{ + /* work mode */ + + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_CONT_MODE); + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG6, + AW86225_BIT_CONTCFG6_TRACK_EN_MASK, + AW86225_BIT_CONTCFG6_TRACK_ENABLE); + + /* f0 driver level */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG6, + AW86225_BIT_CONTCFG6_DRV1_LVL_MASK, + aw86225->cont_drv1_lvl); + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG7, + aw86225->cont_drv2_lvl); + + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG9, 0xff); + + aw86225_haptic_play_go(aw86225, true); + return 0; +} + +static int aw86225_haptic_activate(FAR struct aw86225 *aw86225) +{ + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL2, + AW86225_BIT_SYSCTRL2_STANDBY_MASK, + AW86225_BIT_SYSCTRL2_STANDBY_OFF); + aw86225_interrupt_clear(aw86225); + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, + AW86225_BIT_SYSINTM_UVLM_MASK, + AW86225_BIT_SYSINTM_UVLM_ON); + return 0; +} + +static int aw86225_haptic_start(FAR struct aw86225 *aw86225) +{ + aw86225_haptic_activate(aw86225); + aw86225_haptic_play_go(aw86225, true); + return 0; +} + +static int aw86225_haptic_play_effect_seq(FAR struct aw86225 *aw86225, + unsigned char flag) +{ + if (aw86225->effect_id > aw86225->config->effect_id_boundary) + { + return 0; + } + + iinfo("%s:effect_id =%d, activate_mode = %d\n", + __func__, aw86225->effect_id, aw86225->activate_mode); + if (flag) + { + if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_MODE) + { + if (aw86225->effect_id == 5 || aw86225->effect_id == 6) + { + aw86225->effect_id = 6; + } + else if (aw86225->effect_id == 1) + { + aw86225->effect_id = 3; + } + else if ((aw86225->effect_id >= 2) && (aw86225->effect_id <= 9)) + { + aw86225->effect_id = 8; + } + + aw86225_haptic_set_wav_seq(aw86225, 0x00, + (char)aw86225->effect_id + 1); + aw86225_haptic_set_pwm(aw86225, AW86225_PWM_12K); + aw86225_haptic_set_wav_seq(aw86225, 0x01, 0x00); + aw86225_haptic_set_wav_loop(aw86225, 0x00, 0x00); + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_RAM_MODE); + aw86225_haptic_effect_strength(aw86225); + aw86225_haptic_set_gain(aw86225, aw86225->level); + aw86225_haptic_start(aw86225); + } + + if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE) + { + aw86225_haptic_set_repeat_wav_seq(aw86225, + (aw86225->config->effect_id_boundary + 1)); + + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL7, + AW86225_BIT_SYSCTRL7_GAIN_BYPASS_MASK, + AW86225_BIT_SYSCTRL7_GAIN_CHANGEABLE); + + aw86225_haptic_set_pwm(aw86225, AW86225_PWM_12K); + aw86225_haptic_set_gain(aw86225, aw86225->level); + aw86225_haptic_play_repeat_seq(aw86225, true); + } + } + + iinfo("%s: exit\n", __func__); + return 0; +} + +static void aw86225_haptic_misc_para_init(FAR struct aw86225 *aw86225) +{ + aw86225->cont_drv1_lvl = aw86225->config->cont_drv1_lvl_dt; + aw86225->cont_drv2_lvl = aw86225->config->cont_drv2_lvl_dt; + aw86225->cont_drv1_time = aw86225->config->cont_drv1_time_dt; + aw86225->cont_drv2_time = aw86225->config->cont_drv2_time_dt; + aw86225->cont_brk_time = aw86225->config->cont_brk_time_dt; + aw86225->cont_wait_num = aw86225->config->cont_wait_num_dt; + + /* SIN_H */ + + aw86225_i2c_write(aw86225, AW86225_REG_SYSCTRL3, + aw86225->config->sine_array[0]); + + /* SIN_L */ + + aw86225_i2c_write(aw86225, AW86225_REG_SYSCTRL4, + aw86225->config->sine_array[1]); + + /* COS_H */ + + aw86225_i2c_write(aw86225, AW86225_REG_SYSCTRL5, + aw86225->config->sine_array[2]); + + /* COS_L */ + + aw86225_i2c_write(aw86225, AW86225_REG_SYSCTRL6, + aw86225->config->sine_array[3]); + aw86225_i2c_write_bits(aw86225, AW86225_REG_TRGCFG8, + AW86225_BIT_TRGCFG8_TRG_TRIG1_MODE_MASK, + AW86225_BIT_TRGCFG8_TRIG1); + aw86225_i2c_write_bits(aw86225, AW86225_REG_ANACFG8, + AW86225_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK, + AW86225_BIT_ANACFG8_TRTF_CTRL_HDRV); + + /* d2s_gain */ + + if (!aw86225->config->d2s_gain) + { + iinfo("%s aw86225->config->d2s_gain = 0!\n", __func__); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL7, + AW86225_BIT_SYSCTRL7_D2S_GAIN_MASK, + aw86225->config->d2s_gain); + } + + /* cont_tset */ + + if (!aw86225->config->cont_tset) + { + iinfo("%s aw86225->config->cont_tset = 0!\n", __func__); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG13, + AW86225_BIT_CONTCFG13_TSET_MASK, + aw86225->config->cont_tset << 4); + } + + /* cont_bemf_set */ + + if (!aw86225->config->cont_bemf_set) + { + iinfo("%s aw86225->config->cont_bemf_set = 0!\n", __func__); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG13, + AW86225_BIT_CONTCFG13_BEME_SET_MASK, + aw86225->config->cont_bemf_set); + } + + /* cont_brk_time */ + + if (!aw86225->cont_brk_time) + { + iinfo("%s aw86225->cont_brk_time = 0!\n", __func__); + } + else + { + aw86225_i2c_write(aw86225, AW86225_REG_CONTCFG10, + aw86225->cont_brk_time); + } + + /* cont_brk_gain */ + + if (!aw86225->config->cont_brk_gain) + { + iinfo("%s aw86225->config->cont_brk_gain = 0!\n", __func__); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_CONTCFG5, + AW86225_BIT_CONTCFG5_BRK_GAIN_MASK, + aw86225->config->cont_brk_gain); + } +} + +/**************************************************************************** + * Name: offset calibration + ****************************************************************************/ + +static int +aw86225_haptic_offset_calibration(FAR struct aw86225 *aw86225) +{ + unsigned int cont = 2000; + unsigned char reg_val = 0; + + aw86225_haptic_raminit(aw86225, true); + aw86225_i2c_write_bits(aw86225, AW86225_REG_DETCFG2, + AW86225_BIT_DETCFG2_DIAG_GO_MASK, + AW86225_BIT_DETCFG2_DIAG_GO_ON); + + while (1) + { + aw86225_i2c_read(aw86225, AW86225_REG_DETCFG2, ®_val); + if ((reg_val & 0x01) == 0 || cont == 0) + { + break; + } + + cont--; + } + + if (cont == 0) + { + ierr("%s calibration offset failed!\n", __func__); + } + + aw86225_haptic_raminit(aw86225, false); + return 0; +} + +static void +aw86225_haptic_vbat_mode_config(FAR struct aw86225 *aw86225, + unsigned char flag) +{ + if (flag == AW86225_HAPTIC_CONT_VBAT_HW_ADJUST_MODE) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL1, + AW86225_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW86225_BIT_SYSCTRL1_VBAT_MODE_HW); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSCTRL1, + AW86225_BIT_SYSCTRL1_VBAT_MODE_MASK, + AW86225_BIT_SYSCTRL1_VBAT_MODE_SW); + } +} + +static void aw86225_haptic_auto_bst_enable(FAR struct aw86225 *aw86225, + unsigned char flag) +{ + if (flag) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_BRK_EN_MASK, + AW86225_BIT_PLAYCFG3_BRK_ENABLE); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_PLAYCFG3, + AW86225_BIT_PLAYCFG3_BRK_EN_MASK, + AW86225_BIT_PLAYCFG3_BRK_DISABLE); + } +} + +static int aw86225_read_chipid(FAR struct aw86225 *aw86225) +{ + int ret; + uint8_t devid = 1; /* set nonzero, because chipid is 0! */ + + ret = aw86225_i2c_read(aw86225, 0x00, &devid); + if (ret < 0 || devid != 0) + { + ierr("Wrong Device ID! %02x\n\n", devid); + ret = -ENODEV; + } + + return ret; +} + +static void aw86225_ram_work_routine(FAR void *arg) +{ + struct aw86225_firmware rtp_file; + FAR struct aw86225 *aw86225 = arg; + + aw86225->ram_init = 0; + aw86225->rtp_init = 0; + + aw86225_ram_loaded(&rtp_file, aw86225); +} + +static void aw86225_long_vibrate_work_routine(FAR void *arg) +{ + FAR struct aw86225 *aw86225 = arg; + + iinfo("effect_id = %d state=%d activate_mode = %d duration = %d\n", + aw86225->effect_id, aw86225->state, + aw86225->activate_mode, aw86225->duration); + + nxmutex_lock(&aw86225->lock); + + /* Enter standby mode */ + + aw86225_haptic_stop(aw86225); + aw86225_haptic_upload_lra(aw86225, AW86225_F0_CALI); + if (aw86225->state) + { + if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_MODE) + { + aw86225_haptic_ram_vbat_compensate(aw86225, false); + aw86225_haptic_play_effect_seq(aw86225, true); + } + else if (aw86225->activate_mode == + AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE) + { + aw86225_haptic_ram_vbat_compensate(aw86225, true); + aw86225_haptic_play_effect_seq(aw86225, true); + + /* run ms timer */ + + wd_start(&aw86225->timer, MSEC2TICK(aw86225->duration), + aw86225_vibrator_timer_func, (wdparm_t)aw86225); + aw86225->wk_lock_flag = 1; + } + else if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_CONT_MODE) + { + aw86225_haptic_cont_config(aw86225); + + /* run ms timer */ + + wd_start(&aw86225->timer, MSEC2TICK(aw86225->duration), + aw86225_vibrator_timer_func, (wdparm_t)aw86225); + } + else + { + ierr("%s: activate_mode error\n", __func__); + } + } + else + { + if (aw86225->wk_lock_flag == 1) + { + aw86225->wk_lock_flag = 0; + } + } + + nxmutex_unlock(&aw86225->lock); +} + +static int aw86225_vibrator_init(FAR struct aw86225 *aw86225) +{ + nxmutex_init(&aw86225->lock); + nxmutex_init(&aw86225->rtp_lock); + nxsem_init(&aw86225->wait_q, 0, 0); + nxsem_init(&aw86225->stop_wait_q, 0, 0); + + return 0; +} + +static int aw86225_ram_work_init(FAR struct aw86225 *aw86225) +{ + int ram_timer_val = 8000; + + work_queue(HPWORK, &aw86225->ram_work, + aw86225_ram_work_routine, aw86225, MSEC2TICK(ram_timer_val)); + + return 0; +} + +static int aw86225_haptic_init(FAR struct aw86225 *aw86225) +{ + int ret; + unsigned char i; + unsigned char reg_val = 0; + + nxmutex_lock(&aw86225->lock); + + /* haptic init */ + + aw86225->ram_state = 0; + aw86225->activate_mode = aw86225->config->mode; + ret = aw86225_i2c_read(aw86225, AW86225_REG_WAVCFG1, ®_val); + aw86225->index = reg_val & 0x7f; + ret = aw86225_i2c_read(aw86225, AW86225_REG_PLAYCFG2, ®_val); + aw86225->gain = reg_val & 0xff; + iinfo("%s aw86225->gain =0x%02X\n", __func__, aw86225->gain); + for (i = 0; i < AW86225_SEQUENCER_SIZE; i++) + { + ret = aw86225_i2c_read(aw86225, AW86225_REG_WAVCFG1 + i, ®_val); + aw86225->seq[i] = reg_val; + } + + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_STANDBY_MODE); + aw86225_haptic_set_pwm(aw86225, AW86225_PWM_12K); + + /* misc value init */ + + aw86225_haptic_misc_para_init(aw86225); + + /* set motor protect */ + + aw86225_haptic_swicth_motor_protect_config(aw86225, 0x00, 0x00); + aw86225_haptic_trig_config(aw86225); + aw86225_haptic_offset_calibration(aw86225); + + /* config auto_brake */ + + aw86225_haptic_auto_bst_enable(aw86225, + aw86225->config->is_enabled_auto_bst); + + /* vbat compensation */ + + aw86225_haptic_vbat_mode_config(aw86225, + AW86225_HAPTIC_CONT_VBAT_HW_ADJUST_MODE); + aw86225->ram_vbat_compensate = AW86225_HAPTIC_RAM_VBAT_COMP_ENABLE; + + /* f0 calibration LRA trim source select register */ + + aw86225_i2c_write_bits(aw86225, AW86225_REG_TRIMCFG1, + AW86225_BIT_TRIMCFG1_RL_TRIM_SRC_MASK, + AW86225_BIT_TRIMCFG1_RL_TRIM_SRC_REG); + aw86225_haptic_upload_lra(aw86225, AW86225_WRITE_ZERO); + aw86225_haptic_f0_calibration(aw86225); + nxmutex_unlock(&aw86225->lock); + return ret; +} + +static int aw86225_haptics_upload_effect(FAR struct ff_lowerhalf_s *lower, + FAR struct ff_effect *effect, + FAR struct ff_effect *old) +{ + FAR struct aw86225 *aw86225 = (FAR struct aw86225 *)lower; + FAR struct aw86225_hap_play_info *play = &aw86225->play; + int16_t data[AW86225_CUSTOM_DATA_LEN]; + sclock_t time_us; + int ret; + + time_us = wd_gettime(&aw86225->timer); + usleep(time_us); + + iinfo("%s: effect->type=0x%x,FF_CONSTANT=0x%x,FF_PERIODIC=0x%x\n", + __func__, effect->type, FF_CONSTANT, FF_PERIODIC); + + aw86225->effect_type = effect->type; + nxmutex_lock(&aw86225->lock); + while (atomic_load(&aw86225->exit_in_rtp_loop)) + { + iinfo("%s: goint to waiting rtp exit\n", __func__); + nxmutex_unlock(&aw86225->lock); + ret = nxsem_post(&aw86225->stop_wait_q); + iinfo("%s: wakeup \n", __func__); + if (ret == -ERESTART) + { + ierr("%s: wake up by signal return erro\n", __func__); + return ret; + } + + nxmutex_lock(&aw86225->lock); + } + + if (aw86225->effect_type == FF_CONSTANT) + { + /* cont mode set duration */ + + aw86225->duration = effect->replay.length; + aw86225->activate_mode = AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE; + aw86225->effect_id = aw86225->config->effect_id_boundary; + } + else if (aw86225->effect_type == FF_PERIODIC) + { + if (aw86225->effects_count == 0) + { + nxmutex_unlock(&aw86225->lock); + return -EINVAL; + } + + memcpy(data, effect->u.periodic.custom_data, sizeof(int16_t) * 3); + + aw86225->effect_id = data[0]; + if (aw86225->effect_id == 521) + { + aw86225->effect_id = 21; + } + + iinfo("%s: aw86225->effect_id = %d \n", __func__, aw86225->effect_id); + play->vmax_mv = effect->u.periodic.magnitude; + + if (aw86225->effect_id < 0 || + aw86225->effect_id > aw86225->config->effect_max) + { + nxmutex_unlock(&aw86225->lock); + return 0; + } + + if (aw86225->effect_id < aw86225->config->effect_id_boundary) + { + aw86225->activate_mode = AW86225_HAPTIC_ACTIVATE_RAM_MODE; + data[1] = aw86225->predefined[aw86225->effect_id].play_rate_us + / 1000000; + data[2] = aw86225->predefined[aw86225->effect_id].play_rate_us + / 1000; + iinfo("aw86225->predefined[aw86225->effect_id] \ + .play_rate_us/1000 = %d\n", \ + aw86225->predefined[aw86225->effect_id].play_rate_us + / 1000); + } + + if (aw86225->effect_id >= aw86225->config->effect_id_boundary) + { + aw86225->activate_mode = AW86225_HAPTIC_ACTIVATE_RTP_MODE; + iinfo("%s: aw86225->effect_id=%d , aw86225->activate_mode = %d\n", + __func__, aw86225->effect_id, aw86225->activate_mode); + int budry = aw86225->effect_id - + aw86225->config->effect_id_boundary; + data[1] = aw86225->config->rtp_time[budry] / 1000; + data[2] = aw86225->config->rtp_time[budry] % 1000; + iinfo("%s: data[1] = %d data[2] = %d, rtp_time %d\n", __func__, + data[1], data[2], + aw86225->config->rtp_time[budry]); + } + + memcpy(effect->u.periodic.custom_data, data, sizeof(int16_t) * 3); + } + else + { + ierr("%s: unsupported effect type: %d\n", __func__, effect->type); + } + + nxmutex_unlock(&aw86225->lock); + return 0; +} + +static int aw86225_haptics_playback(struct ff_lowerhalf_s *lower, + int effect_id, int val) +{ + FAR struct aw86225 *aw86225 = (FAR struct aw86225 *)lower; + + iinfo("%s: aw86225->effect_id=%d , aw86225->activate_mode = %d\n", + __func__, aw86225->effect_id, aw86225->activate_mode); + + /* for osc calibration */ + + if (val > 0) + { + aw86225->state = 1; + } + + if (val <= 0) + { + aw86225->state = 0; + } + + wd_cancel(&aw86225->timer); + if (aw86225->effect_type == FF_CONSTANT && + aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE) + { + iinfo("%s: enter ram_loop_mode \n", __func__); + work_queue(HPWORK, &aw86225->long_vibrate_work, + aw86225_long_vibrate_work_routine, aw86225, 0); + } + else if (aw86225->effect_type == FF_PERIODIC && + aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_MODE) + { + iinfo("%s: enter ram_mode\n", __func__); + work_queue(HPWORK, &aw86225->long_vibrate_work, + aw86225_long_vibrate_work_routine, aw86225, 0); + } + else if (aw86225->effect_type == FF_PERIODIC && + aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RTP_MODE) + { + iinfo("%s: enter rtp_mode\n", __func__); + work_queue(HPWORK, &aw86225->rtp_work, + aw86225_rtp_work_routine, aw86225, 0); + if (val == 0) + { + atomic_store(&aw86225->exit_in_rtp_loop, 1); + } + } + + return OK; +} + +static int aw86225_haptics_erase(FAR struct ff_lowerhalf_s *lower, + int effect_id) +{ + FAR struct aw86225 *aw86225 = (FAR struct aw86225 *)lower; + + /* for osc calibration */ + + aw86225->effect_type = 0; + aw86225->duration = 0; + return OK; +} + +static void aw86225_haptics_set_gain_work_routine(FAR void *arg) +{ + FAR struct aw86225 *aw86225 = arg; + + if (aw86225->new_gain >= 0x7fff) + { + aw86225->level = 0x80; + } + else if (aw86225->new_gain <= 0x3fff) + { + aw86225->level = 0x1e; + } + else + { + aw86225->level = (aw86225->new_gain - 16383) / 128; + } + + if (aw86225->level < 0x1e) + { + aw86225->level = 0x1e; + } + + iinfo("%s: set_gain queue work, new_gain = %x level = %x \n", __func__, + aw86225->new_gain, aw86225->level); + + if (aw86225->ram_vbat_compensate == AW86225_HAPTIC_RAM_VBAT_COMP_ENABLE + && aw86225->vbat) + { + unsigned char comp_level = + aw86225->level * AW86225_VBAT_REFER / aw86225->vbat; + if (comp_level > (128 * AW86225_VBAT_REFER / AW86225_VBAT_MIN)) + { + comp_level = 128 * AW86225_VBAT_REFER / AW86225_VBAT_MIN; + iinfo("%s: comp level limit is %d ", __func__, comp_level); + } + + iinfo("%s: enable vbat comp, level = %x comp level = %x", __func__, + aw86225->level, comp_level); + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG2, comp_level); + } + else + { + iinfo("%s: disable compsensation, vbat=%d, vbat_min=%d, vbat_ref=%d", + __func__, aw86225->vbat, AW86225_VBAT_MIN, AW86225_VBAT_REFER); + aw86225_i2c_write(aw86225, AW86225_REG_PLAYCFG2, aw86225->level); + } +} + +static void aw86225_haptics_set_gain(FAR struct ff_lowerhalf_s *lower, + uint16_t gain) +{ + FAR struct aw86225 *aw86225 = (FAR struct aw86225 *)lower; + + aw86225->new_gain = gain; + work_queue(HPWORK, &aw86225->set_gain_work, + aw86225_haptics_set_gain_work_routine, aw86225, 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: aw86225_initialize + * + * Description: + * aw86225 motor driver initialize + * + * Input Parameters: + * master - i2c master param + * ioedev - io dev pin set + * config - the board config param of aw86225 + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int aw86225_initialize(FAR struct i2c_master_s *master, + FAR struct ioexpander_dev_s *ioedev, + FAR const struct aw86225_board_config *config) +{ + FAR struct ff_lowerhalf_s *lower = NULL; + FAR struct aw86225 *aw86225; + int effect_count_max; + int ret; + + DEBUGASSERT(master != NULL && ioedev != NULL && config != NULL); + + aw86225 = kmm_zalloc(sizeof(struct aw86225)); + if (NULL == aw86225) + { + ierr("Failed to allocate instance\n\n"); + return -ENOMEM; + } + + aw86225->effects_count = config->effects_count; + aw86225->is_used_irq = config->is_used_irq; + aw86225->predefined = config->predefined; + aw86225->config = config->config; + aw86225->irq = config->irq; + aw86225->i2c = master; + aw86225->addr = config->addr; + aw86225->freq = config->freq; + aw86225->level = 0x80; + + lower = &aw86225->lower; + lower->upload = aw86225_haptics_upload_effect; + lower->erase = aw86225_haptics_erase; + lower->playback = aw86225_haptics_playback; + lower->set_gain = aw86225_haptics_set_gain; + lower->set_autocenter = NULL; + lower->destroy = NULL; + + /* Interrupt register. */ + + ret = IOEXP_SETDIRECTION(ioedev, config->rstpin, IOEXPANDER_DIRECTION_OUT); + if (ret < 0) + { + ierr("ioexpander set direction error: %d\n", ret); + goto err; + } + + ret = IOEXP_WRITEPIN(ioedev, config->rstpin, 0); + if (ret < 0) + { + ierr("ioexpander set direction error: %d\n", ret); + goto err; + } + + usleep(2000); + + ret = IOEXP_WRITEPIN(ioedev, config->rstpin, 1); + if (ret < 0) + { + ierr("ioexpander gpio write failed: %d\n", ret); + goto err; + } + + usleep(5000); + + /* int pin set */ + + ret = IOEXP_SETDIRECTION(ioedev, config->intpin, + IOEXPANDER_DIRECTION_IN_PULLUP); + if (ret < 0) + { + ierr("ioexpander set direction error: %d\n", ret); + goto err; + } + + ret = IOEXP_SETDIRECTION(ioedev, config->powerpin, + IOEXPANDER_DIRECTION_OUT); + if (ret < 0) + { + ierr("ioexpander set direction error: %d\n", ret); + goto err; + } + + ret = IOEXP_WRITEPIN(ioedev, config->powerpin, true); + if (ret < 0) + { + ierr("Error: Failed to write pin: %d\n", ret); + return ret; + } + + ret = aw86225_read_chipid(aw86225); + if (ret < 0) + { + ierr("Check chip id failed!\n\n"); + goto err; + } + + aw86225_vibrator_init(aw86225); + aw86225_haptic_init(aw86225); + aw86225_ram_work_init(aw86225); + + __set_bit(FF_CUSTOM, lower->ffbit); + __set_bit(FF_GAIN, lower->ffbit); + __set_bit(FF_CONSTANT, lower->ffbit); + __set_bit(FF_PERIODIC, lower->ffbit); + + if (aw86225->effects_count + 1 > FF_EFFECT_COUNT_MAX) + { + effect_count_max = aw86225->effects_count + 1; + } + else + { + effect_count_max = FF_EFFECT_COUNT_MAX; + } + + ret = ff_register(lower, config->path, effect_count_max); + if (ret < 0) + { + ierr("Failed to register driver:%d\n", ret); + nxsem_destroy(&aw86225->wait_q); + nxsem_destroy(&aw86225->stop_wait_q); + work_cancel(HPWORK, &aw86225->ram_work); + goto err; + } + + return ret; + +err: + kmm_free(aw86225); + return ret; +} diff --git a/drivers/input/aw86225_internal.h b/drivers/input/aw86225_internal.h new file mode 100644 index 0000000000..b4f9601c40 --- /dev/null +++ b/drivers/input/aw86225_internal.h @@ -0,0 +1,293 @@ +/**************************************************************************** + * drivers/input/aw86225_internal.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_INPUT_AW86225_INTERNAL_H_ +#define __DRIVERS_INPUT_AW86225_INTERNAL_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AW86225_I2C_RETRIES (5) +#define AW86225_RTP_NAME_MAX (64) +#define AW86225_SEQUENCER_SIZE (8) +#define AW86225_SEQUENCER_LOOP_SIZE (4) +#define AW86225_OSC_CALI_MAX_LENGTH (11000000) +#define AW86225_PM_QOS_VALUE_VB (0) +#define AW86225_VBAT_REFER (4200) +#define AW86225_VBAT_MIN (3000) +#define AW86225_VBAT_MAX (5500) +#define AW86225_TRIG_NUM (3) +#define AW86225_I2C_RETRY_DELAY (2) +#define FF_EFFECT_COUNT_MAX 5 +#define HAP_BRAKE_PATTERN_MAX 4 + +#define AW_CHECK_RAM_DATA +#define AW_READ_BIN_FLEXBALLY + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum aw86225_haptics_custom_effect_param +{ + AW86225_CUSTOM_DATA_EFFECT_IDX, + AW86225_CUSTOM_DATA_TIMEOUT_SEC_IDX, + AW86225_CUSTOM_DATA_TIMEOUT_MSEC_IDX, + AW86225_CUSTOM_DATA_LEN, +}; + +enum haptic_nv_read_chip_type +{ + AW86225_FIRST_TRY = 0, + AW86225_LAST_TRY = 1, +}; + +enum aw86225_flags +{ + AW86225_FLAG_NONR = 0, + AW86225_FLAG_SKIP_INTERRUPTS = 1, +}; + +enum aw86225_haptic_work_mode +{ + AW86225_HAPTIC_STANDBY_MODE = 0, + AW86225_HAPTIC_RAM_MODE = 1, + AW86225_HAPTIC_RTP_MODE = 2, + AW86225_HAPTIC_TRIG_MODE = 3, + AW86225_HAPTIC_CONT_MODE = 4, + AW86225_HAPTIC_RAM_LOOP_MODE = 5, +}; + +enum aw86225_haptic_activate_mode +{ + AW86225_HAPTIC_ACTIVATE_RAM_MODE = 0, + AW86225_HAPTIC_ACTIVATE_CONT_MODE = 1, + AW86225_HAPTIC_ACTIVATE_RTP_MODE = 2, + AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3, +}; + +enum aw86225_haptic_cont_vbat_comp_mode +{ + AW86225_HAPTIC_CONT_VBAT_SW_ADJUST_MODE = 0, + AW86225_HAPTIC_CONT_VBAT_HW_ADJUST_MODE = 1, +}; + +enum aw86225_haptic_ram_vbat_compensate_mode +{ + AW86225_HAPTIC_RAM_VBAT_COMP_DISABLE = 0, + AW86225_HAPTIC_RAM_VBAT_COMP_ENABLE = 1, +}; + +enum aw86225_haptic_f0_flag +{ + AW86225_HAPTIC_LRA_F0 = 0, + AW86225_HAPTIC_CALI_F0 = 1, +}; + +enum aw86225_sram_size_flag +{ + AW86225_HAPTIC_SRAM_1K = 0, + AW86225_HAPTIC_SRAM_2K = 1, + AW86225_HAPTIC_SRAM_3K = 2, +}; + +enum aw86225_haptic_pwm_mode +{ + AW86225_PWM_48K = 0, + AW86225_PWM_24K = 1, + AW86225_PWM_12K = 2, +}; + +enum aw86225_haptic_play +{ + AW86225_HAPTIC_PLAY_NULL = 0, + AW86225_HAPTIC_PLAY_ENABLE = 1, + AW86225_HAPTIC_PLAY_STOP = 2, + AW86225_HAPTIC_PLAY_GAIN = 8, +}; + +enum aw86225_haptic_cmd +{ + AW86225_HAPTIC_CMD_NULL = 0, + AW86225_HAPTIC_CMD_ENABLE = 1, + AW86225_HAPTIC_CMD_HAPTIC = 0x0f, + AW86225_HAPTIC_CMD_TP = 0x10, + AW86225_HAPTIC_CMD_SYS = 0xf0, + AW86225_HAPTIC_CMD_STOP = 255, +}; + +enum aw86225_haptic_cali_lra +{ + AW86225_WRITE_ZERO = 0, + AW86225_F0_CALI = 1, + AW86225_OSC_CALI = 2, +}; + +enum aw86225_haptic_rtp_mode +{ + AW86225_RTP_SHORT = 4, + AW86225_RTP_LONG = 5, + AW86225_RTP_SEGMENT = 6, +}; + +enum aw86225_ef_id +{ + AW86225_EF_ID = 0x00, +}; + +struct aw86225_firmware +{ + FAR const uint8_t *data; + size_t size; +}; + +struct aw86225_hap_play_info +{ + FAR struct aw86225_hap_effect *effect; + uint16_t vmax_mv; + int length_us; + int playing_pos; + bool playing_pattern; +}; + +struct aw86225_hap_config +{ + uint16_t vmax_mv; + uint16_t play_rate_us; + bool lra_allow_variable_play_rate; + bool use_ext_wf_src; +}; + +struct aw86225_ram +{ + unsigned int len; + unsigned int check_sum; + unsigned int base_addr; + unsigned char version; + unsigned char ram_shift; + unsigned char baseaddr_shift; +}; + +struct aw86225_container +{ + int len; + unsigned char data[]; +}; + +struct aw86225 +{ + struct ff_lowerhalf_s lower; + FAR struct i2c_master_s *i2c; + FAR struct ioexpander_dev_s *ioedev; + + /* Struct snd_soc_codec *codec; */ + + mutex_t lock; + mutex_t rtp_lock; + struct wdog_s timer; + struct wdog_s ram_timer; + struct work_s long_vibrate_work; + struct work_s rtp_work; + struct work_s set_gain_work; + struct work_s ram_work; + struct aw86225_hap_config hap_config; + struct aw86225_hap_play_info play; + FAR struct aw86225_hap_effect *predefined; + struct aw86225_hap_effect constant; + FAR struct aw86225_config *config; + struct aw86225_ram ram; + FAR struct aw86225_container *rtp_container; + + unsigned char seq[AW86225_SEQUENCER_SIZE]; + unsigned char loop[AW86225_SEQUENCER_SIZE]; + unsigned char rtp_init; + unsigned char ram_init; + unsigned char ram_vbat_compensate; + unsigned char play_mode; + unsigned char activate_mode; + unsigned char ram_state; + unsigned char wk_lock_flag; + + bool is_used_irq; + + int name; + int freq; + int reset_gpio; + int irq_gpio; + int irq; + int state; + int duration; + int effect_type; + int amplitude; + int index; + int gain; + int effect_id; + int effects_count; + + unsigned int rtp_cnt; + unsigned int rtp_file_num; + unsigned int f0; + unsigned int cont_f0; + unsigned int cont_drv1_lvl; + unsigned int cont_drv2_lvl; + unsigned int cont_brk_time; + unsigned int cont_wait_num; + unsigned int cont_drv1_time; + unsigned int cont_drv2_time; + unsigned int vbat; + unsigned int lra; + unsigned int ram_update_flag; + unsigned int rtp_update_flag; + unsigned int osc_cali_data; + unsigned int f0_cali_data; + unsigned int timeval_flags; + unsigned int osc_cali_flag; + unsigned int sys_frequency; + unsigned int rtp_len; + unsigned long int microsecond; + + uint8_t addr; + uint16_t new_gain; + unsigned char level; + unsigned int osc_cali_run; + unsigned char ram_vbat_comp; + atomic_int is_in_rtp_loop; + atomic_int exit_in_rtp_loop; + sem_t wait_q; + sem_t stop_wait_q; +}; + +#endif /* __DRIVERS_INPUT_AW86225_INTERNAL_H */ diff --git a/drivers/input/aw86225_reg.h b/drivers/input/aw86225_reg.h new file mode 100644 index 0000000000..5081051c32 --- /dev/null +++ b/drivers/input/aw86225_reg.h @@ -0,0 +1,707 @@ +/**************************************************************************** + * drivers/input/aw86225_reg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_INPUT_AW86225_REG_H +#define __DRIVERS_INPUT_AW86225_REG_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AW86225_REG_ID (0x00) +#define AW86225_REG_SYSST (0x01) +#define AW86225_REG_SYSINT (0x02) +#define AW86225_REG_SYSINTM (0x03) +#define AW86225_REG_SYSST2 (0x04) +#define AW86225_REG_SYSER (0x05) +#define AW86225_REG_PLAYCFG2 (0x07) +#define AW86225_REG_PLAYCFG3 (0x08) +#define AW86225_REG_PLAYCFG4 (0x09) +#define AW86225_REG_WAVCFG1 (0x0A) +#define AW86225_REG_WAVCFG2 (0x0B) +#define AW86225_REG_WAVCFG3 (0x0C) +#define AW86225_REG_WAVCFG4 (0x0D) +#define AW86225_REG_WAVCFG5 (0x0E) +#define AW86225_REG_WAVCFG6 (0x0F) +#define AW86225_REG_WAVCFG7 (0x10) +#define AW86225_REG_WAVCFG8 (0x11) +#define AW86225_REG_WAVCFG9 (0x12) +#define AW86225_REG_WAVCFG10 (0x13) +#define AW86225_REG_WAVCFG11 (0x14) +#define AW86225_REG_WAVCFG12 (0x15) +#define AW86225_REG_WAVCFG13 (0x16) +#define AW86225_REG_WAVCFG14 (0x17) +#define AW86225_REG_CONTCFG1 (0x18) +#define AW86225_REG_CONTCFG2 (0x19) +#define AW86225_REG_CONTCFG3 (0x1A) +#define AW86225_REG_CONTCFG4 (0x1B) +#define AW86225_REG_CONTCFG5 (0x1C) +#define AW86225_REG_CONTCFG6 (0x1D) +#define AW86225_REG_CONTCFG7 (0x1E) +#define AW86225_REG_CONTCFG8 (0x1F) +#define AW86225_REG_CONTCFG9 (0x20) +#define AW86225_REG_CONTCFG10 (0x21) +#define AW86225_REG_CONTCFG11 (0x22) +#define AW86225_REG_CONTCFG12 (0x23) +#define AW86225_REG_CONTCFG13 (0x24) +#define AW86225_REG_CONTRD14 (0x25) +#define AW86225_REG_CONTRD15 (0x26) +#define AW86225_REG_CONTRD16 (0x27) +#define AW86225_REG_CONTRD17 (0x28) +#define AW86225_REG_CONTRD18 (0x29) +#define AW86225_REG_CONTRD19 (0x2A) +#define AW86225_REG_CONTRD20 (0x2B) +#define AW86225_REG_CONTRD21 (0x2C) +#define AW86225_REG_RTPCFG1 (0x2D) +#define AW86225_REG_RTPCFG2 (0x2E) +#define AW86225_REG_RTPCFG3 (0x2F) +#define AW86225_REG_RTPCFG4 (0x30) +#define AW86225_REG_RTPCFG5 (0x31) +#define AW86225_REG_RTPDATA (0x32) +#define AW86225_REG_TRGCFG1 (0x33) +#define AW86225_REG_TRGCFG2 (0x34) +#define AW86225_REG_TRGCFG3 (0x35) +#define AW86225_REG_TRGCFG4 (0x36) +#define AW86225_REG_TRGCFG5 (0x37) +#define AW86225_REG_TRGCFG6 (0x38) +#define AW86225_REG_TRGCFG7 (0x39) +#define AW86225_REG_TRGCFG8 (0x3A) +#define AW86225_REG_GLBCFG1 (0x3B) +#define AW86225_REG_GLBCFG2 (0x3C) +#define AW86225_REG_GLBCFG3 (0x3D) +#define AW86225_REG_GLBCFG4 (0x3E) +#define AW86225_REG_GLBRD5 (0x3F) +#define AW86225_REG_RAMADDRH (0x40) +#define AW86225_REG_RAMADDRL (0x41) +#define AW86225_REG_RAMDATA (0x42) +#define AW86225_REG_SYSCTRL1 (0x43) +#define AW86225_REG_SYSCTRL2 (0x44) +#define AW86225_REG_SYSCTRL3 (0x45) +#define AW86225_REG_SYSCTRL4 (0x46) +#define AW86225_REG_SYSCTRL5 (0x47) +#define AW86225_REG_SYSCTRL6 (0x48) +#define AW86225_REG_SYSCTRL7 (0x49) +#define AW86225_REG_PWMCFG1 (0x4C) +#define AW86225_REG_PWMCFG2 (0x4D) +#define AW86225_REG_PWMCFG3 (0x4E) +#define AW86225_REG_PWMCFG4 (0x4F) +#define AW86225_REG_TMCFG (0x50) +#define AW86225_REG_DETCFG1 (0x51) +#define AW86225_REG_DETCFG2 (0x52) +#define AW86225_REG_DET_RL (0x53) +#define AW86225_REG_DET_OS (0x54) +#define AW86225_REG_DET_VBAT (0x55) +#define AW86225_REG_DET_TEST (0x56) +#define AW86225_REG_DET_LO (0x57) +#define AW86225_REG_TRIMCFG1 (0x58) +#define AW86225_REG_TRIMCFG3 (0x5A) +#define AW86225_REG_TRIMCFG4 (0x5B) +#define AW86225_REG_EFCFG1 (0x5C) +#define AW86225_REG_EFCFG2 (0x5D) +#define AW86225_REG_EFCFG3 (0x5E) +#define AW86225_REG_EFCFG4 (0x5F) +#define AW86225_REG_EFCFG5 (0x60) +#define AW86225_REG_EFCFG6 (0x61) +#define AW86225_REG_EFRD9 (0x64) +#define AW86225_REG_EFRD10 (0x65) +#define AW86225_REG_ANACFG1 (0x6A) +#define AW86225_REG_ANACFG2 (0x6B) +#define AW86225_REG_ANACFG3 (0x6C) +#define AW86225_REG_ANACFG4 (0x73) +#define AW86225_REG_ANACFG5 (0x74) +#define AW86225_REG_ANACFG6 (0x75) +#define AW86225_REG_ANACFG7 (0x76) +#define AW86225_REG_ANACFG8 (0x77) +#define AW86225_REG_SPACE (0x78) +#define AW86225_REG_MBIST (0x79) + +#define REG_NONE_ACCESS (0) +#define REG_RD_ACCESS (1 << 0) +#define REG_WR_ACCESS (1 << 1) +#define AW86225_REG_MAX 0xff + +/* SYSST: reg 0x01 RO */ + +#define AW86225_BIT_SYSST_UVLS (1<<5) +#define AW86225_BIT_SYSST_FF_AES (1<<4) +#define AW86225_BIT_SYSST_FF_AFS (1<<3) +#define AW86225_BIT_SYSST_OCDS (1<<2) +#define AW86225_BIT_SYSST_OTS (1<<1) +#define AW86225_BIT_SYSST_DONES (1<<0) + +/* SYSINT: reg 0x02 RC */ + +#define AW86225_BIT_SYSINT_UVLI (1<<5) +#define AW86225_BIT_SYSINT_FF_AEI (1<<4) +#define AW86225_BIT_SYSINT_FF_AFI (1<<3) +#define AW86225_BIT_SYSINT_OCDI (1<<2) +#define AW86225_BIT_SYSINT_OTI (1<<1) +#define AW86225_BIT_SYSINT_DONEI (1<<0) + +/* SYSINTM: reg 0x03 RW */ + +#define AW86225_BIT_SYSINTM_UVLM_MASK (~(1<<5)) +#define AW86225_BIT_SYSINTM_UVLM_OFF (1<<5) +#define AW86225_BIT_SYSINTM_UVLM_ON (0<<5) +#define AW86225_BIT_SYSINTM_FF_AEM_MASK (~(1<<4)) +#define AW86225_BIT_SYSINTM_FF_AEM_OFF (1<<4) +#define AW86225_BIT_SYSINTM_FF_AEM_ON (0<<4) +#define AW86225_BIT_SYSINTM_FF_AFM_MASK (~(1<<3)) +#define AW86225_BIT_SYSINTM_FF_AFM_OFF (1<<3) +#define AW86225_BIT_SYSINTM_FF_AFM_ON (0<<3) +#define AW86225_BIT_SYSINTM_OCDM_MASK (~(1<<2)) +#define AW86225_BIT_SYSINTM_OCDM_OFF (1<<2) +#define AW86225_BIT_SYSINTM_OCDM_ON (0<<2) +#define AW86225_BIT_SYSINTM_OTM_MASK (~(1<<1)) +#define AW86225_BIT_SYSINTM_OTM_OFF (1<<1) +#define AW86225_BIT_SYSINTM_OTM_ON (0<<1) +#define AW86225_BIT_SYSINTM_DONEM_MASK (~(1<<0)) +#define AW86225_BIT_SYSINTM_DONEM_OFF (1<<0) +#define AW86225_BIT_SYSINTM_DONEM_ON (0<<0) + +/* SYSST2: reg 0x04 RO */ + +#define AW86225_BIT_SYSST2_RAM_ADDR_ER (1<<7) +#define AW86225_BIT_SYSST2_TRG_ADDR_ER (1<<6) +#define AW86225_BIT_SYSST2_VBG_OK (1<<3) +#define AW86225_BIT_SYSST2_LDO_OK (1<<2) +#define AW86225_BIT_SYSST2_FF_FULL (1<<1) +#define AW86225_BIT_SYSST2_FF_EMPTY (1<<0) + +/* SYSER: reg 0x05 RC */ + +#define AW86225_BIT_SYSER_I2S_ERR (1<<7) +#define AW86225_BIT_SYSER_TRIG1_EVENT (1<<6) +#define AW86225_BIT_SYSER_TRIG2_EVENT (1<<5) +#define AW86225_BIT_SYSER_TRIG3_EVENT (1<<4) +#define AW86225_BIT_SYSER_OV (1<<3) +#define AW86225_BIT_SYSER_ADDR_ER (1<<2) +#define AW86225_BIT_SYSER_FF_ER (1<<1) +#define AW86225_BIT_SYSER_PLL_REF_ER (1<<0) + +/* PLAYCFG3: reg 0x08 RW */ + +#define AW86225_BIT_PLAYCFG3_STOP_MODE_MASK (~(1<<5)) +#define AW86225_BIT_PLAYCFG3_STOP_MODE_NOW (1<<5) +#define AW86225_BIT_PLAYCFG3_STOP_MODE_LATER (0<<5) +#define AW86225_BIT_PLAYCFG3_BRK_EN_MASK (~(1<<2)) +#define AW86225_BIT_PLAYCFG3_BRK_ENABLE (1<<2) +#define AW86225_BIT_PLAYCFG3_BRK_DISABLE (0<<2) +#define AW86225_BIT_PLAYCFG3_PLAY_MODE_MASK (~(3<<0)) +#define AW86225_BIT_PLAYCFG3_PLAY_MODE_STOP (3<<0) +#define AW86225_BIT_PLAYCFG3_PLAY_MODE_CONT (2<<0) +#define AW86225_BIT_PLAYCFG3_PLAY_MODE_RTP (1<<0) +#define AW86225_BIT_PLAYCFG3_PLAY_MODE_RAM (0<<0) + +/* PLAYCFG4: reg 0x09 RW */ + +#define AW86225_BIT_PLAYCFG4_STOP_MASK (~(1<<1)) +#define AW86225_BIT_PLAYCFG4_STOP_ON (1<<1) +#define AW86225_BIT_PLAYCFG4_STOP_OFF (0<<1) +#define AW86225_BIT_PLAYCFG4_GO_MASK (~(1<<0)) +#define AW86225_BIT_PLAYCFG4_GO_ON (1<<0) +#define AW86225_BIT_PLAYCFG4_GO_OFF (0<<0) + +/* WAVCFG1-8: reg 0x0A - reg 0x11 RW */ + +#define AW86225_BIT_WAVCFG_SEQWAIT_MASK (~(1<<7)) +#define AW86225_BIT_WAVCFG_SEQWAIT_TIME (1<<7) +#define AW86225_BIT_WAVCFG_SEQWAIT_NUMBER (0<<7) + +/* WAVCFG9-12: reg 0x12 - reg 0x15 RW */ + +#define AW86225_BIT_WAVLOOP_SEQ_ODD_MASK (~(0x0F<<4)) +#define AW86225_BIT_WAVLOOP_SEQ_ODD_INIFINITELY (0x0F<<4) +#define AW86225_BIT_WAVLOOP_SEQ_EVEN_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVLOOP_SEQ_EVEN_INIFINITELY (0x0F<<0) +#define AW86225_BIT_WAVLOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG9: reg 0x12 RW */ + +#define AW86225_BIT_WAVCFG9_SEQ1LOOP_MASK (~(0x0F<<4)) +#define AW86225_BIT_WAVCFG9_SEQ1LOOP_INIFINITELY (0x0F<<4) +#define AW86225_BIT_WAVCFG9_SEQ2LOOP_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVCFG9_SEQ2LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG10: reg 0x13 RW */ + +#define AW86225_BIT_WAVCFG10_SEQ3LOOP_MASK (~(0x0F<<4)) +#define AW86225_BIT_WAVCFG10_SEQ3LOOP_INIFINITELY (0x0F<<4) +#define AW86225_BIT_WAVCFG10_SEQ4LOOP_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVCFG10_SEQ4LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG11: reg 0x14 RW */ + +#define AW86225_BIT_WAVCFG11_SEQ5LOOP_MASK (~(0x0F<<4)) +#define AW86225_BIT_WAVCFG11_SEQ5LOOP_INIFINITELY (0x0F<<4) +#define AW86225_BIT_WAVCFG11_SEQ6LOOP_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVCFG11_SEQ6LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG12: reg 0x15 RW */ +#define AW86225_BIT_WAVCFG12_SEQ7LOOP_MASK (~(0x0F<<4)) +#define AW86225_BIT_WAVCFG12_SEQ7LOOP_INIFINITELY (0x0F<<4) +#define AW86225_BIT_WAVCFG12_SEQ8LOOP_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVCFG12_SEQ8LOOP_INIFINITELY (0x0F<<0) + +/* WAVCFG13: reg 0x16 RW */ + +#define AW86225_BIT_WAVCFG13_WAITSLOT_MASK (~(3<<5)) +#define AW86225_BIT_WAVCFG13_WAITSLOT_DIV_1 (0<<5) +#define AW86225_BIT_WAVCFG13_WAITSLOT_DIV_8 (1<<5) +#define AW86225_BIT_WAVCFG13_WAITSLOT_DIV_64 (2<<5) +#define AW86225_BIT_WAVCFG13_WAITSLOT_DIV_512 (3<<5) +#define AW86225_BIT_WAVCFG13_AUTO_MD_MASK (~(1<<4)) +#define AW86225_BIT_WAVCFG13_AUTO_MD_CONT_MODE (1<<4) +#define AW86225_BIT_WAVCFG13_AUTO_MD_SIN_WAV (0<<4) +#define AW86225_BIT_WAVCFG13_MAINLOOP_MASK (~(0x0F<<0)) +#define AW86225_BIT_WAVCFG13_MAINLOOP_INIFINITELY (0x0F<<0) + +/* CONTCFG1: reg 0x18 RW */ + +#define AW86225_BIT_CONTCFG1_EDGE_FRE_MASK (~(0x0F<<4)) +#define AW86225_BIT_CONTCFG1_EN_F0_DET_MASK (~(1<<3)) +#define AW86225_BIT_CONTCFG1_F0_DET_ENABLE (1<<3) +#define AW86225_BIT_CONTCFG1_F0_DET_DISABLE (0<<3) +#define AW86225_BIT_CONTCFG1_SIN_MODE_MASK (~(1<<0)) +#define AW86225_BIT_CONTCFG1_SIN_MODE_COS (1<<0) +#define AW86225_BIT_CONTCFG1_SIN_MODE_SINE (0<<0) + +/* CONTCFG5: reg 0x1C RW */ + +#define AW86225_BIT_CONTCFG5_BRK_GAIN_MASK (~(0x0F<<0)) + +/* CONTCFG6: reg 0x1D RW */ + +#define AW86225_BIT_CONTCFG6_TRACK_EN_MASK (~(1<<7)) +#define AW86225_BIT_CONTCFG6_TRACK_ENABLE (1<<7) +#define AW86225_BIT_CONTCFG6_TRACK_DISABLE (0<<7) +#define AW86225_BIT_CONTCFG6_DRV1_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG7: reg 0x1E RW */ + +#define AW86225_BIT_CONTCFG7_DRV2_LVL_MASK (~(0x7F<<0)) + +/* CONTCFG13: reg 0x24 RW */ + +#define AW86225_BIT_CONTCFG13_TSET_MASK (~(0x0F<<4)) +#define AW86225_BIT_CONTCFG13_BEME_SET_MASK (~(0x0F<<0)) + +/* RTPCFG1: reg 0x2D RW */ + +#define AW86225_BIT_RTPCFG1_ADDRH_MASK (~(0x0F<<0)) + +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_MASK (~(1<<5)) +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_EN (1<<5) +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_2K_DIS (0<<5) + +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_MASK (~(1<<4)) +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_EN (1<<4) +#define AW86225_BIT_RTPCFG1_SRAM_SIZE_1K_DIS (0<<4) + +/* RTPCFG3: reg 0x2F RW */ + +#define AW86225_BIT_RTPCFG3_FIFO_AEH_MASK (~(0x0F<<4)) +#define AW86225_BIT_RTPCFG3_FIFO_AFH_MASK (~(0x0F<<0)) + +#define AW86225_BIT_TRG_ENABLE_MASK (~(1<<7)) +#define AW86225_BIT_TRG_ENABLE (1<<7) +#define AW86225_BIT_TRG_DISABLE (0<<7) +#define AW86225_BIT_TRG_SEQ_MASK (~(0x7F<<0)) + +/* TRGCFG1: reg 0x33 RW */ + +#define AW86225_BIT_TRGCFG1_TRG1_POS_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG1_TRG1_POS_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG1_TRG1_POS_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG1_TRG1SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG2: reg 0x34 RW */ + +#define AW86225_BIT_TRGCFG2_TRG2_POS_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG2_TRG2_POS_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG2_TRG2_POS_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG2_TRG2SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG3: reg 0x35 RW */ + +#define AW86225_BIT_TRGCFG3_TRG3_POS_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG3_TRG3_POS_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG3_TRG3_POS_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG3_TRG3SEQ_P_MASK (~(0x7F<<0)) + +/* TRGCFG4: reg 0x36 RW */ + +#define AW86225_BIT_TRGCFG4_TRG1_NEG_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG4_TRG1_NEG_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG4_TRG1_NEG_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG4_TRG1SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG5: reg 0x37 RW */ + +#define AW86225_BIT_TRGCFG5_TRG2_NEG_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG5_TRG2_NEG_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG5_TRG2_NEG_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG5_TRG2SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG6: reg 0x38 RW */ + +#define AW86225_BIT_TRGCFG6_TRG3_NEG_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG6_TRG3_NEG_ENABLE (1<<7) +#define AW86225_BIT_TRGCFG6_TRG3_NEG_DISABLE (0<<7) +#define AW86225_BIT_TRGCFG6_TRG3SEQ_N_MASK (~(0x7F<<0)) + +/* TRGCFG7: reg 0x39 RW */ + +#define AW86225_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK (~(7<<5)) +#define AW86225_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK (~(7<<1)) +#define AW86225_BIT_TRGCFG7_TRG1_POLAR_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG7_TRG1_POLAR_NEG (1<<7) +#define AW86225_BIT_TRGCFG7_TRG1_POLAR_POS (0<<7) +#define AW86225_BIT_TRGCFG7_TRG1_MODE_MASK (~(1<<6)) +#define AW86225_BIT_TRGCFG7_TRG1_MODE_LEVEL (1<<6) +#define AW86225_BIT_TRGCFG7_TRG1_MODE_EDGE (0<<6) +#define AW86225_BIT_TRGCFG7_TRG1_AUTO_BRK_MASK (~(1<<5)) +#define AW86225_BIT_TRGCFG7_TRG1_AUTO_BRK_ENABLE (1<<5) +#define AW86225_BIT_TRGCFG7_TRG1_AUTO_BRK_DISABLE (0<<5) +#define AW86225_BIT_TRGCFG7_TRG2_POLAR_MASK (~(1<<3)) +#define AW86225_BIT_TRGCFG7_TRG2_POLAR_NEG (1<<3) +#define AW86225_BIT_TRGCFG7_TRG2_POLAR_POS (0<<3) +#define AW86225_BIT_TRGCFG7_TRG2_MODE_MASK (~(1<<2)) +#define AW86225_BIT_TRGCFG7_TRG2_MODE_LEVEL (1<<2) +#define AW86225_BIT_TRGCFG7_TRG2_MODE_EDGE (0<<2) +#define AW86225_BIT_TRGCFG7_TRG2_AUTO_BRK_MASK (~(1<<1)) +#define AW86225_BIT_TRGCFG7_TRG2_AUTO_BRK_ENABLE (1<<1) +#define AW86225_BIT_TRGCFG7_TRG2_AUTO_BRK_DISABLE (0<<1) + +/* TRGCFG8: reg 0x3A RW */ +#define AW86225_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK (~(7<<5)) +#define AW86225_BIT_TRGCFG8_TRG3_POLAR_MASK (~(1<<7)) +#define AW86225_BIT_TRGCFG8_TRG3_POLAR_NEG (1<<7) +#define AW86225_BIT_TRGCFG8_TRG3_POLAR_POS (0<<7) +#define AW86225_BIT_TRGCFG8_TRG3_MODE_MASK (~(1<<6)) +#define AW86225_BIT_TRGCFG8_TRG3_MODE_LEVEL (1<<6) +#define AW86225_BIT_TRGCFG8_TRG3_MODE_EDGE (0<<6) +#define AW86225_BIT_TRGCFG8_TRG3_AUTO_BRK_MASK (~(1<<5)) +#define AW86225_BIT_TRGCFG8_TRG3_AUTO_BRK_ENABLE (1<<5) +#define AW86225_BIT_TRGCFG8_TRG3_AUTO_BRK_DISABLE (0<<5) +#define AW86225_BIT_TRGCFG8_TRG_TRIG1_MODE_MASK (~(3<<3)) +#define AW86225_BIT_TRGCFG8_PWM_LRA (0<<3) +#define AW86225_BIT_TRGCFG8_PWM_ERA (1<<3) +#define AW86225_BIT_TRGCFG8_TRIG1 (2<<3) +#define AW86225_BIT_TRGCFG8_DISABLE (3<<3) +#define AW86225_BIT_TRGCFG8_TRG1_STOP_MASK (~(1<<2)) +#define AW86225_BIT_TRGCFG8_TRG1_STOP (1<<2) +#define AW86225_BIT_TRGCFG8_TRG2_STOP_MASK (~(1<<1)) +#define AW86225_BIT_TRGCFG8_TRG2_STOP (1<<1) +#define AW86225_BIT_TRGCFG8_TRG3_STOP_MASK (~(1<<0)) +#define AW86225_BIT_TRGCFG8_TRG3_STOP (1<<0) + +/* GLBCFG4: reg 0x3E RW */ + +#define AW86225_BIT_GLBCFG4_GO_PRIO_MASK (~(3<<6)) +#define AW86225_BIT_GLBCFG4_TRG3_PRIO_MASK (~(3<<4)) +#define AW86225_BIT_GLBCFG4_TRG2_PRIO_MASK (~(3<<2)) +#define AW86225_BIT_GLBCFG4_TRG1_PRIO_MASK (~(3<<0)) + +/* GLBRD5: reg 0x3F R0 */ + +#define AW86225_BIT_GLBRD5_STATE_MASK (~(15<<0)) +#define AW86225_BIT_GLBRD5_STATE_STANDBY (0<<0) +#define AW86225_BIT_GLBRD5_STATE_WAKEUP (1<<0) +#define AW86225_BIT_GLBRD5_STATE_STARTUP (2<<0) +#define AW86225_BIT_GLBRD5_STATE_WAIT (3<<0) +#define AW86225_BIT_GLBRD5_STATE_CONT_GO (6<<0) +#define AW86225_BIT_GLBRD5_STATE_RAM_GO (7<<0) +#define AW86225_BIT_GLBRD5_STATE_RTP_GO (8<<0) +#define AW86225_BIT_GLBRD5_STATE_TRIG_GO (9<<0) +#define AW86225_BIT_GLBRD5_STATE_I2S_GO (10<<0) +#define AW86225_BIT_GLBRD5_STATE_BRAKE (11<<0) +#define AW86225_BIT_GLBRD5_STATE_END (12<<0) + +/* RAMADDRH: reg 0x40 RWS */ + +#define AW86225_BIT_RAMADDRH_MASK (~(63<<0)) + +/* SYSCTRL1: reg 0x43 RW */ + +#define AW86225_BIT_SYSCTRL1_VBAT_MODE_MASK (~(1<<7)) +#define AW86225_BIT_SYSCTRL1_VBAT_MODE_HW (1<<7) +#define AW86225_BIT_SYSCTRL1_VBAT_MODE_SW (0<<7) +#define AW86225_BIT_SYSCTRL1_PERP_MASK (~(1<<6)) +#define AW86225_BIT_SYSCTRL1_PERP_ON (1<<6) +#define AW86225_BIT_SYSCTRL1_PERP_OFF (0<<6) +#define AW86225_BIT_SYSCTRL1_CLK_SEL_MASK (~(3<<4)) +#define AW86225_BIT_SYSCTRL1_CLK_SEL_OSC (1<<4) +#define AW86225_BIT_SYSCTRL1_CLK_SEL_AUTO (0<<4) +#define AW86225_BIT_SYSCTRL1_RAMINIT_MASK (~(1<<3)) +#define AW86225_BIT_SYSCTRL1_RAMINIT_ON (1<<3) +#define AW86225_BIT_SYSCTRL1_RAMINIT_OFF (0<<3) +#define AW86225_BIT_SYSCTRL1_EN_FIR_MASK (~(1<<2)) +#define AW86225_BIT_SYSCTRL1_FIR_ENABLE (0<<2) +#define AW86225_BIT_SYSCTRL1_WAKE_MODE_MASK (~(1<<1)) +#define AW86225_BIT_SYSCTRL1_WAKE_MODE_WAKEUP (1<<1) +#define AW86225_BIT_SYSCTRL1_WAKE_MODE_BST (0<<1) +#define AW86225_BIT_SYSCTRL1_RTP_CLK_MASK (~(1<<0)) +#define AW86225_BIT_SYSCTRL1_RTP_PLL (1<<0) +#define AW86225_BIT_SYSCTRL1_RTP_OSC (0<<0) + +/* SYSCTRL2: reg 0x44 RW */ + +#define AW86225_BIT_SYSCTRL2_WAKE_MASK (~(1<<7)) +#define AW86225_BIT_SYSCTRL2_WAKE_ON (1<<7) +#define AW86225_BIT_SYSCTRL2_WAKE_OFF (0<<7) +#define AW86225_BIT_SYSCTRL2_STANDBY_MASK (~(1<<6)) +#define AW86225_BIT_SYSCTRL2_STANDBY_ON (1<<6) +#define AW86225_BIT_SYSCTRL2_STANDBY_OFF (0<<6) +#define AW86225_BIT_SYSCTRL2_RTP_DLY_MASK (~(3<<4)) +#define AW86225_BIT_SYSCTRL2_INTN_PIN_MASK (~(1<<3)) +#define AW86225_BIT_SYSCTRL2_INTN (1<<3) +#define AW86225_BIT_SYSCTRL2_TRIG1 (0<<3) +#define AW86225_BIT_SYSCTRL2_WCK_PIN_MASK (~(1<<2)) +#define AW86225_BIT_SYSCTRL2_ENABLE_TRIG2 (1<<2) +#define AW86225_BIT_SYSCTRL2_DISENABLE_TRIG2 (0<<2) +#define AW86225_BIT_SYSCTRL2_WAVDAT_MODE_MASK (~(3<<0)) +#define AW86225_BIT_SYSCTRL2_RATE_12K (2<<0) +#define AW86225_BIT_SYSCTRL2_RATE_24K (0<<0) +#define AW86225_BIT_SYSCTRL2_RATE_48K (1<<0) + +/* SYSCTRL7: reg 0x49 RW */ + +#define AW86225_BIT_SYSCTRL7_GAIN_BYPASS_MASK (~(1<<6)) +#define AW86225_BIT_SYSCTRL7_GAIN_CHANGEABLE (1<<6) +#define AW86225_BIT_SYSCTRL7_GAIN_FIXED (0<<6) + +#define AW86225_BIT_SYSCTRL7_INT_EDGE_MODE_MASK (~(1<<5)) +#define AW86225_BIT_SYSCTRL7_INT_EDGE_MODE_POS (0<<5) +#define AW86225_BIT_SYSCTRL7_INT_EDGE_MODE_BOTH (1<<5) +#define AW86225_BIT_SYSCTRL7_INT_MODE_MASK (~(1<<4)) +#define AW86225_BIT_SYSCTRL7_INT_MODE_EDGE (1<<4) +#define AW86225_BIT_SYSCTRL7_INT_MODE_LEVEL (0<<4) + +#define AW86225_BIT_SYSCTRL7_INTP_MASK (~(1<<3)) +#define AW86225_BIT_SYSCTRL7_INTP_HIGH (1<<3) +#define AW86225_BIT_SYSCTRL7_INTP_LOW (0<<3) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_MASK (~(7<<0)) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_1 (0<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_2 (1<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_4 (2<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_5 (3<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_8 (4<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_10 (5<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_20 (6<<0) +#define AW86225_BIT_SYSCTRL7_D2S_GAIN_40 (7<<0) + +/* I2SCFG1: reg 0x4A RW */ + +#define AW86225_BIT_I2SCFG1_I2SMD_MASK (~(3<<6)) +#define AW86225_BIT_I2SCFG1_I2SFS_MASK (~(3<<4)) +#define AW86225_BIT_I2SCFG1_I2SFS_16BIT (0<<4) +#define AW86225_BIT_I2SCFG1_I2SFS_20BIT (1<<4) +#define AW86225_BIT_I2SCFG1_I2SFS_24BIT (2<<4) +#define AW86225_BIT_I2SCFG1_I2SFS_32BIT (3<<4) +#define AW86225_BIT_I2SCFG1_I2SBCK_MASK (~(3<<2)) +#define AW86225_BIT_I2SCFG1_I2SBCK_32FS (0<<2) +#define AW86225_BIT_I2SCFG1_I2SBCK_48FS (1<<2) +#define AW86225_BIT_I2SCFG1_I2SBCK_64FS (2<<2) +#define AW86225_BIT_I2SCFG1_RX_THRS_MASK (~(3<<0)) + +/* I2SCFG2: reg 0x4B RW */ + +#define AW86225_BIT_I2SCFG2_WSINV_MASK (~(1<<4)) +#define AW86225_BIT_I2SCFG2_WSINV_SWITCH (1<<4) +#define AW86225_BIT_I2SCFG2_WSINV_NO_SWITCH (0<<4) +#define AW86225_BIT_I2SCFG2_BCKINV_MASK (~(1<<3)) +#define AW86225_BIT_I2SCFG2_BCKINV_INVERT (1<<3) +#define AW86225_BIT_I2SCFG2_BCKINV_NOTINVT (0<<3) +#define AW86225_BIT_I2SCFG2_CHSEL_MASK (~(1<<2)) +#define AW86225_BIT_I2SCFG2_CHSEL_LEFT (1<<2) +#define AW86225_BIT_I2SCFG2_CHSEL_RIGHT (0<<2) +#define AW86225_BIT_I2SCFG2_I2S_INT_MASK (~(1<<1)) +#define AW86225_BIT_I2SCFG2_I2S_INT_ON (1<<1) +#define AW86225_BIT_I2SCFG2_I2S_INT_OFF (0<<1) +#define AW86225_BIT_I2SCFG2_I2S_EN_MASK (~(1<<0)) +#define AW86225_BIT_I2SCFG2_I2S_ENABLE (1<<0) +#define AW86225_BIT_I2SCFG2_I2S_DISABLE (0<<0) + +/* PWMCFG1: reg 0x4C RW */ + +#define AW86225_BIT_PWMCFG1_PRC_EN_MASK (~(1<<7)) +#define AW86225_BIT_PWMCFG1_PRC_ENABLE (1<<7) +#define AW86225_BIT_PWMCFG1_PRC_DISABLE (0<<7) +#define AW86225_BIT_PWMCFG1_PRCTIME_MASK (~(0x7F<<0)) + +/* PWMCFG2: reg 0x4D RW */ + +#define AW86225_BIT_PWMCFG2_REF_SEL_MASK (~(1<<5)) +#define AW86225_BIT_PWMCFG2_REF_SEL_TRIANGLE (1<<5) +#define AW86225_BIT_PWMCFG2_REF_SEL_SAWTOOTH (0<<5) +#define AW86225_BIT_PWMCFG2_PD_HWM_MASK (~(1<<4)) +#define AW86225_BIT_PWMCFG2_PD_HWM_ON (1<<4) +#define AW86225_BIT_PWMCFG2_PWMOE_MASK (~(1<<3)) +#define AW86225_BIT_PWMCFG2_PWMOE_ON (1<<3) +#define AW86225_BIT_PWMCFG2_PWMFRC_MASK (~(7<<0)) + +/* PWMCFG3: reg 0x4E RW */ + +#define AW86225_BIT_PWMCFG3_PR_EN_MASK (~(1<<7)) +#define AW86225_BIT_PWMCFG3_PR_ENABLE (1<<7) +#define AW86225_BIT_PWMCFG3_PR_DISABLE (0<<7) +#define AW86225_BIT_PWMCFG3_PRLVL_MASK (~(0x7F<<0)) + +/* DETCFG1: reg 0x51 RW */ + +#define AW86225_BIT_DETCFG1_FTS_GO_MASK (~(1<<7)) +#define AW86225_BIT_DETCFG1_FTS_GO_ENABLE (1<<7) +#define AW86225_BIT_DETCFG1_TEST_GO_MASK (~(1<<6)) +#define AW86225_BIT_DETCFG1_TEST_GO_ENABLE (1<<6) +#define AW86225_BIT_DETCFG1_ADO_SLOT_MODE_MASK (~(1<<5)) +#define AW86225_BIT_DETCFG1_ADO_SLOT_ADC_32 (1<<5) +#define AW86225_BIT_DETCFG1_ADO_SLOT_ADC_256 (0<<5) +#define AW86225_BIT_DETCFG1_RL_OS_MASK (~(1<<4)) +#define AW86225_BIT_DETCFG1_RL (1<<4) +#define AW86225_BIT_DETCFG1_OS (0<<4) +#define AW86225_BIT_DETCFG1_PRCT_MODE_MASK (~(1<<3)) +#define AW86225_BIT_DETCFG1_PRCT_MODE_INVALID (1<<3) +#define AW86225_BIT_DETCFG1_PRCT_MODE_VALID (0<<3) +#define AW86225_BIT_DETCFG1_CLK_ADC_MASK (~(7<<0)) +#define AW86225_BIT_DETCFG1_CLK_ADC_12M (0<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_6M (1<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_3M (2<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_1M5 (3<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_M75 (4<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_M37 (5<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_M18 (6<<0) +#define AW86225_BIT_DETCFG1_CLK_ADC_M09 (7<<0) + +/* DETCFG2: reg 0x52 RW */ + +#define AW86225_BIT_DETCFG2_VBAT_GO_MASK (~(1<<1)) +#define AW86225_BIT_DETCFG2_VABT_GO_ON (1<<1) +#define AW86225_BIT_DETCFG2_DIAG_GO_MASK (~(1<<0)) +#define AW86225_BIT_DETCFG2_DIAG_GO_ON (1<<0) + +/* DET_LO: reg 0x57 RW */ + +#define AW86225_BIT_DET_LO_TEST_MASK (~(3<<6)) +#define AW86225_BIT_DET_LO_VBAT_MASK (~(3<<4)) +#define AW86225_BIT_DET_LO_OS_MASK (~(3<<2)) +#define AW86225_BIT_DET_LO_RL_MASK (~(3<<0)) + +/* TRIMCFG1: reg:0x58 RW */ + +#define AW86225_BIT_TRIMCFG1_RL_TRIM_SRC_MASK (~(1<<6)) +#define AW86225_BIT_TRIMCFG1_RL_TRIM_SRC_REG (1<<6) +#define AW86225_BIT_TRIMCFG1_RL_TRIM_SRC_EFUSE (0<<6) +#define AW86225_BIT_TRIMCFG1_TRIM_RL_MASK (~(63<<0)) + +/* TRIMCFG3: reg:0x5A RW */ +#define AW86225_BIT_TRIMCFG3_OSC_TRIM_SRC_MASK (~(1<<7)) +#define AW86225_BIT_TRIMCFG3_OSC_TRIM_SRC_REG (1<<7) +#define AW86225_BIT_TRIMCFG3_OSC_TRIM_SRC_EFUSE (0<<7) +#define AW86225_BIT_TRIMCFG3_TRIM_LRA_MASK (~(63<<0)) + +/* PLLCFG1: reg:0x68 RW */ + +#define AW86225_BIT_PLLCFG1_PLL_TEST_EN_MASK (~(1<<6)) +#define AW86225_BIT_PLLCFG1_PLL_TEST_ENABLE (1<<6) +#define AW86225_BIT_PLLCFG1_PLL_TEST_DIV_MASK (~(3<<4)) +#define AW86225_BIT_PLLCFG1_PLL_TEST_DIV_1 (0<<4) +#define AW86225_BIT_PLLCFG1_PLL_TEST_DIV_2 (1<<4) +#define AW86225_BIT_PLLCFG1_PLL_TEST_DIV_4 (2<<4) +#define AW86225_BIT_PLLCFG1_PLL_TEST_DIV_8 (3<<4) +#define AW86225_BIT_PLLCFG1_PLL_BIAS_CP1_IEN_MASK (~(1<<3)) +#define AW86225_BIT_PLLCFG1_PLL_BIAS_CP1_IENABLE (1<<3) +#define AW86225_BIT_PLLCFG1_PLL_VTI_CP1_IEN_MASK (~(1<<2)) +#define AW86225_BIT_PLLCFG1_PLL_VTI_CP1_IENABLE (1<<2) +#define AW86225_BIT_PLLCFG1_PLL_DELAY_SEL_MASK (~(1<<1)) +#define AW86225_BIT_PLLCFG1_PLL_R1_SEL_MASK (~(1<<0)) + +/* PLLCFG2: reg:0x69 RW */ + +#define AW86225_BIT_PLLCFG2_PLL_CP1_SEL_MASK (~(0x0F<<4)) +#define AW86225_BIT_PLLCFG2_PLL_CP1_40UA (4<<4) +#define AW86225_BIT_PLLCFG2_PLL_CP1_50UA (5<<4) +#define AW86225_BIT_PLLCFG2_PLL_CP1_80UA (8<<4) +#define AW86225_BIT_PLLCFG2_PLL_CP1_100UA (10<<4) +#define AW86225_BIT_PLLCFG2_PLL_CP2_SEL_MASK (~(0x0F<<0)) +#define AW86225_BIT_PLLCFG2_PLL_CP2_40NA (1<<0) +#define AW86225_BIT_PLLCFG2_PLL_CP2_600NA (8<<0) +#define AW86225_BIT_PLLCFG2_PLL_CP2_800NA (10<<0) +#define AW86225_BIT_PLLCFG2_PLL_CP2_1200NA (12<<0) + +/* HDRVCFG1: reg:0x6A RW */ + +#define AW86225_BIT_HDRVCFG1_EN_HD_LOW_MASK (~(1<<7)) +#define AW86225_BIT_HDRVCFG1_EN_HD_HZ (0<<7) +#define AW86225_BIT_HDRVCFG1_EN_HD_PD (1<<7) + +/* IOCFG1: reg:0x6B RW */ + +#define AW86225_BIT_IOCFG1_HSEN_MASK (~(1<<6)) +#define AW86225_BIT_IOCFG1_HS_ENABLE (1<<6) +#define AW86225_BIT_IOCFG1_HS_DISABLE (0<<6) +#define AW86225_BIT_IOCFG1_IO_FAST_MASK (~(3<<4)) +#define AW86225_BIT_IOCFG1_ALL_IO_FAST_ENABLE (3<<4) +#define AW86225_BIT_IOCFG1_IIS_IO_FAST_ENABLE (2<<4) +#define AW86225_BIT_IOCFG1_IIC_IO_FAST_ENABLE (1<<4) +#define AW86225_BIT_IOCFG1_IO_FAST_DISABLE (0<<4) + +/* OCCFG1: reg:0x74 RW */ + +#define AW86225_BIT_OCCFG1_HS_IOC_MASK (~(3<<6)) +#define AW86225_BIT_OCCFG1_HS_IOC_3A15 (0<<6) +#define AW86225_BIT_OCCFG1_HS_IOC_3A65 (1<<6) +#define AW86225_BIT_OCCFG1_HS_IOC_4A15 (2<<6) +#define AW86225_BIT_OCCFG1_HS_IOC_4A65 (3<<6) +#define AW86225_BIT_OCCFG1_LS_IOC_MASK (~(3<<4)) +#define AW86225_BIT_OCCFG1_LS_IOC_3A15 (0<<4) +#define AW86225_BIT_OCCFG1_LS_IOC_3A65 (1<<4) +#define AW86225_BIT_OCCFG1_LS_IOC_4A15 (2<<4) +#define AW86225_BIT_OCCFG1_LS_IOC_4A65 (3<<4) +#define AW86225_BIT_OCCFG1_OCDT_MASK (~(3<<2)) + +#define AW86225_BIT_OCCLK_MODE_MASK (~(3<<0)) + +/* ADCCFG1: reg:0x75 RW */ + +#define AW86225_BIT_ADCCFG1_EN_OS_DET_MASK (~(1<<7)) +#define AW86225_BIT_ADCCFG1_EN_RL_DET_MASK (~(1<<6)) +#define AW86225_BIT_ADCCFG1_D2S_SEL_HDRV_MASK (~(1<<5)) +#define AW86225_BIT_ADCCFG1_AD_SEL_HDP_MASK (~(1<<4)) +#define AW86225_BIT_ADCCFG1_AD_SEL_HDN_MASK (~(1<<3)) +#define AW86225_BIT_ADCCFG1_AD_SEL_VBAT_MASK (~(1<<2)) +#define AW86225_BIT_ADCCFG1_AD_SEL_TEST_MASK (~(1<<1)) +#define AW86225_BIT_ADCCFG1_AD_SEL_D2S_MASK (~(1<<0)) + +/* D2SCFG1: reg:0x76 RW */ + +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_MASK (~(7<<0)) +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_48K (0<<0) +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_24K (1<<0) +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_12K (2<<0) +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_6K (3<<0) +#define AW86225_BIT_D2SCFG1_CLK_TRIM_MODE_12M (4<<0) + +/* ANACFG8: reg:0x77 RW */ + +#define AW86225_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK (~(1<<6)) +#define AW86225_BIT_ANACFG8_TRTF_CTRL_HDRV (3<<6) + +#endif /* __DRIVERS_INPUT_AW86225_REG_H */ diff --git a/include/nuttx/input/aw86225.h b/include/nuttx/input/aw86225.h new file mode 100644 index 0000000000..2e2a5ececa --- /dev/null +++ b/include/nuttx/input/aw86225.h @@ -0,0 +1,161 @@ +/**************************************************************************** + * include/nuttx/input/aw86225.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_INPUT_AW86225_H_ +#define __INCLUDE_NUTTX_INPUT_AW86225_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AW86225_HAP_BRAKE_PATTERN_MAX 4 /* waveform brake pattern length */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* struct aw86225_hap_effect - effect configuration parameters + */ + +struct aw86225_hap_effect +{ + int id; + FAR uint8_t *pattern; + int pattern_length; + uint16_t play_rate_us; + uint16_t vmax_mv; + uint8_t wf_repeat_n; + uint8_t wf_s_repeat_n; + uint8_t brake[AW86225_HAP_BRAKE_PATTERN_MAX]; + int brake_pattern_length; + bool brake_en; + bool lra_auto_res_disable; +}; + +/* struct aw86225_config - defines parameters of aw86225 + * configuration. + */ + +struct aw86225_config +{ + /* AW86225 work mode init */ + + unsigned int mode; + + /* F0 work param */ + + unsigned int f0_ref; + unsigned int f0_cali_percent; + + /* Cont work param */ + + unsigned int cont_drv1_lvl_dt; + unsigned int cont_drv2_lvl_dt; + unsigned int cont_drv1_time_dt; + unsigned int cont_drv2_time_dt; + unsigned int cont_wait_num_dt; + unsigned int cont_brk_time_dt; + unsigned int cont_track_margin; + unsigned int cont_tset; + unsigned int cont_bemf_set; + unsigned int cont_brk_gain; + + /* Motor d2s_gain strength param */ + + unsigned int d2s_gain; + + /* AW86225 reg sysctrl value */ + + unsigned int sine_array[4]; + + /* The boundry between ram mode and rtp mode */ + + unsigned int effect_id_boundary; + + /* The number of rtp file max */ + + unsigned int effect_max; + + /* Duration of vibration for each rtp file */ + + unsigned int rtp_time[190]; + + /* Whether to activate automatic braking after RTP/RAM/CONT */ + + bool is_enabled_auto_bst; +}; + +/* struct aw86225_board_config - aw86225 driver param + * configuration. + */ + +struct aw86225_board_config +{ + bool is_used_irq; + int rstpin; + int intpin; + int powerpin; + int irq; + int effects_count; + uint8_t addr; /* I2C address */ + int freq; /* I2C frequency */ + FAR struct aw86225_hap_effect *predefined; + + /* Motor driver registration path */ + + FAR const char *path; + FAR struct aw86225_config *config; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: aw86225_initialize + * + * Description: + * aw86225 motor driver initialize + * + * Input Parameters: + * master - i2c master param + * ioedev - io dev pin set + * config - the board config param of aw86225 + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int aw86225_initialize(FAR struct i2c_master_s *master, + FAR struct ioexpander_dev_s *ioedev, + FAR const struct aw86225_board_config *config); + +#endif /* __INCLUDE_NUTTX_INPUT_AW86225_H_ */