ASoC: wcd934x: Add support for codec MCLK2 enablement

Add support to enable codec MCLK2 which is used for
44.1KHz and its multiples sample rate audio playback.

CRs-Fixed: 1054643
Change-Id: Id157439b2a46ac4fa54b4a768f9555cf390399b5
Signed-off-by: Phani Kumar Uppalapati <phaniu@codeaurora.org>
This commit is contained in:
Phani Kumar Uppalapati 2016-08-10 23:59:41 -07:00 committed by Gerrit - the friendly Code Review server
parent 6ed085d498
commit 2071a4cd7d

View file

@ -492,6 +492,8 @@ struct tavil_priv {
/* SVS voting related */ /* SVS voting related */
struct mutex svs_mutex; struct mutex svs_mutex;
int svs_ref_cnt; int svs_ref_cnt;
int native_clk_users;
}; };
static const struct tavil_reg_mask_val tavil_spkr_default[] = { static const struct tavil_reg_mask_val tavil_spkr_default[] = {
@ -2198,6 +2200,62 @@ done:
return rc; return rc;
} }
static int tavil_enable_native_supply(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (++tavil->native_clk_users == 1) {
snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
0x01, 0x01);
/* Sleep 100 us as per HW sequence */
usleep_range(100, 120);
snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
0x06, 0x02);
snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
0x01, 0x01);
snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
0x04, 0x00);
/* Sleep 30 us as per HW sequence */
usleep_range(30, 50);
snd_soc_update_bits(codec,
WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
0x02, 0x02);
snd_soc_update_bits(codec,
WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
0x10, 0x10);
}
break;
case SND_SOC_DAPM_PRE_PMD:
if (tavil->native_clk_users &&
(--tavil->native_clk_users == 0)) {
snd_soc_update_bits(codec,
WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
0x10, 0x00);
snd_soc_update_bits(codec,
WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
0x02, 0x00);
snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
0x04, 0x04);
snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
0x01, 0x00);
snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
0x06, 0x00);
snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
0x01, 0x00);
}
break;
}
dev_dbg(codec->dev, "%s: native_clk_users: %d, event: %d\n",
__func__, tavil->native_clk_users, event);
return 0;
}
static int tavil_codec_enable_interpolator(struct snd_soc_dapm_widget *w, static int tavil_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, struct snd_kcontrol *kcontrol,
int event) int event)
@ -5050,6 +5108,26 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
tavil_codec_enable_rx_bias, tavil_codec_enable_rx_bias,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("RX INT1 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_HPHL, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("RX INT2 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_HPHR, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("RX INT3 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_LO1, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("RX INT4 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_LO2, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("RX INT7 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_SPKR1, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("RX INT8 NATIVE SUPPLY", SND_SOC_NOPM,
INTERP_SPKR2, 0, tavil_enable_native_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
}; };
static int tavil_get_channel_map(struct snd_soc_dai *dai, static int tavil_get_channel_map(struct snd_soc_dai *dai,
@ -5801,6 +5879,31 @@ static const struct wcd_resmgr_cb tavil_resmgr_cb = {
.cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl, .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
}; };
static const struct tavil_reg_mask_val tavil_codec_mclk2_defaults[] = {
/*
* PLL Settings:
* Clock Root: MCLK2,
* Clock Source: EXT_CLK,
* Clock Destination: MCLK2
* Clock Freq In: 19.2MHz,
* Clock Freq Out: 11.2896MHz
*/
{WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
{WCD934X_CLK_SYS_INT_POST_DIV_REG0, 0xFF, 0x5E},
{WCD934X_CLK_SYS_INT_POST_DIV_REG1, 0x1F, 0x1F},
{WCD934X_CLK_SYS_INT_REF_DIV_REG0, 0xFF, 0x54},
{WCD934X_CLK_SYS_INT_REF_DIV_REG1, 0xFF, 0x01},
{WCD934X_CLK_SYS_INT_FILTER_REG1, 0x07, 0x04},
{WCD934X_CLK_SYS_INT_PLL_L_VAL, 0xFF, 0x93},
{WCD934X_CLK_SYS_INT_PLL_N_VAL, 0xFF, 0xFA},
{WCD934X_CLK_SYS_INT_TEST_REG0, 0xFF, 0x90},
{WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG, 0xFF, 0x7E},
{WCD934X_CLK_SYS_INT_VCO_PROG, 0xFF, 0xF8},
{WCD934X_CLK_SYS_INT_TEST_REG1, 0xFF, 0x68},
{WCD934X_CLK_SYS_INT_LDO_LOCK_CFG, 0xFF, 0x40},
{WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG, 0xFF, 0x32},
};
static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = { static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
{WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75}, {WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
{WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */ {WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
@ -6248,6 +6351,18 @@ struct wcd934x_mbhc *tavil_soc_get_mbhc(struct snd_soc_codec *codec)
} }
EXPORT_SYMBOL(tavil_soc_get_mbhc); EXPORT_SYMBOL(tavil_soc_get_mbhc);
static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil)
{
int i;
struct snd_soc_codec *codec = tavil->codec;
/* MCLK2 configuration */
for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_defaults); i++)
snd_soc_update_bits(codec, tavil_codec_mclk2_defaults[i].reg,
tavil_codec_mclk2_defaults[i].mask,
tavil_codec_mclk2_defaults[i].val);
}
static int tavil_soc_codec_probe(struct snd_soc_codec *codec) static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
{ {
struct wcd9xxx *control; struct wcd9xxx *control;
@ -6366,6 +6481,9 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork, INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork,
tavil_tx_mute_update_callback); tavil_tx_mute_update_callback);
} }
tavil_mclk2_reg_defaults(tavil);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
tavil_wdsp_initialize(codec); tavil_wdsp_initialize(codec);