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

Commit c8eb7197 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

soc: qcom: qpnp-haptic: Overhaul the driver



Currently, the driver does read-modify-write to registers in so
many places. It would be better to have a masked_write API to do
this. This also needs a change in the mask definitions used in
all places where these writes are made. Also, create separate
functions that deals with a particular configuration so that they
can be reused later.

Change-Id: Ice07297b1542640e82c7adc12d323258440edb77
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent d7d3139e
Loading
Loading
Loading
Loading
+246 −290
Original line number Diff line number Diff line
@@ -27,9 +27,10 @@
#include <linux/qpnp/pwm.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/log2.h>
#include <linux/qpnp-misc.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/qpnp/qpnp-haptic.h>
#include <linux/qpnp/qpnp-revid.h>
#include "../../staging/android/timed_output.h"

#define QPNP_IRQ_FLAGS	(IRQF_TRIGGER_RISING | \
@@ -42,9 +43,9 @@
#define QPNP_HAP_EN_CTL_REG(b)		(b + 0x46)
#define QPNP_HAP_EN_CTL2_REG(b)		(b + 0x48)
#define QPNP_HAP_AUTO_RES_CTRL(b)	(b + 0x4B)
#define QPNP_HAP_ACT_TYPE_REG(b)	(b + 0x4C)
#define QPNP_HAP_WAV_SHAPE_REG(b)	(b + 0x4D)
#define QPNP_HAP_PLAY_MODE_REG(b)	(b + 0x4E)
#define QPNP_HAP_CFG1_REG(b)		(b + 0x4C)
#define QPNP_HAP_CFG2_REG(b)		(b + 0x4D)
#define QPNP_HAP_SEL_REG(b)		(b + 0x4E)
#define QPNP_HAP_LRA_AUTO_RES_REG(b)	(b + 0x4F)
#define QPNP_HAP_VMAX_REG(b)		(b + 0x51)
#define QPNP_HAP_ILIM_REG(b)		(b + 0x52)
@@ -64,7 +65,7 @@
#define QPNP_HAP_TEST2_REG(b)		(b + 0xE3)

#define QPNP_HAP_STATUS_BUSY		0x02
#define QPNP_HAP_ACT_TYPE_MASK		0xFE
#define QPNP_HAP_ACT_TYPE_MASK		BIT(0)
#define QPNP_HAP_LRA			0x0
#define QPNP_HAP_ERM			0x1
#define QPNP_HAP_AUTO_RES_MODE_MASK	GENMASK(6, 4)
@@ -84,29 +85,27 @@
#define QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK	GENMASK(2, 0)
#define QPNP_HAP_RES_CAL_PERIOD_MIN		4
#define QPNP_HAP_RES_CAL_PERIOD_MAX		32
#define QPNP_HAP_PM660_RES_CAL_PERIOD_MIN	4
#define QPNP_HAP_PM660_RES_CAL_PERIOD_MAX	256
#define QPNP_HAP_PLAY_MODE_MASK		0xCF
#define QPNP_HAP_PLAY_MODE_SHFT		4
#define QPNP_HAP_VMAX_MASK		0xC1
#define QPNP_HAP_WF_SOURCE_MASK		GENMASK(5, 4)
#define QPNP_HAP_WF_SOURCE_SHIFT	4
#define QPNP_HAP_VMAX_MASK		GENMASK(5, 1)
#define QPNP_HAP_VMAX_SHIFT		1
#define QPNP_HAP_VMAX_MIN_MV		116
#define QPNP_HAP_VMAX_MAX_MV		3596
#define QPNP_HAP_ILIM_MASK		0xFE
#define QPNP_HAP_ILIM_MASK		BIT(0)
#define QPNP_HAP_ILIM_MIN_MV		400
#define QPNP_HAP_ILIM_MAX_MV		800
#define QPNP_HAP_SC_DEB_MASK		0xF8
#define QPNP_HAP_SC_DEB_SUB		2
#define QPNP_HAP_SC_DEB_MASK		GENMASK(2, 0)
#define QPNP_HAP_SC_DEB_CYCLES_MIN	0
#define QPNP_HAP_DEF_SC_DEB_CYCLES	8
#define QPNP_HAP_SC_DEB_CYCLES_MAX	32
#define QPNP_HAP_SC_CLR			1
#define QPNP_HAP_INT_PWM_MASK		0xFC
#define QPNP_HAP_INT_PWM_MASK		GENMASK(1, 0)
#define QPNP_HAP_INT_PWM_FREQ_253_KHZ	253
#define QPNP_HAP_INT_PWM_FREQ_505_KHZ	505
#define QPNP_HAP_INT_PWM_FREQ_739_KHZ	739
#define QPNP_HAP_INT_PWM_FREQ_1076_KHZ	1076
#define QPNP_HAP_WAV_SHAPE_MASK		0xFE
#define QPNP_HAP_WAV_SHAPE_MASK		BIT(0)
#define QPNP_HAP_RATE_CFG1_MASK		0xFF
#define QPNP_HAP_RATE_CFG2_MASK		0xF0
#define QPNP_HAP_RATE_CFG2_SHFT		8
@@ -114,9 +113,9 @@
#define QPNP_HAP_WAV_PLAY_RATE_US_MIN	0
#define QPNP_HAP_DEF_WAVE_PLAY_RATE_US	5715
#define QPNP_HAP_WAV_PLAY_RATE_US_MAX	20475
#define QPNP_HAP_WAV_REP_MASK		0x8F
#define QPNP_HAP_WAV_S_REP_MASK		0xFC
#define QPNP_HAP_WAV_REP_SHFT		4
#define QPNP_HAP_WAV_REP_MASK		GENMASK(6, 4)
#define QPNP_HAP_WAV_S_REP_MASK		GENMASK(1, 0)
#define QPNP_HAP_WAV_REP_SHIFT		4
#define QPNP_HAP_WAV_REP_MIN		1
#define QPNP_HAP_WAV_REP_MAX		128
#define QPNP_HAP_WAV_S_REP_MIN		1
@@ -124,13 +123,13 @@
#define QPNP_HAP_BRAKE_PAT_MASK		0x3
#define QPNP_HAP_ILIM_MIN_MA		400
#define QPNP_HAP_ILIM_MAX_MA		800
#define QPNP_HAP_EXT_PWM_MASK		0xFC
#define QPNP_HAP_EXT_PWM_MASK		GENMASK(1, 0)
#define QPNP_HAP_EXT_PWM_FREQ_25_KHZ	25
#define QPNP_HAP_EXT_PWM_FREQ_50_KHZ	50
#define QPNP_HAP_EXT_PWM_FREQ_75_KHZ	75
#define QPNP_HAP_EXT_PWM_FREQ_100_KHZ	100
#define PWM_MAX_DTEST_LINES		4
#define QPNP_HAP_EXT_PWM_DTEST_MASK	0x0F
#define QPNP_HAP_EXT_PWM_DTEST_MASK	GENMASK(6, 4)
#define QPNP_HAP_EXT_PWM_DTEST_SHFT	4
#define QPNP_HAP_EXT_PWM_PEAK_DATA	0x7F
#define QPNP_HAP_EXT_PWM_HALF_DUTY	50
@@ -143,10 +142,9 @@
#define QPNP_HAP_BRAKE_PAT_LEN		4
#define QPNP_HAP_PLAY_EN		0x80
#define QPNP_HAP_EN			0x80
#define QPNP_HAP_BRAKE_MASK		0xFE
#define QPNP_HAP_TEST2_AUTO_RES_MASK	0x7F
#define QPNP_HAP_SEC_UNLOCK		0xA5
#define AUTO_RES_ENABLE			0x80
#define QPNP_HAP_BRAKE_MASK		BIT(0)
#define QPNP_HAP_AUTO_RES_MASK		BIT(7)
#define AUTO_RES_ENABLE			BIT(7)
#define AUTO_RES_ERR_BIT		0x10
#define SC_FOUND_BIT			0x08
#define SC_MAX_DURATION			5
@@ -342,6 +340,7 @@ struct qpnp_hap {
	struct qpnp_pwm_info		pwm_info;
	struct mutex			lock;
	struct mutex			wf_lock;
	spinlock_t			bus_lock;
	struct completion		completion;
	enum qpnp_hap_mode		play_mode;
	enum qpnp_hap_high_z		lra_high_z;
@@ -412,42 +411,62 @@ static int qpnp_hap_read_reg(struct qpnp_hap *hap, u16 addr, u8 *val)
/* helper to write a pmic register */
static int qpnp_hap_write_reg(struct qpnp_hap *hap, u16 addr, u8 val)
{
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&hap->bus_lock, flags);
	rc = regmap_write(hap->regmap, addr, val);
	if (rc < 0)
		pr_err("Error writing address: %X - ret %X\n", addr, rc);

	spin_unlock_irqrestore(&hap->bus_lock, flags);
	if (!rc)
		pr_debug("wrote: HAP_0x%x = 0x%x\n", addr, val);
	return rc;
}

static int
qpnp_hap_masked_write_reg(struct qpnp_hap *hap, u16 addr, u8 mask, u8 val)
/* helper to access secure registers */
#define QPNP_HAP_SEC_UNLOCK		0xA5
static int qpnp_hap_sec_masked_write_reg(struct qpnp_hap *hap, u16 addr,
					u8 mask, u8 val)
{
	unsigned long flags;
	int rc;
	u8 tmp = QPNP_HAP_SEC_UNLOCK;

	spin_lock_irqsave(&hap->bus_lock, flags);
	rc = regmap_write(hap->regmap, QPNP_HAP_SEC_ACCESS_REG(hap->base), tmp);
	if (rc < 0) {
		pr_err("Error writing sec_code - ret %X\n", rc);
		goto out;
	}

	rc = regmap_update_bits(hap->regmap, addr, mask, val);
	if (rc < 0)
		pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
			rc);
	else
		pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
		pr_err("Error writing address: %X - ret %X\n", addr, rc);

out:
	spin_unlock_irqrestore(&hap->bus_lock, flags);
	if (!rc)
		pr_debug("wrote: HAP_0x%x = 0x%x\n", addr, val);
	return rc;
}

/* helper to access secure registers */
static int qpnp_hap_sec_access(struct qpnp_hap *hap)
static int qpnp_hap_masked_write_reg(struct qpnp_hap *hap, u16 addr, u8 mask,
					u8 val)
{
	unsigned long flags;
	int rc;
	u8 val = QPNP_HAP_SEC_UNLOCK;

	rc = qpnp_hap_write_reg(hap, QPNP_HAP_SEC_ACCESS_REG(hap->base), val);
	if (rc)
		return rc;
	spin_lock_irqsave(&hap->bus_lock, flags);
	rc = regmap_update_bits(hap->regmap, addr, mask, val);
	if (rc < 0)
		pr_err("Error writing address: %X - ret %X\n", addr, rc);

	return 0;
	spin_unlock_irqrestore(&hap->bus_lock, flags);
	if (!rc)
		pr_debug("wrote: HAP_0x%x = 0x%x\n", addr, val);
	return rc;
}

static void qpnp_handle_sc_irq(struct work_struct *work)
@@ -612,7 +631,7 @@ static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc, i, temp;
	int rc, i;

	/* Configure the WAVE_REPEAT register */
	if (hap->wave_rep_cnt < QPNP_HAP_WAV_REP_MIN)
@@ -625,16 +644,10 @@ static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
	else if (hap->wave_s_rep_cnt > QPNP_HAP_WAV_S_REP_MAX)
		hap->wave_s_rep_cnt = QPNP_HAP_WAV_S_REP_MAX;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_WAV_REP_MASK;
	temp = fls(hap->wave_rep_cnt) - 1;
	val |= (temp << QPNP_HAP_WAV_REP_SHFT);
	val &= QPNP_HAP_WAV_S_REP_MASK;
	temp = fls(hap->wave_s_rep_cnt) - 1;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), val);
	val = ilog2(hap->wave_rep_cnt) << QPNP_HAP_WAV_REP_SHIFT |
			ilog2(hap->wave_s_rep_cnt);
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base),
			QPNP_HAP_WAV_REP_MASK | QPNP_HAP_WAV_S_REP_MASK, val);
	if (rc)
		return rc;

@@ -668,37 +681,30 @@ static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc, temp;
	int rc;

	/* Configure the EXTERNAL_PWM register */
	if (hap->ext_pwm_freq_khz <= QPNP_HAP_EXT_PWM_FREQ_25_KHZ) {
		hap->ext_pwm_freq_khz = QPNP_HAP_EXT_PWM_FREQ_25_KHZ;
		temp = 0;
		val = 0;
	} else if (hap->ext_pwm_freq_khz <=
				QPNP_HAP_EXT_PWM_FREQ_50_KHZ) {
		hap->ext_pwm_freq_khz = QPNP_HAP_EXT_PWM_FREQ_50_KHZ;
		temp = 1;
		val = 1;
	} else if (hap->ext_pwm_freq_khz <=
				QPNP_HAP_EXT_PWM_FREQ_75_KHZ) {
		hap->ext_pwm_freq_khz = QPNP_HAP_EXT_PWM_FREQ_75_KHZ;
		temp = 2;
		val = 2;
	} else {
		hap->ext_pwm_freq_khz = QPNP_HAP_EXT_PWM_FREQ_100_KHZ;
		temp = 3;
		val = 3;
	}

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_EXT_PWM_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_EXT_PWM_MASK;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_EXT_PWM_REG(hap->base), val);
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_EXT_PWM_REG(hap->base),
			QPNP_HAP_EXT_PWM_MASK, val);
	if (rc)
		return rc;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_TEST2_REG(hap->base), &val);
	if (rc)
		return rc;
	if (!hap->ext_pwm_dtest_line ||
			hap->ext_pwm_dtest_line > PWM_MAX_DTEST_LINES) {
		pr_err("invalid dtest line\n");
@@ -706,16 +712,9 @@ static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
	}

	/* disable auto res for PWM mode */
	val &= QPNP_HAP_EXT_PWM_DTEST_MASK;
	temp = hap->ext_pwm_dtest_line << QPNP_HAP_EXT_PWM_DTEST_SHFT;
	val |= temp;

	/* TEST2 is a secure access register */
	rc = qpnp_hap_sec_access(hap);
	if (rc)
		return rc;

	rc = qpnp_hap_write_reg(hap, QPNP_HAP_TEST2_REG(hap->base), val);
	val = hap->ext_pwm_dtest_line << QPNP_HAP_EXT_PWM_DTEST_SHFT;
	rc = qpnp_hap_sec_masked_write_reg(hap, QPNP_HAP_TEST2_REG(hap->base),
		QPNP_HAP_EXT_PWM_DTEST_MASK | QPNP_HAP_AUTO_RES_MASK, val);
	if (rc)
		return rc;

@@ -733,72 +732,171 @@ static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
	return 0;
}

static int qpnp_hap_lra_auto_res_config(struct qpnp_hap *hap)
{
	int rc;
	u8 val, mask;

	/* disable auto resonance for ERM */
	if (hap->act_type == QPNP_HAP_ERM) {
		val = 0x00;
		rc = qpnp_hap_write_reg(hap,
			QPNP_HAP_LRA_AUTO_RES_REG(hap->base), val);
		return rc;
	}

	if (hap->lra_res_cal_period < QPNP_HAP_RES_CAL_PERIOD_MIN)
		hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MIN;

	if (hap->pmic_subtype == PM660_SUBTYPE) {
		if (hap->lra_res_cal_period >
				QPNP_HAP_PM660_RES_CAL_PERIOD_MAX)
			hap->lra_res_cal_period =
				QPNP_HAP_PM660_RES_CAL_PERIOD_MAX;

		if (hap->auto_res_mode == QPNP_HAP_PM660_AUTO_RES_QWD)
			hap->lra_res_cal_period = 0;
	} else {
		if (hap->lra_res_cal_period > QPNP_HAP_RES_CAL_PERIOD_MAX)
			hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
	}

	val = mask = 0;
	if (hap->lra_res_cal_period)
		val = ilog2(hap->lra_res_cal_period /
				QPNP_HAP_RES_CAL_PERIOD_MIN);

	if (hap->pmic_subtype == PM660_SUBTYPE) {
		val |= hap->auto_res_mode <<
			QPNP_HAP_PM660_AUTO_RES_MODE_SHIFT;
		mask = QPNP_HAP_PM660_AUTO_RES_MODE_BIT;
		val |= hap->lra_high_z <<
				QPNP_HAP_PM660_CALIBRATE_DURATION_SHIFT;
		mask |= QPNP_HAP_PM660_CALIBRATE_DURATION_MASK;
		if (hap->lra_qwd_drive_duration != -EINVAL) {
			val |= hap->lra_qwd_drive_duration <<
				QPNP_HAP_PM660_QWD_DRIVE_DURATION_SHIFT;
			mask |= QPNP_HAP_PM660_QWD_DRIVE_DURATION_BIT;
		}
		if (hap->calibrate_at_eop != -EINVAL) {
			val |= hap->calibrate_at_eop <<
				QPNP_HAP_PM660_CALIBRATE_AT_EOP_SHIFT;
			mask |= QPNP_HAP_PM660_CALIBRATE_AT_EOP_BIT;
		}
		mask |= QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK;
	} else {
		val |= (hap->auto_res_mode << QPNP_HAP_AUTO_RES_MODE_SHIFT);
		val |= (hap->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
		mask = QPNP_HAP_AUTO_RES_MODE_MASK | QPNP_HAP_LRA_HIGH_Z_MASK |
			QPNP_HAP_LRA_RES_CAL_PER_MASK;
	}

	rc = qpnp_hap_masked_write_reg(hap,
			QPNP_HAP_LRA_AUTO_RES_REG(hap->base), mask, val);
	return rc;
}

/* configuration api for play mode */
static int qpnp_hap_play_mode_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc, temp;
	int rc;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_PLAY_MODE_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_PLAY_MODE_MASK;
	temp = hap->play_mode << QPNP_HAP_PLAY_MODE_SHFT;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_PLAY_MODE_REG(hap->base), val);
	if (rc)
	val = hap->play_mode << QPNP_HAP_WF_SOURCE_SHIFT;
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_SEL_REG(hap->base),
			QPNP_HAP_WF_SOURCE_MASK, val);
	return rc;
	return 0;
}

/* configuration api for max volatge */
/* configuration api for max voltage */
static int qpnp_hap_vmax_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc, temp;
	int rc;

	if (hap->vmax_mv < QPNP_HAP_VMAX_MIN_MV)
		hap->vmax_mv = QPNP_HAP_VMAX_MIN_MV;
	else if (hap->vmax_mv > QPNP_HAP_VMAX_MAX_MV)
		hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_VMAX_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_VMAX_MASK;
	temp = hap->vmax_mv / QPNP_HAP_VMAX_MIN_MV;
	val |= (temp << QPNP_HAP_VMAX_SHIFT);
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_VMAX_REG(hap->base), val);
	if (rc)
	val = (hap->vmax_mv / QPNP_HAP_VMAX_MIN_MV) << QPNP_HAP_VMAX_SHIFT;
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_VMAX_REG(hap->base),
			QPNP_HAP_VMAX_MASK, val);
	return rc;
}

	return 0;
/* configuration api for ilim */
static int qpnp_hap_ilim_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc;

	if (hap->ilim_ma < QPNP_HAP_ILIM_MIN_MA)
		hap->ilim_ma = QPNP_HAP_ILIM_MIN_MA;
	else if (hap->ilim_ma > QPNP_HAP_ILIM_MAX_MA)
		hap->ilim_ma = QPNP_HAP_ILIM_MAX_MA;

	val = (hap->ilim_ma / QPNP_HAP_ILIM_MIN_MA) - 1;
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_ILIM_REG(hap->base),
			QPNP_HAP_ILIM_MASK, val);
	return rc;
}

/* configuration api for short circuit debounce */
static int qpnp_hap_sc_deb_config(struct qpnp_hap *hap)
{
	u8 val = 0;
	int rc, temp;
	int rc;

	if (hap->sc_deb_cycles < QPNP_HAP_SC_DEB_CYCLES_MIN)
		hap->sc_deb_cycles = QPNP_HAP_SC_DEB_CYCLES_MIN;
	else if (hap->sc_deb_cycles > QPNP_HAP_SC_DEB_CYCLES_MAX)
		hap->sc_deb_cycles = QPNP_HAP_SC_DEB_CYCLES_MAX;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_SC_DEB_REG(hap->base), &val);
	if (rc < 0)
	if (hap->sc_deb_cycles != QPNP_HAP_SC_DEB_CYCLES_MIN)
		val = ilog2(hap->sc_deb_cycles /
			QPNP_HAP_DEF_SC_DEB_CYCLES) + 1;
	else
		val = QPNP_HAP_SC_DEB_CYCLES_MIN;

	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_SC_DEB_REG(hap->base),
			QPNP_HAP_SC_DEB_MASK, val);

	return rc;
	val &= QPNP_HAP_SC_DEB_MASK;
	if (hap->sc_deb_cycles) {
		temp = fls(hap->sc_deb_cycles) - 1;
		val |= temp - QPNP_HAP_SC_DEB_SUB;
}
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_SC_DEB_REG(hap->base), val);

static int qpnp_hap_int_pwm_config(struct qpnp_hap *hap)
{
	int rc;
	u8 val;

	if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_253_KHZ) {
		if (hap->pmic_subtype == PM660_SUBTYPE) {
			hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
			val = 1;
		} else {
			hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_253_KHZ;
			val = 0;
		}
	} else if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_505_KHZ) {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
		val = 1;
	} else if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_739_KHZ) {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_739_KHZ;
		val = 2;
	} else {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_1076_KHZ;
		val = 3;
	}

	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_INT_PWM_REG(hap->base),
			QPNP_HAP_INT_PWM_MASK, val);
	if (rc)
		return rc;

	return 0;
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_PWM_CAP_REG(hap->base),
			QPNP_HAP_INT_PWM_MASK, val);
	return rc;
}

/* DT parsing api for buffer mode */
@@ -1090,7 +1188,7 @@ static ssize_t qpnp_hap_wf_rep_store(struct device *dev,
	struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
	struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
					 timed_dev);
	int data, rc, temp;
	int data, rc;
	u8 val;

	rc = kstrtoint(buf, 10, &data);
@@ -1102,16 +1200,10 @@ static ssize_t qpnp_hap_wf_rep_store(struct device *dev,
	else if (data > QPNP_HAP_WAV_REP_MAX)
		data = QPNP_HAP_WAV_REP_MAX;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_WAV_REP_MASK;
	temp = fls(data) - 1;
	val |= (temp << QPNP_HAP_WAV_REP_SHFT);
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), val);
	if (rc)
		return rc;

	val = ilog2(data) << QPNP_HAP_WAV_REP_SHIFT;
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base),
			QPNP_HAP_WAV_REP_MASK, val);
	if (!rc)
		hap->wave_rep_cnt = data;

	return count;
@@ -1135,7 +1227,7 @@ static ssize_t qpnp_hap_wf_s_rep_store(struct device *dev,
	struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
	struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
					 timed_dev);
	int data, rc, temp;
	int data, rc;
	u8 val;

	rc = kstrtoint(buf, 10, &data);
@@ -1147,16 +1239,10 @@ static ssize_t qpnp_hap_wf_s_rep_store(struct device *dev,
	else if (data > QPNP_HAP_WAV_S_REP_MAX)
		data = QPNP_HAP_WAV_S_REP_MAX;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_WAV_S_REP_MASK;
	temp = fls(data) - 1;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base), val);
	if (rc)
		return rc;

	val = ilog2(hap->wave_s_rep_cnt);
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_WAV_REP_REG(hap->base),
			QPNP_HAP_WAV_S_REP_MASK, val);
	if (!rc)
		hap->wave_s_rep_cnt = data;

	return count;
@@ -1426,24 +1512,18 @@ static int calculate_lra_code(struct qpnp_hap *hap)
static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
{
	int rc = 0;
	u8 val = 0;
	u16 addr;

	if (hap->pmic_subtype == PM660_SUBTYPE) {
		addr = QPNP_HAP_AUTO_RES_CTRL(hap->base);
	} else {
		addr = QPNP_HAP_TEST2_REG(hap->base);
		/* TEST2 is a secure access register */
		rc = qpnp_hap_sec_access(hap);
		if (rc)
			return rc;
	}

	if (enable)
		val |= AUTO_RES_ENABLE;
	u8 val;

	rc = qpnp_hap_masked_write_reg(hap, addr, AUTO_RES_ENABLE, val);
	if (rc)
	val = enable ? AUTO_RES_ENABLE : 0;
	if (hap->pmic_subtype == PM660_SUBTYPE)
		rc = qpnp_hap_masked_write_reg(hap,
				QPNP_HAP_AUTO_RES_CTRL(hap->base),
				QPNP_HAP_AUTO_RES_MASK, val);
	else
		rc = qpnp_hap_sec_masked_write_reg(hap,
				QPNP_HAP_TEST2_REG(hap->base),
				QPNP_HAP_AUTO_RES_MASK, val);
	if (rc < 0)
		return rc;

	if (enable)
@@ -1451,7 +1531,7 @@ static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
	else
		hap->status_flags &= ~AUTO_RESONANCE_ENABLED;

	return 0;
	return rc;
}

static void update_lra_frequency(struct qpnp_hap *hap)
@@ -1802,7 +1882,7 @@ static SIMPLE_DEV_PM_OPS(qpnp_haptic_pm_ops, qpnp_haptic_suspend, NULL);
/* Configuration api for haptics registers */
static int qpnp_hap_config(struct qpnp_hap *hap)
{
	u8 val = 0, mask;
	u8 val = 0;
	u32 temp;
	int rc, i;

@@ -1811,89 +1891,16 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
	 */
	u8 rc_clk_err_percent_x10;

	/* Configure the ACTUATOR TYPE register */
	rc = qpnp_hap_read_reg(hap, QPNP_HAP_ACT_TYPE_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_ACT_TYPE_MASK;
	val |= hap->act_type;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_ACT_TYPE_REG(hap->base), val);
	/* Configure the CFG1 register for actuator type */
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_CFG1_REG(hap->base),
			QPNP_HAP_ACT_TYPE_MASK, hap->act_type);
	if (rc)
		return rc;

	/* Configure auto resonance parameters */
	if (hap->act_type == QPNP_HAP_LRA) {
		if (hap->pmic_subtype == PM660_SUBTYPE) {
			if (hap->lra_res_cal_period <
					QPNP_HAP_PM660_RES_CAL_PERIOD_MIN)
				hap->lra_res_cal_period =
					QPNP_HAP_PM660_RES_CAL_PERIOD_MIN;
			else if (hap->lra_res_cal_period >
					QPNP_HAP_PM660_RES_CAL_PERIOD_MAX)
				hap->lra_res_cal_period =
					QPNP_HAP_PM660_RES_CAL_PERIOD_MAX;
		} else if (hap->pmic_subtype != PM660_SUBTYPE) {
			if (hap->lra_res_cal_period <
					QPNP_HAP_RES_CAL_PERIOD_MIN)
				hap->lra_res_cal_period =
					QPNP_HAP_RES_CAL_PERIOD_MIN;
			else if (hap->lra_res_cal_period >
					QPNP_HAP_RES_CAL_PERIOD_MAX)
				hap->lra_res_cal_period =
					QPNP_HAP_RES_CAL_PERIOD_MAX;
		}
		if (hap->pmic_subtype == PM660_SUBTYPE &&
			hap->auto_res_mode == QPNP_HAP_PM660_AUTO_RES_QWD) {
			hap->lra_res_cal_period = 0;
		}

		val = mask = 0;
		if (hap->pmic_subtype == PM660_SUBTYPE) {
			val |= hap->auto_res_mode <<
				QPNP_HAP_PM660_AUTO_RES_MODE_SHIFT;
			mask = QPNP_HAP_PM660_AUTO_RES_MODE_BIT;
			val |= hap->lra_high_z <<
					QPNP_HAP_PM660_CALIBRATE_DURATION_SHIFT;
			mask |= QPNP_HAP_PM660_CALIBRATE_DURATION_MASK;
			if (hap->lra_qwd_drive_duration != -EINVAL) {
				val |= hap->lra_qwd_drive_duration <<
					QPNP_HAP_PM660_QWD_DRIVE_DURATION_SHIFT;
				mask |= QPNP_HAP_PM660_QWD_DRIVE_DURATION_BIT;
			}
			if (hap->calibrate_at_eop != -EINVAL) {
				val |= hap->calibrate_at_eop <<
					QPNP_HAP_PM660_CALIBRATE_AT_EOP_SHIFT;
				mask |= QPNP_HAP_PM660_CALIBRATE_AT_EOP_BIT;
			}
			if (hap->lra_res_cal_period) {
				temp = fls(hap->lra_res_cal_period) - 1;
				val |= (temp - 1);
			}
			mask |= QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK;
		} else {
			val |= (hap->auto_res_mode <<
						QPNP_HAP_AUTO_RES_MODE_SHIFT);
			mask = QPNP_HAP_AUTO_RES_MODE_MASK;
			val |= (hap->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
			mask |= QPNP_HAP_LRA_HIGH_Z_MASK;
			temp = fls(hap->lra_res_cal_period) - 1;
			val |= (temp - 2);
			mask |= QPNP_HAP_LRA_RES_CAL_PER_MASK;
		}
		rc = qpnp_hap_masked_write_reg(hap,
				QPNP_HAP_LRA_AUTO_RES_REG(hap->base), mask,
				val);
	rc = qpnp_hap_lra_auto_res_config(hap);
	if (rc)
		return rc;
	} else {
		/* disable auto resonance for ERM */
		val = 0x00;

		rc = qpnp_hap_write_reg(hap,
				QPNP_HAP_LRA_AUTO_RES_REG(hap->base), val);
		if (rc)
			return rc;
	}

	/* Configure the PLAY MODE register */
	rc = qpnp_hap_play_mode_config(hap);
@@ -1906,18 +1913,7 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
		return rc;

	/* Configure the ILIM register */
	if (hap->ilim_ma < QPNP_HAP_ILIM_MIN_MA)
		hap->ilim_ma = QPNP_HAP_ILIM_MIN_MA;
	else if (hap->ilim_ma > QPNP_HAP_ILIM_MAX_MA)
		hap->ilim_ma = QPNP_HAP_ILIM_MAX_MA;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_ILIM_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_ILIM_MASK;
	temp = (hap->ilim_ma / QPNP_HAP_ILIM_MIN_MA) >> 1;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_ILIM_REG(hap->base), val);
	rc = qpnp_hap_ilim_config(hap);
	if (rc)
		return rc;

@@ -1927,50 +1923,13 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
		return rc;

	/* Configure the INTERNAL_PWM register */
	if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_253_KHZ) {
		if (hap->pmic_subtype == PM660_SUBTYPE) {
			hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
			temp = 1;
		} else {
			hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_253_KHZ;
			temp = 0;
		}
	} else if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_505_KHZ) {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
		temp = 1;
	} else if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_739_KHZ) {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_739_KHZ;
		temp = 2;
	} else {
		hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_1076_KHZ;
		temp = 3;
	}

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_INT_PWM_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_INT_PWM_MASK;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_INT_PWM_REG(hap->base), val);
	if (rc)
		return rc;

	rc = qpnp_hap_read_reg(hap, QPNP_HAP_PWM_CAP_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_INT_PWM_MASK;
	val |= temp;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_PWM_CAP_REG(hap->base), val);
	rc = qpnp_hap_int_pwm_config(hap);
	if (rc)
		return rc;

	/* Configure the WAVE SHAPE register */
	rc = qpnp_hap_read_reg(hap, QPNP_HAP_WAV_SHAPE_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_WAV_SHAPE_MASK;
	val |= hap->wave_shape;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_WAV_SHAPE_REG(hap->base), val);
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_CFG2_REG(hap->base),
			QPNP_HAP_WAV_SHAPE_MASK, hap->wave_shape);
	if (rc)
		return rc;

@@ -2058,12 +2017,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
	}

	/* Configure BRAKE register */
	rc = qpnp_hap_read_reg(hap, QPNP_HAP_EN_CTL2_REG(hap->base), &val);
	if (rc < 0)
		return rc;
	val &= QPNP_HAP_BRAKE_MASK;
	val |= hap->en_brake;
	rc = qpnp_hap_write_reg(hap, QPNP_HAP_EN_CTL2_REG(hap->base), val);
	rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_EN_CTL2_REG(hap->base),
			QPNP_HAP_BRAKE_MASK, (u8)hap->en_brake);
	if (rc)
		return rc;

@@ -2491,6 +2446,7 @@ static int qpnp_haptic_probe(struct platform_device *pdev)
		return rc;
	}

	spin_lock_init(&hap->bus_lock);
	rc = qpnp_hap_config(hap);
	if (rc) {
		pr_err("hap config failed\n");