diff options
| -rw-r--r-- | Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt | 13 | ||||
| -rw-r--r-- | drivers/soc/qcom/qpnp-haptic.c | 44 |
2 files changed, 50 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt index fe94e40a27cd..4d7239be023b 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt @@ -67,6 +67,18 @@ Optional properties when qcom,actuator-type is "lra" - qcom,lra-res-cal-period : Auto resonance calibration period. The values range from 4 to 32(default) +Optional properties when qcom,lra-auto-res-mode is "qwd" + - qcom,time-required-to-generate-back-emf-us: Time period required to generate sufficient + back-emf (in case of QWD mode only) in us. For auto resonance + detection to work properly,sufficient back-emf has to be + generated. In general, back-emf takes some time to build up. + When the auto resonance mode is chosen as QWD, high-z will + be applied for every LRA cycle and hence there won't be + enough back-emf at the start-up. So we need to drive the + motor for a few LRA cycles. Hence, auto resonance detection + is enabled after this delay period after the PLAY bit is + asserted. The default value is 20000us. + Example: qcom,haptic@c000 { status = "disabled"; @@ -94,4 +106,5 @@ Example: qcom,lra-high-z = "opt1"; qcom,lra-auto-res-mode = "qwd"; qcom,lra-res-cal-period = <4>; + qcom,time-required-to-generate-back-emf-us = <20000>; }; diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c index 39070561d7e4..7033a2c0df2b 100644 --- a/drivers/soc/qcom/qpnp-haptic.c +++ b/drivers/soc/qcom/qpnp-haptic.c @@ -141,7 +141,7 @@ #define QPNP_HAP_CYCLS 5 #define QPNP_TEST_TIMER_MS 5 -#define AUTO_RES_ENABLE_TIMEOUT 20000 +#define QPNP_HAP_TIME_REQ_FOR_BACK_EMF_GEN 20000 #define AUTO_RES_ERR_CAPTURE_RES 5 #define AUTO_RES_ERR_MAX 15 @@ -250,6 +250,8 @@ struct qpnp_pwm_info { * @ auto_res_mode - auto resonace mode * @ lra_high_z - high z option line * @ timeout_ms - max timeout in ms + * @ time_required_to_generate_back_emf_us - the time required for sufficient + back-emf to be generated for auto resonance to be successful * @ vmax_mv - max voltage in mv * @ ilim_ma - limiting current in ma * @ sc_deb_cycles - short circuit debounce cycles @@ -301,6 +303,7 @@ struct qpnp_hap { enum qpnp_hap_auto_res_mode auto_res_mode; enum qpnp_hap_high_z lra_high_z; u32 timeout_ms; + u32 time_required_to_generate_back_emf_us; u32 vmax_mv; u32 ilim_ma; u32 sc_deb_cycles; @@ -1455,6 +1458,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) int rc = 0; u8 val = 0; unsigned long timeout_ns = POLL_TIME_AUTO_RES_ERR_NS; + u32 back_emf_delay_us = hap->time_required_to_generate_back_emf_us; if (hap->play_mode == QPNP_HAP_PWM) { if (on) @@ -1464,6 +1468,18 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } else if (hap->play_mode == QPNP_HAP_BUFFER || hap->play_mode == QPNP_HAP_DIRECT) { if (on) { + /* + * For auto resonance detection to work properly, + * sufficient back-emf has to be generated. In general, + * back-emf takes some time to build up. When the auto + * resonance mode is chosen as QWD, high-z will be + * applied for every LRA cycle and hence there won't be + * enough back-emf at the start-up. Hence, the motor + * needs to vibrate for few LRA cycles after the PLAY + * bit is asserted. So disable the auto resonance here + * and enable it after the sleep of + * 'time_required_to_generate_back_emf_us' is completed. + */ if (hap->correct_lra_drive_freq || hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD) qpnp_hap_auto_res_enable(hap, 0); @@ -1474,17 +1490,18 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) rc = qpnp_hap_play(hap, on); - if ((hap->act_type == QPNP_HAP_LRA && - hap->correct_lra_drive_freq) || - hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD) { - usleep_range(AUTO_RES_ENABLE_TIMEOUT, - (AUTO_RES_ENABLE_TIMEOUT + 1)); + if (hap->act_type == QPNP_HAP_LRA && + (hap->correct_lra_drive_freq || + hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD)) { + usleep_range(back_emf_delay_us, + (back_emf_delay_us + 1)); rc = qpnp_hap_auto_res_enable(hap, 1); if (rc < 0) return rc; } - if (hap->correct_lra_drive_freq) { + if (hap->act_type == QPNP_HAP_LRA && + hap->correct_lra_drive_freq) { /* * Start timer to poll Auto Resonance error bit */ @@ -2038,6 +2055,19 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) hap->misc_trim_error_rc19p2_clk_reg_present = of_property_read_bool(pdev->dev.of_node, "qcom,misc-trim-error-rc19p2-clk-reg-present"); + + if (hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD) { + hap->time_required_to_generate_back_emf_us = + QPNP_HAP_TIME_REQ_FOR_BACK_EMF_GEN; + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,time-required-to-generate-back-emf-us", + &temp); + if (!rc) + hap->time_required_to_generate_back_emf_us = + temp; + } else { + hap->time_required_to_generate_back_emf_us = 0; + } } rc = of_property_read_string(pdev->dev.of_node, |
