From 90f05606d24226151104ac39cf1df594f1341e26 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 25 Mar 2021 08:54:24 +0800 Subject: [PATCH 1/2] asoc: codec: swr-haptics: update slave-vdd regulator control logic Update the slave-vdd regulator control logic to avoid unbalanced regulator_enable() regulator_disable() calls. Meanwhile, correct the jump label when bailing out from soundwire enumeration failure. This helps to avoid the regulator_put() call in the device remove process throwing a warning for a dangling regulator enable status. Change-Id: I89157f5f9177db69bbbf6aedcc8e605c43a7584e Signed-off-by: Fenglin Wu --- asoc/codecs/swr-haptics.c | 86 +++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index c4a433fcfed3..1f1702d6c445 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -76,10 +76,10 @@ 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; u8 vmax; }; @@ -168,6 +168,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, @@ -438,7 +476,6 @@ static int swr_haptics_probe(struct swr_device *sdev) swr_hap->swr_slave = sdev; swr_hap->dev = &sdev->dev; swr_set_dev_data(sdev, swr_hap); - swr_hap->enable_cnt = 0; rc = swr_haptics_parse_port_mapping(sdev); if (rc < 0) { @@ -447,9 +484,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 +513,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 +529,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 +551,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 +570,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 +585,6 @@ clean: 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) { @@ -557,16 +593,7 @@ static int swr_haptics_device_up(struct swr_device *sdev) } /* 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++; - } - - return 0; + return swr_haptics_slave_enable(swr_hap); } static int swr_haptics_device_down(struct swr_device *sdev) @@ -579,20 +606,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 +614,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) From 4eac240bd3841ee47782e2afa3e3abf7b5d4172b Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 2 Apr 2021 11:12:51 +0800 Subject: [PATCH 2/2] 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, + }, { }, };