From 7d939baa4674e04ca5c29dd755f6430929d2b670 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 25 Mar 2021 09:35:43 +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 | 104 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 5970a74eb8..60903cfcd3 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -77,7 +77,10 @@ struct swr_haptics_dev { struct regmap *regmap; struct swr_port port; struct regulator *slave_vdd; + struct regulator *hpwr_vreg; + u32 hpwr_voltage_mv; bool slave_enabled; + bool hpwr_vreg_enabled; u8 vmax; }; @@ -120,6 +123,60 @@ 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) +{ + int rc; + + if (swr_hap->hpwr_vreg == NULL || swr_hap->hpwr_vreg_enabled) + return 0; + + 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; + } + + dev_dbg(swr_hap->dev, "%s: enabled hpwr_regulator\n", __func__); + swr_hap->hpwr_vreg_enabled = true; + return 0; +} + +static int swr_hap_disable_hpwr_vreg(struct swr_haptics_dev *swr_hap) +{ + int rc; + + if (swr_hap->hpwr_vreg == NULL || !swr_hap->hpwr_vreg_enabled) + return 0; + + 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: disabled hpwr_regulator\n", __func__); + swr_hap->hpwr_vreg_enabled = false; + return 0; +} + static int swr_haptics_slave_enable(struct swr_haptics_dev *swr_hap) { int rc; @@ -223,6 +280,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); + 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 */ @@ -231,6 +295,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_disable_hpwr_vreg(swr_hap); return rc; } break; @@ -243,6 +310,13 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, __func__, rc); return rc; } + + rc = swr_hap_disable_hpwr_vreg(swr_hap); + 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, @@ -396,6 +470,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; @@ -427,6 +502,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 = swr_haptics_slave_enable(swr_hap); if (rc < 0) { dev_err(swr_hap->dev, "%s: enable swr-slave-vdd failed, rc=%d\n", @@ -513,12 +608,21 @@ static int swr_haptics_device_up(struct swr_device *sdev) static int swr_haptics_device_down(struct swr_device *sdev) { struct swr_haptics_dev *swr_hap = swr_get_dev_data(sdev); + int rc; if (!swr_hap) { dev_err(&sdev->dev, "%s: no data for swr_hap\n", __func__); return -ENODEV; } + /* Disable HAP_PWR regulator */ + rc = swr_hap_disable_hpwr_vreg(swr_hap); + if (rc < 0) { + dev_err(swr_hap->dev, "Disable hpwr_vreg failed, rc=%d\n", + rc); + return rc; + } + /* Put SWR slave into reset */ return swr_haptics_slave_disable(swr_hap); }