summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorLaxminath Kasam <lkasam@codeaurora.org>2016-06-24 22:48:48 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-17 09:19:07 -0700
commit9acf4ffae1418375692efeaad8e17899f8f24db1 (patch)
tree3529d8b4319e4248a2a60926e8e5e0bdaf8dd9b5 /sound
parent6391697ab216ab43904d3d5735359213747f6ca9 (diff)
ASoC: wcd934x: Add RCO enablement support
WCD934X audio codec has internal clock (RCO) that will be used during some usecases (ex: using WCD DSP, etc). Add support in WCD934X codec and resource manager driver to provide RCO clock enable and disable functionality. CRs-Fixed: 1049012 Change-Id: I9636dad9b81aeb3a4aa5c09776026d0c2014c05b Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org> Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c62
-rw-r--r--sound/soc/codecs/wcd9xxx-resmgr-v2.c45
2 files changed, 106 insertions, 1 deletions
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index bd116ee8685c..7d30d317597f 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -5170,6 +5170,67 @@ int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
}
EXPORT_SYMBOL(tavil_cdc_mclk_enable);
+static int __tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
+ bool enable)
+{
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ if (enable) {
+ if (wcd_resmgr_get_clk_type(tavil->resmgr) ==
+ WCD_CLK_RCO) {
+ ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
+ WCD_CLK_RCO);
+ } else {
+ ret = tavil_cdc_req_mclk_enable(tavil, true);
+ if (ret) {
+ dev_err(codec->dev,
+ "%s: mclk_enable failed, err = %d\n",
+ __func__, ret);
+ goto done;
+ }
+ ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
+ WCD_CLK_RCO);
+ ret |= tavil_cdc_req_mclk_enable(tavil, false);
+ }
+
+ } else {
+ ret = wcd_resmgr_disable_clk_block(tavil->resmgr,
+ WCD_CLK_RCO);
+ }
+
+ if (ret) {
+ dev_err(codec->dev, "%s: Error in %s RCO\n",
+ __func__, (enable ? "enabling" : "disabling"));
+ ret = -EINVAL;
+ }
+
+done:
+ return ret;
+}
+
+/*
+ * tavil_codec_internal_rco_ctrl: Enable/Disable codec's RCO clock
+ * @codec: Handle to the codec
+ * @enable: Indicates whether clock should be enabled or disabled
+ */
+int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
+ bool enable)
+{
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
+ ret = __tavil_codec_internal_rco_ctrl(codec, enable);
+ WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
+ return ret;
+}
+EXPORT_SYMBOL(tavil_codec_internal_rco_ctrl);
+
+static const struct wcd_resmgr_cb tavil_resmgr_cb = {
+ .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
+};
+
static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
{WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
{WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
@@ -5218,6 +5279,7 @@ static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = {
{WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
{WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
{WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
+ {WCD934X_CODEC_RPM_CLK_GATE, 0x08, 0x00},
};
static void tavil_codec_init_reg(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.c b/sound/soc/codecs/wcd9xxx-resmgr-v2.c
index 7ea1a93d7fb7..29718a8d7c04 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr-v2.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.c
@@ -245,6 +245,8 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
* to CLK_SYS_MCLK_PRG
*/
wcd_resmgr_codec_reg_update_bits(resmgr,
+ WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x00);
+ wcd_resmgr_codec_reg_update_bits(resmgr,
WCD934X_CLK_SYS_MCLK_PRG, 0x91, 0x91);
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
@@ -297,6 +299,8 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD9335_ANA_CLK_TOP,
0x08, 0x08);
+ wcd_resmgr_codec_reg_update_bits(resmgr,
+ WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x02);
resmgr->clk_type = WCD_CLK_RCO;
} else {
wcd_resmgr_codec_reg_update_bits(resmgr,
@@ -318,6 +322,22 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
return 0;
}
+static void wcd_resmgr_set_buck_accuracy(struct wcd9xxx_resmgr_v2 *resmgr)
+{
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x02, 0x02);
+ /* 100us sleep needed after HIGH_ACCURACY_PRE_EN1 */
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x01, 0x01);
+ /* 100us sleep needed after HIGH_ACCURACY_PRE_EN2 */
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x04, 0x04);
+ /* 100us sleep needed after HIGH_ACCURACY_EN */
+ usleep_range(100, 110);
+}
+
static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
{
bool rco_cal_done = true;
@@ -333,10 +353,14 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
} else if ((resmgr->clk_rco_users == 1) &&
(resmgr->clk_mclk_users)) {
/* RCO Enable */
- if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL)
+ if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) {
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD9335_ANA_RCO,
0x80, 0x80);
+ if (resmgr->codec_type == WCD934X)
+ wcd_resmgr_set_buck_accuracy(resmgr);
+ }
+
/*
* 20us required after RCO BG is enabled as per HW
* requirements
@@ -352,8 +376,21 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
/* RCO Calibration */
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO,
0x04, 0x04);
+ if (resmgr->codec_type == WCD934X)
+ /*
+ * For wcd934x codec, 20us sleep is needed
+ * after enabling RCO calibration
+ */
+ usleep_range(20, 25);
+
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO,
0x04, 0x00);
+ if (resmgr->codec_type == WCD934X)
+ /*
+ * For wcd934x codec, 20us sleep is needed
+ * after disabling RCO calibration
+ */
+ usleep_range(20, 25);
/* RCO calibration takes app. 5ms to complete */
usleep_range(WCD9XXX_RCO_CALIBRATION_DELAY_INC_US,
@@ -368,6 +405,9 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD9335_ANA_CLK_TOP,
0x08, 0x08);
+ wcd_resmgr_codec_reg_update_bits(resmgr,
+ WCD934X_CLK_SYS_MCLK_PRG,
+ 0x02, 0x02);
resmgr->clk_type = WCD_CLK_RCO;
}
}
@@ -393,6 +433,9 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
(resmgr->clk_type == WCD_CLK_RCO)) {
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
0x08, 0x00);
+ wcd_resmgr_codec_reg_update_bits(resmgr,
+ WCD934X_CLK_SYS_MCLK_PRG,
+ 0x02, 0x00);
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
0x04, 0x00);
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO,