From 7ccda9fb5c869ba00afd3acb4205da972fc6dbc4 Mon Sep 17 00:00:00 2001 From: Jaswinder Jassal Date: Wed, 31 Aug 2016 18:30:51 +0100 Subject: [PATCH] ASoC: cs47l15: Add IN1 mid-mode support Change-Id: I0cab152c40a00684f45c5c1df203edcb044cb7db Signed-off-by: Jaswinder Jassal Signed-off-by: Charles Keepax --- sound/soc/codecs/cs47l15.c | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 9e37df85ce46..c928667ac909 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -31,9 +31,17 @@ #define CS47L15_NUM_ADSP 1 #define CS47L15_MONO_OUTPUTS 1 +/* Mid-mode registers */ +#define CS47L15_ADC_INT_BIAS_MASK 0x3800 +#define CS47L15_ADC_INT_BIAS_SHIFT 11 +#define CS47L15_PGA_BIAS_SEL_MASK 0x03 +#define CS47L15_PGA_BIAS_SEL_SHIFT 0 + struct cs47l15 { struct madera_priv core; struct madera_fll fll[2]; + + bool in1_lp_mode; }; static const struct wm_adsp_region cs47l15_dsp1_regions[] = { @@ -95,6 +103,55 @@ static int cs47l15_adsp_power_ev(struct snd_soc_dapm_widget *w, SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) +static int cs47l15_in1_adc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct cs47l15 *cs47l15 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = cs47l15->in1_lp_mode ? 1 : 0; + + return 0; +} + +static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct cs47l15 *cs47l15 = snd_soc_codec_get_drvdata(codec); + + switch (ucontrol->value.integer.value[0]) { + case 0: + /* Set IN1 to normal mode */ + snd_soc_update_bits(codec, MADERA_DMIC1L_CONTROL, + MADERA_IN1_OSR_MASK, + 5 << MADERA_IN1_OSR_SHIFT); + snd_soc_update_bits(codec, CS47L15_ADC_INT_BIAS, + CS47L15_ADC_INT_BIAS_MASK, + 4 << CS47L15_ADC_INT_BIAS_SHIFT); + snd_soc_update_bits(codec, CS47L15_PGA_BIAS_SEL, + CS47L15_PGA_BIAS_SEL_MASK, + 0); + cs47l15->in1_lp_mode = false; + break; + default: + /* Set IN1 to LP mode */ + snd_soc_update_bits(codec, MADERA_DMIC1L_CONTROL, + MADERA_IN1_OSR_MASK, + 4 << MADERA_IN1_OSR_SHIFT); + snd_soc_update_bits(codec, CS47L15_ADC_INT_BIAS, + CS47L15_ADC_INT_BIAS_MASK, + 1 << CS47L15_ADC_INT_BIAS_SHIFT); + snd_soc_update_bits(codec, CS47L15_PGA_BIAS_SEL, + CS47L15_PGA_BIAS_SEL_MASK, + 3 << CS47L15_PGA_BIAS_SEL_SHIFT); + cs47l15->in1_lp_mode = true; + break; + } + + return 0; +} + static const struct snd_kcontrol_new cs47l15_snd_controls[] = { SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), @@ -275,6 +332,9 @@ SOC_ENUM_EXT("IN1L Rate", madera_input_rate[0], SOC_ENUM_EXT("IN1R Rate", madera_input_rate[1], snd_soc_get_enum_double, madera_in_rate_put), +SOC_SINGLE_BOOL_EXT("IN1 LP Mode Switch", 0, + cs47l15_in1_adc_get, cs47l15_in1_adc_put), + SOC_ENUM_EXT("IN2L Rate", madera_input_rate[2], snd_soc_get_enum_double, madera_in_rate_put), SOC_ENUM_EXT("IN2R Rate", madera_input_rate[3], -- 2.20.1