ASoC: da7210: Add support for ALC and Noise suppression
Subsystems (3)
PATCH v5 2/2 ASoC: da7210: Add support for ALC and Noise suppression
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.
---
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(-)
sound/soc/codecs/da7210.c +109 -0
@@ -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 ; + } + } +/* 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 ) + 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 ; +} +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 */
Signature · 1 line
1.7.1
Quoted 97 lines · Ashish Chavan
This patch adds controls to set following ALC parameters,
- Max gain, Min gain, Noise gain, Attack rate, Release rate and delayIt 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 <[email protected]>Signed-off-by David Dajun Chen <[email protected]>---
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(-)sound/soc/codecs/da7210.c +34
-0@@ -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_enumda7210_hp_mode_sel=SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);sound/soc/codecs/da7210.c +2
-0+/* ALC can be enabled only if noise suppression is disabled */ +static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
sound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 250
Quoted 10 lines
sound/soc/codecs/da7210.c +10
-0+ 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
Quoted 17 lines
+ }
+ }
+ /* If all conditions are met or we are actually disabling ALC */
+ returnsnd_soc_put_volsw(kcontrol, ucontrol);sound/soc/codecs/da7210.c +13
-0+} + +/* 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;
sound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 277
Quoted 10 lines
sound/soc/codecs/da7210.c +10
-0+ + 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.
Quoted 11 lines
+ goto err;
sound/soc/codecs/da7210.c +10
-0+ + /* 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) <
sound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 298
Quoted 10 lines
sound/soc/codecs/da7210.c +10
-0+ 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
Quoted 30 lines
sound/soc/codecs/da7210.c +2
-0+} +static const struct
snd_kcontrol_newda7210_snd_controls[] = {SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
sound/soc/codecs/da7210.c +13
-1@@ -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
Quoted 18 lines
sound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 250
Quoted 6 lines
sound/soc/codecs/da7210.c +6
-0+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 ;
-EINVALsound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 277
Quoted 4 lines
sound/soc/codecs/da7210.c +4
-0+/* 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.
Quoted 8 lines
sound/soc/codecs/da7210.c static const char *da7210_hp_mode_txt[] = { · line 298
Quoted 5 lines
sound/soc/codecs/da7210.c +5
-0+/* If all conditions are met or we are actually disabling Noise sup */ +return snd_soc_put_volsw (kcontrol, ucontrol); + +err: +return -EPERM ;
-EINVAL
Thanks. Updating and reposting the patch set.