mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
ASoC: wcd9304: Turn off mclk during clock transition
The clock is not usable when either the clock source changes between external MCLK and internal RCO or the bandgap mode changes to fast mode. In such cases, turn off master clock and turn on again later to avoid codec from going into bad state CRs-fixed: 442464 Change-Id: Id8d07bbbd4bf6c7be16016800d19ab332b960d1a Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
This commit is contained in:
parent
08436ad97a
commit
a76e7e31e0
1 changed files with 42 additions and 28 deletions
|
@ -2541,6 +2541,12 @@ static void sitar_codec_enable_bandgap(struct snd_soc_codec *codec,
|
|||
(choice == SITAR_BANDGAP_AUDIO_MODE)) {
|
||||
sitar_codec_enable_audio_mode_bandgap(codec);
|
||||
} else if (choice == SITAR_BANDGAP_MBHC_MODE) {
|
||||
/*
|
||||
* bandgap mode becomes fast,
|
||||
* mclk should be off or clk buff source shouldn't be VBG
|
||||
* Let's turn off mclk always
|
||||
*/
|
||||
WARN_ON(snd_soc_read(codec, SITAR_A_CLK_BUFF_EN2) & (1 << 2));
|
||||
snd_soc_update_bits(codec, SITAR_A_BIAS_CURR_CTL_2, 0x0C, 0x08);
|
||||
snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x2,
|
||||
0x2);
|
||||
|
@ -2576,23 +2582,23 @@ static int sitar_codec_enable_config_mode(struct snd_soc_codec *codec,
|
|||
{
|
||||
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable = %d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x10, 0);
|
||||
/* bandgap mode to fast */
|
||||
snd_soc_write(codec, SITAR_A_BIAS_OSC_BG_CTL, 0x17);
|
||||
usleep_range(5, 5);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x80,
|
||||
0x80);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_TEST, 0x80,
|
||||
0x80);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x80, 0x80);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_TEST, 0x80, 0x80);
|
||||
usleep_range(10, 10);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_TEST, 0x80, 0);
|
||||
usleep_range(20, 20);
|
||||
usleep_range(10000, 10000);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x08);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, SITAR_A_BIAS_OSC_BG_CTL, 0x1,
|
||||
0);
|
||||
snd_soc_update_bits(codec, SITAR_A_BIAS_OSC_BG_CTL, 0x1, 0);
|
||||
snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x80, 0);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
|
||||
/* clk source to ext clk and clk buff ref to VBG */
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x0C, 0x04);
|
||||
}
|
||||
sitar->config_mode_active = enable ? true : false;
|
||||
|
||||
|
@ -2606,23 +2612,28 @@ static int sitar_codec_enable_clock_block(struct snd_soc_codec *codec,
|
|||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
/* transit to RCO requires mclk off */
|
||||
WARN_ON(snd_soc_read(codec, SITAR_A_CLK_BUFF_EN2) & (1 << 2));
|
||||
if (config_mode) {
|
||||
/* enable RCO and switch to it */
|
||||
sitar_codec_enable_config_mode(codec, 1);
|
||||
snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x00);
|
||||
snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
|
||||
snd_soc_write(codec, SITAR_A_CLK_BUFF_EN1, 0x0D);
|
||||
usleep_range(1000, 1000);
|
||||
} else
|
||||
} else {
|
||||
/* switch to MCLK */
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
|
||||
|
||||
if (!config_mode && sitar->mbhc_polling_active) {
|
||||
snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
|
||||
sitar_codec_enable_config_mode(codec, 0);
|
||||
|
||||
if (sitar->mbhc_polling_active) {
|
||||
snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
|
||||
sitar_codec_enable_config_mode(codec, 0);
|
||||
}
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
|
||||
/* on MCLK */
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
|
||||
usleep_range(50, 50);
|
||||
sitar->clock_active = true;
|
||||
|
@ -2633,9 +2644,10 @@ static void sitar_codec_disable_clock_block(struct snd_soc_codec *codec)
|
|||
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
|
||||
pr_debug("%s\n", __func__);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
|
||||
ndelay(160);
|
||||
usleep_range(50, 50);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x00);
|
||||
usleep_range(50, 50);
|
||||
sitar->clock_active = false;
|
||||
}
|
||||
|
||||
|
@ -2754,16 +2766,18 @@ int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
|
|||
if (mclk_enable) {
|
||||
sitar->mclk_enabled = true;
|
||||
|
||||
if (sitar->mbhc_polling_active && (sitar->mclk_enabled)) {
|
||||
if (sitar->mbhc_polling_active) {
|
||||
sitar_codec_pause_hs_polling(codec);
|
||||
sitar_codec_disable_clock_block(codec);
|
||||
sitar_codec_enable_bandgap(codec,
|
||||
SITAR_BANDGAP_AUDIO_MODE);
|
||||
SITAR_BANDGAP_AUDIO_MODE);
|
||||
sitar_codec_enable_clock_block(codec, 0);
|
||||
sitar_codec_calibrate_hs_polling(codec);
|
||||
sitar_codec_start_hs_polling(codec);
|
||||
} else {
|
||||
sitar_codec_disable_clock_block(codec);
|
||||
sitar_codec_enable_bandgap(codec,
|
||||
SITAR_BANDGAP_AUDIO_MODE);
|
||||
SITAR_BANDGAP_AUDIO_MODE);
|
||||
sitar_codec_enable_clock_block(codec, 0);
|
||||
}
|
||||
} else {
|
||||
|
@ -2777,21 +2791,20 @@ int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
|
|||
sitar->mclk_enabled = false;
|
||||
|
||||
if (sitar->mbhc_polling_active) {
|
||||
if (!sitar->mclk_enabled) {
|
||||
sitar_codec_pause_hs_polling(codec);
|
||||
sitar_codec_enable_bandgap(codec,
|
||||
SITAR_BANDGAP_MBHC_MODE);
|
||||
sitar_enable_rx_bias(codec, 1);
|
||||
sitar_codec_enable_clock_block(codec, 1);
|
||||
sitar_codec_calibrate_hs_polling(codec);
|
||||
sitar_codec_start_hs_polling(codec);
|
||||
}
|
||||
sitar_codec_pause_hs_polling(codec);
|
||||
sitar_codec_disable_clock_block(codec);
|
||||
sitar_codec_enable_bandgap(codec,
|
||||
SITAR_BANDGAP_MBHC_MODE);
|
||||
sitar_enable_rx_bias(codec, 1);
|
||||
sitar_codec_enable_clock_block(codec, 1);
|
||||
sitar_codec_calibrate_hs_polling(codec);
|
||||
sitar_codec_start_hs_polling(codec);
|
||||
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1,
|
||||
0x05, 0x01);
|
||||
} else {
|
||||
sitar_codec_disable_clock_block(codec);
|
||||
sitar_codec_enable_bandgap(codec,
|
||||
SITAR_BANDGAP_OFF);
|
||||
SITAR_BANDGAP_OFF);
|
||||
}
|
||||
}
|
||||
if (dapm)
|
||||
|
@ -3437,6 +3450,7 @@ static short sitar_codec_setup_hs_polling(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
if (!sitar->mclk_enabled) {
|
||||
sitar_codec_disable_clock_block(codec);
|
||||
sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_MBHC_MODE);
|
||||
sitar_enable_rx_bias(codec, 1);
|
||||
sitar_codec_enable_clock_block(codec, 1);
|
||||
|
|
Loading…
Reference in a new issue