Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c194abb authored by Fenglin Wu's avatar Fenglin Wu Committed by Fenglin Wu
Browse files

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: default avatarFenglin Wu <fenglinw@codeaurora.org>
parent 7fbe930d
Loading
Loading
Loading
Loading
+54 −7
Original line number Diff line number Diff line
@@ -8,6 +8,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>
@@ -511,6 +512,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;
@@ -529,6 +531,7 @@ struct haptics_chip {
	bool				clamp_at_5v;
	bool				hpwr_vreg_enabled;
	bool				is_hv_haptics;
	bool				hboost_enabled;
};

struct haptics_reg_info {
@@ -1292,6 +1295,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);
@@ -1304,13 +1310,16 @@ 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;
	}

	chip->hboost_enabled = en;
	return 0;
}

static bool is_swr_play_enabled(struct haptics_chip *chip)
{
	int rc;
@@ -1357,6 +1366,14 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip)

	if (is_haptics_external_powered(chip))
		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
@@ -1493,6 +1510,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;
@@ -1526,11 +1544,17 @@ 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 (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;
@@ -4582,6 +4606,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;
@@ -4646,6 +4685,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);
@@ -4755,6 +4796,12 @@ 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
	 */
	hrtimer_cancel(&chip->hbst_off_timer);
	haptics_boost_vreg_enable(chip, false);
	rc = haptics_enable_hpwr_vreg(chip, false);
	if (rc < 0)
		return rc;