ASoC: cs47l15: Add IN1 mid-mode support
authorJaswinder Jassal <jjassal@opensource.wolfsonmicro.com>
Wed, 31 Aug 2016 17:30:51 +0000 (18:30 +0100)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:29 +0000 (20:22 +0300)
Change-Id: I0cab152c40a00684f45c5c1df203edcb044cb7db
Signed-off-by: Jaswinder Jassal <jjassal@opensource.wolfsonmicro.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
sound/soc/codecs/cs47l15.c

index 9e37df85ce46ccdbcc0ce08a5c23f38489d2b17f..c928667ac909f1ee35e5f53b0378e687fe3f60e7 100644 (file)
 #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],