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

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

Merge "asoc: swr-haptics: Toggle swr-slave-vdd supply for SSR recovery"

parents 5a167206 4eac240b
Loading
Loading
Loading
Loading
+85 −38
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -41,6 +42,14 @@

#define SWR_HAP_REG_MAX			(SWR_HAP_ACCESS_BASE + 0xff)

enum pmic_type {
	PM8350B = 1,
};

enum {
	HAP_SSR_RECOVERY = BIT(0),
};

static struct reg_default swr_hap_reg_defaults[] = {
	{FIFO_WR_READY_REG, 1},
	{NUM_PAT_SMPL_REG, 8},
@@ -76,12 +85,14 @@ struct swr_haptics_dev {
	struct snd_soc_component	*component;
	struct regmap			*regmap;
	struct swr_port			port;
	struct regulator		*vdd;
	u32 enable_cnt;
	struct regulator		*slave_vdd;
	struct regulator		*hpwr_vreg;
	u32				hpwr_voltage_mv;
	bool				slave_enabled;
	bool				hpwr_vreg_enabled;
	bool				ssr_recovery;
	u8				vmax;
	u8				flags;
};

static bool swr_hap_volatile_register(struct device *dev, unsigned int reg)
@@ -168,6 +179,44 @@ static int swr_hap_enable_hpwr_vreg(struct swr_haptics_dev *swr_hap, bool en)
	return 0;
}

static int swr_haptics_slave_enable(struct swr_haptics_dev *swr_hap)
{
	int rc;

	if (swr_hap->slave_enabled)
		return 0;

	rc = regulator_enable(swr_hap->slave_vdd);
	if (rc < 0) {
		dev_err(swr_hap->dev, "%s: enable swr-slave-vdd failed, rc=%d\n",
				__func__, rc);
		return rc;
	}

	dev_dbg(swr_hap->dev, "%s: enable swr-slave-vdd success\n", __func__);
	swr_hap->slave_enabled = true;
	return 0;
}

static int swr_haptics_slave_disable(struct swr_haptics_dev *swr_hap)
{
	int rc;

	if (!swr_hap->slave_enabled)
		return 0;

	rc = regulator_disable(swr_hap->slave_vdd);
	if (rc < 0) {
		dev_err(swr_hap->dev, "%s: disable swr-slave-vdd failed, rc=%d\n",
				__func__, rc);
		return rc;
	}

	dev_dbg(swr_hap->dev, "%s: disable swr-slave-vdd success\n", __func__);
	swr_hap->slave_enabled = false;
	return 0;
}

struct regmap_config swr_hap_regmap_config = {
	.reg_bits		= 16,
	.val_bits		= 8,
@@ -219,6 +268,14 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		/* If SSR ever happened, toggle swr-slave-vdd for HW recovery */
		if ((swr_hap->flags & HAP_SSR_RECOVERY)
				&& swr_hap->ssr_recovery) {
			swr_haptics_slave_disable(swr_hap);
			swr_haptics_slave_enable(swr_hap);
			swr_hap->ssr_recovery = false;
		}

		rc = regmap_write(swr_hap->regmap, SWR_VMAX_REG, swr_hap->vmax);
		if (rc) {
			dev_err(swr_hap->dev, "%s: SWR_VMAX update failed, rc=%d\n",
@@ -426,6 +483,7 @@ static int swr_haptics_probe(struct swr_device *sdev)
	struct device_node *node = sdev->dev.of_node;
	int rc;
	u8 devnum;
	u32 pmic_type;
	int retry = 5;

	swr_hap = devm_kzalloc(&sdev->dev,
@@ -437,8 +495,11 @@ static int swr_haptics_probe(struct swr_device *sdev)
	swr_hap->vmax = 100;
	swr_hap->swr_slave = sdev;
	swr_hap->dev = &sdev->dev;
	pmic_type = (uintptr_t)of_device_get_match_data(swr_hap->dev);
	if (pmic_type == PM8350B)
		swr_hap->flags |= HAP_SSR_RECOVERY;

	swr_set_dev_data(sdev, swr_hap);
	swr_hap->enable_cnt = 0;

	rc = swr_haptics_parse_port_mapping(sdev);
	if (rc < 0) {
@@ -447,9 +508,9 @@ static int swr_haptics_probe(struct swr_device *sdev)
		goto clean;
	}

	swr_hap->vdd = devm_regulator_get(swr_hap->dev, "swr-slave");
	if (IS_ERR(swr_hap->vdd)) {
		rc = PTR_ERR(swr_hap->vdd);
	swr_hap->slave_vdd = devm_regulator_get(swr_hap->dev, "swr-slave");
	if (IS_ERR(swr_hap->slave_vdd)) {
		rc = PTR_ERR(swr_hap->slave_vdd);
		if (rc != -EPROBE_DEFER)
			dev_err(swr_hap->dev, "%s: get swr-slave-supply failed, rc=%d\n",
					__func__, rc);
@@ -476,7 +537,7 @@ static int swr_haptics_probe(struct swr_device *sdev)
		}
	}

	rc = regulator_enable(swr_hap->vdd);
	rc = swr_haptics_slave_enable(swr_hap);
	if (rc < 0) {
		dev_err(swr_hap->dev, "%s: enable swr-slave-vdd failed, rc=%d\n",
				__func__, rc);
@@ -492,7 +553,7 @@ static int swr_haptics_probe(struct swr_device *sdev)
		dev_err(swr_hap->dev, "%s: failed to get devnum for swr-haptics, rc=%d\n",
				__func__, rc);
		rc = -EPROBE_DEFER;
		goto clean;
		goto dev_err;
	}

	sdev->dev_num = devnum;
@@ -514,7 +575,7 @@ static int swr_haptics_probe(struct swr_device *sdev)

	return 0;
dev_err:
	regulator_disable(swr_hap->vdd);
	swr_haptics_slave_disable(swr_hap);
	swr_remove_device(sdev);
clean:
	swr_set_dev_data(sdev, NULL);
@@ -533,7 +594,7 @@ static int swr_haptics_remove(struct swr_device *sdev)
		goto clean;
	}

	rc = regulator_disable(swr_hap->vdd);
	rc = swr_haptics_slave_disable(swr_hap);
	if (rc < 0) {
		dev_err(swr_hap->dev, "%s: disable swr-slave failed, rc=%d\n",
				__func__, rc);
@@ -548,7 +609,6 @@ static int swr_haptics_remove(struct swr_device *sdev)
static int swr_haptics_device_up(struct swr_device *sdev)
{
	struct swr_haptics_dev *swr_hap;
	int rc;

	swr_hap = swr_get_dev_data(sdev);
	if (!swr_hap) {
@@ -556,17 +616,11 @@ static int swr_haptics_device_up(struct swr_device *sdev)
		return -ENODEV;
	}

	/* Take SWR slave out of reset */
	rc = regulator_enable(swr_hap->vdd);
	if (rc < 0) {
		dev_err(swr_hap->dev, "%s: enable swr-slave failed, rc=%d\n",
				__func__, rc);
		return rc;
	} else {
		swr_hap->enable_cnt++;
	}
	if (swr_hap->flags & HAP_SSR_RECOVERY)
		swr_hap->ssr_recovery = true;

	return 0;
	/* Take SWR slave out of reset */
	return swr_haptics_slave_enable(swr_hap);
}

static int swr_haptics_device_down(struct swr_device *sdev)
@@ -579,20 +633,6 @@ static int swr_haptics_device_down(struct swr_device *sdev)
		return -ENODEV;
	}

	/* Put SWR slave into reset */
	if (swr_hap->enable_cnt > 0) {
		rc = regulator_disable(swr_hap->vdd);
		if (rc < 0) {
			dev_err(swr_hap->dev, "%s: disable swr-slave failed, rc=%d\n",
				__func__, rc);
			return rc;
		} else {
			swr_hap->enable_cnt--;
		}
	} else {
		swr_hap->enable_cnt = 0;
	}

	/* Disable HAP_PWR regulator */
	rc = swr_hap_enable_hpwr_vreg(swr_hap, false);
	if (rc < 0) {
@@ -601,7 +641,8 @@ static int swr_haptics_device_down(struct swr_device *sdev)
		return rc;
	}

	return 0;
	/* Put SWR slave into reset */
	return swr_haptics_slave_disable(swr_hap);
}

static int swr_haptics_suspend(struct device *dev)
@@ -635,8 +676,14 @@ static int swr_haptics_resume(struct device *dev)
}

static const struct of_device_id swr_haptics_match_table[] = {
	{ .compatible = "qcom,swr-haptics", },
	{ .compatible = "qcom,pm8350b-swr-haptics", },
	{
		.compatible = "qcom,swr-haptics",
		.data = NULL,
	},
	{
		.compatible = "qcom,pm8350b-swr-haptics",
		.data = (void *)PM8350B,
	},
	{ },
};