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

Commit 4d4ccd5c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: qpnp-haptic: disable haptics during permanent short circuit"

parents 08b81f4d a1c44fd5
Loading
Loading
Loading
Loading
+58 −7
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#define QPNP_HAP_EXT_PWM_REG(b)		(b + 0x57)
#define QPNP_HAP_PWM_CAP_REG(b)		(b + 0x58)
#define QPNP_HAP_SC_CLR_REG(b)		(b + 0x59)
#define QPNP_HAP_SC_IRQ_STATUS_DELAY   msecs_to_jiffies(1000)
#define QPNP_HAP_BRAKE_REG(b)		(b + 0x5C)
#define QPNP_HAP_WAV_REP_REG(b)		(b + 0x5E)
#define QPNP_HAP_WAV_S_REG_BASE(b)	(b + 0x60)
@@ -128,6 +129,8 @@
#define AUTO_RES_ENABLE			0x80
#define AUTO_RES_DISABLE		0x00
#define AUTO_RES_ERR_BIT		0x10
#define SC_FOUND_BIT			0x08
#define SC_MAX_DURATION			5

#define QPNP_HAP_TIMEOUT_MS_MAX		15000
#define QPNP_HAP_STR_SIZE		20
@@ -236,6 +239,7 @@ struct qpnp_pwm_info {
 *  @ timed_dev - timed output device
 *  @ work - worker
 *  @ auto_res_err_work - correct auto resonance error
 *  @ sc_work - worker to handle short circuit condition
 *  @ pwm_info - pwm info
 *  @ lock - mutex lock
 *  @ wf_lock - mutex lock for waveform
@@ -262,6 +266,7 @@ struct qpnp_pwm_info {
 *  @ reg_en_ctl - enable control register
 *  @ reg_play - play register
 *  @ lra_res_cal_period - period for resonance calibration
 *  @ sc_duration - counter to determine the duration of short circuit condition
 *  @ state - current state of haptics
 *  @ use_play_irq - play irq usage state
 *  @ use_sc_irq - short circuit irq usage state
@@ -280,6 +285,7 @@ struct qpnp_hap {
	struct timed_output_dev timed_dev;
	struct work_struct work;
	struct work_struct auto_res_err_work;
	struct delayed_work sc_work;
	struct hrtimer hap_test_timer;
	struct work_struct test_work;
	struct qpnp_pwm_info pwm_info;
@@ -309,6 +315,7 @@ struct qpnp_hap {
	u8 reg_en_ctl;
	u8 reg_play;
	u8 lra_res_cal_period;
	u8 sc_duration;
	u8 ext_pwm_dtest_line;
	bool state;
	bool use_play_irq;
@@ -367,6 +374,21 @@ static int qpnp_hap_sec_access(struct qpnp_hap *hap)
	return 0;
}

static void qpnp_handle_sc_irq(struct work_struct *work)
{
	struct qpnp_hap *hap = container_of(work,
				struct qpnp_hap, sc_work.work);
	u8 val, reg;

	qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base));

	/* clear short circuit register */
	if (val & SC_FOUND_BIT) {
		hap->sc_duration++;
		reg = QPNP_HAP_SC_CLR;
		qpnp_hap_write_reg(hap, &reg, QPNP_HAP_SC_CLR_REG(hap->base));
	}
}

static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on)
{
@@ -488,12 +510,28 @@ unlock:
static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
{
	struct qpnp_hap *hap = _hap;
	u8 reg;
	int rc;
	u8 disable_haptics = 0x00;
	u8 val;

	/* clear short circuit register */
	dev_dbg(&hap->spmi->dev, "Short circuit detected\n");
	reg = QPNP_HAP_SC_CLR;
	qpnp_hap_write_reg(hap, &reg, QPNP_HAP_SC_CLR_REG(hap->base));

	if (hap->sc_duration < SC_MAX_DURATION) {
		qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base));
		if (val & SC_FOUND_BIT)
			schedule_delayed_work(&hap->sc_work,
					QPNP_HAP_SC_IRQ_STATUS_DELAY);
		else
			hap->sc_duration = 0;
	} else {
		/* Disable haptics module if the duration of short circuit
		 * exceeds the maximum limit (5 secs).
		 */
		rc = qpnp_hap_write_reg(hap, &disable_haptics,
					QPNP_HAP_EN_CTL_REG(hap->base));
		dev_err(&hap->spmi->dev,
			"Haptics disabled permanently due to short circuit\n");
	}

	return IRQ_HANDLED;
}
@@ -1587,11 +1625,21 @@ static void qpnp_hap_worker(struct work_struct *work)
{
	struct qpnp_hap *hap = container_of(work, struct qpnp_hap,
					 work);
	u8 val = 0x00;
	int rc;

	/* Disable haptics module if the duration of short circuit
	 * exceeds the maximum limit (5 secs).
	 */
	if (hap->sc_duration == SC_MAX_DURATION) {
		rc = qpnp_hap_write_reg(hap, &val,
				QPNP_HAP_EN_CTL_REG(hap->base));
	} else {
		if (hap->play_mode == QPNP_HAP_PWM)
			qpnp_hap_mod_enable(hap, hap->state);
		qpnp_hap_set(hap, hap->state);
	}
}

/* get time api to know the remaining time */
static int qpnp_hap_get_time(struct timed_output_dev *dev)
@@ -1886,6 +1934,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
		}
	}

	hap->sc_duration = 0;

	return rc;
}

@@ -2143,6 +2193,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi)
	mutex_init(&hap->lock);
	mutex_init(&hap->wf_lock);
	INIT_WORK(&hap->work, qpnp_hap_worker);
	INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq);
	init_completion(&hap->completion);

	hrtimer_init(&hap->hap_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);