mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
input: qcom-hv-haptics: delay hBoost turning off
Extend hBoost PBS control to all play modes, so hBoost disabling will be always handled in the driver by triggering the PBS. Also, delay hBoost turning off 2 seconds after the stop command to prevent hBoost being enabled/disabled too frequently in repeated short vibration case, this help to avoid hBoost lockup when it's enabled and disabled very quickly. Change-Id: I76263e51ad00a01d95ff7fd7b08c1655031516e6 Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
This commit is contained in:
parent
bf0527051c
commit
48c4987a4a
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
@ -543,6 +544,7 @@ struct haptics_chip {
|
|||
struct device_node *pbs_node;
|
||||
struct class hap_class;
|
||||
struct regulator *hpwr_vreg;
|
||||
struct hrtimer hbst_off_timer;
|
||||
int fifo_empty_irq;
|
||||
u32 hpwr_voltage_mv;
|
||||
u32 effects_count;
|
||||
|
|
@ -561,6 +563,7 @@ struct haptics_chip {
|
|||
bool clamp_at_5v;
|
||||
bool hpwr_vreg_enabled;
|
||||
bool is_hv_haptics;
|
||||
bool hboost_enabled;
|
||||
};
|
||||
|
||||
struct haptics_reg_info {
|
||||
|
|
@ -1218,6 +1221,9 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (chip->hboost_enabled == en)
|
||||
return 0;
|
||||
|
||||
val = en ? HAP_VREG_ON_VAL : HAP_VREG_OFF_VAL;
|
||||
rc = nvmem_device_write(chip->hap_cfg_nvmem,
|
||||
PBS_ARG_REG, 1, &val);
|
||||
|
|
@ -1230,11 +1236,14 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
|||
val = PBS_TRIG_SET_VAL;
|
||||
rc = nvmem_device_write(chip->hap_cfg_nvmem,
|
||||
PBS_TRIG_SET_REG, 1, &val);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Write SDAM %#x failed, rc=%d\n",
|
||||
PBS_TRIG_SET_REG, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
chip->hboost_enabled = en;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_swr_play_enabled(struct haptics_chip *chip)
|
||||
|
|
@ -1286,6 +1295,14 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip)
|
|||
|
||||
if (!(chip->wa_flags & SW_CTRL_HBST))
|
||||
return 0;
|
||||
|
||||
if ((hrtimer_get_remaining(&chip->hbst_off_timer) > 0) ||
|
||||
hrtimer_active(&chip->hbst_off_timer)) {
|
||||
hrtimer_cancel(&chip->hbst_off_timer);
|
||||
dev_dbg(chip->dev, "hboost is still on, ignore\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait ~20ms until hBoost is ready, otherwise
|
||||
* bail out and return -EBUSY
|
||||
|
|
@ -1425,6 +1442,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define BOOST_VREG_OFF_DELAY_SECONDS 2
|
||||
static int haptics_enable_play(struct haptics_chip *chip, bool en)
|
||||
{
|
||||
struct haptics_play_info *play = &chip->play;
|
||||
|
|
@ -1461,11 +1479,19 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en)
|
|||
return rc;
|
||||
}
|
||||
|
||||
if (play->pattern_src == FIFO) {
|
||||
rc = haptics_boost_vreg_enable(chip, en);
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "Notify vreg %s failed, rc=%d\n",
|
||||
en ? "enabling" : "disabling", rc);
|
||||
if (chip->wa_flags & SW_CTRL_HBST) {
|
||||
if (en) {
|
||||
rc = haptics_boost_vreg_enable(chip, true);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Keep boost vreg on failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
hrtimer_start(&chip->hbst_off_timer,
|
||||
ktime_set(BOOST_VREG_OFF_DELAY_SECONDS, 0),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -4758,6 +4784,21 @@ static bool is_swr_supported(struct haptics_chip *chip)
|
|||
return true;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart haptics_disable_hbst_timer(struct hrtimer *timer)
|
||||
{
|
||||
struct haptics_chip *chip = container_of(timer,
|
||||
struct haptics_chip, hbst_off_timer);
|
||||
int rc;
|
||||
|
||||
rc = haptics_boost_vreg_enable(chip, false);
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "disable boost vreg failed, rc=%d\n", rc);
|
||||
else
|
||||
dev_dbg(chip->dev, "boost vreg is disabled\n");
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int haptics_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct haptics_chip *chip;
|
||||
|
|
@ -4819,6 +4860,8 @@ static int haptics_probe(struct platform_device *pdev)
|
|||
mutex_init(&chip->play.lock);
|
||||
disable_irq_nosync(chip->fifo_empty_irq);
|
||||
chip->fifo_empty_irq_en = false;
|
||||
hrtimer_init(&chip->hbst_off_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
chip->hbst_off_timer.function = haptics_disable_hbst_timer;
|
||||
|
||||
atomic_set(&chip->play.fifo_status.is_busy, 0);
|
||||
atomic_set(&chip->play.fifo_status.written_done, 0);
|
||||
|
|
@ -4925,6 +4968,15 @@ static int haptics_suspend(struct device *dev)
|
|||
}
|
||||
mutex_unlock(&play->lock);
|
||||
|
||||
/*
|
||||
* Cancel the hBoost turning off timer and disable
|
||||
* hBoost if it's still enabled
|
||||
*/
|
||||
if (chip->wa_flags & SW_CTRL_HBST) {
|
||||
hrtimer_cancel(&chip->hbst_off_timer);
|
||||
haptics_boost_vreg_enable(chip, false);
|
||||
}
|
||||
|
||||
rc = haptics_enable_hpwr_vreg(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user