Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit e7ea5788 authored by tianlang.zhou's avatar tianlang.zhou Committed by Michael Bestas
Browse files

[4 of 4][ALM:10923711] [FP4]:develope aw8695 vibrator

 &&&%%%comment:[FP4]:develope aw8695 vibrator
 &&&%%%bug number:10923711
 &&&%%%product name:sm7225_r_fp4
 &&&%%%root cause:Coding
 &&&%%%Bug category:T2M
 &&&%%%Module_Impact:kernel
 &&&%%%Test_Suggestion:reset
 &&&%%%Solution:develope drivers
 &&&%%%Test_Report:local test is ok
 &&&%%%VAL Can Test:NO

Change-Id: I7d5057c7590d6b0be001538e262d2c8202706298
parent fd27f77c
Loading
Loading
Loading
Loading
+3412 −3264
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <aw8695_reg.h>
#include <aw8695.h>

#define AW_UEFI_CAL_F0
/******************************************************
 *
 * Marco
@@ -52,6 +53,7 @@
#define AWINIC_READ_BIN_FLEXBALLY

#define AW8695_MAX_FIRMWARE_LOAD_CNT 20
#define PM_QOS_VALUE_VB 100   //Daniel 20201105 modify start
struct pm_qos_request pm_qos_req_vb;
/******************************************************
 *
@@ -67,6 +69,10 @@ static char aw8695_rtp_name[][AW8695_RTP_NAME_MAX] = {
struct aw8695_container *aw8695_rtp;
struct aw8695 *g_aw8695;

#ifdef AW_UEFI_CAL_F0
unsigned int aw8695_f0_cal = 0;
#endif
unsigned int aw8695_test_index = 0;
/******************************************************
 *
 * functions
@@ -74,6 +80,17 @@ struct aw8695 *g_aw8695;
 ******************************************************/
static void aw8695_interrupt_clear(struct aw8695 *aw8695);
static int aw8695_haptic_trig_enable_config(struct aw8695 *aw8695);
extern int i2c_check_status_create(char *name,int value);

static bool aw_debug = false;
module_param(aw_debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(aw_debug, "Debugging mode enabled or not");

#define aw_dbg_info(format, arg...)		\
	do {							\
		if (aw_debug)					\
			pr_info(format , ##arg);		\
	} while (0)

 /******************************************************
 *
@@ -598,11 +615,11 @@ static int aw8695_haptic_juge_RTP_is_going_on(struct aw8695 *aw8695)
        && (!(reg_val & AW8695_BIT_SYSCTRL_STANDBY)))
        rtp_state = 1;	/*is going on */
    if (pre_reg_val != reg_val)
		pr_info("%sAW8695_REG_SYSCTRL 0x04==%02x rtp_state=%d\n",
        aw_dbg_info("%sAW8695_REG_SYSCTRL 0x04==%02x rtp_state=%d\n",
            __func__, reg_val, rtp_state);
    pre_reg_val = reg_val;
    if (aw8695->rtp_routine_on) {
		pr_info("%s:rtp_routine_on\n", __func__);
        aw_dbg_info("%s:rtp_routine_on\n", __func__);
        rtp_state = 1;	/*is going on */
    }
    return rtp_state;
@@ -1181,6 +1198,36 @@ static int aw8695_haptic_read_beme(struct aw8695 *aw8695)
    return 0;
}

static int aw8695_haptic_ram_config(struct aw8695 *aw8695)
{
    unsigned char wavloop = 0;
    pr_info("%s duration =%d\n", __func__, aw8695->duration);

    if ((aw8695->duration >0 ) && (aw8695->duration <= 20)){//index 3 0~20ms
        aw8695->index = 1;
    } else if((aw8695->duration >20 ) && (aw8695->duration <= 40)){//index 2 20~30ms
        if(aw8695_test_index)
            aw8695->index = aw8695_test_index;
        else {
            /* code */
            aw8695->index = 5;
        }
    } else if((aw8695->duration >40 ) && (aw8695->duration <= 60)){//index 1 30~60ms
        aw8695->index = 6;
    } else {//index 4  	 >60ms
        aw8695->index = 2;
        wavloop = 15;
    }

    pr_info("%s wave index =%d\n", __func__, aw8695->index);
    aw8695_haptic_set_wav_seq(aw8695, 0, aw8695->index);
    aw8695_haptic_set_wav_loop(aw8695, 0, wavloop);
    aw8695_haptic_set_wav_seq(aw8695, 1, 0);
    aw8695_haptic_set_wav_loop(aw8695, 1, 0);

    return 0;
}

/*****************************************************
 *
 * rtp
@@ -1281,8 +1328,9 @@ static int aw8695_haptic_rtp_init(struct aw8695 *aw8695)
    unsigned int buf_len = 0;
    unsigned char glb_state_val = 0;


    //Daniel 20201105 modify start 
    pr_info("%s enter\n", __func__);
    pm_qos_add_request(&pm_qos_req_vb, PM_QOS_CPU_DMA_LATENCY, PM_QOS_VALUE_VB);
    aw8695->rtp_cnt = 0;
    mutex_lock(&aw8695->rtp_lock);
    while ((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) &&
@@ -1315,7 +1363,9 @@ static int aw8695_haptic_rtp_init(struct aw8695 *aw8695)
        if ((aw8695->rtp_cnt == aw8695_rtp->len) || ((glb_state_val & 0x0f) == 0x00)) {
            pr_info("%s: rtp update complete\n", __func__);
            aw8695->rtp_cnt = 0;
			atomic_set(&aw8695->is_rtp, 0);
            mutex_unlock(&aw8695->rtp_lock);
            pm_qos_remove_request(&pm_qos_req_vb);
            return 0;
        }
    }
@@ -1325,7 +1375,7 @@ static int aw8695_haptic_rtp_init(struct aw8695 *aw8695)
        aw8695_haptic_set_rtp_aei(aw8695, true);

    pr_info("%s exit\n", __func__);

    pm_qos_remove_request(&pm_qos_req_vb);//Daniel 20201105 modify end
    return 0;
}

@@ -1447,7 +1497,8 @@ static int aw8695_rtp_osc_calibration(struct aw8695 *aw8695)
    disable_irq(gpio_to_irq(aw8695->irq_gpio));
    /* haptic start */
    aw8695_haptic_start(aw8695);

    //Daniel 20201105 modify start
    pm_qos_add_request(&pm_qos_req_vb, PM_QOS_CPU_DMA_LATENCY, PM_QOS_VALUE_VB);
    aw8695_i2c_read(aw8695, AW8695_REG_PWMDBG, &reg_val);
    fre_val = (reg_val & 0x006f) >> 5;

@@ -1571,6 +1622,7 @@ static void aw8695_rtp_work_routine(struct work_struct *work)

    mutex_lock(&aw8695->lock);
    aw8695->rtp_init = 1;
	atomic_set(&aw8695->is_rtp, 1);
    /* gain */
    aw8695_haptic_ram_vbat_comp(aw8695, false);

@@ -1691,7 +1743,7 @@ static void aw8695_haptic_audio_work_routine(struct work_struct *work)

    int rtp_is_going_on = 0;

	pr_debug("%s enter\n", __func__);
    aw_dbg_info("%s enter\n", __func__);

    haptic_audio = &(aw8695->haptic_audio);
    mutex_lock(&aw8695->haptic_audio.lock);
@@ -1703,7 +1755,7 @@ static void aw8695_haptic_audio_work_routine(struct work_struct *work)
        break;
    }
    if (ctr_list_flag == 0)
		pr_info("%s: ctr list empty\n", __func__);
        aw_dbg_info("%s: ctr list empty\n", __func__);
    if (ctr_list_flag == 1) {
        list_for_each_entry_safe(p_ctr, p_ctr_bak,
                     &(haptic_audio->ctr_list), list) {
@@ -1757,7 +1809,7 @@ static void aw8695_haptic_audio_work_routine(struct work_struct *work)
        break;
    }
    if (aw8695->haptic_audio.ctr.play) {
		pr_info
        aw_dbg_info
        ("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n",
         __func__, aw8695->haptic_audio.ctr.cnt,
         aw8695->haptic_audio.ctr.cmd,
@@ -1777,7 +1829,7 @@ static void aw8695_haptic_audio_work_routine(struct work_struct *work)
    if (aw8695->haptic_audio.ctr.cmd == AW8695_HAPTIC_CMD_ENABLE) {
        if
        (aw8695->haptic_audio.ctr.play == AW8695_HAPTIC_PLAY_ENABLE) {
			pr_info("%s: haptic_audio_play_start\n", __func__);
            aw_dbg_info("%s: haptic_audio_play_start\n", __func__);
            mutex_lock(&aw8695->lock);
            aw8695_haptic_stop(aw8695);
            aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE);
@@ -2371,7 +2423,9 @@ static int aw8695_haptic_init(struct aw8695 *aw8695)
    unsigned char i = 0;
    unsigned char reg_val = 0;
    unsigned char bemf_config = 0;

#ifdef AW_UEFI_CAL_F0
    double f0_pre_low,f0_pre_high;
#endif
    pr_info("%s enter\n", __func__);

    ret = misc_register(&aw8695_haptic_misc);
@@ -2434,7 +2488,7 @@ static int aw8695_haptic_init(struct aw8695 *aw8695)
    aw8695_haptic_auto_boost_config(aw8695, false);

    aw8695_haptic_trig_param_init(aw8695);
	aw8695_haptic_trig_param_config(aw8695);
    /*aw8695_haptic_trig_param_config(aw8695);*/

    aw8695_haptic_offset_calibration(aw8695);

@@ -2446,11 +2500,73 @@ static int aw8695_haptic_init(struct aw8695 *aw8695)
    mutex_unlock(&aw8695->lock);

    /* f0 calibration */
#ifdef AW_UEFI_CAL_F0
    pr_info("%s pre_f0 = %d \n", __func__,aw8695->info.f0_pre);;
    pr_info("%s aw8695_f0_cal = %d \n", __func__,aw8695_f0_cal);

    f0_pre_low = aw8695->info.f0_pre*0.93;
    f0_pre_high = aw8695->info.f0_pre * 1.07;
       if(aw8695_f0_cal > (aw8695->info.f0_pre * 1.07) || aw8695_f0_cal < (aw8695->info.f0_pre*0.93)){ //dtsi 里定义的校准偏差值 7%
         mutex_lock(&aw8695->lock);
         aw8695_haptic_f0_calibration(aw8695); //调用 1 次振动对 f0 值完成重新检测及校准
         mutex_unlock(&aw8695->lock);
        pr_info("%s new f0 = %d \n", __func__,aw8695->f0);
     }
     else{ //对 UEFI 传入的 f0 检测值校准
        unsigned int f0_limit = 0;
        char f0_cali_lra = 0;
        int f0_cali_step = 0;

         aw8695_i2c_write(aw8695, AW8695_REG_TRIM_LRA, 0x00);

         /* max and min limit */
         aw8695->f0 = aw8695_f0_cal;
         f0_limit = aw8695->f0;
         if (aw8695->f0 * 100 <
             aw8695->info.f0_pre * (100 - aw8695->info.f0_cali_percen)) {
             f0_limit = aw8695->info.f0_pre;
         }
         if (aw8695->f0 * 100 >
             aw8695->info.f0_pre * (100 + aw8695->info.f0_cali_percen)) {
             f0_limit = aw8695->info.f0_pre;
         }
         /* calculate cali step */
         f0_cali_step = 100000 * ((int)f0_limit -
             (int)aw8695->info.f0_pre) / ((int)f0_limit * 25);

         pr_info("%s line=%d f0_cali_step=%d\n", __func__, __LINE__, f0_cali_step);
         pr_info("%s line=%d f0_limit=%d\n", __func__, __LINE__, (int)f0_limit);

         if (f0_cali_step >= 0) { /*f0_cali_step >= 0 */
             if (f0_cali_step % 10 >= 5) {
                 f0_cali_step = f0_cali_step / 10 + 1 + 32;
             } else {
                 f0_cali_step = f0_cali_step / 10 + 32;
             }
         } 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;
         }
         pr_info("%s f0_cali_lra=%d\n", __func__, (int)f0_cali_lra);
         /* update cali step */
         aw8695_i2c_write(aw8695, AW8695_REG_TRIM_LRA, (char)f0_cali_lra);
         aw8695_i2c_read(aw8695, AW8695_REG_TRIM_LRA, &reg_val);
         pr_info("%s final trim_lra=0x%02x\n", __func__, reg_val);
     }
#else
    mutex_lock(&aw8695->lock);

    aw8695_haptic_f0_calibration(aw8695);
    mutex_unlock(&aw8695->lock);

#endif
    /* beme config */
    bemf_config = aw8695->info.bemf_config[0];
    aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_H, bemf_config);
@@ -2599,11 +2715,11 @@ static ssize_t aw8695_duration_store(struct device *dev,
    if (val <= 0)
        return count;

    //tianlang modify start
    //Leo 20210105 modify start
    mutex_lock(&aw8695->lock);
    aw8695->duration = val;
    mutex_unlock(&aw8695->lock);
    //tianlang modify end
    //Leo 20210105 modify end

    return count;
}
@@ -2733,6 +2849,7 @@ static ssize_t aw8695_index_store(struct device *dev,
    pr_debug("%s: value=%d\n", __func__, val);

    mutex_lock(&aw8695->lock);
    aw8695_test_index = val;
    aw8695->index = val;
    aw8695_haptic_set_repeat_wav_seq(aw8695, aw8695->index);
    mutex_unlock(&aw8695->lock);
@@ -3739,13 +3856,15 @@ static ssize_t aw8695_haptic_audio_store(struct device *dev,
    unsigned int databuf[6] = { 0 };
    struct haptic_ctr *hap_ctr = NULL;

	if (!aw8695->ram_init)
    aw_dbg_info("%s: haptic_audio enter\n", __func__);

    if (!(aw8695->ram_init) || atomic_read(&aw8695->is_rtp))
        return count;
    if (6 ==
        sscanf(buf, "%d %d %d %d %d %d", &databuf[0], &databuf[1],
           &databuf[2], &databuf[3], &databuf[4], &databuf[5])) {
        if (databuf[2]) {
			pr_info
            aw_dbg_info
            ("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n",
             __func__, databuf[0], databuf[1], databuf[2],
             databuf[3], databuf[4], databuf[5]);
@@ -3769,9 +3888,9 @@ static ssize_t aw8695_haptic_audio_store(struct device *dev,
                            hap_ctr);

        if (hap_ctr->cmd == 0xff) {
			pr_info("%s: haptic_audio stop\n", __func__);
            aw_dbg_info("%s: haptic_audio stop\n", __func__);
            if (hrtimer_active(&aw8695->haptic_audio.timer)) {
				pr_info("%s: cancel haptic_audio_timer\n",
                aw_dbg_info("%s: cancel haptic_audio_timer\n",
                    __func__);
                hrtimer_cancel(&aw8695->haptic_audio.timer);
                aw8695->haptic_audio.ctr.cnt = 0;
@@ -3780,7 +3899,7 @@ static ssize_t aw8695_haptic_audio_store(struct device *dev,
        } else {
            if (hrtimer_active(&aw8695->haptic_audio.timer)) {
            } else {
				pr_info("%s: start haptic_audio_timer\n",
                aw_dbg_info("%s: start haptic_audio_timer\n",
                    __func__);
                aw8695_haptic_audio_init(aw8695);
                hrtimer_start(&aw8695->haptic_audio.timer,
@@ -3963,19 +4082,31 @@ static void aw8695_vibrator_work_routine(struct work_struct *work)
    aw8695_haptic_stop(aw8695);
    if (aw8695->state) {
        if (aw8695->activate_mode == AW8695_HAPTIC_ACTIVATE_RAM_MODE) {
            //Leo 20210105 modify start	
            aw8695_haptic_ram_config(aw8695);
            if (aw8695->duration >= 60) {
                aw8695_haptic_ram_vbat_comp(aw8695, true);
                aw8695_haptic_play_repeat_seq(aw8695, true);
            } else {
                aw8695_haptic_ram_vbat_comp(aw8695, false);
                aw8695_haptic_play_wav_seq(aw8695, true);
            }
            //Leo 20210105 modify end	
           
        } else if (aw8695->activate_mode ==
               AW8695_HAPTIC_ACTIVATE_CONT_MODE) {
            aw8695_haptic_cont(aw8695);
        } else {
        }
        /* run ms timer */
        if(aw8695->duration >=60){
             hrtimer_start(&aw8695->timer,
                  ktime_set(aw8695->duration / 1000,
                    (aw8695->duration % 1000) * 1000000),
                  HRTIMER_MODE_REL);
        }
       
    }
    mutex_unlock(&aw8695->lock);
}

@@ -4092,9 +4223,9 @@ static irqreturn_t aw8695_irq(int irq, void *data)
    pr_debug("%s enter\n", __func__);

    aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, &reg_val);
	pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
    aw_dbg_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
    aw8695_i2c_read(aw8695, AW8695_REG_DBGSTAT, &dbg_val);
	pr_info("%s: reg DBGSTAT=0x%x\n", __func__, dbg_val);
    aw_dbg_info("%s: reg DBGSTAT=0x%x\n", __func__, dbg_val);

    if (reg_val & AW8695_BIT_SYSINT_OVI) {
        aw8695_op_clean_status(aw8695);
@@ -4114,20 +4245,20 @@ static irqreturn_t aw8695_irq(int irq, void *data)
    }
    if (reg_val & AW8695_BIT_SYSINT_DONEI) {
        aw8695_op_clean_status(aw8695);
		pr_info("%s chip playback done\n", __func__);
        aw_dbg_info("%s chip playback done\n", __func__);
    }

    if (reg_val & AW8695_BIT_SYSINT_FF_AEI) {
		pr_info("%s: aw8695 rtp fifo almost empty int\n", __func__);
        aw_dbg_info("%s: aw8695 rtp fifo almost empty int\n", __func__);
        if (aw8695->rtp_init) {
            while ((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) &&
                   (aw8695->play_mode == AW8695_HAPTIC_RTP_MODE)) {
                mutex_lock(&aw8695->rtp_lock);
				pr_info
                aw_dbg_info
                ("%s: aw8695 rtp mode fifo update, cnt=%d\n",
                 __func__, aw8695->rtp_cnt);
                if (!aw8695_rtp) {
					pr_info("%s:aw8695_rtp is null break\n",
                    aw_dbg_info("%s:aw8695_rtp is null break\n",
                        __func__);
                    mutex_unlock(&aw8695->rtp_lock);
                    break;
@@ -4148,35 +4279,36 @@ static irqreturn_t aw8695_irq(int irq, void *data)
                aw8695_i2c_read(aw8695, AW8695_REG_GLB_STATE, &glb_state_val);
                if ((aw8695->rtp_cnt == aw8695_rtp->len) || ((glb_state_val & 0x0f) == 0x00)) {
                    aw8695_op_clean_status(aw8695);
					pr_info("%s: rtp update complete\n",
                    aw_dbg_info("%s: rtp update complete\n",
                           __func__);
                    aw8695_haptic_set_rtp_aei(aw8695,
                                  false);
                    aw8695->rtp_cnt = 0;
                    aw8695->rtp_init = 0;
                    atomic_set(&aw8695->is_rtp, 0);
                    mutex_unlock(&aw8695->rtp_lock);
                    break;
                }
                mutex_unlock(&aw8695->rtp_lock);
            }
        } else {
			pr_info("%s: aw8695 rtp init = %d, init error\n",
            aw_dbg_info("%s: aw8695 rtp init = %d, init error\n",
                   __func__, aw8695->rtp_init);
        }
    }

    if (reg_val & AW8695_BIT_SYSINT_FF_AFI)
		pr_info("%s: aw8695 rtp mode fifo full empty\n", __func__);
        aw_dbg_info("%s: aw8695 rtp mode fifo full empty\n", __func__);

    if (aw8695->play_mode != AW8695_HAPTIC_RTP_MODE)
        aw8695_haptic_set_rtp_aei(aw8695, false);

    aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, &reg_val);
	pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
    aw_dbg_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
    aw8695_i2c_read(aw8695, AW8695_REG_SYSST, &reg_val);
	pr_info("%s: reg SYSST=0x%x\n", __func__, reg_val);
    aw_dbg_info("%s: reg SYSST=0x%x\n", __func__, reg_val);

	pr_info("%s exit\n", __func__);
    aw_dbg_info("%s exit\n", __func__);

    return IRQ_HANDLED;
}
@@ -4503,6 +4635,7 @@ static int aw8695_i2c_probe(struct i2c_client *i2c,
    if (ret < 0) {
        dev_err(&i2c->dev, "%s: aw8695_read_chipid failed ret=%d\n",
            __func__, ret);
		i2c_check_status_create("viber_aw8695",0);
        goto err_id;
    }

@@ -4545,7 +4678,7 @@ static int aw8695_i2c_probe(struct i2c_client *i2c,
    aw8695_ram_init(aw8695);

    pr_info("%s probe completed successfully!\n", __func__);

    i2c_check_status_create("viber_aw8695",1);
    return 0;

 err_sysfs:
@@ -4605,6 +4738,22 @@ static int aw8695_resume(struct device *dev)

static SIMPLE_DEV_PM_OPS(aw8695_pm_ops, aw8695_suspend, aw8695_resume);

#ifdef AW_UEFI_CAL_F0
static int __init aw8695_get_f0_cmd(char *str)
{

    if (kstrtol(str, 10,
                (unsigned long *)&aw8695_f0_cal)) {
        pr_err("invalid f0 : %s. \n",
            str);
    }
    pr_info("cmdline_f0=%ld \n", aw8695_f0_cal);

    return 0;
}
__setup("haptic_f0:f0=",aw8695_get_f0_cmd);
#endif

static const struct i2c_device_id aw8695_i2c_id[] = {
    {AW8695_I2C_NAME, 0},
    {}
@@ -4658,4 +4807,3 @@ module_exit(aw8695_i2c_exit);

MODULE_DESCRIPTION("AW8695 Haptic Driver");
MODULE_LICENSE("GPL v2");
+1 −0
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ struct aw8695 {
	unsigned long int microsecond;
	unsigned int sys_frequency;
	unsigned int rtp_len;
	atomic_t is_rtp;

	int reset_gpio;
	int irq_gpio;