diff options
author | Laxminath Kasam <lkasam@codeaurora.org> | 2016-06-24 22:48:48 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-08-17 09:19:07 -0700 |
commit | 9acf4ffae1418375692efeaad8e17899f8f24db1 (patch) | |
tree | 3529d8b4319e4248a2a60926e8e5e0bdaf8dd9b5 | |
parent | 6391697ab216ab43904d3d5735359213747f6ca9 (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>
-rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x.c | 62 | ||||
-rw-r--r-- | sound/soc/codecs/wcd9xxx-resmgr-v2.c | 45 |
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, |