Merge "asoc: wcd938x: Add vdd-buck as on demand supply"
diff --git a/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c
index 220da9d..831562f 100644
--- a/asoc/codecs/msm-cdc-supply.c
+++ b/asoc/codecs/msm-cdc-supply.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -119,6 +119,47 @@
}
/*
+ * 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 8ade1d9..c90bba4 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -2360,6 +2360,67 @@
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)
{
@@ -2779,6 +2840,10 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_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),
@@ -2936,6 +3001,7 @@
{"DMIC8_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"},
@@ -2943,6 +3009,7 @@
{"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"},
@@ -2950,6 +3017,7 @@
{"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"},
@@ -3792,6 +3860,37 @@
#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 c6aacf6..cff1a4a 100644
--- a/include/asoc/msm-cdc-supply.h
+++ b/include/asoc/msm-cdc-supply.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2016, 2018-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016, 2018-2020 The Linux Foundation. All rights reserved.
*/
#ifndef __CODEC_POWER_SUPPLY_H__
@@ -21,6 +21,10 @@
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,