Loading drivers/platform/msm/qpnp-haptic.c +58 −7 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #define QPNP_HAP_EXT_PWM_REG(b) (b + 0x57) #define QPNP_HAP_PWM_CAP_REG(b) (b + 0x58) #define QPNP_HAP_SC_CLR_REG(b) (b + 0x59) #define QPNP_HAP_SC_IRQ_STATUS_DELAY msecs_to_jiffies(1000) #define QPNP_HAP_BRAKE_REG(b) (b + 0x5C) #define QPNP_HAP_WAV_REP_REG(b) (b + 0x5E) #define QPNP_HAP_WAV_S_REG_BASE(b) (b + 0x60) Loading Loading @@ -128,6 +129,8 @@ #define AUTO_RES_ENABLE 0x80 #define AUTO_RES_DISABLE 0x00 #define AUTO_RES_ERR_BIT 0x10 #define SC_FOUND_BIT 0x08 #define SC_MAX_DURATION 5 #define QPNP_HAP_TIMEOUT_MS_MAX 15000 #define QPNP_HAP_STR_SIZE 20 Loading Loading @@ -236,6 +239,7 @@ struct qpnp_pwm_info { * @ timed_dev - timed output device * @ work - worker * @ auto_res_err_work - correct auto resonance error * @ sc_work - worker to handle short circuit condition * @ pwm_info - pwm info * @ lock - mutex lock * @ wf_lock - mutex lock for waveform Loading @@ -262,6 +266,7 @@ struct qpnp_pwm_info { * @ reg_en_ctl - enable control register * @ reg_play - play register * @ lra_res_cal_period - period for resonance calibration * @ sc_duration - counter to determine the duration of short circuit condition * @ state - current state of haptics * @ use_play_irq - play irq usage state * @ use_sc_irq - short circuit irq usage state Loading @@ -280,6 +285,7 @@ struct qpnp_hap { struct timed_output_dev timed_dev; struct work_struct work; struct work_struct auto_res_err_work; struct delayed_work sc_work; struct hrtimer hap_test_timer; struct work_struct test_work; struct qpnp_pwm_info pwm_info; Loading Loading @@ -309,6 +315,7 @@ struct qpnp_hap { u8 reg_en_ctl; u8 reg_play; u8 lra_res_cal_period; u8 sc_duration; u8 ext_pwm_dtest_line; bool state; bool use_play_irq; Loading Loading @@ -367,6 +374,21 @@ static int qpnp_hap_sec_access(struct qpnp_hap *hap) return 0; } static void qpnp_handle_sc_irq(struct work_struct *work) { struct qpnp_hap *hap = container_of(work, struct qpnp_hap, sc_work.work); u8 val, reg; qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base)); /* clear short circuit register */ if (val & SC_FOUND_BIT) { hap->sc_duration++; reg = QPNP_HAP_SC_CLR; qpnp_hap_write_reg(hap, ®, QPNP_HAP_SC_CLR_REG(hap->base)); } } static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on) { Loading Loading @@ -488,12 +510,28 @@ unlock: static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap) { struct qpnp_hap *hap = _hap; u8 reg; int rc; u8 disable_haptics = 0x00; u8 val; /* clear short circuit register */ dev_dbg(&hap->spmi->dev, "Short circuit detected\n"); reg = QPNP_HAP_SC_CLR; qpnp_hap_write_reg(hap, ®, QPNP_HAP_SC_CLR_REG(hap->base)); if (hap->sc_duration < SC_MAX_DURATION) { qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base)); if (val & SC_FOUND_BIT) schedule_delayed_work(&hap->sc_work, QPNP_HAP_SC_IRQ_STATUS_DELAY); else hap->sc_duration = 0; } else { /* Disable haptics module if the duration of short circuit * exceeds the maximum limit (5 secs). */ rc = qpnp_hap_write_reg(hap, &disable_haptics, QPNP_HAP_EN_CTL_REG(hap->base)); dev_err(&hap->spmi->dev, "Haptics disabled permanently due to short circuit\n"); } return IRQ_HANDLED; } Loading Loading @@ -1587,11 +1625,21 @@ static void qpnp_hap_worker(struct work_struct *work) { struct qpnp_hap *hap = container_of(work, struct qpnp_hap, work); u8 val = 0x00; int rc; /* Disable haptics module if the duration of short circuit * exceeds the maximum limit (5 secs). */ if (hap->sc_duration == SC_MAX_DURATION) { rc = qpnp_hap_write_reg(hap, &val, QPNP_HAP_EN_CTL_REG(hap->base)); } else { if (hap->play_mode == QPNP_HAP_PWM) qpnp_hap_mod_enable(hap, hap->state); qpnp_hap_set(hap, hap->state); } } /* get time api to know the remaining time */ static int qpnp_hap_get_time(struct timed_output_dev *dev) Loading Loading @@ -1886,6 +1934,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap) } } hap->sc_duration = 0; return rc; } Loading Loading @@ -2143,6 +2193,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) mutex_init(&hap->lock); mutex_init(&hap->wf_lock); INIT_WORK(&hap->work, qpnp_hap_worker); INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq); init_completion(&hap->completion); hrtimer_init(&hap->hap_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); Loading Loading
drivers/platform/msm/qpnp-haptic.c +58 −7 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #define QPNP_HAP_EXT_PWM_REG(b) (b + 0x57) #define QPNP_HAP_PWM_CAP_REG(b) (b + 0x58) #define QPNP_HAP_SC_CLR_REG(b) (b + 0x59) #define QPNP_HAP_SC_IRQ_STATUS_DELAY msecs_to_jiffies(1000) #define QPNP_HAP_BRAKE_REG(b) (b + 0x5C) #define QPNP_HAP_WAV_REP_REG(b) (b + 0x5E) #define QPNP_HAP_WAV_S_REG_BASE(b) (b + 0x60) Loading Loading @@ -128,6 +129,8 @@ #define AUTO_RES_ENABLE 0x80 #define AUTO_RES_DISABLE 0x00 #define AUTO_RES_ERR_BIT 0x10 #define SC_FOUND_BIT 0x08 #define SC_MAX_DURATION 5 #define QPNP_HAP_TIMEOUT_MS_MAX 15000 #define QPNP_HAP_STR_SIZE 20 Loading Loading @@ -236,6 +239,7 @@ struct qpnp_pwm_info { * @ timed_dev - timed output device * @ work - worker * @ auto_res_err_work - correct auto resonance error * @ sc_work - worker to handle short circuit condition * @ pwm_info - pwm info * @ lock - mutex lock * @ wf_lock - mutex lock for waveform Loading @@ -262,6 +266,7 @@ struct qpnp_pwm_info { * @ reg_en_ctl - enable control register * @ reg_play - play register * @ lra_res_cal_period - period for resonance calibration * @ sc_duration - counter to determine the duration of short circuit condition * @ state - current state of haptics * @ use_play_irq - play irq usage state * @ use_sc_irq - short circuit irq usage state Loading @@ -280,6 +285,7 @@ struct qpnp_hap { struct timed_output_dev timed_dev; struct work_struct work; struct work_struct auto_res_err_work; struct delayed_work sc_work; struct hrtimer hap_test_timer; struct work_struct test_work; struct qpnp_pwm_info pwm_info; Loading Loading @@ -309,6 +315,7 @@ struct qpnp_hap { u8 reg_en_ctl; u8 reg_play; u8 lra_res_cal_period; u8 sc_duration; u8 ext_pwm_dtest_line; bool state; bool use_play_irq; Loading Loading @@ -367,6 +374,21 @@ static int qpnp_hap_sec_access(struct qpnp_hap *hap) return 0; } static void qpnp_handle_sc_irq(struct work_struct *work) { struct qpnp_hap *hap = container_of(work, struct qpnp_hap, sc_work.work); u8 val, reg; qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base)); /* clear short circuit register */ if (val & SC_FOUND_BIT) { hap->sc_duration++; reg = QPNP_HAP_SC_CLR; qpnp_hap_write_reg(hap, ®, QPNP_HAP_SC_CLR_REG(hap->base)); } } static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on) { Loading Loading @@ -488,12 +510,28 @@ unlock: static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap) { struct qpnp_hap *hap = _hap; u8 reg; int rc; u8 disable_haptics = 0x00; u8 val; /* clear short circuit register */ dev_dbg(&hap->spmi->dev, "Short circuit detected\n"); reg = QPNP_HAP_SC_CLR; qpnp_hap_write_reg(hap, ®, QPNP_HAP_SC_CLR_REG(hap->base)); if (hap->sc_duration < SC_MAX_DURATION) { qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base)); if (val & SC_FOUND_BIT) schedule_delayed_work(&hap->sc_work, QPNP_HAP_SC_IRQ_STATUS_DELAY); else hap->sc_duration = 0; } else { /* Disable haptics module if the duration of short circuit * exceeds the maximum limit (5 secs). */ rc = qpnp_hap_write_reg(hap, &disable_haptics, QPNP_HAP_EN_CTL_REG(hap->base)); dev_err(&hap->spmi->dev, "Haptics disabled permanently due to short circuit\n"); } return IRQ_HANDLED; } Loading Loading @@ -1587,11 +1625,21 @@ static void qpnp_hap_worker(struct work_struct *work) { struct qpnp_hap *hap = container_of(work, struct qpnp_hap, work); u8 val = 0x00; int rc; /* Disable haptics module if the duration of short circuit * exceeds the maximum limit (5 secs). */ if (hap->sc_duration == SC_MAX_DURATION) { rc = qpnp_hap_write_reg(hap, &val, QPNP_HAP_EN_CTL_REG(hap->base)); } else { if (hap->play_mode == QPNP_HAP_PWM) qpnp_hap_mod_enable(hap, hap->state); qpnp_hap_set(hap, hap->state); } } /* get time api to know the remaining time */ static int qpnp_hap_get_time(struct timed_output_dev *dev) Loading Loading @@ -1886,6 +1934,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap) } } hap->sc_duration = 0; return rc; } Loading Loading @@ -2143,6 +2193,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) mutex_init(&hap->lock); mutex_init(&hap->wf_lock); INIT_WORK(&hap->work, qpnp_hap_worker); INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq); init_completion(&hap->completion); hrtimer_init(&hap->hap_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); Loading