From 4eac240bd3841ee47782e2afa3e3abf7b5d4172b Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 2 Apr 2021 11:12:51 +0800 Subject: [PATCH] asoc: swr-haptics: Toggle swr-slave-vdd supply for SSR recovery After ADSP SSR happened, toggle swr_slave_vdd before play to reset haptics HW so that it can function properly. Change-Id: I48bc07c923d1af2041c6c156c699e329084f0d34 Signed-off-by: Fenglin Wu --- asoc/codecs/swr-haptics.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 1f1702d6c445..4b2757466771 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -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}, @@ -81,7 +90,9 @@ struct swr_haptics_dev { 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) @@ -257,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", @@ -464,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, @@ -475,6 +495,10 @@ 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); rc = swr_haptics_parse_port_mapping(sdev); @@ -592,6 +616,9 @@ static int swr_haptics_device_up(struct swr_device *sdev) return -ENODEV; } + if (swr_hap->flags & HAP_SSR_RECOVERY) + swr_hap->ssr_recovery = true; + /* Take SWR slave out of reset */ return swr_haptics_slave_enable(swr_hap); } @@ -649,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, + }, { }, };