diff options
-rw-r--r-- | sound/soc/codecs/da7210.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 4aad01c10c53..e9ee6a4faa26 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -26,11 +26,15 @@ | |||
26 | #include <sound/tlv.h> | 26 | #include <sound/tlv.h> |
27 | 27 | ||
28 | /* DA7210 register space */ | 28 | /* DA7210 register space */ |
29 | #define DA7210_CONTROL 0x01 | ||
29 | #define DA7210_STATUS 0x02 | 30 | #define DA7210_STATUS 0x02 |
30 | #define DA7210_STARTUP1 0x03 | 31 | #define DA7210_STARTUP1 0x03 |
31 | #define DA7210_MIC_L 0x07 | 32 | #define DA7210_MIC_L 0x07 |
32 | #define DA7210_MIC_R 0x08 | 33 | #define DA7210_MIC_R 0x08 |
34 | #define DA7210_AUX1_L 0x09 | ||
35 | #define DA7210_AUX1_R 0x0A | ||
33 | #define DA7210_AUX2 0x0B | 36 | #define DA7210_AUX2 0x0B |
37 | #define DA7210_IN_GAIN 0x0C | ||
34 | #define DA7210_INMIX_L 0x0D | 38 | #define DA7210_INMIX_L 0x0D |
35 | #define DA7210_INMIX_R 0x0E | 39 | #define DA7210_INMIX_R 0x0E |
36 | #define DA7210_ADC_HPF 0x0F | 40 | #define DA7210_ADC_HPF 0x0F |
@@ -59,6 +63,12 @@ | |||
59 | #define DA7210_PLL_DIV2 0x2A | 63 | #define DA7210_PLL_DIV2 0x2A |
60 | #define DA7210_PLL_DIV3 0x2B | 64 | #define DA7210_PLL_DIV3 0x2B |
61 | #define DA7210_PLL 0x2C | 65 | #define DA7210_PLL 0x2C |
66 | #define DA7210_ALC_MAX 0x83 | ||
67 | #define DA7210_ALC_MIN 0x84 | ||
68 | #define DA7210_ALC_NOIS 0x85 | ||
69 | #define DA7210_ALC_ATT 0x86 | ||
70 | #define DA7210_ALC_REL 0x87 | ||
71 | #define DA7210_ALC_DEL 0x88 | ||
62 | #define DA7210_A_HID_UNLOCK 0x8A | 72 | #define DA7210_A_HID_UNLOCK 0x8A |
63 | #define DA7210_A_TEST_UNLOCK 0x8B | 73 | #define DA7210_A_TEST_UNLOCK 0x8B |
64 | #define DA7210_A_PLL1 0x90 | 74 | #define DA7210_A_PLL1 0x90 |
@@ -81,6 +91,7 @@ | |||
81 | #define DA7210_IN_R_EN (1 << 7) | 91 | #define DA7210_IN_R_EN (1 << 7) |
82 | 92 | ||
83 | /* ADC bit fields */ | 93 | /* ADC bit fields */ |
94 | #define DA7210_ADC_ALC_EN (1 << 0) | ||
84 | #define DA7210_ADC_L_EN (1 << 3) | 95 | #define DA7210_ADC_L_EN (1 << 3) |
85 | #define DA7210_ADC_R_EN (1 << 7) | 96 | #define DA7210_ADC_R_EN (1 << 7) |
86 | 97 | ||
@@ -150,6 +161,29 @@ | |||
150 | /* SOFTMUTE bit fields */ | 161 | /* SOFTMUTE bit fields */ |
151 | #define DA7210_RAMP_EN (1 << 6) | 162 | #define DA7210_RAMP_EN (1 << 6) |
152 | 163 | ||
164 | /* CONTROL bit fields */ | ||
165 | #define DA7210_NOISE_SUP_EN (1 << 3) | ||
166 | |||
167 | /* IN_GAIN bit fields */ | ||
168 | #define DA7210_INPGA_L_VOL (0x0F << 0) | ||
169 | #define DA7210_INPGA_R_VOL (0xF0 << 0) | ||
170 | |||
171 | /* ZERO_CROSS bit fields */ | ||
172 | #define DA7210_AUX1_L_ZC (1 << 0) | ||
173 | #define DA7210_AUX1_R_ZC (1 << 1) | ||
174 | #define DA7210_HP_L_ZC (1 << 6) | ||
175 | #define DA7210_HP_R_ZC (1 << 7) | ||
176 | |||
177 | /* AUX1_L bit fields */ | ||
178 | #define DA7210_AUX1_L_VOL (0x3F << 0) | ||
179 | |||
180 | /* AUX1_R bit fields */ | ||
181 | #define DA7210_AUX1_R_VOL (0x3F << 0) | ||
182 | |||
183 | /* Minimum INPGA and AUX1 volume to enable noise suppression */ | ||
184 | #define DA7210_INPGA_MIN_VOL_NS 0x0A /* 10.5dB */ | ||
185 | #define DA7210_AUX1_MIN_VOL_NS 0x35 /* 6dB */ | ||
186 | |||
153 | #define DA7210_VERSION "0.0.1" | 187 | #define DA7210_VERSION "0.0.1" |
154 | 188 | ||
155 | /* | 189 | /* |
@@ -202,6 +236,69 @@ static const char *da7210_hp_mode_txt[] = { | |||
202 | static const struct soc_enum da7210_hp_mode_sel = | 236 | static const struct soc_enum da7210_hp_mode_sel = |
203 | SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); | 237 | SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); |
204 | 238 | ||
239 | /* ALC can be enabled only if noise suppression is disabled */ | ||
240 | static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, | ||
241 | struct snd_ctl_elem_value *ucontrol) | ||
242 | { | ||
243 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
244 | |||
245 | if (ucontrol->value.integer.value[0]) { | ||
246 | /* Check if noise suppression is enabled */ | ||
247 | if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { | ||
248 | dev_dbg(codec->dev, | ||
249 | "Disable noise suppression to enable ALC\n"); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | } | ||
253 | /* If all conditions are met or we are actually disabling ALC */ | ||
254 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
255 | } | ||
256 | |||
257 | /* Noise suppression can be enabled only if following conditions are met | ||
258 | * ALC disabled | ||
259 | * ZC enabled for HP and AUX1 PGA | ||
260 | * INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB | ||
261 | * AUX1_L_VOL and AUX1_R_VOL >= 6 dB | ||
262 | */ | ||
263 | static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol, | ||
264 | struct snd_ctl_elem_value *ucontrol) | ||
265 | { | ||
266 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
267 | u8 val; | ||
268 | |||
269 | if (ucontrol->value.integer.value[0]) { | ||
270 | /* Check if ALC is enabled */ | ||
271 | if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN) | ||
272 | goto err; | ||
273 | |||
274 | /* Check ZC for HP and AUX1 PGA */ | ||
275 | if ((snd_soc_read(codec, DA7210_ZERO_CROSS) & | ||
276 | (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | | ||
277 | DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC | | ||
278 | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) | ||
279 | goto err; | ||
280 | |||
281 | /* Check INPGA_L_VOL and INPGA_R_VOL */ | ||
282 | val = snd_soc_read(codec, DA7210_IN_GAIN); | ||
283 | if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) || | ||
284 | (((val & DA7210_INPGA_R_VOL) >> 4) < | ||
285 | DA7210_INPGA_MIN_VOL_NS)) | ||
286 | goto err; | ||
287 | |||
288 | /* Check AUX1_L_VOL and AUX1_R_VOL */ | ||
289 | if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < | ||
290 | DA7210_AUX1_MIN_VOL_NS) || | ||
291 | ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < | ||
292 | DA7210_AUX1_MIN_VOL_NS)) | ||
293 | goto err; | ||
294 | } | ||
295 | /* If all conditions are met or we are actually disabling Noise sup */ | ||
296 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
297 | |||
298 | err: | ||
299 | return -EINVAL; | ||
300 | } | ||
301 | |||
205 | static const struct snd_kcontrol_new da7210_snd_controls[] = { | 302 | static const struct snd_kcontrol_new da7210_snd_controls[] = { |
206 | 303 | ||
207 | SOC_DOUBLE_R_TLV("HeadPhone Playback Volume", | 304 | SOC_DOUBLE_R_TLV("HeadPhone Playback Volume", |
@@ -260,6 +357,19 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = { | |||
260 | SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0), | 357 | SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0), |
261 | 358 | ||
262 | SOC_ENUM("Headphone Class", da7210_hp_mode_sel), | 359 | SOC_ENUM("Headphone Class", da7210_hp_mode_sel), |
360 | |||
361 | /* ALC controls */ | ||
362 | SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0, | ||
363 | snd_soc_get_volsw, da7210_put_alc_sw), | ||
364 | SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0), | ||
365 | SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0), | ||
366 | SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0), | ||
367 | SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0), | ||
368 | SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0), | ||
369 | SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0), | ||
370 | |||
371 | SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1, | ||
372 | 0, snd_soc_get_volsw, da7210_put_noise_sup_sw), | ||
263 | }; | 373 | }; |
264 | 374 | ||
265 | /* Codec private data */ | 375 | /* Codec private data */ |