ASoC: wcd9xxx: Enhance class H controller to support dynamic CP voltage
Codecs can operate at a lower voltage for vdd_buck, whereas
this voltage source being shared, it is not guaranteed that the
codec will always receive exactly the requested voltage. Add support
to class H controller to handle dynamic switching of the chargepump
voltage.
Change-Id: I68f93e0b070ec51db9b958f56c797edb5cbe0c85
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b31c7c9..7b896c2 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4273,6 +4273,12 @@
*/
TAPAN_REG_VAL(TAPAN_A_MICB_2_MBHC, 0x41),
+ /*
+ * Default register settings to support dynamic change of
+ * vdd_buck between 1.8 volts and 2.15 volts.
+ */
+ TAPAN_REG_VAL(TAPAN_A_BUCK_MODE_2, 0xAA),
+
};
static const struct tapan_reg_mask_val tapan_2_x_reg_reset_values[] = {
@@ -4589,6 +4595,30 @@
return 0;
}
+static enum wcd9xxx_buck_volt tapan_codec_get_buck_mv(
+ struct snd_soc_codec *codec)
+{
+ int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (!strncmp(pdata->regulator[i].name,
+ WCD9XXX_SUPPLY_BUCK_NAME,
+ sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
+ if ((pdata->regulator[i].min_uV ==
+ WCD9XXX_CDC_BUCK_MV_1P8) ||
+ (pdata->regulator[i].min_uV ==
+ WCD9XXX_CDC_BUCK_MV_2P15))
+ buck_volt = pdata->regulator[i].min_uV;
+ break;
+ }
+ }
+ pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
+ return buck_volt;
+}
+
static int tapan_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -4621,10 +4651,6 @@
snd_soc_codec_set_drvdata(codec, tapan);
- /* TODO: Read buck voltage from DT property */
- tapan->clsh_d.buck_mv = WCD9XXX_CDC_BUCK_MV_1P8;
- wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
-
/* codec resmgr module init */
wcd9xxx = codec->control_data;
pdata = dev_get_platdata(codec->dev->parent);
@@ -4635,6 +4661,16 @@
return ret;
}
+ tapan->clsh_d.buck_mv = tapan_codec_get_buck_mv(codec);
+ /*
+ * If 1.8 volts is requested on the vdd_cp line, then
+ * assume that S4 is in a dynamically switchable state
+ * and can switch between 1.8 volts and 2.15 volts
+ */
+ if (tapan->clsh_d.buck_mv == WCD9XXX_CDC_BUCK_MV_1P8)
+ tapan->clsh_d.is_dynamic_vdd_cp = true;
+ wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
+
if (TAPAN_IS_1_0(control->version))
rco_clk_rate = TAPAN_MCLK_CLK_12P288MHZ;
else
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 516ac4f..611a293 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -6389,6 +6389,8 @@
}
taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
+ /* Taiko does not support dynamic switching of vdd_cp */
+ taiko->clsh_d.is_dynamic_vdd_cp = false;
wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
if (TAIKO_IS_1_0(core->version))
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index 916ff1a..b89afa9 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -221,20 +221,26 @@
usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US);
}
-static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec)
+
+/* This will be called for all states except Lineout */
+static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *cdc_clsh_d)
{
int i;
const struct wcd9xxx_reg_mask_val reg_set[] = {
{WCD9XXX_A_BUCK_MODE_5, 0x02, 0x00},
{WCD9XXX_A_NCP_STATIC, 0x20, 0x00},
{WCD9XXX_A_BUCK_MODE_3, 0x04, 0x04},
- {WCD9XXX_A_BUCK_MODE_3, 0x08, 0x08},
};
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
snd_soc_update_bits(codec, reg_set[i].reg,
reg_set[i].mask, reg_set[i].val);
+ if (!cdc_clsh_d->is_dynamic_vdd_cp)
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_3,
+ 0x08, 0x08);
+
dev_dbg(codec->dev, "%s: completed clsh mode settings after PA enable\n",
__func__);
@@ -557,7 +563,7 @@
} else if (req_state != WCD9XXX_CLSH_STATE_LO) {
- wcd9xxx_clsh_enable_post_pa(codec);
+ wcd9xxx_clsh_enable_post_pa(codec, cdc_clsh_d);
}
break;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 316742d..50381c9 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -52,6 +52,7 @@
struct wcd9xxx_clsh_cdc_data {
u8 state;
int buck_mv;
+ bool is_dynamic_vdd_cp;
struct wcd9xxx_resmgr *resmgr;
};