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

Commit e0adc581 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "input: misc: qcom-hv-haptics: Add support for V2 HW module"

parents d851cf4b 43e97617
Loading
Loading
Loading
Loading
+344 −69
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
@@ -26,10 +27,16 @@
/* STATUS_DATA_MSB definitions while MOD_STATUS_SEL is 0 */
#define AUTO_RES_CAL_DONE_BIT			BIT(5)
#define CAL_TLRA_CL_STS_MSB_MASK		GENMASK(4, 0)
/* STATUS_DATA_MSB definition in V1 while MOD_STATUS_SEL is 5 */
#define FIFO_REAL_TIME_FILL_STATUS_MASK_V1	GENMASK(6, 0)
/* STATUS DATA_MSB definition in V2 while MOD_STATUS_SEL is 5 */
#define FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V2	GENMASK(1, 0)

#define HAP_CFG_STATUS_DATA_LSB_REG		0x0A
/* STATUS_DATA_MSB definitions while MOD_STATUS_SEL is 0 */
/* STATUS_DATA_MSB definition while MOD_STATUS_SEL is 0 */
#define CAL_TLRA_CL_STS_LSB_MASK		GENMASK(7, 0)
/* STATUS_DATA_LSB definition in V2 while MOD_STATUS_SEL is 5 */
#define FIFO_REAL_TIME_FILL_STATUS_LSB_MASK_V2	GENMASK(7, 0)

#define HAP_CFG_FAULT_STATUS_REG		0x0C
#define SC_FLAG_BIT				BIT(2)
@@ -61,8 +68,8 @@

#define HAP_CFG_SWR_ACCESS_REG			0x4E
#define SWR_PAT_CFG_EN_BIT			BIT(7)
#define SWR_PAT_INPUT_EN			BIT(6)
#define SWR_PAT_RES_N				BIT(5)
#define SWR_PAT_INPUT_EN_BIT			BIT(6)
#define SWR_PAT_RES_N_BIT			BIT(5)

#define HAP_CFG_BRAKE_MODE_CFG_REG		0x50
#define BRAKE_MODE_MASK				GENMASK(7, 6)
@@ -108,6 +115,17 @@
#define VMAX_HDRM_MASK				GENMASK(6, 0)
#define VMAX_HDRM_STEP_MV			50

#define HAP_CFG_MOD_STATUS_SEL_REG		0x70
#define MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL	5

#define HAP_CFG_MOD_STATUS_XT_V2_REG		0x71
#define MOD_STATUS_XT_V2_FIFO_FILL_STATUS_VAL	0x80

/* version register definitions for HAPTICS_PATTERN module */
#define HAP_PTN_REVISION2_REG			0x01
#define HAP_PTN_V1				0x1
#define HAP_PTN_V2				0x2

/* status register definition for HAPTICS_PATTERN module */
#define HAP_PTN_FIFO_READY_STS_REG		0x08
#define FIFO_READY_BIT				BIT(0)
@@ -115,19 +133,32 @@
#define HAP_PTN_NUM_PAT_REG			0x09

/* config register definition for HAPTICS_PATTERN module */
#define HAP_PTN_FIFO_DIN_MSB_REG		0x20
#define HAP_PTN_FIFO_DIN_MSB_BIT		BIT(0)
#define HAP_PTN_FIFO_DIN_LSB_REG		0x21
#define HAP_PTN_FIFO_DIN_LSB_MASK		GENMASK(7, 0)
/* FIFO configuration registers in V1 chip */
#define HAP_PTN_V1_FIFO_DIN_MSB_REG		0x20
#define HAP_PTN_V1_FIFO_DIN_MSB_BIT		BIT(0)
#define HAP_PTN_V1_FIFO_DIN_LSB_REG		0x21
#define HAP_PTN_V1_FIFO_DIN_LSB_MASK		GENMASK(7, 0)

#define HAP_PTN_FIFO_PLAY_RATE_REG		0x22
#define HAP_PTN_V1_FIFO_PLAY_RATE_REG		0x22
#define FIFO_PLAY_RATE_MASK			GENMASK(3, 0)

#define HAP_PTN_FIFO_EMPTY_CFG_REG		0x23
#define HAP_PTN_V1_FIFO_EMPTY_CFG_REG		0x23
#define EMPTY_THRESH_MASK			GENMASK(3, 0)
#define HAP_PTN_V1_FIFO_THRESH_LSB		4

#define HAP_PTN_V1_FIFO_DEPTH_CFG_REG		0x24

/* FIFO configuration registers in V2 chip */
#define HAP_PTN_V2_FIFO_DIN_0_REG		0x20
#define HAP_PTN_V2_FIFO_DIN_NUM			4

#define HAP_PTN_FIFO_DEPTH_CFG_REG		0x24
#define HAP_PTN_V2_FIFO_PLAY_RATE_REG		0x24
#define HAP_PTN_V2_FIFO_EMPTY_CFG_REG		0x2A
#define HAP_PTN_V2_FIFO_THRESH_LSB		40
#define HAP_PTN_V2_FIFO_DEPTH_CFG_REG		0x2B
#define HAP_PTN_V2_FIFO_DIN_1B_REG		0x2C

/* shared registers between V1 and V2 chips */
#define HAP_PTN_DIRECT_PLAY_REG			0x26

#define HAP_PTN_AUTORES_CAL_CFG_REG		0x28
@@ -151,10 +182,8 @@
/* constant parameters */
#define SAMPLES_PER_PATTERN			8
#define BRAKE_SAMPLE_COUNT			8
#define MAX_FIFO_SAMPLES			104
#define DEFAULT_ERM_PLAY_RATE_US		5000
#define MAX_EFFECT_COUNT			64
#define FIFO_EMPTY_THRESHOLD			48
#define FIFO_READY_TIMEOUT_MS			1000
#define CHAR_PER_PATTERN_S			48
#define CHAR_PER_SAMPLE				8
@@ -162,6 +191,11 @@
#define CHAR_BRAKE_MODE				24
#define HW_BRAKE_CYCLES				5

#define MAX_FIFO_SAMPLES(chip)		\
	((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640)
#define FIFO_EMPTY_THRESHOLD(chip)	\
	((chip)->ptn_revision == HAP_PTN_V1 ? 48 : 280)

enum drv_sig_shape {
	WF_SQUARE,
	WF_SINE,
@@ -266,7 +300,7 @@ struct pattern_cfg {
};

struct fifo_cfg {
	u16			*samples;
	u8			*samples;
	u32			num_s;
	enum s_period		period_per_s;
	u32			play_length_us;
@@ -326,11 +360,14 @@ struct haptics_chip {
	struct haptics_play_info	play;
	struct work_struct		fifo_work;
	struct dentry			*debugfs_dir;
	struct regulator_dev		*swr_slave_rdev;
	int				fifo_empty_irq;
	u32				effects_count;
	u32				cfg_addr_base;
	u32				ptn_addr_base;
	u8				ptn_revision;
	bool				fifo_empty_irq_en;
	bool				swr_slave_enabled;
};

static int haptics_read(struct haptics_chip *chip,
@@ -723,41 +760,30 @@ static int haptics_set_pattern(struct haptics_chip *chip,

}

static int haptics_update_fifo_sample(struct haptics_chip *chip, u16 sample)
static int haptics_update_fifo_sample_v1(struct haptics_chip *chip, u8 sample)
{
	int rc = 0;
	u8 val;
	bool ready;

	rc = haptics_read(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_READY_STS_REG, &val, 1);
	if (rc < 0) {
		dev_err(chip->dev, "read FIFO_READY_STS failed, rc=%d\n",
				rc);
		return rc;
	}

	ready = !!(val & FIFO_READY_BIT);
	/* sleep no more than 10us if FIFO memory is not ready */
	if (!ready)
		usleep_range(1, 10);

	/*
	 * Fill FIFO_DIN registers to update FIFO memory,
	 * need to fill LSB first then MSB
	 * need to fill LSB first then MSB.
	 * The FIFO memory width in V1 chip is 9-bit so shift
	 * 1 bit to left on the 8-bit FIFO sample to achieve a
	 * 9-bit data and fill it into the FIFO_DIN registers.
	 */
	val = sample & HAP_PTN_FIFO_DIN_LSB_MASK;
	val = (sample << 1) & HAP_PTN_V1_FIFO_DIN_LSB_MASK;
	rc = haptics_write(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_DIN_LSB_REG, &val, 1);
			HAP_PTN_V1_FIFO_DIN_LSB_REG, &val, 1);
	if (rc < 0) {
		dev_err(chip->dev, "write FIFO LSB failed, rc=%d\n",
				rc);
		return rc;
	}

	val = (sample >> 8) & HAP_PTN_FIFO_DIN_MSB_BIT;
	val = (sample >> 7) & HAP_PTN_V1_FIFO_DIN_MSB_BIT;
	rc = haptics_write(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_DIN_MSB_REG, &val, 1);
			HAP_PTN_V1_FIFO_DIN_MSB_REG, &val, 1);
	if (rc < 0) {
		dev_err(chip->dev, "write FIFO MSB failed, rc=%d\n",
				rc);
@@ -767,11 +793,127 @@ static int haptics_update_fifo_sample(struct haptics_chip *chip, u16 sample)
	return 0;
}

static int haptics_update_fifo_sample_v2(struct haptics_chip *chip,
					u8 *samples, u32 num)
{
	int rc, i;

	if (num > HAP_PTN_V2_FIFO_DIN_NUM)
		return -EINVAL;

	if (num == HAP_PTN_V2_FIFO_DIN_NUM) {
		rc = haptics_write(chip, chip->ptn_addr_base,
				HAP_PTN_V2_FIFO_DIN_0_REG, samples, num);
		if (rc < 0) {
			dev_err(chip->dev, "bulk write FIFO_DIN failed, rc=%d\n",
					rc);
			return rc;
		}
	} else if (num < HAP_PTN_V2_FIFO_DIN_NUM) {
		for (i = 0; i < num; i++) {
			rc = haptics_write(chip, chip->ptn_addr_base,
					HAP_PTN_V2_FIFO_DIN_1B_REG,
					(samples + i), 1);
			if (rc < 0) {
				dev_err(chip->dev, "write FIFO_DIN_1B failed, rc=%d\n",
						rc);
				return rc;
			}
		}
	}

	return 0;
}

static int haptics_get_available_fifo_memory(struct haptics_chip *chip)
{
	int rc;
	u8 val[2];
	u32 fill, available;

	val[0] = MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL;
	if (chip->ptn_revision == HAP_PTN_V1) {
		rc = haptics_write(chip, chip->cfg_addr_base,
				HAP_CFG_MOD_STATUS_SEL_REG, val, 1);
		if (rc < 0)
			return rc;

		rc = haptics_read(chip, chip->cfg_addr_base,
				HAP_CFG_STATUS_DATA_MSB_REG, val, 1);
		if (rc < 0)
			return rc;

		fill = val[0] & FIFO_REAL_TIME_FILL_STATUS_MASK_V1;
	} else {
		val[1] = MOD_STATUS_XT_V2_FIFO_FILL_STATUS_VAL;
		rc = haptics_write(chip, chip->cfg_addr_base,
				HAP_CFG_MOD_STATUS_SEL_REG, val, 2);
		if (rc < 0)
			return rc;

		rc = haptics_read(chip, chip->cfg_addr_base,
				HAP_CFG_STATUS_DATA_MSB_REG, val, 2);
		if (rc < 0)
			return rc;

		fill = ((val[0] & FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V2)
				<< 8) | val[1];
	}

	if (fill > MAX_FIFO_SAMPLES(chip)) {
		dev_err(chip->dev, "Filled FIFO number %d exceed the max %d\n",
				fill, MAX_FIFO_SAMPLES(chip));
		return -EINVAL;
	} else if (fill == MAX_FIFO_SAMPLES(chip)) {
		dev_err(chip->dev, "no FIFO space available\n");
		return -EBUSY;
	}

	available = MAX_FIFO_SAMPLES(chip) - fill;
	dev_dbg(chip->dev, "Available FIFO memory: %d bytes\n", available);
	return available;
}

static int haptics_update_fifo_samples(struct haptics_chip *chip,
					u8 *samples, u32 length)
{
	int rc, count, i;

	if (chip->ptn_revision == HAP_PTN_V1) {
		for (i = 0; i < length; i++) {
			rc = haptics_update_fifo_sample_v1(chip, samples[i]);
			if (rc < 0)
				return rc;
		}
	} else {
		count = length / HAP_PTN_V2_FIFO_DIN_NUM;
		for (i = 0; i < count; i++) {
			rc = haptics_update_fifo_sample_v2(chip,
					samples, HAP_PTN_V2_FIFO_DIN_NUM);
			if (rc < 0)
				return rc;

			samples += HAP_PTN_V2_FIFO_DIN_NUM;
		}

		if (length % HAP_PTN_V2_FIFO_DIN_NUM) {
			rc = haptics_update_fifo_sample_v2(chip,
					samples,
					length % HAP_PTN_V2_FIFO_DIN_NUM);
			if (rc < 0)
				return rc;
		}
	}

	return 0;
}

static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
{
	struct fifo_play_status *status = &chip->play.fifo_status;
	u32 num, fifo_thresh;
	int rc, i;
	int rc, thresh_per_bit, available;
	u8 reg;

	if (atomic_read(&status->is_busy) == 1) {
		dev_err(chip->dev, "FIFO is busy\n");
@@ -779,9 +921,10 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
	}

	/* Configure FIFO play rate */
	reg = (chip->ptn_revision == HAP_PTN_V1) ?
		HAP_PTN_V1_FIFO_PLAY_RATE_REG : HAP_PTN_V2_FIFO_PLAY_RATE_REG;
	rc = haptics_masked_write(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_PLAY_RATE_REG,
			FIFO_PLAY_RATE_MASK, fifo->period_per_s);
			reg, FIFO_PLAY_RATE_MASK, fifo->period_per_s);
	if (rc < 0)
		return rc;

@@ -790,17 +933,18 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)

	/*
	 * Write the 1st set of the data into FIFO if there are
	 * more than 104 samples, the rest will be written if
	 * any FIFO memory is available after playing.
	 * more than MAX_FIFO_SAMPLES samples, the rest will be
	 * written if any FIFO memory is available after playing.
	 */
	if (fifo->num_s > MAX_FIFO_SAMPLES)
		num = MAX_FIFO_SAMPLES;
	else
		num = fifo->num_s;
	num = min_t(u32, fifo->num_s, MAX_FIFO_SAMPLES(chip));
	available = haptics_get_available_fifo_memory(chip);
	if (available < 0)
		return available;

	for (i = 0; i < num; i++) {
		rc = haptics_update_fifo_sample(chip, fifo->samples[i]);
		if (rc < 0)
	num = min_t(u32, available, num);
	rc = haptics_update_fifo_samples(chip, fifo->samples, num);
	if (rc < 0) {
		dev_err(chip->dev, "write FIFO samples failed, rc=%d\n", rc);
		return rc;
	}

@@ -811,7 +955,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
		atomic_set(&status->written_done, 1);
	} else {
		reinit_completion(&status->fifo_ready);
		fifo_thresh = FIFO_EMPTY_THRESHOLD;
		fifo_thresh = FIFO_EMPTY_THRESHOLD(chip);
	}

	/*
@@ -819,9 +963,12 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
	 * more data can be written into FIFO memory after
	 * the IRQ is triggered.
	 */
	reg = (chip->ptn_revision == HAP_PTN_V1) ?
		HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG;
	thresh_per_bit = (chip->ptn_revision == HAP_PTN_V1) ?
		HAP_PTN_V1_FIFO_THRESH_LSB : HAP_PTN_V2_FIFO_THRESH_LSB;
	rc = haptics_masked_write(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_EMPTY_CFG_REG, EMPTY_THRESH_MASK,
			fifo_thresh / 4);
			reg, EMPTY_THRESH_MASK, fifo_thresh / thresh_per_bit);
	if (rc < 0)
		return rc;

@@ -1142,11 +1289,12 @@ static void update_fifo_work(struct work_struct *work)
			struct haptics_chip, fifo_work);
	struct fifo_cfg *fifo = chip->play.effect->fifo;
	struct fifo_play_status *status = &chip->play.fifo_status;
	u32 num, samples_written, samples_left;
	int rc, i;
	u32 samples_written, samples_left;
	u8 *samples;
	u8 reg;
	int rc, num;

	samples_written = status->samples_written;
	num = MAX_FIFO_SAMPLES - FIFO_EMPTY_THRESHOLD;
	samples_left = fifo->num_s - samples_written;

	while (samples_left > 0) {
@@ -1158,16 +1306,22 @@ static void update_fifo_work(struct work_struct *work)
			return;
		}

		num = haptics_get_available_fifo_memory(chip);
		if (num < 0)
			return;

		if (samples_left <= num)
			num = samples_left;
		else
			reinit_completion(&status->fifo_ready);

		/* Write more pattern data into FIFO memory */
		for (i = 0; i < num; i++) {
			rc = haptics_update_fifo_sample(chip,
					fifo->samples[samples_written + i]);
			if (rc < 0)
		samples = fifo->samples + samples_written;

		/* Write more pattern data into FIFO memory. */
		rc = haptics_update_fifo_samples(chip, samples, num);
		if (rc < 0) {
			dev_err(chip->dev, "Update FIFO samples failed in fifo_work, rc=%d\n",
					rc);
			return;
		}

@@ -1184,9 +1338,10 @@ static void update_fifo_work(struct work_struct *work)
	 */
	dev_dbg(chip->dev, "FIFO programmed done\n");
	atomic_set(&chip->play.fifo_status.written_done, 1);
	reg = (chip->ptn_revision == HAP_PTN_V1) ?
		HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG;
	rc = haptics_masked_write(chip, chip->ptn_addr_base,
			HAP_PTN_FIFO_EMPTY_CFG_REG,
			EMPTY_THRESH_MASK, 0);
			reg, EMPTY_THRESH_MASK, 0);
	if (rc < 0)
		dev_err(chip->dev, "set FIFO empty threshold to 0 failed, rc=%d\n",
				rc);
@@ -1432,7 +1587,7 @@ static ssize_t fifo_s_dbgfs_write(struct file *fp,
	char *kbuf, *token;
	int rc, i = 0;
	u32 val;
	u16 *samples;
	u8 *samples;

	kbuf = kzalloc(count + 1, GFP_KERNEL);
	if (!kbuf)
@@ -1447,7 +1602,7 @@ static ssize_t fifo_s_dbgfs_write(struct file *fp,
	kbuf[count] = '\0';
	*ppos += count;

	samples = kcalloc(fifo->num_s, sizeof(u16), GFP_KERNEL);
	samples = kcalloc(fifo->num_s, sizeof(*samples), GFP_KERNEL);
	if (!samples) {
		rc = -ENOMEM;
		goto exit;
@@ -1460,16 +1615,16 @@ static ssize_t fifo_s_dbgfs_write(struct file *fp,
			goto exit2;
		}

		if (val > 0x1ff)
			val = 0x1ff;
		if (val > 0xff)
			val = 0xff;

		samples[i++] = (u16)val;
		samples[i++] = val;
		/* only support fifo pattern no longer than before */
		if (i >= fifo->num_s)
			break;
	}

	memcpy(fifo->samples, samples, sizeof(*fifo->samples) * fifo->num_s);
	memcpy(fifo->samples, samples, fifo->num_s);
	fifo->play_length_us = get_fifo_play_length_us(fifo, effect->t_lra_us);
	if (fifo->play_length_us == -EINVAL) {
		pr_err("get fifo play length failed\n");
@@ -1915,7 +2070,7 @@ static int haptics_parse_per_effect_dt(struct haptics_chip *chip,
		}
	}

	tmp = of_property_count_u16_elems(node, "qcom,wf-fifo-data");
	tmp = of_property_count_u8_elems(node, "qcom,wf-fifo-data");
	if (tmp > 0) {
		effect->fifo = devm_kzalloc(chip->dev,
				sizeof(*effect->fifo), GFP_KERNEL);
@@ -1923,11 +2078,11 @@ static int haptics_parse_per_effect_dt(struct haptics_chip *chip,
			return -ENOMEM;

		effect->fifo->samples = devm_kcalloc(chip->dev,
				tmp, sizeof(u16), GFP_KERNEL);
				tmp, sizeof(u8), GFP_KERNEL);
		if (!effect->fifo->samples)
			return -ENOMEM;

		rc = of_property_read_u16_array(node, "qcom,wf-fifo-data",
		rc = of_property_read_u8_array(node, "qcom,wf-fifo-data",
				effect->fifo->samples, tmp);
		if (rc < 0) {
			dev_err(chip->dev, "Read wf-fifo-data failed, rc=%d\n",
@@ -2149,6 +2304,22 @@ static int haptics_parse_lra_dt(struct haptics_chip *chip)
	return 0;
}

static int haptics_get_revision(struct haptics_chip *chip)
{
	int rc;
	u8 val;

	rc = haptics_read(chip, chip->ptn_addr_base,
			HAP_PTN_REVISION2_REG, &val, 1);
	if (rc < 0)
		return rc;

	chip->ptn_revision = val;
	dev_dbg(chip->dev, "haptics ptn module revision: %#x\n",
			chip->ptn_revision);
	return 0;
}

static int haptics_parse_dt(struct haptics_chip *chip)
{
	struct haptics_hw_config *config = &chip->config;
@@ -2173,6 +2344,12 @@ static int haptics_parse_dt(struct haptics_chip *chip)
	}

	chip->ptn_addr_base = be32_to_cpu(*addr);
	rc = haptics_get_revision(chip);
	if (rc < 0) {
		dev_err(chip->dev, "Get revision failed, rc=%d\n", rc);
		return rc;
	}

	chip->fifo_empty_irq = platform_get_irq_byname(pdev, "fifo-empty");
	if (!chip->fifo_empty_irq) {
		dev_err(chip->dev, "Get fifo-empty IRQ failed\n");
@@ -2243,6 +2420,97 @@ static int haptics_parse_dt(struct haptics_chip *chip)
	return 0;
}

static int swr_slave_reg_enable(struct regulator_dev *rdev)
{
	struct haptics_chip *chip = rdev_get_drvdata(rdev);
	int rc;
	u8 mask = SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT | SWR_PAT_CFG_EN_BIT;

	rc = haptics_masked_write(chip, chip->cfg_addr_base,
			HAP_CFG_SWR_ACCESS_REG, mask, mask);
	if (rc < 0) {
		dev_err(chip->dev, "Failed to enable SWR_PAT, rc=%d\n",
				rc);
		return rc;
	}

	chip->swr_slave_enabled = true;
	return 0;
}

static int swr_slave_reg_disable(struct regulator_dev *rdev)
{
	struct haptics_chip *chip = rdev_get_drvdata(rdev);
	int rc;

	rc = haptics_masked_write(chip, chip->cfg_addr_base,
			HAP_CFG_SWR_ACCESS_REG,
			SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT |
			SWR_PAT_CFG_EN_BIT, 0);
	if (rc < 0) {
		dev_err(chip->dev, "Failed to disable SWR_PAT, rc=%d\n", rc);
		return rc;
	}

	chip->swr_slave_enabled = false;
	return 0;
}

static int swr_slave_reg_is_enabled(struct regulator_dev *rdev)
{
	struct haptics_chip *chip = rdev_get_drvdata(rdev);

	return chip->swr_slave_enabled;
}

static struct regulator_ops swr_slave_reg_ops = {
	.enable		= swr_slave_reg_enable,
	.disable	= swr_slave_reg_disable,
	.is_enabled	= swr_slave_reg_is_enabled,
};

static struct regulator_desc swr_slave_reg_rdesc = {
	.owner		= THIS_MODULE,
	.of_match	= "qcom,hap-swr-slave-reg",
	.name		= "hap-swr-slave-reg",
	.type		= REGULATOR_VOLTAGE,
	.ops		= &swr_slave_reg_ops,
};

static int haptics_init_swr_slave_regulator(struct haptics_chip *chip)
{
	struct regulator_config cfg = {};
	u8 val, mask;
	int rc = 0;

	rc = haptics_read(chip, chip->cfg_addr_base,
			HAP_CFG_SWR_ACCESS_REG, &val, 1);
	if (rc < 0) {
		dev_err(chip->dev, "Failed to read SWR_ACCESS, rc=%d\n",
				rc);
		return rc;
	}

	mask = SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT | SWR_PAT_CFG_EN_BIT;
	val &= mask;
	chip->swr_slave_enabled = ((val == mask) ? true : false);

	cfg.dev = chip->dev;
	cfg.driver_data = chip;
	chip->swr_slave_rdev = devm_regulator_register(chip->dev,
			&swr_slave_reg_rdesc, &cfg);
	if (IS_ERR(chip->swr_slave_rdev)) {
		rc = PTR_ERR(chip->swr_slave_rdev);
		chip->swr_slave_rdev = NULL;

		if (rc != -EPROBE_DEFER)
			dev_err(chip->dev, "register swr-slave-reg regulator failed, rc=%d\n",
					rc);
	}

	return rc;
}

static int haptics_probe(struct platform_device *pdev)
{
	struct haptics_chip *chip;
@@ -2277,6 +2545,13 @@ static int haptics_probe(struct platform_device *pdev)
		return rc;
	}

	rc = haptics_init_swr_slave_regulator(chip);
	if (rc < 0) {
		dev_err(chip->dev, "Initialize swr slave regulator failed, rc = %d\n",
				rc);
		return rc;
	}

	rc = devm_request_threaded_irq(chip->dev, chip->fifo_empty_irq,
			NULL, fifo_empty_irq_handler,
			IRQF_ONESHOT, "fifo-empty", chip);