dlkm: aw8624: update haptic driver

1. Support to call different seq wave on haptic.bin
   and make it as an dts option "vib_ram_config"
2. Update some patch from vendor.

Change-Id: I0381fe51fa3389eaba67a897d461b72ee42d7e0d
Signed-off-by: Weilong Wu <wuwl10@motorola.com>
Reviewed-on: https://gerrit.mot.com/1422693
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Weilong Wu 2019-09-18 17:18:11 +08:00
commit 5e67ae4b6c
3 changed files with 161 additions and 31 deletions

View file

@ -1,7 +1,7 @@
/*
* aw8624.c aw8624 haptic module
*
* Version: v1.0.6
* Version: v1.0.7
*
* Copyright (c) 2018 AWINIC Technology CO., LTD
*
@ -40,7 +40,7 @@
******************************************************/
#define AW8624_I2C_NAME "aw8624_haptic"
#define AW8624_HAPTIC_NAME "aw8624_haptic"
#define AW8624_VERSION "v1.0.6"
#define AW8624_VERSION "v1.0.7"
#define AWINIC_RAM_UPDATE_DELAY
#define AW_I2C_RETRIES 2
#define AW_I2C_RETRY_DELAY 2
@ -71,7 +71,7 @@ struct aw8624_dts_info aw8624_dts_data;
*
******************************************************/
static void aw8624_interrupt_clear(struct aw8624 *aw8624);
static int aw8624_haptic_trig1_config(struct aw8624 *aw8624, unsigned char flag);
/******************************************************
*
* aw8624 i2c write/read
@ -163,6 +163,15 @@ static void aw8624_interrupt_clear(struct aw8624 *aw8624)
aw8624_i2c_read(aw8624, AW8624_REG_SYSINT, &reg_val);
pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
}
static void aw8624_init_extra(struct aw8624 *aw8624)
{
if (aw8624->IsUsedIRQ==false){
aw8624_haptic_trig1_config(aw8624, true);
pr_info("enter %s \n",__func__);
}
}
/*****************************************************
*
* ram update
@ -195,6 +204,7 @@ static void aw8624_rtp_loaded(const struct firmware *cont, void *context)
release_firmware(cont);
aw8624->rtp_init = 1;
aw8624_init_extra(aw8624);
pr_info("%s: rtp update complete\n", __func__);
}
@ -377,31 +387,42 @@ static int aw8624_haptic_play_mode(struct aw8624 *aw8624, unsigned char play_mod
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_WORK_MODE_MASK, AW8624_BIT_SYSCTRL_STANDBY);
break;
case AW8624_HAPTIC_RAM_MODE:
aw8624->play_mode = AW8624_HAPTIC_RAM_MODE;
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_PLAY_MODE_MASK, AW8624_BIT_SYSCTRL_PLAY_MODE_RAM);
aw8624_haptic_active(aw8624);
break;
case AW8624_HAPTIC_RAM_LOOP_MODE:
aw8624->play_mode = AW8624_HAPTIC_RAM_LOOP_MODE;
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_PLAY_MODE_MASK, AW8624_BIT_SYSCTRL_PLAY_MODE_RAM);
aw8624_haptic_active(aw8624);
break;
case AW8624_HAPTIC_RTP_MODE:
aw8624->play_mode = AW8624_HAPTIC_RTP_MODE;
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_PLAY_MODE_MASK, AW8624_BIT_SYSCTRL_PLAY_MODE_RTP);
aw8624_haptic_active(aw8624);
break;
case AW8624_HAPTIC_TRIG_MODE:
aw8624->play_mode = AW8624_HAPTIC_TRIG_MODE;
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_PLAY_MODE_MASK, AW8624_BIT_SYSCTRL_PLAY_MODE_RAM);
aw8624_haptic_active(aw8624);
break;
case AW8624_HAPTIC_CONT_MODE:
aw8624->play_mode = AW8624_HAPTIC_CONT_MODE;
aw8624_i2c_write_bits(aw8624, AW8624_REG_SYSCTRL,
AW8624_BIT_SYSCTRL_PLAY_MODE_MASK, AW8624_BIT_SYSCTRL_PLAY_MODE_CONT);
aw8624_haptic_active(aw8624);
break;
default:
dev_err(aw8624->dev, "%s: play mode %d err",
__func__, play_mode);
@ -412,12 +433,23 @@ static int aw8624_haptic_play_mode(struct aw8624 *aw8624, unsigned char play_mod
static int aw8624_haptic_play_go(struct aw8624 *aw8624, bool flag)
{
pr_debug("%s enter\n", __func__);
if (!flag) {
do_gettimeofday(&aw8624->current_time);
aw8624->interval_us = (aw8624->current_time.tv_sec-aw8624->pre_enter_time.tv_sec) * 1000000
+ (aw8624->current_time.tv_usec-aw8624->pre_enter_time.tv_usec);
if (aw8624->interval_us < 2000) {
pr_info("aw8624->interval_us t=%d\n",aw8624->interval_us);
mdelay(2);
}
}
if (flag == true) {
aw8624_i2c_write_bits(aw8624, AW8624_REG_GO,
AW8624_BIT_GO_MASK, AW8624_BIT_GO_ENABLE);
AW8624_BIT_GO_MASK, AW8624_BIT_GO_ENABLE);
do_gettimeofday(&aw8624->pre_enter_time);
} else {
aw8624_i2c_write_bits(aw8624, AW8624_REG_GO,
AW8624_BIT_GO_MASK, AW8624_BIT_GO_DISABLE);
AW8624_BIT_GO_MASK, AW8624_BIT_GO_DISABLE);
}
return 0;
}
@ -430,11 +462,11 @@ static int aw8624_haptic_stop_delay(struct aw8624 *aw8624)
while (cnt--) {
aw8624_i2c_read(aw8624, AW8624_REG_GLB_STATE, &reg_val);
if ((reg_val & 0x0f) == 0x00) {
return 0;
msleep(2);
}
pr_debug("%s wait for standby, reg glb_state=0x%02x\n",
__func__, reg_val);
return 0;
}
msleep(2);
pr_debug("%s wait for standby, reg glb_state=0x%02x\n",
__func__, reg_val);
}
pr_err("%s do not enter standby automatically\n", __func__);
return 0;
@ -685,6 +717,46 @@ static int aw8624_haptic_brake_config(struct aw8624 *aw8624)
td_brake = (char)(aw8624_dts_data.aw8624_td_brake[level] / 4160 );
aw8624_i2c_write_bits(aw8624, AW8624_REG_TD_H, AW8624_BIT_TDH_TD_BRAKE_MASK, (td_brake << 4));
return 0;
}
static int aw8624_haptic_ram_config(struct aw8624 *aw8624)
{
unsigned char wavseq = 0;
unsigned char wavloop = 0;
if((aw8624->duration > 0) && (aw8624->duration < 20))
{
wavseq = aw8624_dts_data.aw8624_wavseq[3]; //2
wavloop = 0;
}
else if((aw8624->duration >= 20) && (aw8624->duration < 30))
{
wavseq = aw8624_dts_data.aw8624_wavseq[5]; //3
wavloop = 0;
}
else if((aw8624->duration >= 30) && (aw8624->duration < 60))
{
wavseq = aw8624_dts_data.aw8624_wavseq[7]; //4
wavloop = 0;
}
else if(aw8624->duration >= 60)
{
wavseq = aw8624_dts_data.aw8624_wavseq[1]; //1
wavloop = 15; //long vibration
}
else
{
wavseq = 0;
wavloop = 0;
}
aw8624_haptic_set_wav_seq(aw8624, 0, wavseq);
aw8624_haptic_set_wav_loop(aw8624, 0, wavloop);
aw8624_haptic_set_wav_seq(aw8624, 1, 0);
aw8624_haptic_set_wav_loop(aw8624, 1, 0);
return 0;
}
@ -747,6 +819,29 @@ static int aw8624_lra_resistance_detector(struct aw8624 *aw8624)
return r_lra;
}
static int aw8624_haptic_ram_vbat_comp(struct aw8624 *aw8624, bool flag)
{
int temp_gain = 0;
int vbat = 0;
if(flag) {
if(aw8624->ram_vbat_comp == AW8624_HAPTIC_RAM_VBAT_COMP_ENABLE) {
vbat = aw8624_vbat_monitor_detector(aw8624);
temp_gain = aw8624->gain * AW8624_VBAT_REFER / vbat;
if(temp_gain > (128*AW8624_VBAT_REFER/AW8624_VBAT_MIN)) {
temp_gain = 128*AW8624_VBAT_REFER/AW8624_VBAT_MIN;
pr_debug("%s gain limit=%d\n", __func__, temp_gain);
}
aw8624_haptic_set_gain(aw8624, temp_gain);
} else {
aw8624_haptic_set_gain(aw8624, aw8624->gain);
}
} else {
aw8624_haptic_set_gain(aw8624, aw8624->gain);
}
return 0;
}
static void aw8624_haptic_set_rtp_aei(struct aw8624 *aw8624, bool flag)
{
@ -1075,6 +1170,7 @@ static int aw8624_haptic_f0_calibration(struct aw8624 *aw8624)
aw8624->f0_cali_flag = AW8624_HAPTIC_CALI_F0;
aw8624_i2c_write(aw8624, AW8624_REG_TRIM_LRA, 0x00);
if (aw8624_haptic_get_f0(aw8624)) {
pr_err("%s get f0 error, user defafult f0\n", __func__);
} else {
@ -1088,11 +1184,20 @@ static int aw8624_haptic_f0_calibration(struct aw8624 *aw8624)
}
/* calculate cali step */
f0_cali_step = 100000*((int)f0_limit-(int)aw8624->f0_pre)/((int)f0_limit*25);
if(f0_cali_step % 10 >= 5 )
f0_cali_step = f0_cali_step/10 + 1 + (aw8624->chipid_flag == 1 ? 32 : 16);
else
f0_cali_step = f0_cali_step/10 + (aw8624->chipid_flag == 1 ? 32 : 16);
pr_info("%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 = f0_cali_step/10 + 1 + (aw8624->chipid_flag ==1 ? 32 : 16);
} else {
f0_cali_step = f0_cali_step/10 + (aw8624->chipid_flag ==1 ? 32 : 16);
}
} else { /*f0_cali_step < 0*/
if(f0_cali_step % 10 <= -5 ){
f0_cali_step = (aw8624->chipid_flag ==1 ? 32 : 16) + (f0_cali_step/10 -1);
} else {
f0_cali_step = (aw8624->chipid_flag ==1 ? 32 : 16) + f0_cali_step/10;
}
}
if (aw8624->chipid_flag == 1) {
if (f0_cali_step > 31) {
@ -1317,6 +1422,9 @@ static int aw8624_haptic_init(struct aw8624 *aw8624)
aw8624->activate_mode = AW8624_HAPTIC_ACTIVATE_RAM_MODE;
ret = aw8624_i2c_read(aw8624, AW8624_REG_WAVSEQ1, &reg_val);
aw8624->index = reg_val & 0x7F;
aw8624_haptic_set_gain(aw8624, 0x80);
ret = aw8624_i2c_read(aw8624, AW8624_REG_DATDBG, &reg_val);
aw8624->gain = reg_val & 0xFF;
for (i = 0; i < AW8624_SEQUENCER_SIZE; i++) {
@ -1341,8 +1449,11 @@ static int aw8624_haptic_init(struct aw8624 *aw8624)
aw8624->cont_td = aw8624_dts_data.aw8624_cont_td;
aw8624->cont_zc_thr = aw8624_dts_data.aw8624_cont_zc_thr;
aw8624->cont_num_brk = aw8624_dts_data.aw8624_cont_num_brk;
mutex_lock(&aw8624->lock);
aw8624->ram_vbat_comp = AW8624_HAPTIC_RAM_VBAT_COMP_ENABLE;
mutex_lock(&aw8624->lock);
aw8624_i2c_write_bits(aw8624, AW8624_REG_R_SPARE,
AW8624_BIT_R_SPARE_MASK, AW8624_BIT_R_SPARE_ENABLE);
aw8624_haptic_f0_calibration(aw8624);
mutex_unlock(&aw8624->lock);
@ -2285,9 +2396,9 @@ static enum hrtimer_restart aw8624_vibrator_timer_func(struct hrtimer *timer)
return HRTIMER_NORESTART;
}
static void aw8624_irq_work_routine(struct work_struct *work)
static irqreturn_t aw8624_irq(int irq, void *data)
{
struct aw8624 *aw8624 = container_of(work, struct aw8624, irq_work);
struct aw8624 *aw8624 = data;
unsigned char reg_val = 0;
unsigned int buf_len = 0;
@ -2322,6 +2433,7 @@ static void aw8624_irq_work_routine(struct work_struct *work)
aw8624_i2c_read(aw8624, AW8624_REG_SYSINT, &reg_val);
aw8624_i2c_read(aw8624, AW8624_REG_SYSST, &reg_val);
return IRQ_HANDLED;
}
static void aw8624_vibrator_work_routine(struct work_struct *work)
@ -2333,7 +2445,21 @@ static void aw8624_vibrator_work_routine(struct work_struct *work)
mutex_lock(&aw8624->lock);
aw8624_haptic_stop(aw8624);
if (aw8624->state) {
aw8624_haptic_brake_config(aw8624);
if(aw8624_dts_data.aw8624_ram_config == 1) {
aw8624_haptic_ram_config(aw8624);
} else {
aw8624_haptic_brake_config(aw8624);
}
if((aw8624->duration > 0) && (aw8624->duration < 60)) {
aw8624_haptic_set_gain(aw8624, 0x80);
} else {
if(aw8624_dts_data.aw8624_vbat_comp == 1) {
aw8624_haptic_ram_vbat_comp(aw8624, true);
} else {
aw8624_haptic_ram_vbat_comp(aw8624, false);
}
}
aw8624_haptic_play_repeat_seq(aw8624, true);
/* run ms timer */
hrtimer_start(&aw8624->timer,
@ -2379,7 +2505,6 @@ static int aw8624_vibrator_init(struct aw8624 *aw8624)
if (aw8624->IsUsedIRQ) {
INIT_WORK(&aw8624->rtp_work, aw8624_rtp_work_routine);
INIT_WORK(&aw8624->irq_work, aw8624_irq_work_routine);
}
mutex_init(&aw8624->lock);
@ -2408,13 +2533,6 @@ static void aw8624_interrupt_setup(struct aw8624 *aw8624)
AW8624_BIT_SYSINTM_OT_MASK, AW8624_BIT_SYSINTM_OT_EN);
}
static irqreturn_t aw8624_irq(int irq, void *data)
{
struct aw8624 *aw8624 = (struct aw8624 *)data;
schedule_work(&aw8624->irq_work);
return IRQ_HANDLED;
}
/*****************************************************
*
* device tree
@ -2461,7 +2579,13 @@ static int aw8624_parse_dt(struct device *dev, struct aw8624 *aw8624,
dev_info(dev, "find real-i2c-addr option in dts\n");
aw8624->dts_addr_real = true;
}
val = of_property_read_u32(np, "vib_ram_config", &aw8624_dts_data.aw8624_ram_config);
if (val != 0)
dev_info(dev, "vib_ram_config not found\n");
val = of_property_read_u32(np, "vib_vbat_comp", &aw8624_dts_data.aw8624_vbat_comp);
if (val != 0)
dev_info(dev, "vib_vbat_comp not found\n");
val = of_property_read_u32(np, "vib_f0_pre", &aw8624_dts_data.aw8624_f0_pre);
if (val != 0)
dev_info(dev, "vib_f0_pre not found\n");
@ -2765,7 +2889,8 @@ static int aw8624_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *
}
/* aw8624 irq */
if (gpio_is_valid(aw8624->irq_gpio)) {
if (gpio_is_valid(aw8624->irq_gpio)&&
!(aw8624->flags & AW8624_FLAG_SKIP_INTERRUPTS)) {
/* register irq handler */
aw8624_interrupt_setup(aw8624);
ret = devm_request_threaded_irq(&i2c->dev,
@ -2822,7 +2947,6 @@ static int aw8624_i2c_remove(struct i2c_client *i2c)
hrtimer_cancel(&aw8624->haptic_audio.timer);
if (aw8624->IsUsedIRQ) {
cancel_work_sync(&aw8624->irq_work);
cancel_work_sync(&aw8624->rtp_work);
}
cancel_work_sync(&aw8624->vibrator_work);

View file

@ -61,6 +61,9 @@ struct aw8624_dts_info {
int aw8624_td_brake[3];
int aw8624_tset;
int aw8624_parameter1;
int aw8624_timed_output;
int aw8624_ram_config;
int aw8624_vbat_comp;
};
@ -168,11 +171,11 @@ struct aw8624 {
unsigned char wk_lock_flag;
struct hrtimer timer;
struct work_struct vibrator_work;
struct work_struct irq_work;
struct work_struct rtp_work;
struct delayed_work ram_work;
struct delayed_work stop_work;
struct timeval current_time;
struct timeval pre_enter_time;
struct led_classdev to_dev;
struct fileops fileops;
@ -227,6 +230,7 @@ struct aw8624 {
unsigned char ram_vbat_comp;
unsigned int vbat;
unsigned int lra;
unsigned int interval_us;
};
struct aw8624_container {

View file

@ -591,5 +591,7 @@ const unsigned char aw8624_reg_access[AW8624_REG_MAX] = {
#define AW8624_BIT_BEMF_NUM_BRK_MASK (~(0xf<<0))
#define AW8624_BIT_TDH_TD_BRAKE_MASK (~(0xF<<4))
#define AW8624_BIT_R_SPARE_MASK (~(1<<7))
#define AW8624_BIT_R_SPARE_ENABLE (1<<7)
#endif