msm: qpnp-haptic: add DT property for back-emf generation delay

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 and enable it back
after some delay. Add a DT property to configure this delay value.

CRs-Fixed: 833062
Change-Id: I688329f642ca9d506e203f448da5d874b91b77ff
Signed-off-by: Abinaya P <abinayap@codeaurora.org>
This commit is contained in:
Abinaya P 2016-03-07 13:09:45 +05:30
parent df445619c8
commit 88bd2ac302
2 changed files with 46 additions and 5 deletions

View File

@ -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-req-for-back-emf-generation-us = <20000>;
};

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -139,7 +139,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
@ -248,6 +248,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
@ -298,6 +300,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;
@ -1478,6 +1481,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)
@ -1487,6 +1491,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);
@ -1500,9 +1516,8 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int 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));
usleep_range(back_emf_delay_us,
back_emf_delay_us + 1);
rc = qpnp_hap_auto_res_enable(hap, 1);
if (rc < 0)
return rc;
@ -2049,6 +2064,19 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
hap->misc_trim_error_rc19p2_clk_reg_present =
of_property_read_bool(spmi->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(spmi->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(spmi->dev.of_node,