[alsa-devel] [PATCH v5 2/2] ASoC: da7210: Add support for ALC and Noise suppression

Girdwood, Liam lrg at ti.com
Wed Oct 19 09:57:57 CEST 2011


On 18 October 2011 14:43, Ashish Chavan <ashish.chavan at kpitcummins.com> wrote:
> This patch adds controls to set following ALC parameters,
>  - Max gain, Min gain, Noise gain, Attack rate, Release rate and delay
>
> It also adds a switch to enable/disable noise suppression.
>
> As per DA7210 data sheet, ALC and noise suppression can be enabled
> only if certain conditions are met. This condition checks are handled
> by simply using "_EXT" version of controls to capture change events.
>
> Signed-off-by: Ashish Chavan <ashish.chavan at kpitcummins.com>
> Signed-off-by: David Dajun Chen <dchen at diasemi.com>
> ---
> Changes since v1:
> - Reading from register instead of cache
> - Made debug message more specific about error
> - Changed "Gain" to "Volume" in names of ALC controls
> ---
>  sound/soc/codecs/da7210.c |  109 +++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 109 insertions(+), 0 deletions(-)
>
> diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
> index a31be70..edcfc36 100644
> --- a/sound/soc/codecs/da7210.c
> +++ b/sound/soc/codecs/da7210.c
> @@ -26,11 +26,15 @@
>  #include <sound/tlv.h>
>
>  /* DA7210 register space */
> +#define DA7210_CONTROL                 0x01
>  #define DA7210_STATUS                  0x02
>  #define DA7210_STARTUP1                        0x03
>  #define DA7210_MIC_L                   0x07
>  #define DA7210_MIC_R                   0x08
> +#define DA7210_AUX1_L                  0x09
> +#define DA7210_AUX1_R                  0x0A
>  #define DA7210_AUX2                    0x0B
> +#define DA7210_IN_GAIN                 0x0C
>  #define DA7210_INMIX_L                 0x0D
>  #define DA7210_INMIX_R                 0x0E
>  #define DA7210_ADC_HPF                 0x0F
> @@ -59,6 +63,12 @@
>  #define DA7210_PLL_DIV2                        0x2A
>  #define DA7210_PLL_DIV3                        0x2B
>  #define DA7210_PLL                     0x2C
> +#define DA7210_ALC_MAX                 0x83
> +#define DA7210_ALC_MIN                 0x84
> +#define DA7210_ALC_NOIS                        0x85
> +#define DA7210_ALC_ATT                 0x86
> +#define DA7210_ALC_REL                 0x87
> +#define DA7210_ALC_DEL                 0x88
>  #define DA7210_A_HID_UNLOCK            0x8A
>  #define DA7210_A_TEST_UNLOCK           0x8B
>  #define DA7210_A_PLL1                  0x90
> @@ -81,6 +91,7 @@
>  #define DA7210_IN_R_EN                 (1 << 7)
>
>  /* ADC bit fields */
> +#define DA7210_ADC_ALC_EN              (1 << 0)
>  #define DA7210_ADC_L_EN                        (1 << 3)
>  #define DA7210_ADC_R_EN                        (1 << 7)
>
> @@ -150,6 +161,29 @@
>  /* SOFTMUTE bit fields */
>  #define DA7210_RAMP_EN                 (1 << 6)
>
> +/* CONTROL bit fields */
> +#define DA7210_NOISE_SUP_EN            (1 << 3)
> +
> +/* IN_GAIN bit fields */
> +#define DA7210_INPGA_L_VOL             (0x0F << 0)
> +#define DA7210_INPGA_R_VOL             (0xF0 << 0)
> +
> +/* ZERO_CROSS bit fields */
> +#define DA7210_AUX1_L_ZC               (1 << 0)
> +#define DA7210_AUX1_R_ZC               (1 << 1)
> +#define DA7210_HP_L_ZC                 (1 << 6)
> +#define DA7210_HP_R_ZC                 (1 << 7)
> +
> +/* AUX1_L bit fields */
> +#define DA7210_AUX1_L_VOL              (0x3F << 0)
> +
> +/* AUX1_R bit fields */
> +#define DA7210_AUX1_R_VOL              (0x3F << 0)
> +
> +/* Minimum INPGA and AUX1 volume to enable noise suppression */
> +#define DA7210_INPGA_MIN_VOL_NS                0x0A  /* 10.5dB */
> +#define DA7210_AUX1_MIN_VOL_NS         0x35  /* 6dB */
> +
>  #define DA7210_VERSION "0.0.1"
>
>  /*
> @@ -202,6 +236,68 @@ static const char *da7210_hp_mode_txt[] = {
>  static const struct soc_enum da7210_hp_mode_sel =
>        SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
>
> +/* ALC can be enabled only if noise suppression is disabled */
> +static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
> +                            struct snd_ctl_elem_value *ucontrol)
> +{
> +       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> +       if (ucontrol->value.integer.value[0]) {
> +               /* Check if noise suppression is enabled */
> +               if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) {
> +                       dev_dbg(codec->dev,
> +                               "Disable noise suppression to enable ALC\n");
> +                       return -EPERM;

-EINVAL


> +               }
> +       }
> +       /* If all conditions are met or we are actually disabling ALC */
> +       return snd_soc_put_volsw(kcontrol, ucontrol);
> +}
> +
> +/* Noise suppression can be enabled only if following conditions are met
> + *  ALC disabled
> + *  ZC enabled for HP and AUX1 PGA
> + *  INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB
> + *  AUX1_L_VOL and AUX1_R_VOL >= 6 dB
> + */
> +static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
> +                                  struct snd_ctl_elem_value *ucontrol)
> +{
> +       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +       u8 val;
> +
> +       if (ucontrol->value.integer.value[0]) {
> +               /* Check if ALC is enabled */
> +               if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN)
> +                       goto err;
> +
> +               /* Check ZC for HP and AUX1 PGA */
> +               if ((snd_soc_read(codec, DA7210_ZERO_CROSS) &
> +                       (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC |
> +                       DA7210_HP_R_ZC)) != 0xc3)

It may be clearer if you don't use the magic number here and specify
the bits you are checking.

> +                       goto err;
> +
> +               /* Check INPGA_L_VOL and INPGA_R_VOL */
> +               val = snd_soc_read(codec, DA7210_IN_GAIN);
> +               if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) ||
> +                       (((val & DA7210_INPGA_R_VOL) >> 4) <
> +                       DA7210_INPGA_MIN_VOL_NS))
> +                       goto err;
> +
> +               /* Check AUX1_L_VOL and AUX1_R_VOL */
> +               if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) <
> +                   DA7210_AUX1_MIN_VOL_NS) ||
> +                   ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) <
> +                   DA7210_AUX1_MIN_VOL_NS))
> +                       goto err;
> +       }
> +       /* If all conditions are met or we are actually disabling Noise sup */
> +       return snd_soc_put_volsw(kcontrol, ucontrol);
> +
> +err:
> +       return -EPERM;

-EINVAL

> +}
> +
>  static const struct snd_kcontrol_new da7210_snd_controls[] = {
>
>        SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
> @@ -260,6 +356,19 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
>        SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0),
>
>        SOC_ENUM("Headphone Class", da7210_hp_mode_sel),
> +
> +       /* ALC controls */
> +       SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0,
> +                      snd_soc_get_volsw, da7210_put_alc_sw),
> +       SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0),
> +       SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0),
> +       SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0),
> +       SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0),
> +       SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0),
> +       SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0),
> +
> +       SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1,
> +                      0, snd_soc_get_volsw, da7210_put_noise_sup_sw),
>  };
>
>  /* Codec private data */
> --
> 1.7.1
>
>
>


More information about the Alsa-devel mailing list