Loading Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt +3 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ Optional properties when qcom,actuator-type is "lra" - qcom,lra-high-z : High Z configuration for auto resonance. Possible string values are "none", "opt1", "opt2" and "opt3" (default). For PM660, "opt0" is valid value for 1 LRA period. - qcom,lra-hw-auto-resonance : boolean, enable Hardware auto-resonance for PM660. Use this property to enable Hardware auto-resonance. If not defined then Software auto-resonance is enabled(default). - qcom,lra-qwd-drive-duration : Drive duration of LRA in QWD mode for PM660. Possible values are: 0: 1/4 LRA PERIOD and 1: 3/8 LRA PERIOD - qcom,lra-calibrate-at-eop : To calibrate at End of Pattern for PM660. Loading drivers/platform/msm/qpnp-haptic.c +30 −7 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ #define QPNP_HAP_ACT_TYPE_MASK 0xFE #define QPNP_HAP_LRA 0x0 #define QPNP_HAP_ERM 0x1 #define QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT BIT(3) #define QPNP_HAP_AUTO_RES_MODE_MASK GENMASK(6, 4) #define QPNP_HAP_AUTO_RES_MODE_SHIFT 4 #define QPNP_HAP_PM660_AUTO_RES_MODE_BIT BIT(7) Loading Loading @@ -315,6 +316,7 @@ struct qpnp_pwm_info { * @ reg_play - play register * @ lra_res_cal_period - period for resonance calibration * @ sc_duration - counter to determine the duration of short circuit condition * @ lra_hw_auto_resonance - enable hardware auto resonance * @ state - current state of haptics * @ use_play_irq - play irq usage state * @ use_sc_irq - short circuit irq usage state Loading Loading @@ -377,6 +379,7 @@ struct qpnp_hap { u8 ext_pwm_dtest_line; u8 pmic_subtype; u8 auto_res_mode; bool lra_hw_auto_resonance; bool vcc_pon_enabled; bool state; bool use_play_irq; Loading Loading @@ -1636,7 +1639,8 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) return rc; } if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { /* * Start timer to poll Auto Resonance error bit */ Loading @@ -1654,12 +1658,14 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && (hap->status_flags & AUTO_RESONANCE_ENABLED)) (hap->status_flags & AUTO_RESONANCE_ENABLED) && !hap->lra_hw_auto_resonance) update_lra_frequency(hap); rc = qpnp_hap_mod_enable(hap, on); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { hrtimer_cancel(&hap->auto_res_err_poll_timer); } } Loading @@ -1677,7 +1683,8 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) mutex_lock(&hap->lock); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); Loading Loading @@ -1873,6 +1880,15 @@ static int qpnp_hap_config(struct qpnp_hap *hap) /* Configure auto resonance parameters */ if (hap->act_type == QPNP_HAP_LRA) { if (hap->lra_hw_auto_resonance) { rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT, QPNP_HAP_AUTO_RES_CTRL(hap->base), QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT); if (rc) return rc; } if (hap->pmic_subtype == PM660_SUBTYPE) { if (hap->lra_res_cal_period < QPNP_HAP_PM660_RES_CAL_PERIOD_MIN) Loading Loading @@ -2300,6 +2316,10 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) return rc; } hap->lra_hw_auto_resonance = of_property_read_bool(spmi->dev.of_node, "qcom,lra-hw-auto-resonance"); hap->perform_lra_auto_resonance_search = of_property_read_bool(spmi->dev.of_node, "qcom,perform-lra-auto-resonance-search"); Loading Loading @@ -2554,7 +2574,8 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) hap->timed_dev.get_time = qpnp_hap_get_time; hap->timed_dev.enable = qpnp_hap_td_enable; if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { hrtimer_init(&hap->auto_res_err_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hap->auto_res_err_poll_timer.function = detect_auto_res_error; Loading Loading @@ -2597,7 +2618,8 @@ sysfs_fail: timed_output_dev_unregister(&hap->timed_dev); timed_output_fail: cancel_work_sync(&hap->work); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); mutex_destroy(&hap->lock); Loading @@ -2616,7 +2638,8 @@ static int qpnp_haptic_remove(struct spmi_device *spmi) &qpnp_hap_attrs[i].attr); cancel_work_sync(&hap->work); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); timed_output_dev_unregister(&hap->timed_dev); Loading Loading
Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt +3 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ Optional properties when qcom,actuator-type is "lra" - qcom,lra-high-z : High Z configuration for auto resonance. Possible string values are "none", "opt1", "opt2" and "opt3" (default). For PM660, "opt0" is valid value for 1 LRA period. - qcom,lra-hw-auto-resonance : boolean, enable Hardware auto-resonance for PM660. Use this property to enable Hardware auto-resonance. If not defined then Software auto-resonance is enabled(default). - qcom,lra-qwd-drive-duration : Drive duration of LRA in QWD mode for PM660. Possible values are: 0: 1/4 LRA PERIOD and 1: 3/8 LRA PERIOD - qcom,lra-calibrate-at-eop : To calibrate at End of Pattern for PM660. Loading
drivers/platform/msm/qpnp-haptic.c +30 −7 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ #define QPNP_HAP_ACT_TYPE_MASK 0xFE #define QPNP_HAP_LRA 0x0 #define QPNP_HAP_ERM 0x1 #define QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT BIT(3) #define QPNP_HAP_AUTO_RES_MODE_MASK GENMASK(6, 4) #define QPNP_HAP_AUTO_RES_MODE_SHIFT 4 #define QPNP_HAP_PM660_AUTO_RES_MODE_BIT BIT(7) Loading Loading @@ -315,6 +316,7 @@ struct qpnp_pwm_info { * @ reg_play - play register * @ lra_res_cal_period - period for resonance calibration * @ sc_duration - counter to determine the duration of short circuit condition * @ lra_hw_auto_resonance - enable hardware auto resonance * @ state - current state of haptics * @ use_play_irq - play irq usage state * @ use_sc_irq - short circuit irq usage state Loading Loading @@ -377,6 +379,7 @@ struct qpnp_hap { u8 ext_pwm_dtest_line; u8 pmic_subtype; u8 auto_res_mode; bool lra_hw_auto_resonance; bool vcc_pon_enabled; bool state; bool use_play_irq; Loading Loading @@ -1636,7 +1639,8 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) return rc; } if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { /* * Start timer to poll Auto Resonance error bit */ Loading @@ -1654,12 +1658,14 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && (hap->status_flags & AUTO_RESONANCE_ENABLED)) (hap->status_flags & AUTO_RESONANCE_ENABLED) && !hap->lra_hw_auto_resonance) update_lra_frequency(hap); rc = qpnp_hap_mod_enable(hap, on); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { hrtimer_cancel(&hap->auto_res_err_poll_timer); } } Loading @@ -1677,7 +1683,8 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) mutex_lock(&hap->lock); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); Loading Loading @@ -1873,6 +1880,15 @@ static int qpnp_hap_config(struct qpnp_hap *hap) /* Configure auto resonance parameters */ if (hap->act_type == QPNP_HAP_LRA) { if (hap->lra_hw_auto_resonance) { rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT, QPNP_HAP_AUTO_RES_CTRL(hap->base), QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT); if (rc) return rc; } if (hap->pmic_subtype == PM660_SUBTYPE) { if (hap->lra_res_cal_period < QPNP_HAP_PM660_RES_CAL_PERIOD_MIN) Loading Loading @@ -2300,6 +2316,10 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) return rc; } hap->lra_hw_auto_resonance = of_property_read_bool(spmi->dev.of_node, "qcom,lra-hw-auto-resonance"); hap->perform_lra_auto_resonance_search = of_property_read_bool(spmi->dev.of_node, "qcom,perform-lra-auto-resonance-search"); Loading Loading @@ -2554,7 +2574,8 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) hap->timed_dev.get_time = qpnp_hap_get_time; hap->timed_dev.enable = qpnp_hap_td_enable; if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) { if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) { hrtimer_init(&hap->auto_res_err_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hap->auto_res_err_poll_timer.function = detect_auto_res_error; Loading Loading @@ -2597,7 +2618,8 @@ sysfs_fail: timed_output_dev_unregister(&hap->timed_dev); timed_output_fail: cancel_work_sync(&hap->work); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); mutex_destroy(&hap->lock); Loading @@ -2616,7 +2638,8 @@ static int qpnp_haptic_remove(struct spmi_device *spmi) &qpnp_hap_attrs[i].attr); cancel_work_sync(&hap->work); if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && !hap->lra_hw_auto_resonance) hrtimer_cancel(&hap->auto_res_err_poll_timer); hrtimer_cancel(&hap->hap_timer); timed_output_dev_unregister(&hap->timed_dev); Loading