From 2f2e85ea28db2b4b6070179e000e3ce4cf8aba38 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 13 Oct 2020 18:07:35 +0800 Subject: [PATCH] asoc: swr-haptics: add non-HBoost regulator support Haptics module is supplied by HBoost regulator by default, it requests voltage to HBoost regulator through hardware channel. Haptics module can also be configured to use other regulator device, in this case, it requires software to request the voltage from the regulator before enabling the play. Add support for this. Change-Id: I4a8305ff2732a92bc8be90bd3ed197fa643a101e Signed-off-by: Fenglin Wu --- asoc/codecs/swr-haptics.c | 95 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 20657d57200a..29681cef4f82 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -78,6 +78,9 @@ struct swr_haptics_dev { struct swr_port port; struct regulator *vdd; u32 enable_cnt; + struct regulator *hpwr_vreg; + u32 hpwr_voltage_mv; + bool hpwr_vreg_enabled; }; static bool swr_hap_volatile_register(struct device *dev, unsigned int reg) @@ -119,6 +122,51 @@ static bool swr_hap_writeable_register(struct device *dev, unsigned int reg) return 1; } +static int swr_hap_enable_hpwr_vreg(struct swr_haptics_dev *swr_hap, bool en) +{ + int rc; + + if (swr_hap->hpwr_vreg == NULL || swr_hap->hpwr_vreg_enabled == en) + return 0; + + if (en) { + rc = regulator_set_voltage(swr_hap->hpwr_vreg, + swr_hap->hpwr_voltage_mv * 1000, INT_MAX); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Set hpwr voltage failed, rc=%d\n", + __func__, rc); + return rc; + } + + rc = regulator_enable(swr_hap->hpwr_vreg); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Enable hpwr failed, rc=%d\n", + __func__, rc); + regulator_set_voltage(swr_hap->hpwr_vreg, 0, INT_MAX); + return rc; + } + } else { + rc = regulator_disable(swr_hap->hpwr_vreg); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Disable hpwr failed, rc=%d\n", + __func__, rc); + return rc; + } + + rc = regulator_set_voltage(swr_hap->hpwr_vreg, 0, INT_MAX); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Set hpwr voltage failed, rc=%d\n", + __func__, rc); + return rc; + } + } + + dev_dbg(swr_hap->dev, "%s: swr-haptics: %s hpwr_regulator\n", + __func__, en ? "enabled" : "disabled"); + swr_hap->hpwr_vreg_enabled = en; + return 0; +} + struct regmap_config swr_hap_regmap_config = { .reg_bits = 16, .val_bits = 8, @@ -175,6 +223,13 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, &ch_mask, &ch_rate, &num_ch, &port_type); break; case SND_SOC_DAPM_POST_PMU: + rc = swr_hap_enable_hpwr_vreg(swr_hap, true); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Enable hpwr_vreg failed, rc=%d\n", + __func__, rc); + return rc; + } + swr_slvdev_datapath_control(swr_hap->swr_slave, swr_hap->swr_slave->dev_num, true); /* trigger SWR play */ @@ -183,6 +238,9 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, if (rc) { dev_err(swr_hap->dev, "%s: Enable SWR_PLAY failed, rc=%d\n", __func__, rc); + swr_slvdev_datapath_control(swr_hap->swr_slave, + swr_hap->swr_slave->dev_num, false); + swr_hap_enable_hpwr_vreg(swr_hap, false); return rc; } break; @@ -195,6 +253,13 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, __func__, rc); return rc; } + + rc = swr_hap_enable_hpwr_vreg(swr_hap, false); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Disable hpwr_vreg failed, rc=%d\n", + __func__, rc); + return rc; + } break; case SND_SOC_DAPM_POST_PMD: swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port, @@ -313,6 +378,7 @@ static int swr_haptics_parse_port_mapping(struct swr_device *sdev) static int swr_haptics_probe(struct swr_device *sdev) { struct swr_haptics_dev *swr_hap; + struct device_node *node = sdev->dev.of_node; int rc; u8 devnum; int retry = 5; @@ -343,6 +409,26 @@ static int swr_haptics_probe(struct swr_device *sdev) goto clean; } + if (of_find_property(node, "qcom,hpwr-supply", NULL)) { + swr_hap->hpwr_vreg = devm_regulator_get(swr_hap->dev, + "qcom,hpwr"); + if (IS_ERR(swr_hap->hpwr_vreg)) { + rc = PTR_ERR(swr_hap->hpwr_vreg); + if (rc != -EPROBE_DEFER) + dev_err(swr_hap->dev, "%s: Get qcom,hpwr-supply failed, rc=%d\n", + __func__, rc); + goto clean; + } + + rc = of_property_read_u32(node, "qcom,hpwr-voltage-mv", + &swr_hap->hpwr_voltage_mv); + if (rc < 0) { + dev_err(swr_hap->dev, "%s: Failed to read qcom,hpwr-voltage-mv, rc=%d\n", + __func__, rc); + goto clean; + } + } + rc = regulator_enable(swr_hap->vdd); if (rc < 0) { dev_err(swr_hap->dev, "%s: enable swr-slave-vdd failed, rc=%d\n", @@ -459,6 +545,15 @@ static int swr_haptics_device_down(struct swr_device *sdev) } else { swr_hap->enable_cnt = 0; } + + /* Disable HAP_PWR regulator */ + rc = swr_hap_enable_hpwr_vreg(swr_hap, false); + if (rc < 0) { + dev_err(swr_hap->dev, "Disable hpwr_vreg failed, rc=%d\n", + rc); + return rc; + } + return 0; }