ASoC: codecs: ES8326: Adding new volume kcontrols
authorZhu Ning <zhuning0077@gmail.com>
Wed, 24 Jan 2024 06:48:06 +0000 (14:48 +0800)
committerMark Brown <broonie@kernel.org>
Wed, 24 Jan 2024 18:28:25 +0000 (18:28 +0000)
ES8326 features a headphone volume control register and four DAC
volume control registers.
We add new volume Kcontrols for these registers to enhance the
configurability of the volume settings, providing users with
greater flexibility.

Signed-off-by: Zhu Ning <zhuning0077@gmail.com>
Link: https://msgid.link/r/20240124064806.30511-2-zhuning0077@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/es8326.c
sound/soc/codecs/es8326.h

index cbcd02e..608862a 100644 (file)
@@ -36,6 +36,8 @@ struct es8326_priv {
        u8 jack_pol;
        u8 interrupt_src;
        u8 interrupt_clk;
+       u8 hpl_vol;
+       u8 hpr_vol;
        bool jd_inverted;
        unsigned int sysclk;
 
@@ -121,6 +123,72 @@ static int es8326_crosstalk2_set(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int es8326_hplvol_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+       ucontrol->value.integer.value[0] = es8326->hpl_vol;
+
+       return 0;
+}
+
+static int es8326_hplvol_set(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+       unsigned int hp_vol;
+
+       hp_vol = ucontrol->value.integer.value[0];
+       if (hp_vol > 5)
+               return -EINVAL;
+       if (es8326->hpl_vol != hp_vol) {
+               es8326->hpl_vol = hp_vol;
+               if (hp_vol >= 3)
+                       hp_vol++;
+               regmap_update_bits(es8326->regmap, ES8326_HP_VOL,
+                               0x70, (hp_vol << 4));
+               return 1;
+       }
+
+       return 0;
+}
+
+static int es8326_hprvol_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+       ucontrol->value.integer.value[0] = es8326->hpr_vol;
+
+       return 0;
+}
+
+static int es8326_hprvol_set(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+       unsigned int hp_vol;
+
+       hp_vol = ucontrol->value.integer.value[0];
+       if (hp_vol > 5)
+               return -EINVAL;
+       if (es8326->hpr_vol != hp_vol) {
+               es8326->hpr_vol = hp_vol;
+               if (hp_vol >= 3)
+                       hp_vol++;
+               regmap_update_bits(es8326->regmap, ES8326_HP_VOL,
+                               0x07, hp_vol);
+               return 1;
+       }
+
+       return 0;
+}
+
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9550, 50, 0);
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9550, 50, 0);
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_analog_pga_tlv, 0, 300, 0);
@@ -151,15 +219,24 @@ static const char *const winsize[] = {
 static const char *const dacpol_txt[] =        {
        "Normal", "R Invert", "L Invert", "L + R Invert" };
 
+static const char *const hp_spkvol_switch[] = {
+       "HPVOL: HPL+HPL, SPKVOL: HPL+HPL",
+       "HPVOL: HPL+HPR, SPKVOL: HPL+HPR",
+       "HPVOL: HPL+HPL, SPKVOL: SPKL+SPKR",
+       "HPVOL: HPL+HPR, SPKVOL: SPKL+SPKR",
+};
+
 static const struct soc_enum dacpol =
        SOC_ENUM_SINGLE(ES8326_DAC_DSM, 4, 4, dacpol_txt);
 static const struct soc_enum alc_winsize =
        SOC_ENUM_SINGLE(ES8326_ADC_RAMPRATE, 4, 16, winsize);
 static const struct soc_enum drc_winsize =
        SOC_ENUM_SINGLE(ES8326_DRC_WINSIZE, 4, 16, winsize);
+static const struct soc_enum hpvol_spkvol_switch =
+       SOC_ENUM_SINGLE(ES8326_HP_MISC, 6, 4, hp_spkvol_switch);
 
 static const struct snd_kcontrol_new es8326_snd_controls[] = {
-       SOC_SINGLE_TLV("DAC Playback Volume", ES8326_DAC_VOL, 0, 0xbf, 0, dac_vol_tlv),
+       SOC_SINGLE_TLV("DAC Playback Volume", ES8326_DACL_VOL, 0, 0xbf, 0, dac_vol_tlv),
        SOC_ENUM("Playback Polarity", dacpol),
        SOC_SINGLE_TLV("DAC Ramp Rate", ES8326_DAC_RAMPRATE, 0, 0x0f, 0, softramp_rate),
        SOC_SINGLE_TLV("DRC Recovery Level", ES8326_DRC_RECOVERY, 0, 4, 0, drc_recovery_tlv),
@@ -182,6 +259,17 @@ static const struct snd_kcontrol_new es8326_snd_controls[] = {
                        es8326_crosstalk1_get, es8326_crosstalk1_set),
        SOC_SINGLE_EXT("CROSSTALK2", SND_SOC_NOPM, 0, 31, 0,
                        es8326_crosstalk2_get, es8326_crosstalk2_set),
+       SOC_SINGLE_EXT("HPL Volume", SND_SOC_NOPM, 0, 5, 0,
+                       es8326_hplvol_get, es8326_hplvol_set),
+       SOC_SINGLE_EXT("HPR Volume", SND_SOC_NOPM, 0, 5, 0,
+                       es8326_hprvol_get, es8326_hprvol_set),
+
+       SOC_SINGLE_TLV("HPL Playback Volume", ES8326_DACL_VOL, 0, 0xbf, 0, dac_vol_tlv),
+       SOC_SINGLE_TLV("HPR Playback Volume", ES8326_DACR_VOL, 0, 0xbf, 0, dac_vol_tlv),
+       SOC_SINGLE_TLV("SPKL Playback Volume", ES8326_SPKL_VOL, 0, 0xbf, 0, dac_vol_tlv),
+       SOC_SINGLE_TLV("SPKR Playback Volume", ES8326_SPKR_VOL, 0, 0xbf, 0, dac_vol_tlv),
+
+       SOC_ENUM("HPVol SPKVol Switch", hpvol_spkvol_switch),
 };
 
 static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = {
@@ -972,6 +1060,8 @@ static int es8326_resume(struct snd_soc_component *component)
 
        es8326->jack_remove_retry = 0;
        es8326->hp = 0;
+       es8326->hpl_vol = 0x03;
+       es8326->hpr_vol = 0x03;
        return 0;
 }
 
index 4234bbb..ee12cae 100644 (file)
@@ -69,7 +69,7 @@
 #define ES8326_DAC_DSM         0x4D
 #define ES8326_DAC_RAMPRATE    0x4E
 #define ES8326_DAC_VPPSCALE    0x4F
-#define ES8326_DAC_VOL         0x50
+#define ES8326_DACL_VOL                0x50
 #define ES8326_DRC_RECOVERY    0x53
 #define ES8326_DRC_WINSIZE     0x54
 #define ES8326_DAC_CROSSTALK   0x55
@@ -81,6 +81,9 @@
 #define ES8326_SDINOUT23_IO    0x5B
 #define ES8326_JACK_PULSE      0x5C
 
+#define ES8326_DACR_VOL                0xF4
+#define ES8326_SPKL_VOL                0xF5
+#define ES8326_SPKR_VOL                0xF6
 #define ES8326_HP_MISC         0xF7
 #define ES8326_CTIA_OMTP_STA   0xF8
 #define ES8326_PULLUP_CTL      0xF9