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

Commit c2935a60 authored by Sultanxda's avatar Sultanxda Committed by TARKZiM
Browse files

msm: qpnp-haptic: Process haptics asynchronously



Blocking the timed_output sysfs node due to mutex contention causes severe
device wake-up latency, as a process crucial to system resume writes to the
timed_output vibrator node every time the device is resumed via the
fingerprint reader (fingerprint reader triggers a haptic response on
success).

By processing haptics asynchronously via a worker, the timed_output sysfs
won't get stalled for long periods of time (>30ms), and thus the device
will consistently wake from sleep faster.

Change-Id: Id482be9e098a77f0859613f0ab52a6f1542b4192
Signed-off-by: default avatarSultanxda <sultanxda@gmail.com>
Signed-off-by: default avatarFrancisco Franco <franciscofranco.1990@gmail.com>
parent cbf8c2f3
Loading
Loading
Loading
Loading
+33 −4
Original line number Diff line number Diff line
@@ -285,6 +285,8 @@ struct qpnp_hap {
	struct qpnp_pwm_info pwm_info;
	struct mutex lock;
	struct mutex wf_lock;
	spinlock_t td_lock;
	struct work_struct td_work;
	struct completion completion;
	enum qpnp_hap_mode play_mode;
	enum qpnp_hap_auto_res_mode auto_res_mode;
@@ -320,6 +322,7 @@ struct qpnp_hap {
	bool sup_brake_pat;
	bool correct_lra_drive_freq;
	bool misc_trim_error_rc19p2_clk_reg_present;
	int td_value;
};

static struct qpnp_hap *ghap;
@@ -1497,11 +1500,15 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
	return rc;
}

/* enable interface from timed output class */
static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value)
static void qpnp_timed_enable_worker(struct work_struct *work)
{
	struct qpnp_hap *hap = container_of(dev, struct qpnp_hap,
					 timed_dev);
	struct qpnp_hap *hap = container_of(work, struct qpnp_hap,
					 td_work);
	int value;

	spin_lock(&hap->td_lock);
	value = hap->td_value;
	spin_unlock(&hap->td_lock);

	mutex_lock(&hap->lock);
	hrtimer_cancel(&hap->hap_timer);
@@ -1524,6 +1531,25 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value)
	schedule_work(&hap->work);
}

/* enable interface from timed output class */
static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value)
{
        struct qpnp_hap *hap = container_of(dev, struct qpnp_hap,
                                         timed_dev);

        spin_lock(&hap->td_lock);
        hap->td_value = value;
        spin_unlock(&hap->td_lock);

        schedule_work(&hap->td_work);
}

void set_vibrate(int value)

{
	qpnp_hap_td_enable(&ghap->timed_dev, value);
}

/* play pwm bytes */
int qpnp_hap_play_byte(u8 data, bool on)
{
@@ -2141,8 +2167,11 @@ static int qpnp_haptic_probe(struct spmi_device *spmi)

	mutex_init(&hap->lock);
	mutex_init(&hap->wf_lock);
	spin_lock_init(&hap->td_lock);

	INIT_WORK(&hap->work, qpnp_hap_worker);
	init_completion(&hap->completion);
	INIT_WORK(&hap->td_work, qpnp_timed_enable_worker);

	hrtimer_init(&hap->hap_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	hap->hap_timer.function = qpnp_hap_timer;