From 1ecf8184d274bbf50990d766aba9bd3f43e64fd2 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Thu, 12 Mar 2020 17:40:47 +0530 Subject: [PATCH] asoc: wcd938x: Add vdd-buck as on demand supply On lagoon, vdd-buck need to be dynamic supply. Add required support to handle buck as dynamic supply. Change-Id: If6c27fffe0d0c44f178e61a6eae6ef63775c8988 Signed-off-by: Laxminath Kasam --- asoc/codecs/msm-cdc-supply.c | 41 +++++++++++++++ asoc/codecs/wcd938x/wcd938x.c | 99 +++++++++++++++++++++++++++++++++++ include/asoc/msm-cdc-supply.h | 4 ++ 3 files changed, 144 insertions(+) diff --git a/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c index e85df2ef47..230a7f9981 100644 --- a/asoc/codecs/msm-cdc-supply.c +++ b/asoc/codecs/msm-cdc-supply.c @@ -119,6 +119,47 @@ static int msm_cdc_check_supply_param(struct device *dev, return 0; } +/* + * msm_cdc_is_ondemand_supply: + * return if ondemand supply true or not + * + * @dev: pointer to codec device + * @supplies: pointer to regulator bulk data + * @cdc_vreg: pointer to platform regulator data + * @num_supplies: number of supplies + * @supply_name: supply name to be checked + * + * Return true/false + */ +bool msm_cdc_is_ondemand_supply(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, + char *supply_name) +{ + bool rc = false; + int ret, i; + + if ((!supply_name) || (!supplies)) { + pr_err("%s: either dev or supplies or cdc_vreg is NULL\n", + __func__); + return rc; + } + /* input parameter validation */ + ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies); + if (ret) + return rc; + + for (i = 0; i < num_supplies; i++) { + if (cdc_vreg[i].ondemand && + !strcmp(cdc_vreg[i].name, supply_name)) + return true; + } + + return rc; +} +EXPORT_SYMBOL(msm_cdc_is_ondemand_supply); + /* * msm_cdc_disable_ondemand_supply: * Disable codec ondemand supply diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 9a0e14371c..9880d7d14d 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -2563,6 +2563,67 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, return 0; } +static int wcd938x_codec_enable_vdd_buck(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + struct wcd938x_pdata *pdata = NULL; + int ret = 0; + + pdata = dev_get_platdata(wcd938x->dev); + + if (!pdata) { + dev_err(component->dev, "%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + if (!msm_cdc_is_ondemand_supply(wcd938x->dev, + wcd938x->supplies, + pdata->regulator, + pdata->num_supplies, + "cdc-vdd-buck")) + return 0; + + dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, + w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) { + dev_dbg(component->dev, + "%s: buck already in enabled state\n", + __func__); + clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); + return 0; + } + ret = msm_cdc_enable_ondemand_supply(wcd938x->dev, + wcd938x->supplies, + pdata->regulator, + pdata->num_supplies, + "cdc-vdd-buck"); + if (ret == -EINVAL) { + dev_err(component->dev, "%s: vdd buck is not enabled\n", + __func__); + return ret; + } + clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); + /* + * 200us sleep is required after LDO is enabled as per + * HW requirement + */ + usleep_range(200, 250); + break; + case SND_SOC_DAPM_POST_PMD: + set_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); + break; + } + return 0; +} + + static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3111,6 +3172,10 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = { wcd938x_codec_force_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0, + wcd938x_codec_enable_vdd_buck, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0, wcd938x_enable_clsh, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -3257,6 +3322,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"WCD_TX_OUTPUT", NULL, "DMIC8_MIXER"}, {"DMIC8_MIXER", "Switch", "DMIC8"}, + {"IN1_HPHL", NULL, "VDD_BUCK"}, {"IN1_HPHL", NULL, "CLS_H_PORT"}, {"RX1", NULL, "IN1_HPHL"}, {"RDAC1", NULL, "RX1"}, @@ -3264,6 +3330,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"HPHL PGA", NULL, "HPHL_RDAC"}, {"HPHL", NULL, "HPHL PGA"}, + {"IN2_HPHR", NULL, "VDD_BUCK"}, {"IN2_HPHR", NULL, "CLS_H_PORT"}, {"RX2", NULL, "IN2_HPHR"}, {"RDAC2", NULL, "RX2"}, @@ -3271,6 +3338,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"HPHR PGA", NULL, "HPHR_RDAC"}, {"HPHR", NULL, "HPHR PGA"}, + {"IN3_AUX", NULL, "VDD_BUCK"}, {"IN3_AUX", NULL, "CLS_H_PORT"}, {"RX3", NULL, "IN3_AUX"}, {"RDAC4", NULL, "RX3"}, @@ -4122,6 +4190,37 @@ static int wcd938x_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int wcd938x_suspend(struct device *dev) { + struct wcd938x_priv *wcd938x = NULL; + int ret = 0; + struct wcd938x_pdata *pdata = NULL; + + if (!dev) + return -ENODEV; + + wcd938x = dev_get_drvdata(dev); + if (!wcd938x) + return -EINVAL; + + pdata = dev_get_platdata(wcd938x->dev); + + if (!pdata) { + dev_err(dev, "%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) { + ret = msm_cdc_disable_ondemand_supply(wcd938x->dev, + wcd938x->supplies, + pdata->regulator, + pdata->num_supplies, + "cdc-vdd-buck"); + if (ret == -EINVAL) { + dev_err(dev, "%s: vdd buck is not disabled\n", + __func__); + return 0; + } + clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); + } return 0; } diff --git a/include/asoc/msm-cdc-supply.h b/include/asoc/msm-cdc-supply.h index f3fc3d53a6..f7fec21c03 100644 --- a/include/asoc/msm-cdc-supply.h +++ b/include/asoc/msm-cdc-supply.h @@ -27,6 +27,10 @@ struct cdc_wcd_supply { extern int msm_cdc_get_power_supplies(struct device *dev, struct cdc_regulator **cdc_vreg, int *total_num_supplies); +extern bool msm_cdc_is_ondemand_supply(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, char *supply_name); extern int msm_cdc_disable_ondemand_supply(struct device *dev, struct regulator_bulk_data *supplies, struct cdc_regulator *cdc_vreg,