From 453824b9ab00af0e113822358872e23a0ed35f9d Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 12 Jan 2018 11:30:55 +0800 Subject: [PATCH] qcom: qpnp-haptics: extend stop timer for a longer request Haptics works as a timed output device and it doesn't expect another enable request while current one is still in progress. If a new enabling request comes in and its duration is longer than current pattern's expiry then extend the stop timer. CRs-Fixed: 2171601 Change-Id: I1f1f4e9a58140114a41d2af54b06cd798332eae4 Signed-off-by: Fenglin Wu --- drivers/soc/qcom/qpnp-haptic.c | 63 ++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c index 38cc86963181..4ca0edf24eed 100644 --- a/drivers/soc/qcom/qpnp-haptic.c +++ b/drivers/soc/qcom/qpnp-haptic.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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 @@ -2231,6 +2231,8 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int time_ms) { struct qpnp_hap *hap = container_of(dev, struct qpnp_hap, timed_dev); + bool state = !!time_ms; + ktime_t rem; int rc; if (time_ms < 0) @@ -2238,38 +2240,49 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int time_ms) mutex_lock(&hap->lock); - if (time_ms == 0) { - /* disable haptics */ - hrtimer_cancel(&hap->hap_timer); - hap->state = 0; - schedule_work(&hap->work); + if (hap->state == state) { + if (state) { + rem = hrtimer_get_remaining(&hap->hap_timer); + if (time_ms > ktime_to_ms(rem)) { + time_ms = (time_ms > hap->timeout_ms ? + hap->timeout_ms : time_ms); + hrtimer_cancel(&hap->hap_timer); + hap->play_time_ms = time_ms; + hrtimer_start(&hap->hap_timer, + ktime_set(time_ms / 1000, + (time_ms % 1000) * 1000000), + HRTIMER_MODE_REL); + } + } mutex_unlock(&hap->lock); return; } - if (time_ms < 10) - time_ms = 10; + hap->state = state; + if (!hap->state) { + hrtimer_cancel(&hap->hap_timer); + } else { + if (time_ms < 10) + time_ms = 10; - if (is_sw_lra_auto_resonance_control(hap)) - hrtimer_cancel(&hap->auto_res_err_poll_timer); - - hrtimer_cancel(&hap->hap_timer); - - if (hap->auto_mode) { - rc = qpnp_hap_auto_mode_config(hap, time_ms); - if (rc < 0) { - pr_err("Unable to do auto mode config\n"); - mutex_unlock(&hap->lock); - return; + if (hap->auto_mode) { + rc = qpnp_hap_auto_mode_config(hap, time_ms); + if (rc < 0) { + pr_err("Unable to do auto mode config\n"); + mutex_unlock(&hap->lock); + return; + } } + + time_ms = (time_ms > hap->timeout_ms ? + hap->timeout_ms : time_ms); + hap->play_time_ms = time_ms; + hrtimer_start(&hap->hap_timer, + ktime_set(time_ms / 1000, + (time_ms % 1000) * 1000000), + HRTIMER_MODE_REL); } - time_ms = (time_ms > hap->timeout_ms ? hap->timeout_ms : time_ms); - hap->play_time_ms = time_ms; - hap->state = 1; - hrtimer_start(&hap->hap_timer, - ktime_set(time_ms / 1000, (time_ms % 1000) * 1000000), - HRTIMER_MODE_REL); mutex_unlock(&hap->lock); schedule_work(&hap->work); }