diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index 3e2161c461d2..7ffc2a28b9ca 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -232,6 +232,27 @@ static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data) priv->component, BOLERO_MACRO_EVT_BCS_CLK_OFF, data); break; + case WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE: + /* Update PA Gain only for bolero version 2.1 */ + if (priv->version == BOLERO_VERSION_2_1) + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE, + data); + break; + case WCD_BOLERO_EVT_HPHL_HD2_ENABLE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, data); + break; + case WCD_BOLERO_EVT_HPHR_HD2_ENABLE: + if (priv->macro_params[RX_MACRO].event_handler) + priv->macro_params[RX_MACRO].event_handler( + priv->component, + BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, data); + break; default: dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n", __func__, event); diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index afd3fdb1eaff..fe0aa64c0ab9 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -50,6 +50,9 @@ enum { BOLERO_MACRO_EVT_BCS_CLK_OFF, BOLERO_MACRO_EVT_SSR_GFMUX_UP, BOLERO_MACRO_EVT_PRE_SSR_UP, + BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE, + BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, /* Enable HD2 cfg for HPHL */ + BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, /* Enable HD2 cfg for HPHR */ }; enum { diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h index d3a072c9cea9..cf132bdd2cfc 100644 --- a/asoc/codecs/bolero/internal.h +++ b/asoc/codecs/bolero/internal.h @@ -33,6 +33,9 @@ enum { WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */ WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST, WCD_BOLERO_EVT_BCS_CLK_OFF, + WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE, + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */ + WCD_BOLERO_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */ }; struct wcd_ctrl_platform_data { diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 3271c0cc9029..7d54d4281a14 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -77,6 +77,11 @@ static const struct snd_kcontrol_new name##_mux = \ #define RX_MACRO_EC_MIX_TX1_MASK 0x0f #define RX_MACRO_EC_MIX_TX2_MASK 0x0f +#define RX_MACRO_GAIN_MAX_VAL 0x28 +#define RX_MACRO_GAIN_VAL_UNITY 0x0 +/* Define macros to increase PA Gain by half */ +#define RX_MACRO_MOD_GAIN (RX_MACRO_GAIN_VAL_UNITY + 6) + #define COMP_MAX_COEFF 25 struct wcd_imped_val { @@ -454,6 +459,8 @@ struct rx_macro_priv { struct rx_macro_bcl_pmic_params bcl_pmic_params; u16 clk_id; u16 default_clk_id; + int8_t rx0_gain_val; + int8_t rx1_gain_val; }; static struct snd_soc_dai_driver rx_macro_dai[]; @@ -1460,6 +1467,56 @@ static int rx_macro_event_handler(struct snd_soc_component *component, case BOLERO_MACRO_EVT_CLK_RESET: bolero_rsc_clk_reset(rx_dev, RX_CORE_CLK); break; + case BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE: + rx_priv->rx0_gain_val = snd_soc_component_read32(component, + BOLERO_CDC_RX_RX0_RX_VOL_CTL); + rx_priv->rx1_gain_val = snd_soc_component_read32(component, + BOLERO_CDC_RX_RX1_RX_VOL_CTL); + if (data) { + /* Reduce gain by half only if its greater than -6DB */ + if ((rx_priv->rx0_gain_val >= RX_MACRO_GAIN_VAL_UNITY) + && (rx_priv->rx0_gain_val <= RX_MACRO_GAIN_MAX_VAL)) + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF, + (rx_priv->rx0_gain_val - + RX_MACRO_MOD_GAIN)); + if ((rx_priv->rx1_gain_val >= RX_MACRO_GAIN_VAL_UNITY) + && (rx_priv->rx1_gain_val <= RX_MACRO_GAIN_MAX_VAL)) + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF, + (rx_priv->rx1_gain_val - + RX_MACRO_MOD_GAIN)); + } + else { + /* Reset gain value to default */ + if ((rx_priv->rx0_gain_val >= + (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) && + (rx_priv->rx0_gain_val <= (RX_MACRO_GAIN_MAX_VAL - + RX_MACRO_MOD_GAIN))) + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF, + (rx_priv->rx0_gain_val + + RX_MACRO_MOD_GAIN)); + if ((rx_priv->rx1_gain_val >= + (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) && + (rx_priv->rx1_gain_val <= (RX_MACRO_GAIN_MAX_VAL - + RX_MACRO_MOD_GAIN))) + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF, + (rx_priv->rx1_gain_val + + RX_MACRO_MOD_GAIN)); + } + break; + case BOLERO_MACRO_EVT_HPHL_HD2_ENABLE: + /* Enable hd2 config for hphl*/ + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX0_RX_PATH_CFG0, 0x04, data); + break; + case BOLERO_MACRO_EVT_HPHR_HD2_ENABLE: + /* Enable hd2 config for hphr*/ + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_RX1_RX_PATH_CFG0, 0x04, data); + break; } done: return ret; @@ -3882,6 +3939,8 @@ static int rx_macro_init(struct snd_soc_component *component) return ret; } rx_priv->dev_up = true; + rx_priv->rx0_gain_val = 0; + rx_priv->rx1_gain_val = 0; snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback"); diff --git a/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c index 1618b83a5516..e7d868038701 100644 --- a/asoc/codecs/msm-cdc-supply.c +++ b/asoc/codecs/msm-cdc-supply.c @@ -173,6 +173,52 @@ bool msm_cdc_is_ondemand_supply(struct device *dev, } EXPORT_SYMBOL(msm_cdc_is_ondemand_supply); +/* + * msm_cdc_set_supply_min_voltage: + * Set min supply voltage for particular supply + * + * @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 change voltage for + * @vval_min: Min voltage to be set in uV + * @override_min_vol: True if override min voltage from default + * Return error code if unable to set voltage + */ +int msm_cdc_set_supply_min_voltage(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, char *supply_name, + int vval_min, bool override_min_vol) +{ + int rc = 0, i; + + if ((!supply_name) || (!supplies)) { + pr_err("%s: either dev or supplies or cdc_vreg is NULL\n", + __func__); + return -EINVAL; + } + /* input parameter validation */ + rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies); + if (rc) + return rc; + for (i = 0; i < num_supplies; i++) { + if (!strcmp(cdc_vreg[i].name, supply_name)) { + if (override_min_vol) + regulator_set_voltage(supplies[i].consumer, + vval_min, cdc_vreg[i].max_uV); + else + regulator_set_voltage(supplies[i].consumer, + cdc_vreg[i].min_uV, cdc_vreg[i].max_uV); + break; + } + } + + return rc; +} +EXPORT_SYMBOL(msm_cdc_set_supply_min_voltage); + /* * msm_cdc_disable_ondemand_supply: * Disable codec ondemand supply diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index cc1500be70d6..a8fc83325c33 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -85,6 +85,11 @@ struct rouleur_priv { struct mutex main_bias_lock; bool dev_up; bool usbc_hs_status; + struct notifier_block psy_nb; + struct work_struct soc_eval_work; + bool low_soc; + int foundry_id_reg; + int foundry_id; }; struct rouleur_micbias_setting { @@ -102,6 +107,7 @@ struct rouleur_pdata { struct cdc_regulator *regulator; int num_supplies; int reset_reg; + int foundry_id_reg; }; struct wcd_ctrl_platform_data { @@ -131,6 +137,9 @@ enum { WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */ WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST, WCD_BOLERO_EVT_BCS_CLK_OFF, + WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE, /* To reduce PA gain for low SoC */ + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */ + WCD_BOLERO_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */ }; enum { diff --git a/asoc/codecs/rouleur/pm2250-spmi.h b/asoc/codecs/rouleur/pm2250-spmi.h index 87c913d43d0f..2eaf28f02cc6 100644 --- a/asoc/codecs/rouleur/pm2250-spmi.h +++ b/asoc/codecs/rouleur/pm2250-spmi.h @@ -7,11 +7,16 @@ #ifdef CONFIG_PM2250_SPMI int pm2250_spmi_write(struct device *dev, int reg, int value); +int pm2250_spmi_read(struct device *dev, int reg, int *value); #else int pm2250_spmi_write(struct device *dev, int reg, int value) { return 0; } +int pm2250_spmi_read(struct device *dev, int reg, int *value); +{ + return 0; +} #endif /* CONFIG_PM2250_SPMI */ #endif diff --git a/asoc/codecs/rouleur/pm2250_spmi.c b/asoc/codecs/rouleur/pm2250_spmi.c index 1e5f70d177e8..10a7d109bbbe 100644 --- a/asoc/codecs/rouleur/pm2250_spmi.c +++ b/asoc/codecs/rouleur/pm2250_spmi.c @@ -25,6 +25,12 @@ static const struct of_device_id pm2250_id_table[] = { }; MODULE_DEVICE_TABLE(of, pm2250_id_table); +/** + * pm2250_spmi_write: Function to write to PMIC register + * @device: node for rouleur device + * @reg: PMIC register to write value + * @value: Value to be written to PMIC register + */ int pm2250_spmi_write(struct device *dev, int reg, int value) { int rc; @@ -47,6 +53,34 @@ int pm2250_spmi_write(struct device *dev, int reg, int value) } EXPORT_SYMBOL(pm2250_spmi_write); +/** + * pm2250_spmi_read: Function to read PMIC register + * @device: node for rouleur device + * @reg: PMIC register to read value + * @value: Pointer to value of reg to be read + */ +int pm2250_spmi_read(struct device *dev, int reg, int *value) +{ + int rc; + struct pm2250_spmi *spmi_dd; + + if (!of_device_is_compatible(dev->of_node, "qcom,pm2250-spmi")) { + pr_err("%s: Device node is invalid\n", __func__); + return -EINVAL; + } + + spmi_dd = dev_get_drvdata(dev); + if (!spmi_dd) + return -EINVAL; + + rc = regmap_read(spmi_dd->regmap, reg, value); + if (rc) + dev_err(dev, "%s: Read from PMIC register failed\n", __func__); + + return rc; +} +EXPORT_SYMBOL(pm2250_spmi_read); + static int pm2250_spmi_probe(struct platform_device *pdev) { struct pm2250_spmi *spmi_dd; diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 8ce51a3b159c..44ec2476a8e0 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -26,6 +26,7 @@ #include #include #include +#include #define DRV_NAME "rouleur_codec" @@ -35,6 +36,10 @@ #define ROULEUR_VERSION_ENTRY_SIZE 32 #define NUM_ATTEMPTS 5 +#define SOC_THRESHOLD_LEVEL 25 +#define LOW_SOC_MBIAS_REG_MIN_VOLTAGE 2850000 + +#define FOUNDRY_ID_SEC 0x5 enum { CODEC_TX = 0, @@ -638,6 +643,11 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, set_bit(HPH_PA_DELAY, &rouleur->status_mask); usleep_range(200, 210); + /* Enable HD2 Config for HPHR if foundry id is SEC */ + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHR_HD2_ENABLE, + 0x04); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_PDM_WD_CTL1, 0x03, 0x03); @@ -682,6 +692,10 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, clear_bit(HPH_PA_DELAY, &rouleur->status_mask); } + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHR_HD2_ENABLE, + 0x00); blocking_notifier_call_chain(&rouleur->mbhc->notifier, WCD_EVENT_POST_HPHR_PA_OFF, &rouleur->mbhc->wcd_mbhc); @@ -712,6 +726,10 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, true); set_bit(HPH_PA_DELAY, &rouleur->status_mask); usleep_range(200, 210); + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, + 0x04); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_PDM_WD_CTL0, 0x03, 0x03); @@ -755,6 +773,10 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, clear_bit(HPH_PA_DELAY, &rouleur->status_mask); } + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, + 0x00); blocking_notifier_call_chain(&rouleur->mbhc->notifier, WCD_EVENT_POST_HPHL_PA_OFF, &rouleur->mbhc->wcd_mbhc); @@ -795,6 +817,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_ANA_COMBOPA_CTL, 0x40, 0x00); + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, + 0x04); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_PDM_WD_CTL0, 0x03, 0x03); @@ -821,6 +847,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: usleep_range(5000, 5100); + if (rouleur->foundry_id == FOUNDRY_ID_SEC) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_HPHL_HD2_ENABLE, + 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_PDM_WD_CTL0, 0x03, 0x00); @@ -2000,6 +2030,126 @@ done: return rc; } +static int rouleur_battery_supply_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct power_supply *psy = data; + struct rouleur_priv *rouleur = + container_of(nb, struct rouleur_priv, psy_nb); + + if (strcmp(psy->desc->name, "battery")) + return NOTIFY_OK; + queue_work(system_freezable_wq, &rouleur->soc_eval_work); + + return NOTIFY_OK; +} + +static int rouleur_read_battery_soc(struct rouleur_priv *rouleur, int *soc_val) +{ + static struct power_supply *batt_psy; + union power_supply_propval ret = {0,}; + int err = 0; + + *soc_val = 100; + if (!batt_psy) + batt_psy = power_supply_get_by_name("battery"); + if (batt_psy) { + err = power_supply_get_property(batt_psy, + POWER_SUPPLY_PROP_CAPACITY, &ret); + if (err) { + pr_err("%s: battery SoC read error:%d\n", + __func__, err); + return err; + } + *soc_val = ret.intval; + } + pr_debug("%s: soc:%d\n", __func__, *soc_val); + + return err; +} + +static void rouleur_evaluate_soc(struct work_struct *work) +{ + struct rouleur_priv *rouleur = + container_of(work, struct rouleur_priv, soc_eval_work); + int soc_val = 0, ret = 0; + struct rouleur_pdata *pdata = NULL; + + pdata = dev_get_platdata(rouleur->dev); + if (!pdata) { + dev_err(rouleur->dev, "%s: pdata is NULL\n", __func__); + return; + } + + if (rouleur_read_battery_soc(rouleur, &soc_val) < 0) { + dev_err(rouleur->dev, "%s unable to read battery SoC\n", + __func__); + return; + } + + if (soc_val < SOC_THRESHOLD_LEVEL) { + dev_dbg(rouleur->dev, + "%s battery SoC less than threshold soc_val = %d\n", + __func__, soc_val); + /* Reduce PA Gain by 6DB for low SoC */ + if (rouleur->update_wcd_event) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE, + true); + rouleur->low_soc = true; + ret = msm_cdc_set_supply_min_voltage(rouleur->dev, + rouleur->supplies, + pdata->regulator, + pdata->num_supplies, + "cdc-vdd-mic-bias", + LOW_SOC_MBIAS_REG_MIN_VOLTAGE, + true); + if (ret < 0) + dev_err(rouleur->dev, + "%s unable to set mbias min voltage\n", + __func__); + } else { + if (rouleur->low_soc == true) { + /* Reset PA Gain to default for normal SoC */ + if (rouleur->update_wcd_event) + rouleur->update_wcd_event(rouleur->handle, + WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE, + false); + ret = msm_cdc_set_supply_min_voltage(rouleur->dev, + rouleur->supplies, + pdata->regulator, + pdata->num_supplies, + "cdc-vdd-mic-bias", + LOW_SOC_MBIAS_REG_MIN_VOLTAGE, + false); + if (ret < 0) + dev_err(rouleur->dev, + "%s unable to set mbias min voltage\n", + __func__); + rouleur->low_soc = false; + } + } +} + +static void rouleur_get_foundry_id(struct rouleur_priv *rouleur) +{ + int ret; + + if (rouleur->foundry_id_reg == 0) { + pr_debug("%s: foundry id not defined\n", __func__); + return; + } + + ret = pm2250_spmi_read(rouleur->spmi_dev, + rouleur->foundry_id_reg, &rouleur->foundry_id); + if (ret == 0) + pr_debug("%s: rouleur foundry id = %x\n", rouleur->foundry_id, + __func__); + else + pr_debug("%s: rouleur error in spmi read ret = %d\n", + __func__, ret); +} + static int rouleur_soc_codec_probe(struct snd_soc_component *component) { struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); @@ -2055,6 +2205,8 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component) snd_soc_dapm_sync(dapm); rouleur_init_reg(component); + /* Get rouleur foundry id */ + rouleur_get_foundry_id(rouleur); rouleur->version = ROULEUR_VERSION_1_0; /* Register event notifier */ @@ -2070,7 +2222,16 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component) return ret; } } + rouleur->low_soc = false; rouleur->dev_up = true; + /* Register notifier to change gain based on state of charge */ + INIT_WORK(&rouleur->soc_eval_work, rouleur_evaluate_soc); + rouleur->psy_nb.notifier_call = rouleur_battery_supply_cb; + if (power_supply_reg_notifier(&rouleur->psy_nb) < 0) + dev_dbg(rouleur->dev, + "%s: could not register pwr supply notifier\n", + __func__); + queue_work(system_freezable_wq, &rouleur->soc_eval_work); done: return ret; } @@ -2304,6 +2465,12 @@ struct rouleur_pdata *rouleur_populate_dt_data(struct device *dev) } pdata->reset_reg = reg; + if (of_property_read_u32(dev->of_node, "qcom,foundry-id-reg", ®)) + dev_dbg(dev, "%s: Failed to obtain foundry id\n", + __func__); + else + pdata->foundry_id_reg = reg; + /* Parse power supplies */ msm_cdc_get_power_supplies(dev, &pdata->regulator, &pdata->num_supplies); @@ -2379,6 +2546,7 @@ static int rouleur_bind(struct device *dev) rouleur->spmi_dev = &pdev->dev; rouleur->reset_reg = pdata->reset_reg; + rouleur->foundry_id_reg = pdata->foundry_id_reg; ret = msm_cdc_init_supplies(dev, &rouleur->supplies, pdata->regulator, pdata->num_supplies); if (!rouleur->supplies) { diff --git a/include/asoc/msm-cdc-supply.h b/include/asoc/msm-cdc-supply.h index c7404007544c..3b19387d4711 100644 --- a/include/asoc/msm-cdc-supply.h +++ b/include/asoc/msm-cdc-supply.h @@ -69,5 +69,10 @@ extern int msm_cdc_init_supplies_v2(struct device *dev, int msm_cdc_init_wcd_supply(struct device_node *np, const char *name, struct cdc_wcd_supply *cdc_supply); int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable); +extern int msm_cdc_set_supply_min_voltage(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, char *supply_name, + int vval_min, bool override_min_vol); #endif