input: misc: Import Awinic AW8697 haptic driver

From branch: redwood-s-oss

Change-Id: I373e5948648e9dec064ea0cbd8c716f51552bab7
This commit is contained in:
Giovanni Ricca 2023-01-30 13:08:13 +05:30
parent b8bcdf05ce
commit eac11eac42
No known key found for this signature in database
10 changed files with 6274 additions and 1 deletions

View File

@ -914,4 +914,7 @@ config INPUT_STPMIC1_ONKEY
To compile this driver as a module, choose M here: the
module will be called stpmic1_onkey.
source "drivers/input/misc/aw8697_haptic/Kconfig"
endif

View File

@ -87,4 +87,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
obj-$(CONFIG_INPUT_AW8697_HAPTIC) += aw8697_haptic/

View File

@ -0,0 +1,14 @@
#
# Awinic aw8697 driver
#
config INPUT_AW8697_HAPTIC
tristate "Awinic AW8697 HAPTIC"
depends on I2C
help
Say Y here if you have Awinic AW8697 haptic controller
chip in your system.
If unsure, say N.
To compile this driver as a module, choose M here.

View File

@ -0,0 +1,8 @@
ifeq ($(TARGET_PRODUCT),lmi)
CDEFINES += -DUSE_CONT_F0_CALI
KBUILD_CPPFLAGS += $(CDEFINES)
endif
aw8697-haptic-objs = ringbuffer.o aw8697.o
obj-$(CONFIG_INPUT_AW8697_HAPTIC) += aw8697-haptic.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,466 @@
#ifndef _AW8697_H_
#define _AW8697_H_
/*********************************************************
*
* kernel version
*
********************************************************/
#define INPUT_DEV
//#define TEST_RTP
#define TEST_CONT_TO_RAM
/*********************************************************
*
* aw8697.h
*
********************************************************/
#include <linux/regmap.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/hrtimer.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/leds.h>
#include <linux/atomic.h>
/*********************************************************
*
* marco
*
********************************************************/
#define AW8697_CHIPID 0x97
#define MAX_I2C_BUFFER_SIZE 65536
#define AW8697_SEQUENCER_SIZE 8
#define AW8697_SEQUENCER_LOOP_SIZE 4
#define AW8697_RTP_I2C_SINGLE_MAX_NUM 512
#define HAPTIC_MAX_TIMEOUT 10000
#define AW8697_VBAT_REFER 4200
#define AW8697_VBAT_MIN 3000
#define AW8697_VBAT_MAX 4500
#define ENABLE_PIN_CONTROL
#ifdef INPUT_DEV
/* common definitions */
#define HAP_BRAKE_PATTERN_MAX 4
#define HAP_WAVEFORM_BUFFER_MAX 8 /*used */
#define HAP_VMAX_MV_DEFAULT 1800
#define HAP_VMAX_MV_MAX 3596
#define HAP_PLAY_RATE_US_DEFAULT 5715 /*used */
#define HAP_PLAY_RATE_US_MAX 20475
#define HAP_PLAY_RATE_US_LSB 5
#define VMAX_MIN_PLAY_TIME_US 20000
#define HAP_SC_DET_MAX_COUNT 5
#define HAP_SC_DET_TIME_US 1000000
#define FF_EFFECT_COUNT_MAX 32
#define HAP_DISABLE_DELAY_USEC 1000
#endif
/*
* trig default high level
* ___________ _________________
* | |
* | |
* |___________|
* first edge
* second edge
*
*
* trig default low level
* ___________
* | |
* | |
* __________| |_________________
* first edge
* second edge
*/
/* trig config */
/*dts config
* default_level -> 1: high level; 0: low level
* dual_edge -> 1: dual edge; 0: first edge
*vib_trig_config = <
* 1 1 1 1 2
* enable default_level dual_edge first_seq second_seq
* 1 1 2 1 2
* enable default_level dual_edge first_seq second_seq
* 1 1 3 1 2
* enable default_level dual_edge first_seq second_seq
*/
#define AW8697_TRIG_NUM 3
enum aw8697_flags {
AW8697_FLAG_NONR = 0,
AW8697_FLAG_SKIP_INTERRUPTS = 1,
};
enum aw8697_haptic_read_write {
AW8697_HAPTIC_CMD_READ_REG = 0,
AW8697_HAPTIC_CMD_WRITE_REG = 1,
};
enum aw8697_haptic_work_mode {
AW8697_HAPTIC_STANDBY_MODE = 0,
AW8697_HAPTIC_RAM_MODE = 1,
AW8697_HAPTIC_RTP_MODE = 2,
AW8697_HAPTIC_TRIG_MODE = 3,
AW8697_HAPTIC_CONT_MODE = 4,
AW8697_HAPTIC_RAM_LOOP_MODE = 5,
};
enum aw8697_haptic_bst_mode {
AW8697_HAPTIC_BYPASS_MODE = 0,
AW8697_HAPTIC_BOOST_MODE = 1,
};
enum aw8697_haptic_activate_mode {
AW8697_HAPTIC_ACTIVATE_RAM_MODE = 0,
AW8697_HAPTIC_ACTIVATE_CONT_MODE = 1,
AW8697_HAPTIC_ACTIVATE_RTP_MODE = 2,
AW8697_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3,
};
enum aw8697_haptic_cont_vbat_comp_mode {
AW8697_HAPTIC_CONT_VBAT_SW_COMP_MODE = 0,
AW8697_HAPTIC_CONT_VBAT_HW_COMP_MODE = 1,
};
enum aw8697_haptic_ram_vbat_comp_mode {
AW8697_HAPTIC_RAM_VBAT_COMP_DISABLE = 0,
AW8697_HAPTIC_RAM_VBAT_COMP_ENABLE = 1,
};
enum aw8697_haptic_f0_flag {
AW8697_HAPTIC_LRA_F0 = 0,
AW8697_HAPTIC_CALI_F0 = 1,
};
enum aw8697_haptic_pwm_mode {
AW8697_PWM_48K = 0,
AW8697_PWM_24K = 1,
AW8697_PWM_12K = 2,
};
enum aw8697_haptic_play {
AW8697_HAPTIC_PLAY_NULL = 0,
AW8697_HAPTIC_PLAY_ENABLE = 1,
AW8697_HAPTIC_PLAY_STOP = 2,
AW8697_HAPTIC_PLAY_GAIN = 8,
};
enum aw8697_haptic_cmd {
AW8697_HAPTIC_CMD_NULL = 0,
AW8697_HAPTIC_CMD_ENABLE = 1,
AW8697_HAPTIC_CMD_STOP = 255,
};
enum haptics_custom_effect_param {
CUSTOM_DATA_EFFECT_IDX,
CUSTOM_DATA_TIMEOUT_SEC_IDX,
CUSTOM_DATA_TIMEOUT_MSEC_IDX,
CUSTOM_DATA_LEN,
};
enum aw8697_haptic_strength {
AW8697_LIGHT_MAGNITUDE = 0x3fff,
AW8697_MEDIUM_MAGNITUDE = 0x5fff,
AW8697_STRONG_MAGNITUDE = 0x7fff,
};
/*********************************************************
*
* struct
*
********************************************************/
struct fileops {
unsigned char cmd;
unsigned char reg;
unsigned char ram_addrh;
unsigned char ram_addrl;
};
struct ram {
unsigned int len;
unsigned int check_sum;
unsigned int base_addr;
unsigned char version;
unsigned char ram_shift;
unsigned char baseaddr_shift;
};
struct haptic_ctr {
unsigned char cmd;
unsigned char play;
unsigned char wavseq;
unsigned char loop;
unsigned char gain;
};
struct haptic_audio {
struct mutex lock;
struct hrtimer timer;
struct work_struct work;
int delay_val;
int timer_val;
unsigned char cnt;
struct haptic_ctr data[256];
struct haptic_ctr ctr;
unsigned char ori_gain;
};
struct trig {
unsigned char enable;
unsigned char default_level;
unsigned char dual_edge;
unsigned char frist_seq;
unsigned char second_seq;
};
struct aw8697_dts_info {
unsigned int mode;
unsigned int f0_pre;
unsigned int f0_cali_percen;
unsigned int cont_drv_lvl;
unsigned int cont_drv_lvl_ov;
unsigned int cont_td;
unsigned int cont_zc_thr;
unsigned int cont_num_brk;
unsigned int f0_coeff;
unsigned int f0_trace_parameter[4];
unsigned int bemf_config[4];
unsigned int sw_brake;
unsigned int tset;
unsigned int r_spare;
unsigned int bstdbg[6];
unsigned int parameter1;
unsigned int effect_id_boundary;
unsigned int effect_max;
unsigned int rtp_time[175];
unsigned int trig_config[3][5];
unsigned int bst_vol_default;
unsigned int bst_vol_ram;
unsigned int bst_vol_rtp;
};
#ifdef INPUT_DEV
enum actutor_type {
ACT_LRA,
ACT_ERM,
};
enum lra_res_sig_shape {
RES_SIG_SINE,
RES_SIG_SQUARE,
};
enum lra_auto_res_mode {
AUTO_RES_MODE_ZXD,
AUTO_RES_MODE_QWD,
};
enum wf_src {
INT_WF_VMAX,
INT_WF_BUFFER,
EXT_WF_AUDIO,
EXT_WF_PWM,
};
struct qti_hap_effect {
int id;
u8 *pattern;
int pattern_length;
u16 play_rate_us;
u16 vmax_mv;
u8 wf_repeat_n;
u8 wf_s_repeat_n;
u8 brake[HAP_BRAKE_PATTERN_MAX];
int brake_pattern_length;
bool brake_en;
bool lra_auto_res_disable;
};
struct qti_hap_play_info {
struct qti_hap_effect *effect;
u16 vmax_mv;
int length_us;
int playing_pos;
bool playing_pattern;
};
struct qti_hap_config {
enum actutor_type act_type;
enum lra_res_sig_shape lra_shape;
enum lra_auto_res_mode lra_auto_res_mode;
enum wf_src ext_src;
u16 vmax_mv;
u16 play_rate_us;
bool lra_allow_variable_play_rate;
bool use_ext_wf_src;
};
#endif
#ifdef ENABLE_PIN_CONTROL
const char * const pctl_names[] = {
"aw8697_reset_reset",
"aw8697_reset_active",
"aw8697_interrupt_active",
};
#endif
struct aw8697 {
struct i2c_client *i2c;
struct mutex lock;
#ifdef ENABLE_PIN_CONTROL
struct pinctrl *aw8697_pinctrl;
struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
#endif
int enable_pin_control;
struct work_struct vibrator_work;
struct work_struct rtp_work;
struct work_struct set_gain_work;
struct delayed_work ram_work;
struct fileops fileops;
struct ram ram;
struct timespec64 start, end;
unsigned int timeval_flags;
unsigned int osc_cali_flag;
unsigned long int microsecond;
unsigned int sys_frequency;
unsigned int rtp_len;
unsigned int lra_calib_data;
unsigned int f0_calib_data;
int reset_gpio;
int irq_gpio;
unsigned char hwen_flag;
unsigned char flags;
unsigned char chipid;
unsigned char play_mode;
unsigned char activate_mode;
unsigned char auto_boost;
unsigned char wk_lock_flag;
int state;
int duration;
int amplitude;
int index;
int vmax;
int gain;
u16 new_gain;
unsigned char level;
unsigned char seq[AW8697_SEQUENCER_SIZE];
unsigned char loop[AW8697_SEQUENCER_SIZE];
unsigned int rtp_cnt;
unsigned int rtp_file_num;
unsigned char rtp_init;
unsigned char ram_init;
unsigned int f0;
unsigned int cont_f0;
unsigned char max_pos_beme;
unsigned char max_neg_beme;
unsigned char f0_cali_flag;
bool f0_cali_status;
unsigned int osc_cali_run;
unsigned char ram_vbat_comp;
unsigned int vbat;
unsigned int lra;
struct trig trig[AW8697_TRIG_NUM];
struct haptic_audio haptic_audio;
struct aw8697_dts_info info;
atomic_t is_in_rtp_loop;
atomic_t exit_in_rtp_loop;
atomic_t is_in_write_loop;
wait_queue_head_t wait_q;//wait queue for exit irq mode
wait_queue_head_t stop_wait_q; //wait queue for stop rtp mode
struct workqueue_struct *work_queue;
#ifdef INPUT_DEV
struct platform_device *pdev;
struct device *dev;
struct regmap *regmap;
struct input_dev *input_dev;
struct pwm_device *pwm_dev;
struct qti_hap_config config;
struct qti_hap_play_info play;
struct qti_hap_effect *predefined;
struct qti_hap_effect constant;
struct regulator *vdd_supply;
struct hrtimer stop_timer;
struct hrtimer hap_disable_timer;
struct hrtimer timer; /*test used ,del */
struct dentry *hap_debugfs;
struct mutex rtp_lock;
spinlock_t bus_lock;
ktime_t last_sc_time;
int play_irq;
int sc_irq;
int effects_count;
int sc_det_count;
u16 reg_base;
bool perm_disable;
bool play_irq_en;
bool vdd_enabled;
int effect_type;
int effect_id;
int test_val;
int is_custom_wave;
#endif
};
struct aw8697_container {
int len;
unsigned char data[];
};
/*********************************************************
*
* ioctl
*
********************************************************/
struct aw8697_seq_loop {
unsigned char loop[AW8697_SEQUENCER_SIZE];
};
struct aw8697_que_seq {
unsigned char index[AW8697_SEQUENCER_SIZE];
};
#define AW8697_HAPTIC_IOCTL_MAGIC 'h'
#define AW8697_HAPTIC_SET_QUE_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
1,\
struct aw8697_que_seq*)
#define AW8697_HAPTIC_SET_SEQ_LOOP _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
2,\
struct aw8697_seq_loop*)
#define AW8697_HAPTIC_PLAY_QUE_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
3,\
unsigned int)
#define AW8697_HAPTIC_SET_BST_VOL _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
4,\
unsigned int)
#define AW8697_HAPTIC_SET_BST_PEAK_CUR _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
5,\
unsigned int)
#define AW8697_HAPTIC_SET_GAIN _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
6,\
unsigned int)
#define AW8697_HAPTIC_PLAY_REPEAT_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
7,\
unsigned int)
#endif

View File

@ -0,0 +1,117 @@
#ifndef __AW8697_CONFIG_H__
#define __AW8697_CONFIG_H__
#define AW8697_BSTCFG_PEAKCUR_LIMIT 0x07
#define AW8697_DEFAULT_PEAKCUR AW8697_BIT_BSTCFG_PEAKCUR_3P5A
#define AW8697_CONT_PLAYBACK_MODE AW8697_BIT_CONT_CTRL_CLOSE_PLAYBACK
/*#define CONFIG_DEBUG_FS*/
/*#ifdef INPUT_DEV*/
#if 1
/* haptics module register definitions */
#define REG_HAP_STATUS1 0x0A
#define HAP_SC_DET_BIT BIT(3)
#define HAP_BUSY_BIT BIT(1)
#define REG_HAP_EN_CTL1 0x46
#define HAP_EN_BIT BIT(7)
#define REG_HAP_EN_CTL2 0x48
#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
#define HAP_BRAKE_EN_BIT BIT(0)
#define REG_HAP_EN_CTL3 0x4A
#define HAP_HBRIDGE_EN_BIT BIT(7)
#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
#define HAP_ILIM_EN_BIT BIT(5)
#define HAP_ILIM_CC_EN_BIT BIT(4)
#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
#define HAP_DAC_EN_BIT BIT(2)
#define HAP_ZX_HYST_EN_BIT BIT(1)
#define HAP_PWM_CTL_EN_BIT BIT(0)
#define REG_HAP_AUTO_RES_CTRL 0x4B
#define HAP_AUTO_RES_EN_BIT BIT(7)
#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
#define AUTO_RES_EN_DLY(x) x
#define REG_HAP_CFG1 0x4C
#define REG_HAP_CFG2 0x4D
#define HAP_LRA_RES_TYPE_BIT BIT(0)
#define REG_HAP_SEL 0x4E
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
#define HAP_WF_SOURCE_SHIFT 4
#define HAP_WF_TRIGGER_BIT BIT(0)
#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
#define REG_HAP_AUTO_RES_CFG 0x4F
#define HAP_AUTO_RES_MODE_BIT BIT(7)
#define HAP_AUTO_RES_MODE_SHIFT 7
#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
#define HAP_CAL_EOP_EN_BIT BIT(3)
#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
#define REG_HAP_SLEW_CFG 0x50
#define REG_HAP_VMAX_CFG 0x51
#define HAP_VMAX_SIGN_BIT BIT(7)
#define HAP_VMAX_OVD_BIT BIT(6)
#define HAP_VMAX_MV_MASK GENMASK(5, 1)
#define HAP_VMAX_MV_SHIFT 1
#define HAP_VMAX_MV_LSB 116
#define REG_HAP_ILIM_CFG 0x52
#define HAP_ILIM_SEL_1000MA BIT(1)
#define HAP_ILIM_DEFAULT_SEL HAP_ILIM_SEL_1000MA
#define REG_HAP_SC_DEB_CFG 0x53
#define REG_HAP_RATE_CFG1 0x54
#define REG_HAP_RATE_CFG2 0x55
#define REG_HAP_INTERNAL_PWM 0x56
#define REG_HAP_EXTERNAL_PWM 0x57
#define REG_HAP_PWM 0x58
#define REG_HAP_SC_CLR 0x59
#define HAP_SC_CLR_BIT BIT(0)
#define REG_HAP_ZX_CFG 0x5A
#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
#define ZX_DET_DEB_10US 0
#define ZX_DET_DEB_20US 1
#define ZX_DET_DEB_40US 2
#define ZX_DET_DEB_80US 3
#define REG_HAP_BRAKE 0x5C
#define HAP_BRAKE_PATTERN_MASK 0x3
#define HAP_BRAKE_PATTERN_SHIFT 2
#define REG_HAP_WF_REPEAT 0x5E
#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
#define HAP_WF_REPEAT_SHIFT 4
#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
#define REG_HAP_WF_S1 0x60
#define HAP_WF_SIGN_BIT BIT(7)
#define HAP_WF_OVD_BIT BIT(6)
#define HAP_WF_AMP_BIT GENMASK(5, 1)
#define HAP_WF_AMP_SHIFT 1
#define REG_HAP_PLAY 0x70
#define HAP_PLAY_BIT BIT(7)
#define REG_HAP_SEC_ACCESS 0xD0
static int wf_repeat[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
static int wf_s_repeat[4] = { 1, 2, 4, 8 };
#endif
#endif

View File

@ -0,0 +1,539 @@
#ifndef _AW8697_REG_H_
#define _AW8697_REG_H_
/********************************************
* Register List
*******************************************/
#define AW8697_REG_ID 0x00
#define AW8697_REG_SYSST 0x01
#define AW8697_REG_SYSINT 0x02
#define AW8697_REG_SYSINTM 0x03
#define AW8697_REG_SYSCTRL 0x04
#define AW8697_REG_GO 0x05
#define AW8697_REG_RTP_DATA 0x06
#define AW8697_REG_WAVSEQ1 0x07
#define AW8697_REG_WAVSEQ2 0x08
#define AW8697_REG_WAVSEQ3 0x09
#define AW8697_REG_WAVSEQ4 0x0a
#define AW8697_REG_WAVSEQ5 0x0b
#define AW8697_REG_WAVSEQ6 0x0c
#define AW8697_REG_WAVSEQ7 0x0d
#define AW8697_REG_WAVSEQ8 0x0e
#define AW8697_REG_WAVLOOP1 0x0f
#define AW8697_REG_WAVLOOP2 0x10
#define AW8697_REG_WAVLOOP3 0x11
#define AW8697_REG_WAVLOOP4 0x12
#define AW8697_REG_MAIN_LOOP 0x13
#define AW8697_REG_TRG1_WAV_P 0x14
#define AW8697_REG_TRG2_WAV_P 0x15
#define AW8697_REG_TRG3_WAV_P 0x16
#define AW8697_REG_TRG1_WAV_N 0x17
#define AW8697_REG_TRG2_WAV_N 0x18
#define AW8697_REG_TRG3_WAV_N 0x19
#define AW8697_REG_TRG_PRIO 0x1a
#define AW8697_REG_TRG_CFG1 0x1b
#define AW8697_REG_TRG_CFG2 0x1c
#define AW8697_REG_DBGCTRL 0x20
#define AW8697_REG_BASE_ADDRH 0x21
#define AW8697_REG_BASE_ADDRL 0x22
#define AW8697_REG_FIFO_AEH 0x23
#define AW8697_REG_FIFO_AEL 0x24
#define AW8697_REG_FIFO_AFH 0x25
#define AW8697_REG_FIFO_AFL 0x26
#define AW8697_REG_WAKE_DLY 0x27
#define AW8697_REG_START_DLY 0x28
#define AW8697_REG_END_DLY_H 0x29
#define AW8697_REG_END_DLY_L 0x2a
#define AW8697_REG_DATCTRL 0x2b
#define AW8697_REG_PWMDEL 0x2c
#define AW8697_REG_PWMPRC 0x2d
#define AW8697_REG_PWMDBG 0x2e
#define AW8697_REG_LDOCTRL 0x2f
#define AW8697_REG_DBGSTAT 0x30
#define AW8697_REG_BSTDBG1 0x31
#define AW8697_REG_BSTDBG2 0x32
#define AW8697_REG_BSTDBG3 0x33
#define AW8697_REG_BSTCFG 0x34
#define AW8697_REG_ANADBG 0x35
#define AW8697_REG_ANACTRL 0x36
#define AW8697_REG_CPDBG 0x37
#define AW8697_REG_GLBDBG 0x38
#define AW8697_REG_DATDBG 0x39
#define AW8697_REG_BSTDBG4 0x3a
#define AW8697_REG_BSTDBG5 0x3b
#define AW8697_REG_BSTDBG6 0x3c
#define AW8697_REG_HDRVDBG 0x3d
#define AW8697_REG_PRLVL 0x3e
#define AW8697_REG_PRTIME 0x3f
#define AW8697_REG_RAMADDRH 0x40
#define AW8697_REG_RAMADDRL 0x41
#define AW8697_REG_RAMDATA 0x42
#define AW8697_REG_GLB_STATE 0x46
#define AW8697_REG_BST_AUTO 0x47
#define AW8697_REG_CONT_CTRL 0x48
#define AW8697_REG_F_PRE_H 0x49
#define AW8697_REG_F_PRE_L 0x4a
#define AW8697_REG_TD_H 0x4b
#define AW8697_REG_TD_L 0x4c
#define AW8697_REG_TSET 0x4d
#define AW8697_REG_TRIM_LRA 0x5b
#define AW8697_REG_R_SPARE 0x5d
#define AW8697_REG_D2SCFG 0x5e
#define AW8697_REG_DETCTRL 0x5f
#define AW8697_REG_RLDET 0x60
#define AW8697_REG_OSDET 0x61
#define AW8697_REG_VBATDET 0x62
#define AW8697_REG_TESTDET 0x63
#define AW8697_REG_DETLO 0x64
#define AW8697_REG_BEMFDBG 0x65
#define AW8697_REG_ADCTEST 0x66
#define AW8697_REG_BEMFTEST 0x67
#define AW8697_REG_F_LRA_F0_H 0x68
#define AW8697_REG_F_LRA_F0_L 0x69
#define AW8697_REG_F_LRA_CONT_H 0x6a
#define AW8697_REG_F_LRA_CONT_L 0x6b
#define AW8697_REG_WAIT_VOL_MP 0x6d
#define AW8697_REG_WAIT_VOL_MN 0x6f
#define AW8697_REG_BEMF_VOL_H 0x70
#define AW8697_REG_BEMF_VOL_L 0x71
#define AW8697_REG_ZC_THRSH_H 0x72
#define AW8697_REG_ZC_THRSH_L 0x73
#define AW8697_REG_BEMF_VTHH_H 0x74
#define AW8697_REG_BEMF_VTHH_L 0x75
#define AW8697_REG_BEMF_VTHL_H 0x76
#define AW8697_REG_BEMF_VTHL_L 0x77
#define AW8697_REG_BEMF_NUM 0x78
#define AW8697_REG_DRV_TIME 0x79
#define AW8697_REG_TIME_NZC 0x7a
#define AW8697_REG_DRV_LVL 0x7b
#define AW8697_REG_DRV_LVL_OV 0x7c
#define AW8697_REG_NUM_F0_1 0x7d
#define AW8697_REG_NUM_F0_2 0x7e
#define AW8697_REG_NUM_F0_3 0x7f
/********************************************
* Register Access
*******************************************/
#define REG_NONE_ACCESS 0
#define REG_RD_ACCESS (1 << 0)
#define REG_WR_ACCESS (1 << 1)
#define AW8697_REG_MAX 0xff
const unsigned char aw8697_reg_access[AW8697_REG_MAX] = {
[AW8697_REG_ID] = REG_RD_ACCESS,
[AW8697_REG_SYSST] = REG_RD_ACCESS,
[AW8697_REG_SYSINT] = REG_RD_ACCESS,
[AW8697_REG_SYSINTM] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_SYSCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_GO] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_RTP_DATA] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ1] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ2] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ3] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ4] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ5] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ6] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ7] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVSEQ8] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVLOOP1] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVLOOP2] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVLOOP3] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAVLOOP4] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_MAIN_LOOP] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG1_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG2_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG3_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG1_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG2_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG3_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG_PRIO] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG_CFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRG_CFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DBGCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BASE_ADDRH] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BASE_ADDRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_FIFO_AEH] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_FIFO_AEL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_FIFO_AFH] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_FIFO_AFL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAKE_DLY] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_START_DLY] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_END_DLY_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_END_DLY_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DATCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_PWMDEL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_PWMPRC] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_PWMDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_LDOCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DBGSTAT] = REG_RD_ACCESS,
[AW8697_REG_BSTDBG1] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTDBG2] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTDBG3] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTCFG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_ANADBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_ANACTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_CPDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_GLBDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DATDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTDBG4] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTDBG5] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BSTDBG6] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_HDRVDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_PRLVL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_PRTIME] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_RAMADDRH] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_RAMADDRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_RAMDATA] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_GLB_STATE] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BST_AUTO] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_CONT_CTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_PRE_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_PRE_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TD_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TD_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TSET] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TRIM_LRA] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_R_SPARE] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_D2SCFG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DETCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_RLDET] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_OSDET] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_VBATDET] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TESTDET] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DETLO] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMFDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_ADCTEST] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMFTEST] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_LRA_F0_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_LRA_F0_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_LRA_CONT_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_F_LRA_CONT_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAIT_VOL_MP] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_WAIT_VOL_MN] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VOL_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VOL_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_ZC_THRSH_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_ZC_THRSH_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VTHH_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VTHH_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VTHL_H] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_VTHL_L] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_BEMF_NUM] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DRV_TIME] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_TIME_NZC] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DRV_LVL] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_DRV_LVL_OV] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_NUM_F0_1] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_NUM_F0_2] = REG_RD_ACCESS | REG_WR_ACCESS,
[AW8697_REG_NUM_F0_3] = REG_RD_ACCESS | REG_WR_ACCESS,
};
/******************************************************
* Register Detail
*****************************************************/
/* SYSST: reg0x01 */
#define AW8697_BIT_SYSST_BSTERRS (1<<7)
#define AW8697_BIT_SYSST_OVS (1<<6)
#define AW8697_BIT_SYSST_UVLS (1<<5)
#define AW8697_BIT_SYSST_FF_AES (1<<4)
#define AW8697_BIT_SYSST_FF_AFS (1<<3)
#define AW8697_BIT_SYSST_OCDS (1<<2)
#define AW8697_BIT_SYSST_OTS (1<<1)
#define AW8697_BIT_SYSST_DONES (1<<0)
/* SYSINT: reg0x02 */
#define AW8697_BIT_SYSINT_BSTERRI (1<<7)
#define AW8697_BIT_SYSINT_OVI (1<<6)
#define AW8697_BIT_SYSINT_UVLI (1<<5)
#define AW8697_BIT_SYSINT_FF_AEI (1<<4)
#define AW8697_BIT_SYSINT_FF_AFI (1<<3)
#define AW8697_BIT_SYSINT_OCDI (1<<2)
#define AW8697_BIT_SYSINT_OTI (1<<1)
#define AW8697_BIT_SYSINT_DONEI (1<<0)
/* SYSINTM: reg0x03 */
#define AW8697_BIT_SYSINTM_BSTERR_MASK (~(1<<7))
#define AW8697_BIT_SYSINTM_BSTERR_OFF (1<<7)
#define AW8697_BIT_SYSINTM_BSTERR_EN (0<<7)
#define AW8697_BIT_SYSINTM_OV_MASK (~(1<<6))
#define AW8697_BIT_SYSINTM_OV_OFF (1<<6)
#define AW8697_BIT_SYSINTM_OV_EN (0<<6)
#define AW8697_BIT_SYSINTM_UVLO_MASK (~(1<<5))
#define AW8697_BIT_SYSINTM_UVLO_OFF (1<<5)
#define AW8697_BIT_SYSINTM_UVLO_EN (0<<5)
#define AW8697_BIT_SYSINTM_FF_AE_MASK (~(1<<4))
#define AW8697_BIT_SYSINTM_FF_AE_OFF (1<<4)
#define AW8697_BIT_SYSINTM_FF_AE_EN (0<<4)
#define AW8697_BIT_SYSINTM_FF_AF_MASK (~(1<<3))
#define AW8697_BIT_SYSINTM_FF_AF_OFF (1<<3)
#define AW8697_BIT_SYSINTM_FF_AF_EN (0<<3)
#define AW8697_BIT_SYSINTM_OCD_MASK (~(1<<2))
#define AW8697_BIT_SYSINTM_OCD_OFF (1<<2)
#define AW8697_BIT_SYSINTM_OCD_EN (0<<2)
#define AW8697_BIT_SYSINTM_OT_MASK (~(1<<1))
#define AW8697_BIT_SYSINTM_OT_OFF (1<<1)
#define AW8697_BIT_SYSINTM_OT_EN (0<<1)
#define AW8697_BIT_SYSINTM_DONE_MASK (~(1<<0))
#define AW8697_BIT_SYSINTM_DONE_OFF (1<<0)
#define AW8697_BIT_SYSINTM_DONE_EN (0<<0)
/* SYSCTRL: reg0x04 */
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6))
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6)
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6)
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6)
#define AW8697_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5))
#define AW8697_BIT_SYSCTRL_RAMINIT_EN (1<<5)
#define AW8697_BIT_SYSCTRL_RAMINIT_OFF (0<<5)
#define AW8697_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2))
#define AW8697_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2)
#define AW8697_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2)
#define AW8697_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2)
#define AW8697_BIT_SYSCTRL_BST_MODE_MASK (~(1<<1))
#define AW8697_BIT_SYSCTRL_BST_MODE_BOOST (1<<1)
#define AW8697_BIT_SYSCTRL_BST_MODE_BYPASS (0<<1)
#define AW8697_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0))
#define AW8697_BIT_SYSCTRL_STANDBY (1<<0)
#define AW8697_BIT_SYSCTRL_ACTIVE (0<<0)
/* GO: reg0x05 */
#define AW8697_BIT_GO_MASK (~(1<<0))
#define AW8697_BIT_GO_ENABLE (1<<0)
#define AW8697_BIT_GO_DISABLE (0<<0)
/* WAVSEQ1: reg0x07 */
#define AW8697_BIT_WAVSEQ1_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0))
/* WAVSEQ2: reg0x08 */
#define AW8697_BIT_WAVSEQ2_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0))
/* WAVSEQ3: reg0x09 */
#define AW8697_BIT_WAVSEQ3_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0))
/* WAVSEQ4: reg0x0a */
#define AW8697_BIT_WAVSEQ4_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0))
/* WAVSEQ5: reg0x0b */
#define AW8697_BIT_WAVSEQ5_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0))
/* WAVSEQ6: reg0x0c */
#define AW8697_BIT_WAVSEQ6_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0))
/* WAVSEQ7: reg0x0d */
#define AW8697_BIT_WAVSEQ7_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0))
/* WAVSEQ8: reg0x0e */
#define AW8697_BIT_WAVSEQ8_WAIT (1<<7)
#define AW8697_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0))
/* WAVLOOP: */
#define AW8697_BIT_WAVLOOP_SEQN_MASK (~(15<<4))
#define AW8697_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0))
#define AW8697_BIT_WAVLOOP_INIFINITELY (15<<0)
/* WAVLOOP1: reg0x0f */
#define AW8697_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4))
#define AW8697_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0))
/* WAVLOOP2: reg0x10 */
#define AW8697_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4))
#define AW8697_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0))
/* WAVLOOP3: reg0x11 */
#define AW8697_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4))
#define AW8697_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0))
/* WAVLOOP4: reg0x12 */
#define AW8697_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4))
#define AW8697_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0))
/* PLAYPRIO: reg0x1a */
#define AW8697_BIT_PLAYPRIO_GO_MASK (~(3<<6))
#define AW8697_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4))
#define AW8697_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2))
#define AW8697_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0))
/* TRGCFG1: reg0x1b */
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5))
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5)
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5)
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4))
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4)
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4)
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3))
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3)
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3)
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2))
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2)
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2)
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1))
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1)
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1)
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0))
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0)
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0)
/* TRGCFG2: reg0x1c */
#define AW8697_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2))
#define AW8697_BIT_TRGCFG2_TRG3_ENABLE (1<<2)
#define AW8697_BIT_TRGCFG2_TRG3_DISABLE (0<<2)
#define AW8697_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1))
#define AW8697_BIT_TRGCFG2_TRG2_ENABLE (1<<1)
#define AW8697_BIT_TRGCFG2_TRG2_DISABLE (0<<1)
#define AW8697_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0))
#define AW8697_BIT_TRGCFG2_TRG1_ENABLE (1<<0)
#define AW8697_BIT_TRGCFG2_TRG1_DISABLE (0<<0)
/* DBGCTRL: reg0x20 */
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_MASK (~(1<<3))
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_POS (1<<3)
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_BOTH (0<<3)
#define AW8697_BIT_DBGCTRL_INT_MODE_MASK (~(1<<2))
#define AW8697_BIT_DBGCTRL_INT_MODE_EDGE (1<<2)
#define AW8697_BIT_DBGCTRL_INT_MODE_LEVEL (0<<2)
/* DATCTRL: reg0x2b */
#define AW8697_BIT_DATCTRL_FC_MASK (~(1<<6))
#define AW8697_BIT_DATCTRL_FC_1000HZ (3<<6)
#define AW8697_BIT_DATCTRL_FC_800HZ (3<<6)
#define AW8697_BIT_DATCTRL_FC_600HZ (1<<6)
#define AW8697_BIT_DATCTRL_FC_400HZ (0<<6)
#define AW8697_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5))
#define AW8697_BIT_DATCTRL_LPF_ENABLE (1<<5)
#define AW8697_BIT_DATCTRL_LPF_DISABLE (0<<5)
#define AW8697_BIT_DATCTRL_WAKEMODE_ENABLE_MASK (~(1<<0))
#define AW8697_BIT_DATCTRL_WAKEMODE_ENABLE (1<<0)
#define AW8697_BIT_DATCTRL_WAKEMODE_DISABLE (0<<0)
/* PWMPRC: reg0x2d */
#define AW8697_BIT_PWMPRC_PRC_MASK (~(1<<7))
#define AW8697_BIT_PWMPRC_PRC_ENABLE (1<<7)
#define AW8697_BIT_PWMPRC_PRC_DISABLE (0<<7)
#define AW8697_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0))
/* PWMDBG: reg0x2e */
#define AW8697_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5))
#define AW8697_BIT_PWMDBG_PWM_12K (3<<5)
#define AW8697_BIT_PWMDBG_PWM_24K (2<<5)
#define AW8697_BIT_PWMDBG_PWM_48K (0<<5)
/* DBGST: reg0x30 */
#define AW8697_BIT_DBGSTAT_FF_EMPTY (1<<0)
/* BSTCFG: reg0x34 */
#define AW8697_BIT_BSTCFG_PEAKCUR_MASK (~(7<<0))
#define AW8697_BIT_BSTCFG_PEAKCUR_4A (7<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_3P75A (6<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_3P5A (5<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_3P25A (4<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_3A (3<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_2P5A (2<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_2A (1<<0)
#define AW8697_BIT_BSTCFG_PEAKCUR_1P5A (0<<0)
/* ANADBG: reg0x35 */
#define AW8697_BIT_ANADBG_IOC_MASK (~(3<<2))
#define AW8697_BIT_ANADBG_IOC_4P65A (3<<2)
#define AW8697_BIT_ANADBG_IOC_4P15A (2<<2)
#define AW8697_BIT_ANADBG_IOC_3P65A (1<<2)
#define AW8697_BIT_ANADBG_IOC_3P15A (0<<2)
/* ANACTRL: reg0x36 */
#define AW8697_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5))
#define AW8697_BIT_ANACTRL_LRA_SRC_REG (1<<5)
#define AW8697_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5)
#define AW8697_BIT_ANACTRL_HD_PD_MASK (~(1<<3))
#define AW8697_BIT_ANACTRL_HD_PD_EN (1<<3)
#define AW8697_BIT_ANACTRL_HD_HZ_EN (0<<3)
/* BSTDBG4: reg0x3a */
#define AW8697_BIT_BSTDBG4_BSTVOL_MASK (~(31<<1))
/* PRLVL: reg0x3e */
#define AW8697_BIT_PRLVL_PR_MASK (~(1<<7))
#define AW8697_BIT_PRLVL_PR_ENABLE (1<<7)
#define AW8697_BIT_PRLVL_PR_DISABLE (0<<7)
#define AW8697_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0))
/*PRTIME: reg0x3f */
#define AW8697_BIT_PRTIME_PRTIME_MASK (~(0xff<<0))
/* BST_AUTO: reg0x47 */
#define AW8697_BIT_BST_AUTO_BST_AUTOSW_MASK (~(1<<2))
#define AW8697_BIT_BST_AUTO_BST_AUTOMATIC_BOOST (1<<2)
#define AW8697_BIT_BST_AUTO_BST_MANUAL_BOOST (0<<2)
#define AW8697_BIT_BST_AUTO_BST_RTP_MASK (~(1<<1))
#define AW8697_BIT_BST_AUTO_BST_RTP_ENABLE (1<<1)
#define AW8697_BIT_BST_AUTO_BST_RTP_DISABLE (0<<1)
#define AW8697_BIT_BST_AUTO_BST_RAM_MASK (~(1<<0))
#define AW8697_BIT_BST_AUTO_BST_RAM_ENABLE (1<<0)
#define AW8697_BIT_BST_AUTO_BST_RAM_DISABLE (0<<0)
/* CONT_CTRL: reg0x48 */
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7))
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7)
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7)
#define AW8697_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5))
#define AW8697_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5)
#define AW8697_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5)
#define AW8697_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5)
#define AW8697_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5)
#define AW8697_BIT_CONT_CTRL_MODE_MASK (~(1<<4))
#define AW8697_BIT_CONT_CTRL_BY_DRV_TIME (1<<4)
#define AW8697_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4)
#define AW8697_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3))
#define AW8697_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3)
#define AW8697_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3)
#define AW8697_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2))
#define AW8697_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2)
#define AW8697_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2)
#define AW8697_BIT_CONT_CTRL_O2C_MASK (~(1<<1))
#define AW8697_BIT_CONT_CTRL_O2C_ENABLE (1<<1)
#define AW8697_BIT_CONT_CTRL_O2C_DISABLE (0<<1)
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0))
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0)
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0)
/* D2SCFG: reg0x5e */
#define AW8697_BIT_D2SCFG_CLK_ADC_MASK (~(7<<5))
#define AW8697_BIT_D2SCFG_CLK_ASC_0P09375MHZ (7<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_0P1875MHZ (6<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_0P375MHZ (5<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_0P75MHZ (4<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_3MHZ (2<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_6MHZ (1<<5)
#define AW8697_BIT_D2SCFG_CLK_ASC_12MHZ (0<<5)
/* DETCTRL: reg0x5f */
#define AW8697_BIT_DETCTRL_RL_OS_MASK (~(1<<6))
#define AW8697_BIT_DETCTRL_RL_DETECT (1<<6)
#define AW8697_BIT_DETCTRL_OS_DETECT (0<<6)
#define AW8697_BIT_DETCTRL_PROTECT_MASK (~(1<<5))
#define AW8697_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5)
#define AW8697_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5)
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_MASK (~(1<<4))
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_ENABLE (1<<4)
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_DISABLE (0<<4)
#define AW8697_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1))
#define AW8697_BIT_DETCTRL_VABT_GO_ENABLE (1<<1)
#define AW8697_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1)
#define AW8697_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0))
#define AW8697_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0)
#define AW8697_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0)
/* ADCTEST: reg0x66 */
#define AW8697_BIT_ADCTEST_VBAT_MODE_MASK (~(1<<6))
#define AW8697_BIT_ADCTEST_VBAT_HW_COMP (1<<6)
#define AW8697_BIT_ADCTEST_VBAT_SW_COMP (0<<6)
/* BEMF_NUM: reg0x78 */
#define AW8697_BIT_BEMF_NUM_BRK_MASK (~(15<<0))
#endif

View File

@ -0,0 +1,215 @@
/*
* reader shoule NEVER block !!!, if no data is avaliable, just return zero
* writer will block if there is no space, and wakend up by reader or force exit
* there is 1 writer and 1 reader for each buffer, so no lock is used
* writer shoule read rd_index to check if free size is enought, and then fill this buffer update wr_index
* reader shoule read wr_index to check if avaliable size is enought, and then read the buffer and update rd_index
* empty: wr_index==rd_index
* full: (wr_index +1) % BUFFER_SIZE == rd_index
* total avaliable size is BUFFER_SIZE -1
*/
#define DEBUG
#include <linux/errno.h>
#include "ringbuffer.h"
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define BUFFER_SIZE (1024 * 8 + 1)
struct rb {
char *gbuffer;
atomic_t wr_index;
atomic_t rd_index;
atomic_t eof;
volatile int32_t aval_size; // avalibale to write size.
atomic_t buf_condition, exit;
wait_queue_head_t wait_q;
};
struct rb *grb;
int32_t get_free_size(int32_t tail, int32_t head)
{
if (head == tail)
return BUFFER_SIZE - 1;
else if (head < tail)
return (head + BUFFER_SIZE - 1 - tail);
else
return(head - tail - 1);
}
int write_rb(const char *data, int32_t size)
{
int32_t tail = atomic_read(&grb->wr_index);
int32_t head = atomic_read(&grb->rd_index);
int32_t part;
int32_t ret;
grb->aval_size = get_free_size(tail, head);
pr_debug("write write index %d, read index %d, free size %d", tail, head, grb->aval_size);
while ((grb->aval_size < size) && (!atomic_read(&grb->exit))) {
pr_debug("no space avaliable");
pr_info("%s goint to waiting irq exit\n", __func__);
ret = wait_event_interruptible(grb->wait_q, atomic_read(&grb->buf_condition) == 1);
if (ret == -ERESTARTSYS) {
pr_err("%s wake up by signal return erro\n", __func__);
return ret;
}
atomic_set(&grb->buf_condition, 0);
tail = atomic_read(&grb->wr_index);
head = atomic_read(&grb->rd_index);
grb->aval_size = get_free_size(tail, head);
}
if (atomic_read(&grb->exit) == 1) {
pr_debug("exit write_rb");
return -EPERM;
}
part = BUFFER_SIZE - tail;
if (part < size) {
memcpy(grb->gbuffer + tail, data, part);
memcpy(grb->gbuffer, data + part, size - part);
tail = size - part;
} else {
memcpy(grb->gbuffer + tail, data, size);
tail += size;
if (tail >= BUFFER_SIZE)
tail = tail % BUFFER_SIZE;
}
atomic_set(&grb->wr_index, tail);
grb->aval_size = get_free_size(tail, head);
pr_debug("after write %d, write index %d, read index %d, aval_size %d", size, tail, head, grb->aval_size);
return size;
}
int read_rb(char *data, int32_t size)
{
int32_t tail;
int32_t head;
int32_t filled_size;
void *buf;
int32_t read_bytes, part;
buf = data;
pr_debug("read_rb data:%p, size %d", data, (int)size);
tail = atomic_read(&grb->wr_index);
head = atomic_read(&grb->rd_index);
grb->aval_size = get_free_size(tail, head);
filled_size = BUFFER_SIZE - 1 - grb->aval_size; // aready write size.
pr_debug("write index %d, read index %d, filled size %d", tail, head, filled_size);
read_bytes = MIN (size, filled_size);
if (size > filled_size)
pr_debug("buffer underrun , req size %d, filled size %d", size, filled_size);
part = BUFFER_SIZE - head;
if (part < read_bytes) {
memcpy(buf, grb->gbuffer + head, part);
memcpy((char *)buf + part, grb->gbuffer, read_bytes - part);
head = read_bytes - part;
} else {
memcpy(buf, grb->gbuffer + head, read_bytes);
head += read_bytes;
if (head >= BUFFER_SIZE)
head = head % BUFFER_SIZE;
}
atomic_set(&grb->rd_index, head);
grb->aval_size = get_free_size(tail, head);
//add wakeup here
atomic_set(&grb->buf_condition, 1);
wake_up_interruptible(&grb->wait_q);
pr_debug("read_rb: after read %d write index %d, read index %d, aval_size %d", read_bytes, tail, head, grb->aval_size);
return atomic_read(&grb->eof) ? read_bytes : size;
}
int get_rb_free_size(void)
{
int32_t tail = atomic_read(&grb->wr_index);
int32_t head = atomic_read(&grb->rd_index);
grb->aval_size = get_free_size(tail, head);
return grb->aval_size;
}
int get_rb_avalible_size(void)
{
return BUFFER_SIZE - 1 - get_rb_free_size();
}
int get_rb_max_size(void)
{
return BUFFER_SIZE - 1;
}
void rb_force_exit(void)
{
pr_debug("rb force exit");
atomic_set(&grb->exit, 1);
atomic_set(&grb->buf_condition, 1);
wake_up_interruptible(&grb->wait_q);
}
void rb_end(void)
{
atomic_set(&grb->eof, 1);
}
int rb_shoule_exit(void)
{
return atomic_read(&grb->eof) || atomic_read(&grb->exit);
}
int create_rb(void)
{
int32_t tail;
int32_t head;
grb = kzalloc(sizeof(struct rb), GFP_KERNEL);
if (grb == NULL) {
goto err;;
}
grb->gbuffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
if (grb->gbuffer == NULL) {
goto err;
}
rb_init();
init_waitqueue_head(&grb->wait_q);
tail = atomic_read(&grb->wr_index);
head = atomic_read(&grb->rd_index);
grb->aval_size = get_free_size(tail, head);
return 0;
err:
if (grb)
kfree(grb);
if (grb->gbuffer)
kfree(grb->gbuffer);
return -EPERM;
}
void rb_init(void)
{
pr_debug("rb init");
atomic_set(&grb->wr_index, 0);
atomic_set(&grb->rd_index, 0);
atomic_set(&grb->buf_condition, 0);
atomic_set(&grb->exit, 0);
atomic_set(&grb->eof, 0);
}
int release_rb(void)
{
if (grb != NULL) {
if (grb->gbuffer) {
kfree(grb->gbuffer);
grb->gbuffer = NULL;
}
kfree(grb);
grb = NULL;
}
return 0;
}

View File

@ -0,0 +1,35 @@
/*
* reader shoule NEVER block !!!, if no data is avaliable, just return zero
* writer will block if there is no space, and wakend up by reader or force exit
* there is 1 writer and 1 reader for each buffer, so no lock is used
* writer shoule read rd_index to check if free size is enought, and then fill this buffer update wr_index
* reader shoule read wr_index to check if avaliable size is enought, and then read the buffer and update rd_index
* empty: wr_index==rd_index
* full: (wr_index +1) % BUFFER_SIZE == rd_index
* total avaliable size is BUFFER_SIZE -1
*/
#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/sched.h>
int write_rb(const char *data, int32_t size);
int read_rb(char *data, int32_t size) ;
int get_rb_free_size(void);
int get_rb_max_size(void);
void rb_force_exit(void);
void rb_end(void);
int rb_shoule_exit(void);
int create_rb(void) ;
void rb_init(void);
int release_rb(void);
int get_rb_avalible_size(void);
#endif