Merge "ASoC: sdm845: add independent clock support on codec"
This commit is contained in:
commit
32f93e4938
3 changed files with 124 additions and 5 deletions
|
|
@ -180,6 +180,8 @@ enum {
|
|||
ANC_MIC_AMIC2,
|
||||
ANC_MIC_AMIC3,
|
||||
ANC_MIC_AMIC4,
|
||||
CLK_INTERNAL,
|
||||
CLK_MODE,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -1071,6 +1073,40 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tavil_get_clkmode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (test_bit(CLK_MODE, &tavil_p->status_mask))
|
||||
ucontrol->value.enumerated.item[0] = 1;
|
||||
else
|
||||
ucontrol->value.enumerated.item[0] = 0;
|
||||
|
||||
dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
|
||||
test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tavil_put_clkmode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0])
|
||||
set_bit(CLK_MODE, &tavil_p->status_mask);
|
||||
else
|
||||
clear_bit(CLK_MODE, &tavil_p->status_mask);
|
||||
|
||||
dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
|
||||
test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
|
@ -5576,6 +5612,9 @@ static const char *const tavil_anc_func_text[] = {"OFF", "ON"};
|
|||
static const struct soc_enum tavil_anc_func_enum =
|
||||
SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
|
||||
|
||||
static const char *const tavil_clkmode_text[] = {"EXTERNAL", "INTERNAL"};
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(tavil_clkmode_enum, tavil_clkmode_text);
|
||||
|
||||
/* Cutoff frequency for high pass filter */
|
||||
static const char * const cf_text[] = {
|
||||
"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
|
||||
|
|
@ -5755,6 +5794,9 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = {
|
|||
SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
|
||||
tavil_put_anc_func),
|
||||
|
||||
SOC_ENUM_EXT("CLK MODE", tavil_clkmode_enum, tavil_get_clkmode,
|
||||
tavil_put_clkmode),
|
||||
|
||||
SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
|
||||
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
|
||||
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
|
||||
|
|
@ -8417,6 +8459,50 @@ static int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* tavil_cdc_mclk_tx_enable: Enable/Disable codec's clock for TX path
|
||||
* @codec: Handle to codec
|
||||
* @enable: Indicates whether clock should be enabled or disabled
|
||||
*/
|
||||
int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct tavil_priv *tavil_p;
|
||||
int ret = 0;
|
||||
bool clk_mode;
|
||||
bool clk_internal;
|
||||
|
||||
if (!codec)
|
||||
return -EINVAL;
|
||||
|
||||
tavil_p = snd_soc_codec_get_drvdata(codec);
|
||||
clk_mode = test_bit(CLK_MODE, &tavil_p->status_mask);
|
||||
clk_internal = test_bit(CLK_INTERNAL, &tavil_p->status_mask);
|
||||
|
||||
dev_dbg(codec->dev, "%s: clkmode: %d, enable: %d, clk_internal: %d\n",
|
||||
__func__, clk_mode, enable, clk_internal);
|
||||
|
||||
if (clk_mode || clk_internal) {
|
||||
if (enable) {
|
||||
wcd_resmgr_enable_master_bias(tavil_p->resmgr);
|
||||
tavil_dig_core_power_collapse(tavil_p, POWER_RESUME);
|
||||
tavil_vote_svs(tavil_p, true);
|
||||
ret = tavil_codec_internal_rco_ctrl(codec, enable);
|
||||
set_bit(CLK_INTERNAL, &tavil_p->status_mask);
|
||||
} else {
|
||||
clear_bit(CLK_INTERNAL, &tavil_p->status_mask);
|
||||
tavil_codec_internal_rco_ctrl(codec, enable);
|
||||
tavil_vote_svs(tavil_p, false);
|
||||
tavil_dig_core_power_collapse(tavil_p, POWER_COLLAPSE);
|
||||
wcd_resmgr_disable_master_bias(tavil_p->resmgr);
|
||||
}
|
||||
} else {
|
||||
ret = __tavil_cdc_mclk_enable(tavil_p, enable);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tavil_cdc_mclk_tx_enable);
|
||||
|
||||
static const struct wcd_resmgr_cb tavil_resmgr_cb = {
|
||||
.cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ struct tavil_reg_mask_val {
|
|||
extern void *tavil_get_afe_config(struct snd_soc_codec *codec,
|
||||
enum afe_config_type config_type);
|
||||
extern int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable);
|
||||
extern int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable);
|
||||
extern int tavil_set_spkr_mode(struct snd_soc_codec *codec, int mode);
|
||||
extern int tavil_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset);
|
||||
extern struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev);
|
||||
|
|
|
|||
|
|
@ -538,10 +538,10 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = {
|
|||
};
|
||||
|
||||
static struct snd_soc_dapm_route wcd_audio_paths[] = {
|
||||
{"MIC BIAS1", NULL, "MCLK"},
|
||||
{"MIC BIAS2", NULL, "MCLK"},
|
||||
{"MIC BIAS3", NULL, "MCLK"},
|
||||
{"MIC BIAS4", NULL, "MCLK"},
|
||||
{"MIC BIAS1", NULL, "MCLK TX"},
|
||||
{"MIC BIAS2", NULL, "MCLK TX"},
|
||||
{"MIC BIAS3", NULL, "MCLK TX"},
|
||||
{"MIC BIAS4", NULL, "MCLK TX"},
|
||||
};
|
||||
|
||||
static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
|
||||
|
|
@ -2784,6 +2784,38 @@ static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
|
||||
int enable, bool dapm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!strcmp(dev_name(codec->dev), "tavil_codec")) {
|
||||
ret = tavil_cdc_mclk_tx_enable(codec, enable);
|
||||
} else {
|
||||
dev_err(codec->dev, "%s: unknown codec to enable TX ext clk\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_mclk_tx_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
|
||||
pr_debug("%s: event = %d\n", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_mclk_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
|
|
@ -2840,7 +2872,7 @@ static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("MCLK TX", SND_SOC_NOPM, 0, 0,
|
||||
NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
msm_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
|
||||
SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
|
||||
|
|
|
|||
Loading…
Reference in a new issue