asoc: codec: Unvote wcd939x vdd-px supply
When codec goes into suspend, disable vdd-px which will cause an unvote in PM. Change-Id: Ia9f958d67fc57dbf3932733797bce7b0eb742363 Signed-off-by: Eric Rosas <quic_erosas@quicinc.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@@ -72,10 +73,22 @@ static int msm_cdc_dt_parse_vreg_info(struct device *dev,
|
|||||||
cdc_vreg->lpm_supported = prop_val;
|
cdc_vreg->lpm_supported = prop_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d\n",
|
/* Parse supply - retention mode */
|
||||||
|
snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-rem-supported", name);
|
||||||
|
rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
|
||||||
|
if (rc) {
|
||||||
|
dev_dbg(dev, "%s: Looking up %s property in node %s failed",
|
||||||
|
__func__, prop_name, dev->of_node->full_name);
|
||||||
|
cdc_vreg->rem_supported = 0;
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
cdc_vreg->rem_supported = prop_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d rem %d\n",
|
||||||
__func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
|
__func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
|
||||||
cdc_vreg->optimum_uA, cdc_vreg->ondemand,
|
cdc_vreg->optimum_uA, cdc_vreg->ondemand,
|
||||||
cdc_vreg->lpm_supported);
|
cdc_vreg->lpm_supported, cdc_vreg->rem_supported);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return rc;
|
return rc;
|
||||||
@@ -173,6 +186,94 @@ bool msm_cdc_is_ondemand_supply(struct device *dev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
|
EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* msm_cdc_supply_supports_retention_mode:
|
||||||
|
* On certain hardware configurations, This means that the
|
||||||
|
* PM will disable the supply and remove its power vote
|
||||||
|
* if the PM enters into a suspended state.
|
||||||
|
*
|
||||||
|
* return if supply supports retention mode 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_supply_supports_retention_mode(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_ratelimited("%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].rem_supported &&
|
||||||
|
!strcmp(cdc_vreg[i].name, supply_name))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_cdc_supply_supports_retention_mode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* msm_cdc_check_supply_vote:
|
||||||
|
*
|
||||||
|
* return true if supply has voted for regulator enable
|
||||||
|
*
|
||||||
|
* @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_check_supply_vote(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_ratelimited("%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 (strcmp(cdc_vreg[i].name, supply_name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return cdc_vreg[i].vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_cdc_check_supply_vote);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* msm_cdc_set_supply_min_voltage:
|
* msm_cdc_set_supply_min_voltage:
|
||||||
* Set min supply voltage for particular supply
|
* Set min supply voltage for particular supply
|
||||||
@@ -257,6 +358,7 @@ int msm_cdc_disable_ondemand_supply(struct device *dev,
|
|||||||
dev_err_ratelimited(dev,
|
dev_err_ratelimited(dev,
|
||||||
"%s: failed to disable supply %s, err:%d\n",
|
"%s: failed to disable supply %s, err:%d\n",
|
||||||
__func__, supplies[i].supply, rc);
|
__func__, supplies[i].supply, rc);
|
||||||
|
cdc_vreg[i].vote = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,6 +409,7 @@ int msm_cdc_enable_ondemand_supply(struct device *dev,
|
|||||||
if (rc)
|
if (rc)
|
||||||
dev_err_ratelimited(dev, "%s: failed to enable supply %s, rc: %d\n",
|
dev_err_ratelimited(dev, "%s: failed to enable supply %s, rc: %d\n",
|
||||||
__func__, supplies[i].supply, rc);
|
__func__, supplies[i].supply, rc);
|
||||||
|
cdc_vreg[i].vote = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -409,9 +512,11 @@ int msm_cdc_disable_static_supplies(struct device *dev,
|
|||||||
if (rc)
|
if (rc)
|
||||||
dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
|
dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
|
||||||
__func__, supplies[i].supply, rc);
|
__func__, supplies[i].supply, rc);
|
||||||
else
|
else {
|
||||||
|
cdc_vreg[i].vote = false;
|
||||||
dev_dbg(dev, "%s: disabled regulator %s\n",
|
dev_dbg(dev, "%s: disabled regulator %s\n",
|
||||||
__func__, supplies[i].supply);
|
__func__, supplies[i].supply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -500,11 +605,21 @@ int msm_cdc_enable_static_supplies(struct device *dev,
|
|||||||
__func__, supplies[i].supply, rc);
|
__func__, supplies[i].supply, rc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cdc_vreg[i].vote = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (rc && i--)
|
if (rc) {
|
||||||
if (!cdc_vreg[i].ondemand)
|
while (i--) {
|
||||||
regulator_disable(supplies[i].consumer);
|
if (cdc_vreg[i].ondemand)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (regulator_disable(supplies[i].consumer) == 0)
|
||||||
|
cdc_vreg[i].vote = false;
|
||||||
|
else
|
||||||
|
dev_err(dev, "%s: failed to disable supply %s during unwind\n",
|
||||||
|
__func__, supplies[i].supply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -594,6 +709,8 @@ int msm_cdc_init_supplies_v2(struct device *dev,
|
|||||||
if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
|
if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
cdc_vreg[i].regulator = vsup[i].consumer;
|
||||||
|
|
||||||
rc = regulator_set_voltage(vsup[i].consumer,
|
rc = regulator_set_voltage(vsup[i].consumer,
|
||||||
cdc_vreg[i].min_uV,
|
cdc_vreg[i].min_uV,
|
||||||
cdc_vreg[i].max_uV);
|
cdc_vreg[i].max_uV);
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
#include <soc/soundwire.h>
|
#include <soc/soundwire.h>
|
||||||
@@ -5316,6 +5317,18 @@ static int wcd939x_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msm_cdc_is_ondemand_supply(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px")) {
|
||||||
|
ret = msm_cdc_enable_ondemand_supply(wcd939x->dev,
|
||||||
|
wcd939x->supplies, pdata->regulator,
|
||||||
|
pdata->num_supplies, "cdc-vdd-px");
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: vdd px supply enable failed!\n",
|
||||||
|
__func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = wcd939x_parse_port_mapping(dev, "qcom,rx_swr_ch_map",
|
ret = wcd939x_parse_port_mapping(dev, "qcom,rx_swr_ch_map",
|
||||||
CODEC_RX);
|
CODEC_RX);
|
||||||
ret |= wcd939x_parse_port_mapping(dev, "qcom,tx_swr_ch_map",
|
ret |= wcd939x_parse_port_mapping(dev, "qcom,tx_swr_ch_map",
|
||||||
@@ -5409,12 +5422,30 @@ static int wcd939x_suspend(struct device *dev)
|
|||||||
pdata->num_supplies,
|
pdata->num_supplies,
|
||||||
true);
|
true);
|
||||||
set_bit(WCD_SUPPLIES_LPM_MODE, &wcd939x->status_mask);
|
set_bit(WCD_SUPPLIES_LPM_MODE, &wcd939x->status_mask);
|
||||||
|
if (msm_cdc_is_ondemand_supply(wcd939x->dev, wcd939x->supplies, pdata->regulator,
|
||||||
|
pdata->num_supplies, "cdc-vdd-px")) {
|
||||||
|
|
||||||
|
if (msm_cdc_supply_supports_retention_mode(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px") &&
|
||||||
|
msm_cdc_check_supply_vote(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px")) {
|
||||||
|
ret = msm_cdc_disable_ondemand_supply(wcd939x->dev,
|
||||||
|
wcd939x->supplies, pdata->regulator,
|
||||||
|
pdata->num_supplies, "cdc-vdd-px");
|
||||||
|
if (ret) {
|
||||||
|
dev_dbg(dev, "%s: vdd px supply suspend failed!\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wcd939x_resume(struct device *dev)
|
static int wcd939x_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
struct wcd939x_priv *wcd939x = NULL;
|
struct wcd939x_priv *wcd939x = NULL;
|
||||||
struct wcd939x_pdata *pdata = NULL;
|
struct wcd939x_pdata *pdata = NULL;
|
||||||
|
|
||||||
@@ -5432,6 +5463,21 @@ static int wcd939x_resume(struct device *dev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msm_cdc_is_ondemand_supply(wcd939x->dev, wcd939x->supplies, pdata->regulator,
|
||||||
|
pdata->num_supplies, "cdc-vdd-px")) {
|
||||||
|
if (msm_cdc_supply_supports_retention_mode(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px") &&
|
||||||
|
!msm_cdc_check_supply_vote(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px")) {
|
||||||
|
ret = msm_cdc_enable_ondemand_supply(wcd939x->dev, wcd939x->supplies,
|
||||||
|
pdata->regulator, pdata->num_supplies, "cdc-vdd-px");
|
||||||
|
if (ret) {
|
||||||
|
dev_dbg(dev, "%s: vdd px supply resume failed!\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (test_bit(WCD_SUPPLIES_LPM_MODE, &wcd939x->status_mask)) {
|
if (test_bit(WCD_SUPPLIES_LPM_MODE, &wcd939x->status_mask)) {
|
||||||
msm_cdc_set_supplies_lpm_mode(wcd939x->dev,
|
msm_cdc_set_supplies_lpm_mode(wcd939x->dev,
|
||||||
wcd939x->supplies,
|
wcd939x->supplies,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* Copyright (c) 2016, 2018-2020 The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2016, 2018-2020 The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CODEC_POWER_SUPPLY_H__
|
#ifndef __CODEC_POWER_SUPPLY_H__
|
||||||
@@ -16,6 +17,8 @@ struct cdc_regulator {
|
|||||||
int optimum_uA;
|
int optimum_uA;
|
||||||
bool ondemand;
|
bool ondemand;
|
||||||
bool lpm_supported;
|
bool lpm_supported;
|
||||||
|
bool rem_supported;
|
||||||
|
bool vote;
|
||||||
struct regulator *regulator;
|
struct regulator *regulator;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,6 +35,14 @@ extern bool msm_cdc_is_ondemand_supply(struct device *dev,
|
|||||||
struct regulator_bulk_data *supplies,
|
struct regulator_bulk_data *supplies,
|
||||||
struct cdc_regulator *cdc_vreg,
|
struct cdc_regulator *cdc_vreg,
|
||||||
int num_supplies, char *supply_name);
|
int num_supplies, char *supply_name);
|
||||||
|
extern bool msm_cdc_supply_supports_retention_mode(struct device *dev,
|
||||||
|
struct regulator_bulk_data *supplies,
|
||||||
|
struct cdc_regulator *cdc_vreg,
|
||||||
|
int num_supplies, char *supply_name);
|
||||||
|
extern bool msm_cdc_check_supply_vote(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,
|
extern int msm_cdc_disable_ondemand_supply(struct device *dev,
|
||||||
struct regulator_bulk_data *supplies,
|
struct regulator_bulk_data *supplies,
|
||||||
struct cdc_regulator *cdc_vreg,
|
struct cdc_regulator *cdc_vreg,
|
||||||
|
Reference in New Issue
Block a user