2 * da7219.c - DA7219 ALSA SoC Codec Driver
4 * Copyright (c) 2015 Dialog Semiconductor
6 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
14 #include <linux/clk.h>
15 #include <linux/i2c.h>
16 #include <linux/of_device.h>
17 #include <linux/regmap.h>
18 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/regulator/consumer.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
26 #include <sound/soc-dapm.h>
27 #include <sound/initval.h>
28 #include <sound/tlv.h>
29 #include <asm/div64.h>
31 #include <sound/da7219.h>
33 #include "da7219-aad.h"
41 static const DECLARE_TLV_DB_SCALE(da7219_mic_gain_tlv
, -600, 600, 0);
42 static const DECLARE_TLV_DB_SCALE(da7219_mixin_gain_tlv
, -450, 150, 0);
43 static const DECLARE_TLV_DB_SCALE(da7219_adc_dig_gain_tlv
, -8325, 75, 0);
44 static const DECLARE_TLV_DB_SCALE(da7219_alc_threshold_tlv
, -9450, 150, 0);
45 static const DECLARE_TLV_DB_SCALE(da7219_alc_gain_tlv
, 0, 600, 0);
46 static const DECLARE_TLV_DB_SCALE(da7219_alc_ana_gain_tlv
, 0, 600, 0);
47 static const DECLARE_TLV_DB_SCALE(da7219_sidetone_gain_tlv
, -4200, 300, 0);
48 static const DECLARE_TLV_DB_SCALE(da7219_tonegen_gain_tlv
, -4500, 300, 0);
51 static const DECLARE_TLV_DB_SCALE(da7219_dac_eq_band_tlv
, -1050, 150, 0);
53 static const DECLARE_TLV_DB_RANGE(da7219_dac_dig_gain_tlv
,
54 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE
, 0, 1),
55 /* -77.25dB to 12dB */
56 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7725, 75, 0)
59 static const DECLARE_TLV_DB_SCALE(da7219_dac_ng_threshold_tlv
, -10200, 600, 0);
60 static const DECLARE_TLV_DB_SCALE(da7219_hp_gain_tlv
, -5700, 100, 0);
63 static const char * const da7219_alc_attack_rate_txt
[] = {
64 "7.33/fs", "14.66/fs", "29.32/fs", "58.64/fs", "117.3/fs", "234.6/fs",
65 "469.1/fs", "938.2/fs", "1876/fs", "3753/fs", "7506/fs", "15012/fs",
69 static const struct soc_enum da7219_alc_attack_rate
=
70 SOC_ENUM_SINGLE(DA7219_ALC_CTRL2
, DA7219_ALC_ATTACK_SHIFT
,
71 DA7219_ALC_ATTACK_MAX
, da7219_alc_attack_rate_txt
);
73 static const char * const da7219_alc_release_rate_txt
[] = {
74 "28.66/fs", "57.33/fs", "114.6/fs", "229.3/fs", "458.6/fs", "917.1/fs",
75 "1834/fs", "3668/fs", "7337/fs", "14674/fs", "29348/fs"
78 static const struct soc_enum da7219_alc_release_rate
=
79 SOC_ENUM_SINGLE(DA7219_ALC_CTRL2
, DA7219_ALC_RELEASE_SHIFT
,
80 DA7219_ALC_RELEASE_MAX
, da7219_alc_release_rate_txt
);
82 static const char * const da7219_alc_hold_time_txt
[] = {
83 "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs",
84 "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs",
85 "253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
88 static const struct soc_enum da7219_alc_hold_time
=
89 SOC_ENUM_SINGLE(DA7219_ALC_CTRL3
, DA7219_ALC_HOLD_SHIFT
,
90 DA7219_ALC_HOLD_MAX
, da7219_alc_hold_time_txt
);
92 static const char * const da7219_alc_env_rate_txt
[] = {
93 "1/4", "1/16", "1/256", "1/65536"
96 static const struct soc_enum da7219_alc_env_attack_rate
=
97 SOC_ENUM_SINGLE(DA7219_ALC_CTRL3
, DA7219_ALC_INTEG_ATTACK_SHIFT
,
98 DA7219_ALC_INTEG_MAX
, da7219_alc_env_rate_txt
);
100 static const struct soc_enum da7219_alc_env_release_rate
=
101 SOC_ENUM_SINGLE(DA7219_ALC_CTRL3
, DA7219_ALC_INTEG_RELEASE_SHIFT
,
102 DA7219_ALC_INTEG_MAX
, da7219_alc_env_rate_txt
);
104 static const char * const da7219_alc_anticlip_step_txt
[] = {
105 "0.034dB/fs", "0.068dB/fs", "0.136dB/fs", "0.272dB/fs"
108 static const struct soc_enum da7219_alc_anticlip_step
=
109 SOC_ENUM_SINGLE(DA7219_ALC_ANTICLIP_CTRL
,
110 DA7219_ALC_ANTICLIP_STEP_SHIFT
,
111 DA7219_ALC_ANTICLIP_STEP_MAX
,
112 da7219_alc_anticlip_step_txt
);
114 /* Input/Output Enums */
115 static const char * const da7219_gain_ramp_rate_txt
[] = {
116 "Nominal Rate * 8", "Nominal Rate", "Nominal Rate / 8",
120 static const struct soc_enum da7219_gain_ramp_rate
=
121 SOC_ENUM_SINGLE(DA7219_GAIN_RAMP_CTRL
, DA7219_GAIN_RAMP_RATE_SHIFT
,
122 DA7219_GAIN_RAMP_RATE_MAX
, da7219_gain_ramp_rate_txt
);
124 static const char * const da7219_hpf_mode_txt
[] = {
125 "Disabled", "Audio", "Voice"
128 static const unsigned int da7219_hpf_mode_val
[] = {
129 DA7219_HPF_DISABLED
, DA7219_HPF_AUDIO_EN
, DA7219_HPF_VOICE_EN
,
132 static const struct soc_enum da7219_adc_hpf_mode
=
133 SOC_VALUE_ENUM_SINGLE(DA7219_ADC_FILTERS1
, DA7219_HPF_MODE_SHIFT
,
134 DA7219_HPF_MODE_MASK
, DA7219_HPF_MODE_MAX
,
135 da7219_hpf_mode_txt
, da7219_hpf_mode_val
);
137 static const struct soc_enum da7219_dac_hpf_mode
=
138 SOC_VALUE_ENUM_SINGLE(DA7219_DAC_FILTERS1
, DA7219_HPF_MODE_SHIFT
,
139 DA7219_HPF_MODE_MASK
, DA7219_HPF_MODE_MAX
,
140 da7219_hpf_mode_txt
, da7219_hpf_mode_val
);
142 static const char * const da7219_audio_hpf_corner_txt
[] = {
143 "2Hz", "4Hz", "8Hz", "16Hz"
146 static const struct soc_enum da7219_adc_audio_hpf_corner
=
147 SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1
,
148 DA7219_ADC_AUDIO_HPF_CORNER_SHIFT
,
149 DA7219_AUDIO_HPF_CORNER_MAX
,
150 da7219_audio_hpf_corner_txt
);
152 static const struct soc_enum da7219_dac_audio_hpf_corner
=
153 SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1
,
154 DA7219_DAC_AUDIO_HPF_CORNER_SHIFT
,
155 DA7219_AUDIO_HPF_CORNER_MAX
,
156 da7219_audio_hpf_corner_txt
);
158 static const char * const da7219_voice_hpf_corner_txt
[] = {
159 "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
162 static const struct soc_enum da7219_adc_voice_hpf_corner
=
163 SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1
,
164 DA7219_ADC_VOICE_HPF_CORNER_SHIFT
,
165 DA7219_VOICE_HPF_CORNER_MAX
,
166 da7219_voice_hpf_corner_txt
);
168 static const struct soc_enum da7219_dac_voice_hpf_corner
=
169 SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1
,
170 DA7219_DAC_VOICE_HPF_CORNER_SHIFT
,
171 DA7219_VOICE_HPF_CORNER_MAX
,
172 da7219_voice_hpf_corner_txt
);
174 static const char * const da7219_tonegen_dtmf_key_txt
[] = {
175 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D",
179 static const struct soc_enum da7219_tonegen_dtmf_key
=
180 SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG1
, DA7219_DTMF_REG_SHIFT
,
181 DA7219_DTMF_REG_MAX
, da7219_tonegen_dtmf_key_txt
);
183 static const char * const da7219_tonegen_swg_sel_txt
[] = {
184 "Sum", "SWG1", "SWG2", "SWG1_1-Cos"
187 static const struct soc_enum da7219_tonegen_swg_sel
=
188 SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG2
, DA7219_SWG_SEL_SHIFT
,
189 DA7219_SWG_SEL_MAX
, da7219_tonegen_swg_sel_txt
);
192 static const char * const da7219_dac_softmute_rate_txt
[] = {
193 "1 Sample", "2 Samples", "4 Samples", "8 Samples", "16 Samples",
194 "32 Samples", "64 Samples"
197 static const struct soc_enum da7219_dac_softmute_rate
=
198 SOC_ENUM_SINGLE(DA7219_DAC_FILTERS5
, DA7219_DAC_SOFTMUTE_RATE_SHIFT
,
199 DA7219_DAC_SOFTMUTE_RATE_MAX
,
200 da7219_dac_softmute_rate_txt
);
202 static const char * const da7219_dac_ng_setup_time_txt
[] = {
203 "256 Samples", "512 Samples", "1024 Samples", "2048 Samples"
206 static const struct soc_enum da7219_dac_ng_setup_time
=
207 SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME
,
208 DA7219_DAC_NG_SETUP_TIME_SHIFT
,
209 DA7219_DAC_NG_SETUP_TIME_MAX
,
210 da7219_dac_ng_setup_time_txt
);
212 static const char * const da7219_dac_ng_rampup_txt
[] = {
213 "0.22ms/dB", "0.0138ms/dB"
216 static const struct soc_enum da7219_dac_ng_rampup_rate
=
217 SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME
,
218 DA7219_DAC_NG_RAMPUP_RATE_SHIFT
,
219 DA7219_DAC_NG_RAMP_RATE_MAX
,
220 da7219_dac_ng_rampup_txt
);
222 static const char * const da7219_dac_ng_rampdown_txt
[] = {
223 "0.88ms/dB", "14.08ms/dB"
226 static const struct soc_enum da7219_dac_ng_rampdown_rate
=
227 SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME
,
228 DA7219_DAC_NG_RAMPDN_RATE_SHIFT
,
229 DA7219_DAC_NG_RAMP_RATE_MAX
,
230 da7219_dac_ng_rampdown_txt
);
233 static const char * const da7219_cp_track_mode_txt
[] = {
234 "Largest Volume", "DAC Volume", "Signal Magnitude"
237 static const unsigned int da7219_cp_track_mode_val
[] = {
238 DA7219_CP_MCHANGE_LARGEST_VOL
, DA7219_CP_MCHANGE_DAC_VOL
,
239 DA7219_CP_MCHANGE_SIG_MAG
242 static const struct soc_enum da7219_cp_track_mode
=
243 SOC_VALUE_ENUM_SINGLE(DA7219_CP_CTRL
, DA7219_CP_MCHANGE_SHIFT
,
244 DA7219_CP_MCHANGE_REL_MASK
, DA7219_CP_MCHANGE_MAX
,
245 da7219_cp_track_mode_txt
,
246 da7219_cp_track_mode_val
);
253 /* Locked Kcontrol calls */
254 static int da7219_volsw_locked_get(struct snd_kcontrol
*kcontrol
,
255 struct snd_ctl_elem_value
*ucontrol
)
257 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
258 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
261 mutex_lock(&da7219
->lock
);
262 ret
= snd_soc_get_volsw(kcontrol
, ucontrol
);
263 mutex_unlock(&da7219
->lock
);
268 static int da7219_volsw_locked_put(struct snd_kcontrol
*kcontrol
,
269 struct snd_ctl_elem_value
*ucontrol
)
271 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
272 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
275 mutex_lock(&da7219
->lock
);
276 ret
= snd_soc_put_volsw(kcontrol
, ucontrol
);
277 mutex_unlock(&da7219
->lock
);
282 static int da7219_enum_locked_get(struct snd_kcontrol
*kcontrol
,
283 struct snd_ctl_elem_value
*ucontrol
)
285 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
286 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
289 mutex_lock(&da7219
->lock
);
290 ret
= snd_soc_get_enum_double(kcontrol
, ucontrol
);
291 mutex_unlock(&da7219
->lock
);
296 static int da7219_enum_locked_put(struct snd_kcontrol
*kcontrol
,
297 struct snd_ctl_elem_value
*ucontrol
)
299 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
300 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
303 mutex_lock(&da7219
->lock
);
304 ret
= snd_soc_put_enum_double(kcontrol
, ucontrol
);
305 mutex_unlock(&da7219
->lock
);
311 static void da7219_alc_calib(struct snd_soc_codec
*codec
)
313 u8 mic_ctrl
, mixin_ctrl
, adc_ctrl
, calib_ctrl
;
315 /* Save current state of mic control register */
316 mic_ctrl
= snd_soc_read(codec
, DA7219_MIC_1_CTRL
);
318 /* Save current state of input mixer control register */
319 mixin_ctrl
= snd_soc_read(codec
, DA7219_MIXIN_L_CTRL
);
321 /* Save current state of input ADC control register */
322 adc_ctrl
= snd_soc_read(codec
, DA7219_ADC_L_CTRL
);
324 /* Enable then Mute MIC PGAs */
325 snd_soc_update_bits(codec
, DA7219_MIC_1_CTRL
, DA7219_MIC_1_AMP_EN_MASK
,
326 DA7219_MIC_1_AMP_EN_MASK
);
327 snd_soc_update_bits(codec
, DA7219_MIC_1_CTRL
,
328 DA7219_MIC_1_AMP_MUTE_EN_MASK
,
329 DA7219_MIC_1_AMP_MUTE_EN_MASK
);
331 /* Enable input mixers unmuted */
332 snd_soc_update_bits(codec
, DA7219_MIXIN_L_CTRL
,
333 DA7219_MIXIN_L_AMP_EN_MASK
|
334 DA7219_MIXIN_L_AMP_MUTE_EN_MASK
,
335 DA7219_MIXIN_L_AMP_EN_MASK
);
337 /* Enable input filters unmuted */
338 snd_soc_update_bits(codec
, DA7219_ADC_L_CTRL
,
339 DA7219_ADC_L_MUTE_EN_MASK
| DA7219_ADC_L_EN_MASK
,
340 DA7219_ADC_L_EN_MASK
);
342 /* Perform auto calibration */
343 snd_soc_update_bits(codec
, DA7219_ALC_CTRL1
,
344 DA7219_ALC_AUTO_CALIB_EN_MASK
,
345 DA7219_ALC_AUTO_CALIB_EN_MASK
);
347 calib_ctrl
= snd_soc_read(codec
, DA7219_ALC_CTRL1
);
348 } while (calib_ctrl
& DA7219_ALC_AUTO_CALIB_EN_MASK
);
350 /* If auto calibration fails, disable DC offset, hybrid ALC */
351 if (calib_ctrl
& DA7219_ALC_CALIB_OVERFLOW_MASK
) {
353 "ALC auto calibration failed with overflow\n");
354 snd_soc_update_bits(codec
, DA7219_ALC_CTRL1
,
355 DA7219_ALC_OFFSET_EN_MASK
|
356 DA7219_ALC_SYNC_MODE_MASK
, 0);
358 /* Enable DC offset cancellation, hybrid mode */
359 snd_soc_update_bits(codec
, DA7219_ALC_CTRL1
,
360 DA7219_ALC_OFFSET_EN_MASK
|
361 DA7219_ALC_SYNC_MODE_MASK
,
362 DA7219_ALC_OFFSET_EN_MASK
|
363 DA7219_ALC_SYNC_MODE_MASK
);
366 /* Restore input filter control register to original state */
367 snd_soc_write(codec
, DA7219_ADC_L_CTRL
, adc_ctrl
);
369 /* Restore input mixer control registers to original state */
370 snd_soc_write(codec
, DA7219_MIXIN_L_CTRL
, mixin_ctrl
);
372 /* Restore MIC control registers to original states */
373 snd_soc_write(codec
, DA7219_MIC_1_CTRL
, mic_ctrl
);
376 static int da7219_mixin_gain_put(struct snd_kcontrol
*kcontrol
,
377 struct snd_ctl_elem_value
*ucontrol
)
379 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
380 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
383 ret
= snd_soc_put_volsw(kcontrol
, ucontrol
);
386 * If ALC in operation and value of control has been updated,
387 * make sure calibrated offsets are updated.
389 if ((ret
== 1) && (da7219
->alc_en
))
390 da7219_alc_calib(codec
);
395 static int da7219_alc_sw_put(struct snd_kcontrol
*kcontrol
,
396 struct snd_ctl_elem_value
*ucontrol
)
398 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
399 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
402 /* Force ALC offset calibration if enabling ALC */
403 if ((ucontrol
->value
.integer
.value
[0]) && (!da7219
->alc_en
)) {
404 da7219_alc_calib(codec
);
405 da7219
->alc_en
= true;
407 da7219
->alc_en
= false;
410 return snd_soc_put_volsw(kcontrol
, ucontrol
);
414 static int da7219_tonegen_freq_get(struct snd_kcontrol
*kcontrol
,
415 struct snd_ctl_elem_value
*ucontrol
)
417 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
418 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
419 struct soc_mixer_control
*mixer_ctrl
=
420 (struct soc_mixer_control
*) kcontrol
->private_value
;
421 unsigned int reg
= mixer_ctrl
->reg
;
425 mutex_lock(&da7219
->lock
);
426 ret
= regmap_raw_read(da7219
->regmap
, reg
, &val
, sizeof(val
));
427 mutex_unlock(&da7219
->lock
);
433 * Frequency value spans two 8-bit registers, lower then upper byte.
434 * Therefore we need to convert to host endianness here.
436 ucontrol
->value
.integer
.value
[0] = le16_to_cpu(val
);
441 static int da7219_tonegen_freq_put(struct snd_kcontrol
*kcontrol
,
442 struct snd_ctl_elem_value
*ucontrol
)
444 struct snd_soc_codec
*codec
= snd_soc_kcontrol_codec(kcontrol
);
445 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
446 struct soc_mixer_control
*mixer_ctrl
=
447 (struct soc_mixer_control
*) kcontrol
->private_value
;
448 unsigned int reg
= mixer_ctrl
->reg
;
453 * Frequency value spans two 8-bit registers, lower then upper byte.
454 * Therefore we need to convert to little endian here to align with
457 val
= cpu_to_le16(ucontrol
->value
.integer
.value
[0]);
459 mutex_lock(&da7219
->lock
);
460 ret
= regmap_raw_write(da7219
->regmap
, reg
, &val
, sizeof(val
));
461 mutex_unlock(&da7219
->lock
);
471 static const struct snd_kcontrol_new da7219_snd_controls
[] = {
473 SOC_SINGLE_TLV("Mic Volume", DA7219_MIC_1_GAIN
,
474 DA7219_MIC_1_AMP_GAIN_SHIFT
, DA7219_MIC_1_AMP_GAIN_MAX
,
475 DA7219_NO_INVERT
, da7219_mic_gain_tlv
),
476 SOC_SINGLE("Mic Switch", DA7219_MIC_1_CTRL
,
477 DA7219_MIC_1_AMP_MUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
481 SOC_SINGLE_EXT_TLV("Mixin Volume", DA7219_MIXIN_L_GAIN
,
482 DA7219_MIXIN_L_AMP_GAIN_SHIFT
,
483 DA7219_MIXIN_L_AMP_GAIN_MAX
, DA7219_NO_INVERT
,
484 snd_soc_get_volsw
, da7219_mixin_gain_put
,
485 da7219_mixin_gain_tlv
),
486 SOC_SINGLE("Mixin Switch", DA7219_MIXIN_L_CTRL
,
487 DA7219_MIXIN_L_AMP_MUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
489 SOC_SINGLE("Mixin Gain Ramp Switch", DA7219_MIXIN_L_CTRL
,
490 DA7219_MIXIN_L_AMP_RAMP_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
492 SOC_SINGLE("Mixin ZC Gain Switch", DA7219_MIXIN_L_CTRL
,
493 DA7219_MIXIN_L_AMP_ZC_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
497 SOC_SINGLE_TLV("Capture Digital Volume", DA7219_ADC_L_GAIN
,
498 DA7219_ADC_L_DIGITAL_GAIN_SHIFT
,
499 DA7219_ADC_L_DIGITAL_GAIN_MAX
, DA7219_NO_INVERT
,
500 da7219_adc_dig_gain_tlv
),
501 SOC_SINGLE("Capture Digital Switch", DA7219_ADC_L_CTRL
,
502 DA7219_ADC_L_MUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
504 SOC_SINGLE("Capture Digital Gain Ramp Switch", DA7219_ADC_L_CTRL
,
505 DA7219_ADC_L_RAMP_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
509 SOC_ENUM("ALC Attack Rate", da7219_alc_attack_rate
),
510 SOC_ENUM("ALC Release Rate", da7219_alc_release_rate
),
511 SOC_ENUM("ALC Hold Time", da7219_alc_hold_time
),
512 SOC_ENUM("ALC Envelope Attack Rate", da7219_alc_env_attack_rate
),
513 SOC_ENUM("ALC Envelope Release Rate", da7219_alc_env_release_rate
),
514 SOC_SINGLE_TLV("ALC Noise Threshold", DA7219_ALC_NOISE
,
515 DA7219_ALC_NOISE_SHIFT
, DA7219_ALC_THRESHOLD_MAX
,
516 DA7219_INVERT
, da7219_alc_threshold_tlv
),
517 SOC_SINGLE_TLV("ALC Min Threshold", DA7219_ALC_TARGET_MIN
,
518 DA7219_ALC_THRESHOLD_MIN_SHIFT
, DA7219_ALC_THRESHOLD_MAX
,
519 DA7219_INVERT
, da7219_alc_threshold_tlv
),
520 SOC_SINGLE_TLV("ALC Max Threshold", DA7219_ALC_TARGET_MAX
,
521 DA7219_ALC_THRESHOLD_MAX_SHIFT
, DA7219_ALC_THRESHOLD_MAX
,
522 DA7219_INVERT
, da7219_alc_threshold_tlv
),
523 SOC_SINGLE_TLV("ALC Max Attenuation", DA7219_ALC_GAIN_LIMITS
,
524 DA7219_ALC_ATTEN_MAX_SHIFT
, DA7219_ALC_ATTEN_GAIN_MAX
,
525 DA7219_NO_INVERT
, da7219_alc_gain_tlv
),
526 SOC_SINGLE_TLV("ALC Max Volume", DA7219_ALC_GAIN_LIMITS
,
527 DA7219_ALC_GAIN_MAX_SHIFT
, DA7219_ALC_ATTEN_GAIN_MAX
,
528 DA7219_NO_INVERT
, da7219_alc_gain_tlv
),
529 SOC_SINGLE_RANGE_TLV("ALC Min Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS
,
530 DA7219_ALC_ANA_GAIN_MIN_SHIFT
,
531 DA7219_ALC_ANA_GAIN_MIN
, DA7219_ALC_ANA_GAIN_MAX
,
532 DA7219_NO_INVERT
, da7219_alc_ana_gain_tlv
),
533 SOC_SINGLE_RANGE_TLV("ALC Max Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS
,
534 DA7219_ALC_ANA_GAIN_MAX_SHIFT
,
535 DA7219_ALC_ANA_GAIN_MIN
, DA7219_ALC_ANA_GAIN_MAX
,
536 DA7219_NO_INVERT
, da7219_alc_ana_gain_tlv
),
537 SOC_ENUM("ALC Anticlip Step", da7219_alc_anticlip_step
),
538 SOC_SINGLE("ALC Anticlip Switch", DA7219_ALC_ANTICLIP_CTRL
,
539 DA7219_ALC_ANTIPCLIP_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
541 SOC_SINGLE_EXT("ALC Switch", DA7219_ALC_CTRL1
, DA7219_ALC_EN_SHIFT
,
542 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
,
543 snd_soc_get_volsw
, da7219_alc_sw_put
),
545 /* Input High-Pass Filters */
546 SOC_ENUM("ADC HPF Mode", da7219_adc_hpf_mode
),
547 SOC_ENUM("ADC HPF Corner Audio", da7219_adc_audio_hpf_corner
),
548 SOC_ENUM("ADC HPF Corner Voice", da7219_adc_voice_hpf_corner
),
550 /* Sidetone Filter */
551 SOC_SINGLE_TLV("Sidetone Volume", DA7219_SIDETONE_GAIN
,
552 DA7219_SIDETONE_GAIN_SHIFT
, DA7219_SIDETONE_GAIN_MAX
,
553 DA7219_NO_INVERT
, da7219_sidetone_gain_tlv
),
554 SOC_SINGLE("Sidetone Switch", DA7219_SIDETONE_CTRL
,
555 DA7219_SIDETONE_MUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
559 SOC_SINGLE_EXT_TLV("ToneGen Volume", DA7219_TONE_GEN_CFG2
,
560 DA7219_TONE_GEN_GAIN_SHIFT
, DA7219_TONE_GEN_GAIN_MAX
,
561 DA7219_NO_INVERT
, da7219_volsw_locked_get
,
562 da7219_volsw_locked_put
, da7219_tonegen_gain_tlv
),
563 SOC_ENUM_EXT("ToneGen DTMF Key", da7219_tonegen_dtmf_key
,
564 da7219_enum_locked_get
, da7219_enum_locked_put
),
565 SOC_SINGLE_EXT("ToneGen DTMF Switch", DA7219_TONE_GEN_CFG1
,
566 DA7219_DTMF_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
567 DA7219_NO_INVERT
, da7219_volsw_locked_get
,
568 da7219_volsw_locked_put
),
569 SOC_ENUM_EXT("ToneGen Sinewave Gen Type", da7219_tonegen_swg_sel
,
570 da7219_enum_locked_get
, da7219_enum_locked_put
),
571 SOC_SINGLE_EXT("ToneGen Sinewave1 Freq", DA7219_TONE_GEN_FREQ1_L
,
572 DA7219_FREQ1_L_SHIFT
, DA7219_FREQ_MAX
, DA7219_NO_INVERT
,
573 da7219_tonegen_freq_get
, da7219_tonegen_freq_put
),
574 SOC_SINGLE_EXT("ToneGen Sinewave2 Freq", DA7219_TONE_GEN_FREQ2_L
,
575 DA7219_FREQ2_L_SHIFT
, DA7219_FREQ_MAX
, DA7219_NO_INVERT
,
576 da7219_tonegen_freq_get
, da7219_tonegen_freq_put
),
577 SOC_SINGLE_EXT("ToneGen On Time", DA7219_TONE_GEN_ON_PER
,
578 DA7219_BEEP_ON_PER_SHIFT
, DA7219_BEEP_ON_OFF_MAX
,
579 DA7219_NO_INVERT
, da7219_volsw_locked_get
,
580 da7219_volsw_locked_put
),
581 SOC_SINGLE("ToneGen Off Time", DA7219_TONE_GEN_OFF_PER
,
582 DA7219_BEEP_OFF_PER_SHIFT
, DA7219_BEEP_ON_OFF_MAX
,
586 SOC_ENUM("Gain Ramp Rate", da7219_gain_ramp_rate
),
588 /* DAC High-Pass Filter */
589 SOC_ENUM_EXT("DAC HPF Mode", da7219_dac_hpf_mode
,
590 da7219_enum_locked_get
, da7219_enum_locked_put
),
591 SOC_ENUM("DAC HPF Corner Audio", da7219_dac_audio_hpf_corner
),
592 SOC_ENUM("DAC HPF Corner Voice", da7219_dac_voice_hpf_corner
),
594 /* DAC 5-Band Equaliser */
595 SOC_SINGLE_TLV("DAC EQ Band1 Volume", DA7219_DAC_FILTERS2
,
596 DA7219_DAC_EQ_BAND1_SHIFT
, DA7219_DAC_EQ_BAND_MAX
,
597 DA7219_NO_INVERT
, da7219_dac_eq_band_tlv
),
598 SOC_SINGLE_TLV("DAC EQ Band2 Volume", DA7219_DAC_FILTERS2
,
599 DA7219_DAC_EQ_BAND2_SHIFT
, DA7219_DAC_EQ_BAND_MAX
,
600 DA7219_NO_INVERT
, da7219_dac_eq_band_tlv
),
601 SOC_SINGLE_TLV("DAC EQ Band3 Volume", DA7219_DAC_FILTERS3
,
602 DA7219_DAC_EQ_BAND3_SHIFT
, DA7219_DAC_EQ_BAND_MAX
,
603 DA7219_NO_INVERT
, da7219_dac_eq_band_tlv
),
604 SOC_SINGLE_TLV("DAC EQ Band4 Volume", DA7219_DAC_FILTERS3
,
605 DA7219_DAC_EQ_BAND4_SHIFT
, DA7219_DAC_EQ_BAND_MAX
,
606 DA7219_NO_INVERT
, da7219_dac_eq_band_tlv
),
607 SOC_SINGLE_TLV("DAC EQ Band5 Volume", DA7219_DAC_FILTERS4
,
608 DA7219_DAC_EQ_BAND5_SHIFT
, DA7219_DAC_EQ_BAND_MAX
,
609 DA7219_NO_INVERT
, da7219_dac_eq_band_tlv
),
610 SOC_SINGLE_EXT("DAC EQ Switch", DA7219_DAC_FILTERS4
,
611 DA7219_DAC_EQ_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
612 DA7219_NO_INVERT
, da7219_volsw_locked_get
,
613 da7219_volsw_locked_put
),
616 SOC_ENUM("DAC Soft Mute Rate", da7219_dac_softmute_rate
),
617 SOC_SINGLE_EXT("DAC Soft Mute Switch", DA7219_DAC_FILTERS5
,
618 DA7219_DAC_SOFTMUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
619 DA7219_NO_INVERT
, da7219_volsw_locked_get
,
620 da7219_volsw_locked_put
),
623 SOC_ENUM("DAC NG Setup Time", da7219_dac_ng_setup_time
),
624 SOC_ENUM("DAC NG Rampup Rate", da7219_dac_ng_rampup_rate
),
625 SOC_ENUM("DAC NG Rampdown Rate", da7219_dac_ng_rampdown_rate
),
626 SOC_SINGLE_TLV("DAC NG Off Threshold", DA7219_DAC_NG_OFF_THRESH
,
627 DA7219_DAC_NG_OFF_THRESHOLD_SHIFT
,
628 DA7219_DAC_NG_THRESHOLD_MAX
, DA7219_NO_INVERT
,
629 da7219_dac_ng_threshold_tlv
),
630 SOC_SINGLE_TLV("DAC NG On Threshold", DA7219_DAC_NG_ON_THRESH
,
631 DA7219_DAC_NG_ON_THRESHOLD_SHIFT
,
632 DA7219_DAC_NG_THRESHOLD_MAX
, DA7219_NO_INVERT
,
633 da7219_dac_ng_threshold_tlv
),
634 SOC_SINGLE("DAC NG Switch", DA7219_DAC_NG_CTRL
, DA7219_DAC_NG_EN_SHIFT
,
635 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
638 SOC_DOUBLE_R_EXT_TLV("Playback Digital Volume", DA7219_DAC_L_GAIN
,
639 DA7219_DAC_R_GAIN
, DA7219_DAC_L_DIGITAL_GAIN_SHIFT
,
640 DA7219_DAC_DIGITAL_GAIN_MAX
, DA7219_NO_INVERT
,
641 da7219_volsw_locked_get
, da7219_volsw_locked_put
,
642 da7219_dac_dig_gain_tlv
),
643 SOC_DOUBLE_R_EXT("Playback Digital Switch", DA7219_DAC_L_CTRL
,
644 DA7219_DAC_R_CTRL
, DA7219_DAC_L_MUTE_EN_SHIFT
,
645 DA7219_SWITCH_EN_MAX
, DA7219_INVERT
,
646 da7219_volsw_locked_get
, da7219_volsw_locked_put
),
647 SOC_DOUBLE_R("Playback Digital Gain Ramp Switch", DA7219_DAC_L_CTRL
,
648 DA7219_DAC_R_CTRL
, DA7219_DAC_L_RAMP_EN_SHIFT
,
649 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
652 SOC_ENUM("Charge Pump Track Mode", da7219_cp_track_mode
),
653 SOC_SINGLE("Charge Pump Threshold", DA7219_CP_VOL_THRESHOLD1
,
654 DA7219_CP_THRESH_VDD2_SHIFT
, DA7219_CP_THRESH_VDD2_MAX
,
658 SOC_DOUBLE_R_EXT_TLV("Headphone Volume", DA7219_HP_L_GAIN
,
659 DA7219_HP_R_GAIN
, DA7219_HP_L_AMP_GAIN_SHIFT
,
660 DA7219_HP_AMP_GAIN_MAX
, DA7219_NO_INVERT
,
661 da7219_volsw_locked_get
, da7219_volsw_locked_put
,
663 SOC_DOUBLE_R_EXT("Headphone Switch", DA7219_HP_L_CTRL
, DA7219_HP_R_CTRL
,
664 DA7219_HP_L_AMP_MUTE_EN_SHIFT
, DA7219_SWITCH_EN_MAX
,
665 DA7219_INVERT
, da7219_volsw_locked_get
,
666 da7219_volsw_locked_put
),
667 SOC_DOUBLE_R("Headphone Gain Ramp Switch", DA7219_HP_L_CTRL
,
668 DA7219_HP_R_CTRL
, DA7219_HP_L_AMP_RAMP_EN_SHIFT
,
669 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
670 SOC_DOUBLE_R("Headphone ZC Gain Switch", DA7219_HP_L_CTRL
,
671 DA7219_HP_R_CTRL
, DA7219_HP_L_AMP_ZC_EN_SHIFT
,
672 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
680 static const char * const da7219_out_sel_txt
[] = {
681 "ADC", "Tone Generator", "DAIL", "DAIR"
684 static const struct soc_enum da7219_out_dail_sel
=
685 SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI
,
686 DA7219_DAI_L_SRC_SHIFT
,
690 static const struct snd_kcontrol_new da7219_out_dail_sel_mux
=
691 SOC_DAPM_ENUM("Out DAIL Mux", da7219_out_dail_sel
);
693 static const struct soc_enum da7219_out_dair_sel
=
694 SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI
,
695 DA7219_DAI_R_SRC_SHIFT
,
699 static const struct snd_kcontrol_new da7219_out_dair_sel_mux
=
700 SOC_DAPM_ENUM("Out DAIR Mux", da7219_out_dair_sel
);
702 static const struct soc_enum da7219_out_dacl_sel
=
703 SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC
,
704 DA7219_DAC_L_SRC_SHIFT
,
708 static const struct snd_kcontrol_new da7219_out_dacl_sel_mux
=
709 SOC_DAPM_ENUM("Out DACL Mux", da7219_out_dacl_sel
);
711 static const struct soc_enum da7219_out_dacr_sel
=
712 SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC
,
713 DA7219_DAC_R_SRC_SHIFT
,
717 static const struct snd_kcontrol_new da7219_out_dacr_sel_mux
=
718 SOC_DAPM_ENUM("Out DACR Mux", da7219_out_dacr_sel
);
722 * DAPM Mixer Controls
725 static const struct snd_kcontrol_new da7219_mixin_controls
[] = {
726 SOC_DAPM_SINGLE("Mic Switch", DA7219_MIXIN_L_SELECT
,
727 DA7219_MIXIN_L_MIX_SELECT_SHIFT
,
728 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
731 static const struct snd_kcontrol_new da7219_mixout_l_controls
[] = {
732 SOC_DAPM_SINGLE("DACL Switch", DA7219_MIXOUT_L_SELECT
,
733 DA7219_MIXOUT_L_MIX_SELECT_SHIFT
,
734 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
737 static const struct snd_kcontrol_new da7219_mixout_r_controls
[] = {
738 SOC_DAPM_SINGLE("DACR Switch", DA7219_MIXOUT_R_SELECT
,
739 DA7219_MIXOUT_R_MIX_SELECT_SHIFT
,
740 DA7219_SWITCH_EN_MAX
, DA7219_NO_INVERT
),
743 #define DA7219_DMIX_ST_CTRLS(reg) \
744 SOC_DAPM_SINGLE("Out FilterL Switch", reg, \
745 DA7219_DMIX_ST_SRC_OUTFILT1L_SHIFT, \
746 DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \
747 SOC_DAPM_SINGLE("Out FilterR Switch", reg, \
748 DA7219_DMIX_ST_SRC_OUTFILT1R_SHIFT, \
749 DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \
750 SOC_DAPM_SINGLE("Sidetone Switch", reg, \
751 DA7219_DMIX_ST_SRC_SIDETONE_SHIFT, \
752 DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT) \
754 static const struct snd_kcontrol_new da7219_st_out_filtl_mix_controls[] = {
755 DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1L
),
758 static const struct snd_kcontrol_new da7219_st_out_filtr_mix_controls
[] = {
759 DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1R
),
767 static int da7219_dai_event(struct snd_soc_dapm_widget
*w
,
768 struct snd_kcontrol
*kcontrol
, int event
)
770 struct snd_soc_codec
*codec
= snd_soc_dapm_to_codec(w
->dapm
);
771 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
772 u8 pll_ctrl
, pll_status
;
774 bool srm_lock
= false;
777 case SND_SOC_DAPM_PRE_PMU
:
779 /* Enable DAI clks for master mode */
780 snd_soc_update_bits(codec
, DA7219_DAI_CLK_MODE
,
781 DA7219_DAI_CLK_EN_MASK
,
782 DA7219_DAI_CLK_EN_MASK
);
784 /* PC synchronised to DAI */
785 snd_soc_update_bits(codec
, DA7219_PC_COUNT
,
786 DA7219_PC_FREERUN_MASK
, 0);
788 /* Slave mode, if SRM not enabled no need for status checks */
789 pll_ctrl
= snd_soc_read(codec
, DA7219_PLL_CTRL
);
790 if ((pll_ctrl
& DA7219_PLL_MODE_MASK
) != DA7219_PLL_MODE_SRM
)
793 /* Check SRM has locked */
795 pll_status
= snd_soc_read(codec
, DA7219_PLL_SRM_STS
);
796 if (pll_status
& DA7219_PLL_SRM_STS_SRM_LOCK
) {
802 } while ((i
< DA7219_SRM_CHECK_RETRIES
) & (!srm_lock
));
805 dev_warn(codec
->dev
, "SRM failed to lock\n");
808 case SND_SOC_DAPM_POST_PMD
:
809 /* PC free-running */
810 snd_soc_update_bits(codec
, DA7219_PC_COUNT
,
811 DA7219_PC_FREERUN_MASK
,
812 DA7219_PC_FREERUN_MASK
);
814 /* Disable DAI clks if in master mode */
816 snd_soc_update_bits(codec
, DA7219_DAI_CLK_MODE
,
817 DA7219_DAI_CLK_EN_MASK
, 0);
829 static const struct snd_soc_dapm_widget da7219_dapm_widgets
[] = {
831 SND_SOC_DAPM_SUPPLY("Mic Bias", DA7219_MICBIAS_CTRL
,
832 DA7219_MICBIAS1_EN_SHIFT
, DA7219_NO_INVERT
,
836 SND_SOC_DAPM_INPUT("MIC"),
839 SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL
,
840 DA7219_MIC_1_AMP_EN_SHIFT
, DA7219_NO_INVERT
,
842 SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL
,
843 DA7219_MIXIN_L_AMP_EN_SHIFT
, DA7219_NO_INVERT
,
847 SND_SOC_DAPM_ADC("ADC", NULL
, DA7219_ADC_L_CTRL
, DA7219_ADC_L_EN_SHIFT
,
851 SND_SOC_DAPM_SIGGEN("TONE"),
852 SND_SOC_DAPM_PGA("Tone Generator", DA7219_TONE_GEN_CFG1
,
853 DA7219_START_STOPN_SHIFT
, DA7219_NO_INVERT
, NULL
, 0),
856 SND_SOC_DAPM_ADC("Sidetone Filter", NULL
, DA7219_SIDETONE_CTRL
,
857 DA7219_SIDETONE_EN_SHIFT
, DA7219_NO_INVERT
),
859 /* Input Mixer Supply */
860 SND_SOC_DAPM_SUPPLY("Mixer In Supply", DA7219_MIXIN_L_CTRL
,
861 DA7219_MIXIN_L_MIX_EN_SHIFT
, DA7219_NO_INVERT
,
865 SND_SOC_DAPM_MIXER("Mixer In", SND_SOC_NOPM
, 0, 0,
866 da7219_mixin_controls
,
867 ARRAY_SIZE(da7219_mixin_controls
)),
870 SND_SOC_DAPM_MUX("Out DAIL Mux", SND_SOC_NOPM
, 0, 0,
871 &da7219_out_dail_sel_mux
),
872 SND_SOC_DAPM_MUX("Out DAIR Mux", SND_SOC_NOPM
, 0, 0,
873 &da7219_out_dair_sel_mux
),
876 SND_SOC_DAPM_SUPPLY("DAI", DA7219_DAI_CTRL
, DA7219_DAI_EN_SHIFT
,
877 DA7219_NO_INVERT
, da7219_dai_event
,
878 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
881 SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM
, 0, 0),
882 SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM
, 0, 0),
885 SND_SOC_DAPM_MUX("Out DACL Mux", SND_SOC_NOPM
, 0, 0,
886 &da7219_out_dacl_sel_mux
),
887 SND_SOC_DAPM_MUX("Out DACR Mux", SND_SOC_NOPM
, 0, 0,
888 &da7219_out_dacr_sel_mux
),
891 SND_SOC_DAPM_MIXER("Mixer Out FilterL", SND_SOC_NOPM
, 0, 0,
892 da7219_mixout_l_controls
,
893 ARRAY_SIZE(da7219_mixout_l_controls
)),
894 SND_SOC_DAPM_MIXER("Mixer Out FilterR", SND_SOC_NOPM
, 0, 0,
895 da7219_mixout_r_controls
,
896 ARRAY_SIZE(da7219_mixout_r_controls
)),
898 /* Sidetone Mixers */
899 SND_SOC_DAPM_MIXER("ST Mixer Out FilterL", SND_SOC_NOPM
, 0, 0,
900 da7219_st_out_filtl_mix_controls
,
901 ARRAY_SIZE(da7219_st_out_filtl_mix_controls
)),
902 SND_SOC_DAPM_MIXER("ST Mixer Out FilterR", SND_SOC_NOPM
, 0,
903 0, da7219_st_out_filtr_mix_controls
,
904 ARRAY_SIZE(da7219_st_out_filtr_mix_controls
)),
907 SND_SOC_DAPM_DAC("DACL", NULL
, DA7219_DAC_L_CTRL
, DA7219_DAC_L_EN_SHIFT
,
909 SND_SOC_DAPM_DAC("DACR", NULL
, DA7219_DAC_R_CTRL
, DA7219_DAC_R_EN_SHIFT
,
913 SND_SOC_DAPM_PGA("Mixout Left PGA", DA7219_MIXOUT_L_CTRL
,
914 DA7219_MIXOUT_L_AMP_EN_SHIFT
, DA7219_NO_INVERT
,
916 SND_SOC_DAPM_PGA("Mixout Right PGA", DA7219_MIXOUT_R_CTRL
,
917 DA7219_MIXOUT_R_AMP_EN_SHIFT
, DA7219_NO_INVERT
,
919 SND_SOC_DAPM_PGA("Headphone Left PGA", DA7219_HP_L_CTRL
,
920 DA7219_HP_L_AMP_EN_SHIFT
, DA7219_NO_INVERT
, NULL
, 0),
921 SND_SOC_DAPM_PGA("Headphone Right PGA", DA7219_HP_R_CTRL
,
922 DA7219_HP_R_AMP_EN_SHIFT
, DA7219_NO_INVERT
, NULL
, 0),
924 /* Output Supplies */
925 SND_SOC_DAPM_SUPPLY("Charge Pump", DA7219_CP_CTRL
, DA7219_CP_EN_SHIFT
,
926 DA7219_NO_INVERT
, NULL
, 0),
929 SND_SOC_DAPM_OUTPUT("HPL"),
930 SND_SOC_DAPM_OUTPUT("HPR"),
938 #define DA7219_OUT_DAI_MUX_ROUTES(name) \
939 {name, "ADC", "Mixer In"}, \
940 {name, "Tone Generator", "Tone Generator"}, \
941 {name, "DAIL", "DAIOUT"}, \
942 {name, "DAIR", "DAIOUT"}
944 #define DA7219_OUT_DAC_MUX_ROUTES(name) \
945 {name, "ADC", "Mixer In"}, \
946 {name, "Tone Generator", "Tone Generator"}, \
947 {name, "DAIL", "DAIIN"}, \
948 {name, "DAIR", "DAIIN"}
954 #define DA7219_DMIX_ST_ROUTES(name) \
955 {name, "Out FilterL Switch", "Mixer Out FilterL"}, \
956 {name, "Out FilterR Switch", "Mixer Out FilterR"}, \
957 {name, "Sidetone Switch", "Sidetone Filter"}
961 * DAPM audio route definition
964 static const struct snd_soc_dapm_route da7219_audio_map
[] = {
966 {"MIC", NULL
, "Mic Bias"},
967 {"Mic PGA", NULL
, "MIC"},
968 {"Mixin PGA", NULL
, "Mic PGA"},
969 {"ADC", NULL
, "Mixin PGA"},
971 {"Mixer In", NULL
, "Mixer In Supply"},
972 {"Mixer In", "Mic Switch", "ADC"},
974 {"Sidetone Filter", NULL
, "Mixer In"},
976 {"Tone Generator", NULL
, "TONE"},
978 DA7219_OUT_DAI_MUX_ROUTES("Out DAIL Mux"),
979 DA7219_OUT_DAI_MUX_ROUTES("Out DAIR Mux"),
981 {"DAIOUT", NULL
, "Out DAIL Mux"},
982 {"DAIOUT", NULL
, "Out DAIR Mux"},
983 {"DAIOUT", NULL
, "DAI"},
986 {"DAIIN", NULL
, "DAI"},
988 DA7219_OUT_DAC_MUX_ROUTES("Out DACL Mux"),
989 DA7219_OUT_DAC_MUX_ROUTES("Out DACR Mux"),
991 {"Mixer Out FilterL", "DACL Switch", "Out DACL Mux"},
992 {"Mixer Out FilterR", "DACR Switch", "Out DACR Mux"},
994 DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterL"),
995 DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterR"),
997 {"DACL", NULL
, "ST Mixer Out FilterL"},
998 {"DACR", NULL
, "ST Mixer Out FilterR"},
1000 {"Mixout Left PGA", NULL
, "DACL"},
1001 {"Mixout Right PGA", NULL
, "DACR"},
1003 {"Headphone Left PGA", NULL
, "Mixout Left PGA"},
1004 {"Headphone Right PGA", NULL
, "Mixout Right PGA"},
1006 {"HPL", NULL
, "Headphone Left PGA"},
1007 {"HPR", NULL
, "Headphone Right PGA"},
1009 {"HPL", NULL
, "Charge Pump"},
1010 {"HPR", NULL
, "Charge Pump"},
1018 static int da7219_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
1019 int clk_id
, unsigned int freq
, int dir
)
1021 struct snd_soc_codec
*codec
= codec_dai
->codec
;
1022 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1025 if ((da7219
->clk_src
== clk_id
) && (da7219
->mclk_rate
== freq
))
1028 if (((freq
< 2000000) && (freq
!= 32768)) || (freq
> 54000000)) {
1029 dev_err(codec_dai
->dev
, "Unsupported MCLK value %d\n",
1035 case DA7219_CLKSRC_MCLK_SQR
:
1036 snd_soc_update_bits(codec
, DA7219_PLL_CTRL
,
1037 DA7219_PLL_MCLK_SQR_EN_MASK
,
1038 DA7219_PLL_MCLK_SQR_EN_MASK
);
1040 case DA7219_CLKSRC_MCLK
:
1041 snd_soc_update_bits(codec
, DA7219_PLL_CTRL
,
1042 DA7219_PLL_MCLK_SQR_EN_MASK
, 0);
1045 dev_err(codec_dai
->dev
, "Unknown clock source %d\n", clk_id
);
1049 da7219
->clk_src
= clk_id
;
1052 freq
= clk_round_rate(da7219
->mclk
, freq
);
1053 ret
= clk_set_rate(da7219
->mclk
, freq
);
1055 dev_err(codec_dai
->dev
, "Failed to set clock rate %d\n",
1061 da7219
->mclk_rate
= freq
;
1066 static int da7219_set_dai_pll(struct snd_soc_dai
*codec_dai
, int pll_id
,
1067 int source
, unsigned int fref
, unsigned int fout
)
1069 struct snd_soc_codec
*codec
= codec_dai
->codec
;
1070 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1072 u8 pll_ctrl
, indiv_bits
, indiv
;
1073 u8 pll_frac_top
, pll_frac_bot
, pll_integer
;
1077 /* Verify 2MHz - 54MHz MCLK provided, and set input divider */
1078 if (da7219
->mclk_rate
< 2000000) {
1079 dev_err(codec
->dev
, "PLL input clock %d below valid range\n",
1082 } else if (da7219
->mclk_rate
<= 5000000) {
1083 indiv_bits
= DA7219_PLL_INDIV_2_5_MHZ
;
1084 indiv
= DA7219_PLL_INDIV_2_5_MHZ_VAL
;
1085 } else if (da7219
->mclk_rate
<= 10000000) {
1086 indiv_bits
= DA7219_PLL_INDIV_5_10_MHZ
;
1087 indiv
= DA7219_PLL_INDIV_5_10_MHZ_VAL
;
1088 } else if (da7219
->mclk_rate
<= 20000000) {
1089 indiv_bits
= DA7219_PLL_INDIV_10_20_MHZ
;
1090 indiv
= DA7219_PLL_INDIV_10_20_MHZ_VAL
;
1091 } else if (da7219
->mclk_rate
<= 40000000) {
1092 indiv_bits
= DA7219_PLL_INDIV_20_40_MHZ
;
1093 indiv
= DA7219_PLL_INDIV_20_40_MHZ_VAL
;
1094 } else if (da7219
->mclk_rate
<= 54000000) {
1095 indiv_bits
= DA7219_PLL_INDIV_40_54_MHZ
;
1096 indiv
= DA7219_PLL_INDIV_40_54_MHZ_VAL
;
1098 dev_err(codec
->dev
, "PLL input clock %d above valid range\n",
1102 freq_ref
= (da7219
->mclk_rate
/ indiv
);
1103 pll_ctrl
= indiv_bits
;
1107 case DA7219_SYSCLK_MCLK
:
1108 pll_ctrl
|= DA7219_PLL_MODE_BYPASS
;
1109 snd_soc_update_bits(codec
, DA7219_PLL_CTRL
,
1110 DA7219_PLL_INDIV_MASK
|
1111 DA7219_PLL_MODE_MASK
, pll_ctrl
);
1113 case DA7219_SYSCLK_PLL
:
1114 pll_ctrl
|= DA7219_PLL_MODE_NORMAL
;
1116 case DA7219_SYSCLK_PLL_SRM
:
1117 pll_ctrl
|= DA7219_PLL_MODE_SRM
;
1120 dev_err(codec
->dev
, "Invalid PLL config\n");
1124 /* Calculate dividers for PLL */
1125 pll_integer
= fout
/ freq_ref
;
1126 frac_div
= (u64
)(fout
% freq_ref
) * 8192ULL;
1127 do_div(frac_div
, freq_ref
);
1128 pll_frac_top
= (frac_div
>> DA7219_BYTE_SHIFT
) & DA7219_BYTE_MASK
;
1129 pll_frac_bot
= (frac_div
) & DA7219_BYTE_MASK
;
1131 /* Write PLL config & dividers */
1132 snd_soc_write(codec
, DA7219_PLL_FRAC_TOP
, pll_frac_top
);
1133 snd_soc_write(codec
, DA7219_PLL_FRAC_BOT
, pll_frac_bot
);
1134 snd_soc_write(codec
, DA7219_PLL_INTEGER
, pll_integer
);
1135 snd_soc_update_bits(codec
, DA7219_PLL_CTRL
,
1136 DA7219_PLL_INDIV_MASK
| DA7219_PLL_MODE_MASK
,
1142 static int da7219_set_dai_fmt(struct snd_soc_dai
*codec_dai
, unsigned int fmt
)
1144 struct snd_soc_codec
*codec
= codec_dai
->codec
;
1145 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1146 u8 dai_clk_mode
= 0, dai_ctrl
= 0;
1148 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
1149 case SND_SOC_DAIFMT_CBM_CFM
:
1150 da7219
->master
= true;
1152 case SND_SOC_DAIFMT_CBS_CFS
:
1153 da7219
->master
= false;
1159 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
1160 case SND_SOC_DAIFMT_I2S
:
1161 case SND_SOC_DAIFMT_LEFT_J
:
1162 case SND_SOC_DAIFMT_RIGHT_J
:
1163 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
1164 case SND_SOC_DAIFMT_NB_NF
:
1166 case SND_SOC_DAIFMT_NB_IF
:
1167 dai_clk_mode
|= DA7219_DAI_WCLK_POL_INV
;
1169 case SND_SOC_DAIFMT_IB_NF
:
1170 dai_clk_mode
|= DA7219_DAI_CLK_POL_INV
;
1172 case SND_SOC_DAIFMT_IB_IF
:
1173 dai_clk_mode
|= DA7219_DAI_WCLK_POL_INV
|
1174 DA7219_DAI_CLK_POL_INV
;
1180 case SND_SOC_DAIFMT_DSP_B
:
1181 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
1182 case SND_SOC_DAIFMT_NB_NF
:
1183 dai_clk_mode
|= DA7219_DAI_CLK_POL_INV
;
1185 case SND_SOC_DAIFMT_NB_IF
:
1186 dai_clk_mode
|= DA7219_DAI_WCLK_POL_INV
|
1187 DA7219_DAI_CLK_POL_INV
;
1189 case SND_SOC_DAIFMT_IB_NF
:
1191 case SND_SOC_DAIFMT_IB_IF
:
1192 dai_clk_mode
|= DA7219_DAI_WCLK_POL_INV
;
1202 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
1203 case SND_SOC_DAIFMT_I2S
:
1204 dai_ctrl
|= DA7219_DAI_FORMAT_I2S
;
1206 case SND_SOC_DAIFMT_LEFT_J
:
1207 dai_ctrl
|= DA7219_DAI_FORMAT_LEFT_J
;
1209 case SND_SOC_DAIFMT_RIGHT_J
:
1210 dai_ctrl
|= DA7219_DAI_FORMAT_RIGHT_J
;
1212 case SND_SOC_DAIFMT_DSP_B
:
1213 dai_ctrl
|= DA7219_DAI_FORMAT_DSP
;
1219 /* By default 64 BCLKs per WCLK is supported */
1220 dai_clk_mode
|= DA7219_DAI_BCLKS_PER_WCLK_64
;
1222 snd_soc_update_bits(codec
, DA7219_DAI_CLK_MODE
,
1223 DA7219_DAI_BCLKS_PER_WCLK_MASK
|
1224 DA7219_DAI_CLK_POL_MASK
| DA7219_DAI_WCLK_POL_MASK
,
1226 snd_soc_update_bits(codec
, DA7219_DAI_CTRL
, DA7219_DAI_FORMAT_MASK
,
1232 static int da7219_set_dai_tdm_slot(struct snd_soc_dai
*dai
,
1233 unsigned int tx_mask
, unsigned int rx_mask
,
1234 int slots
, int slot_width
)
1236 struct snd_soc_codec
*codec
= dai
->codec
;
1237 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1238 u8 dai_bclks_per_wclk
;
1242 /* No channels enabled so disable TDM, revert to 64-bit frames */
1244 snd_soc_update_bits(codec
, DA7219_DAI_TDM_CTRL
,
1245 DA7219_DAI_TDM_CH_EN_MASK
|
1246 DA7219_DAI_TDM_MODE_EN_MASK
, 0);
1247 snd_soc_update_bits(codec
, DA7219_DAI_CLK_MODE
,
1248 DA7219_DAI_BCLKS_PER_WCLK_MASK
,
1249 DA7219_DAI_BCLKS_PER_WCLK_64
);
1253 /* Check we have valid slots */
1254 if (fls(tx_mask
) > DA7219_DAI_TDM_MAX_SLOTS
) {
1255 dev_err(codec
->dev
, "Invalid number of slots, max = %d\n",
1256 DA7219_DAI_TDM_MAX_SLOTS
);
1260 /* Check we have a valid offset given */
1261 if (rx_mask
> DA7219_DAI_OFFSET_MAX
) {
1262 dev_err(codec
->dev
, "Invalid slot offset, max = %d\n",
1263 DA7219_DAI_OFFSET_MAX
);
1267 /* Calculate & validate frame size based on slot info provided. */
1268 frame_size
= slots
* slot_width
;
1269 switch (frame_size
) {
1271 dai_bclks_per_wclk
= DA7219_DAI_BCLKS_PER_WCLK_32
;
1274 dai_bclks_per_wclk
= DA7219_DAI_BCLKS_PER_WCLK_64
;
1277 dai_bclks_per_wclk
= DA7219_DAI_BCLKS_PER_WCLK_128
;
1280 dai_bclks_per_wclk
= DA7219_DAI_BCLKS_PER_WCLK_256
;
1283 dev_err(codec
->dev
, "Invalid frame size %d\n", frame_size
);
1287 snd_soc_update_bits(codec
, DA7219_DAI_CLK_MODE
,
1288 DA7219_DAI_BCLKS_PER_WCLK_MASK
,
1289 dai_bclks_per_wclk
);
1291 offset
= cpu_to_le16(rx_mask
);
1292 regmap_bulk_write(da7219
->regmap
, DA7219_DAI_OFFSET_LOWER
,
1293 &offset
, sizeof(offset
));
1295 snd_soc_update_bits(codec
, DA7219_DAI_TDM_CTRL
,
1296 DA7219_DAI_TDM_CH_EN_MASK
|
1297 DA7219_DAI_TDM_MODE_EN_MASK
,
1298 (tx_mask
<< DA7219_DAI_TDM_CH_EN_SHIFT
) |
1299 DA7219_DAI_TDM_MODE_EN_MASK
);
1304 static int da7219_hw_params(struct snd_pcm_substream
*substream
,
1305 struct snd_pcm_hw_params
*params
,
1306 struct snd_soc_dai
*dai
)
1308 struct snd_soc_codec
*codec
= dai
->codec
;
1309 u8 dai_ctrl
= 0, fs
;
1310 unsigned int channels
;
1312 switch (params_width(params
)) {
1314 dai_ctrl
|= DA7219_DAI_WORD_LENGTH_S16_LE
;
1317 dai_ctrl
|= DA7219_DAI_WORD_LENGTH_S20_LE
;
1320 dai_ctrl
|= DA7219_DAI_WORD_LENGTH_S24_LE
;
1323 dai_ctrl
|= DA7219_DAI_WORD_LENGTH_S32_LE
;
1329 channels
= params_channels(params
);
1330 if ((channels
< 1) || (channels
> DA7219_DAI_CH_NUM_MAX
)) {
1332 "Invalid number of channels, only 1 to %d supported\n",
1333 DA7219_DAI_CH_NUM_MAX
);
1336 dai_ctrl
|= channels
<< DA7219_DAI_CH_NUM_SHIFT
;
1338 switch (params_rate(params
)) {
1340 fs
= DA7219_SR_8000
;
1343 fs
= DA7219_SR_11025
;
1346 fs
= DA7219_SR_12000
;
1349 fs
= DA7219_SR_16000
;
1352 fs
= DA7219_SR_22050
;
1355 fs
= DA7219_SR_24000
;
1358 fs
= DA7219_SR_32000
;
1361 fs
= DA7219_SR_44100
;
1364 fs
= DA7219_SR_48000
;
1367 fs
= DA7219_SR_88200
;
1370 fs
= DA7219_SR_96000
;
1376 snd_soc_update_bits(codec
, DA7219_DAI_CTRL
,
1377 DA7219_DAI_WORD_LENGTH_MASK
|
1378 DA7219_DAI_CH_NUM_MASK
,
1380 snd_soc_write(codec
, DA7219_SR
, fs
);
1385 static const struct snd_soc_dai_ops da7219_dai_ops
= {
1386 .hw_params
= da7219_hw_params
,
1387 .set_sysclk
= da7219_set_dai_sysclk
,
1388 .set_pll
= da7219_set_dai_pll
,
1389 .set_fmt
= da7219_set_dai_fmt
,
1390 .set_tdm_slot
= da7219_set_dai_tdm_slot
,
1393 #define DA7219_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1394 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1396 static struct snd_soc_dai_driver da7219_dai
= {
1397 .name
= "da7219-hifi",
1399 .stream_name
= "Playback",
1401 .channels_max
= DA7219_DAI_CH_NUM_MAX
,
1402 .rates
= SNDRV_PCM_RATE_8000_96000
,
1403 .formats
= DA7219_FORMATS
,
1406 .stream_name
= "Capture",
1408 .channels_max
= DA7219_DAI_CH_NUM_MAX
,
1409 .rates
= SNDRV_PCM_RATE_8000_96000
,
1410 .formats
= DA7219_FORMATS
,
1412 .ops
= &da7219_dai_ops
,
1413 .symmetric_rates
= 1,
1414 .symmetric_channels
= 1,
1415 .symmetric_samplebits
= 1,
1423 static const struct of_device_id da7219_of_match
[] = {
1424 { .compatible
= "dlg,da7219", },
1427 MODULE_DEVICE_TABLE(of
, da7219_of_match
);
1429 static enum da7219_micbias_voltage
1430 da7219_of_micbias_lvl(struct snd_soc_codec
*codec
, u32 val
)
1434 return DA7219_MICBIAS_1_6V
;
1436 return DA7219_MICBIAS_1_8V
;
1438 return DA7219_MICBIAS_2_0V
;
1440 return DA7219_MICBIAS_2_2V
;
1442 return DA7219_MICBIAS_2_4V
;
1444 return DA7219_MICBIAS_2_6V
;
1446 dev_warn(codec
->dev
, "Invalid micbias level");
1447 return DA7219_MICBIAS_2_2V
;
1451 static enum da7219_mic_amp_in_sel
1452 da7219_of_mic_amp_in_sel(struct snd_soc_codec
*codec
, const char *str
)
1454 if (!strcmp(str
, "diff")) {
1455 return DA7219_MIC_AMP_IN_SEL_DIFF
;
1456 } else if (!strcmp(str
, "se_p")) {
1457 return DA7219_MIC_AMP_IN_SEL_SE_P
;
1458 } else if (!strcmp(str
, "se_n")) {
1459 return DA7219_MIC_AMP_IN_SEL_SE_N
;
1461 dev_warn(codec
->dev
, "Invalid mic input type selection");
1462 return DA7219_MIC_AMP_IN_SEL_DIFF
;
1466 static struct da7219_pdata
*da7219_of_to_pdata(struct snd_soc_codec
*codec
)
1468 struct device_node
*np
= codec
->dev
->of_node
;
1469 struct da7219_pdata
*pdata
;
1473 pdata
= devm_kzalloc(codec
->dev
, sizeof(*pdata
), GFP_KERNEL
);
1477 if (of_property_read_u32(np
, "dlg,micbias-lvl", &of_val32
) >= 0)
1478 pdata
->micbias_lvl
= da7219_of_micbias_lvl(codec
, of_val32
);
1480 pdata
->micbias_lvl
= DA7219_MICBIAS_2_2V
;
1482 if (!of_property_read_string(np
, "dlg,mic-amp-in-sel", &of_str
))
1483 pdata
->mic_amp_in_sel
= da7219_of_mic_amp_in_sel(codec
, of_str
);
1485 pdata
->mic_amp_in_sel
= DA7219_MIC_AMP_IN_SEL_DIFF
;
1492 * Codec driver functions
1495 static int da7219_set_bias_level(struct snd_soc_codec
*codec
,
1496 enum snd_soc_bias_level level
)
1498 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1502 case SND_SOC_BIAS_ON
:
1503 case SND_SOC_BIAS_PREPARE
:
1505 case SND_SOC_BIAS_STANDBY
:
1506 if (snd_soc_codec_get_bias_level(codec
) == SND_SOC_BIAS_OFF
) {
1509 ret
= clk_prepare_enable(da7219
->mclk
);
1512 "Failed to enable mclk\n");
1518 snd_soc_update_bits(codec
, DA7219_REFERENCES
,
1519 DA7219_BIAS_EN_MASK
,
1520 DA7219_BIAS_EN_MASK
);
1523 case SND_SOC_BIAS_OFF
:
1524 /* Only disable master bias if jack detection not active */
1525 if (!da7219
->aad
->jack
)
1526 snd_soc_update_bits(codec
, DA7219_REFERENCES
,
1527 DA7219_BIAS_EN_MASK
, 0);
1531 clk_disable_unprepare(da7219
->mclk
);
1538 static const char *da7219_supply_names
[DA7219_NUM_SUPPLIES
] = {
1539 [DA7219_SUPPLY_VDD
] = "VDD",
1540 [DA7219_SUPPLY_VDDMIC
] = "VDDMIC",
1541 [DA7219_SUPPLY_VDDIO
] = "VDDIO",
1544 static int da7219_handle_supplies(struct snd_soc_codec
*codec
)
1546 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1547 struct regulator
*vddio
;
1548 u8 io_voltage_lvl
= DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V
;
1551 /* Get required supplies */
1552 for (i
= 0; i
< DA7219_NUM_SUPPLIES
; ++i
)
1553 da7219
->supplies
[i
].supply
= da7219_supply_names
[i
];
1555 ret
= devm_regulator_bulk_get(codec
->dev
, DA7219_NUM_SUPPLIES
,
1558 dev_err(codec
->dev
, "Failed to get supplies");
1562 /* Determine VDDIO voltage provided */
1563 vddio
= da7219
->supplies
[DA7219_SUPPLY_VDDIO
].consumer
;
1564 ret
= regulator_get_voltage(vddio
);
1566 dev_warn(codec
->dev
, "Invalid VDDIO voltage\n");
1567 else if (ret
< 2800000)
1568 io_voltage_lvl
= DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V
;
1570 /* Enable main supplies */
1571 ret
= regulator_bulk_enable(DA7219_NUM_SUPPLIES
, da7219
->supplies
);
1573 dev_err(codec
->dev
, "Failed to enable supplies");
1577 /* Ensure device in active mode */
1578 snd_soc_write(codec
, DA7219_SYSTEM_ACTIVE
, DA7219_SYSTEM_ACTIVE_MASK
);
1580 /* Update IO voltage level range */
1581 snd_soc_write(codec
, DA7219_IO_CTRL
, io_voltage_lvl
);
1586 static void da7219_handle_pdata(struct snd_soc_codec
*codec
)
1588 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1589 struct da7219_pdata
*pdata
= da7219
->pdata
;
1594 /* Mic Bias voltages */
1595 switch (pdata
->micbias_lvl
) {
1596 case DA7219_MICBIAS_1_6V
:
1597 case DA7219_MICBIAS_1_8V
:
1598 case DA7219_MICBIAS_2_0V
:
1599 case DA7219_MICBIAS_2_2V
:
1600 case DA7219_MICBIAS_2_4V
:
1601 case DA7219_MICBIAS_2_6V
:
1602 micbias_lvl
|= (pdata
->micbias_lvl
<<
1603 DA7219_MICBIAS1_LEVEL_SHIFT
);
1607 snd_soc_write(codec
, DA7219_MICBIAS_CTRL
, micbias_lvl
);
1610 switch (pdata
->mic_amp_in_sel
) {
1611 case DA7219_MIC_AMP_IN_SEL_DIFF
:
1612 case DA7219_MIC_AMP_IN_SEL_SE_P
:
1613 case DA7219_MIC_AMP_IN_SEL_SE_N
:
1614 snd_soc_write(codec
, DA7219_MIC_1_SELECT
,
1615 pdata
->mic_amp_in_sel
);
1621 static struct reg_sequence da7219_rev_aa_patch
[] = {
1622 { DA7219_REFERENCES
, 0x08 },
1625 static int da7219_probe(struct snd_soc_codec
*codec
)
1627 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1631 mutex_init(&da7219
->lock
);
1633 /* Regulator configuration */
1634 ret
= da7219_handle_supplies(codec
);
1638 ret
= regmap_read(da7219
->regmap
, DA7219_CHIP_REVISION
, &rev
);
1640 dev_err(codec
->dev
, "Failed to read chip revision: %d\n", ret
);
1641 goto err_disable_reg
;
1644 switch (rev
& DA7219_CHIP_MINOR_MASK
) {
1646 ret
= regmap_register_patch(da7219
->regmap
, da7219_rev_aa_patch
,
1647 ARRAY_SIZE(da7219_rev_aa_patch
));
1649 dev_err(codec
->dev
, "Failed to register AA patch: %d\n",
1651 goto err_disable_reg
;
1658 /* Handle DT/Platform data */
1659 if (codec
->dev
->of_node
)
1660 da7219
->pdata
= da7219_of_to_pdata(codec
);
1662 da7219
->pdata
= dev_get_platdata(codec
->dev
);
1664 da7219_handle_pdata(codec
);
1666 /* Check if MCLK provided */
1667 da7219
->mclk
= devm_clk_get(codec
->dev
, "mclk");
1668 if (IS_ERR(da7219
->mclk
)) {
1669 if (PTR_ERR(da7219
->mclk
) != -ENOENT
) {
1670 ret
= PTR_ERR(da7219
->mclk
);
1671 goto err_disable_reg
;
1673 da7219
->mclk
= NULL
;
1677 /* Default PC counter to free-running */
1678 snd_soc_update_bits(codec
, DA7219_PC_COUNT
, DA7219_PC_FREERUN_MASK
,
1679 DA7219_PC_FREERUN_MASK
);
1681 /* Default gain ramping */
1682 snd_soc_update_bits(codec
, DA7219_MIXIN_L_CTRL
,
1683 DA7219_MIXIN_L_AMP_RAMP_EN_MASK
,
1684 DA7219_MIXIN_L_AMP_RAMP_EN_MASK
);
1685 snd_soc_update_bits(codec
, DA7219_ADC_L_CTRL
, DA7219_ADC_L_RAMP_EN_MASK
,
1686 DA7219_ADC_L_RAMP_EN_MASK
);
1687 snd_soc_update_bits(codec
, DA7219_DAC_L_CTRL
, DA7219_DAC_L_RAMP_EN_MASK
,
1688 DA7219_DAC_L_RAMP_EN_MASK
);
1689 snd_soc_update_bits(codec
, DA7219_DAC_R_CTRL
, DA7219_DAC_R_RAMP_EN_MASK
,
1690 DA7219_DAC_R_RAMP_EN_MASK
);
1691 snd_soc_update_bits(codec
, DA7219_HP_L_CTRL
,
1692 DA7219_HP_L_AMP_RAMP_EN_MASK
,
1693 DA7219_HP_L_AMP_RAMP_EN_MASK
);
1694 snd_soc_update_bits(codec
, DA7219_HP_R_CTRL
,
1695 DA7219_HP_R_AMP_RAMP_EN_MASK
,
1696 DA7219_HP_R_AMP_RAMP_EN_MASK
);
1698 /* Default infinite tone gen, start/stop by Kcontrol */
1699 snd_soc_write(codec
, DA7219_TONE_GEN_CYCLES
, DA7219_BEEP_CYCLES_MASK
);
1701 /* Initialise AAD block */
1702 ret
= da7219_aad_init(codec
);
1704 goto err_disable_reg
;
1709 regulator_bulk_disable(DA7219_NUM_SUPPLIES
, da7219
->supplies
);
1714 static int da7219_remove(struct snd_soc_codec
*codec
)
1716 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1718 da7219_aad_exit(codec
);
1721 return regulator_bulk_disable(DA7219_NUM_SUPPLIES
, da7219
->supplies
);
1725 static int da7219_suspend(struct snd_soc_codec
*codec
)
1727 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1729 snd_soc_codec_force_bias_level(codec
, SND_SOC_BIAS_OFF
);
1731 /* Put device into standby mode if jack detection disabled */
1732 if (!da7219
->aad
->jack
)
1733 snd_soc_write(codec
, DA7219_SYSTEM_ACTIVE
, 0);
1738 static int da7219_resume(struct snd_soc_codec
*codec
)
1740 struct da7219_priv
*da7219
= snd_soc_codec_get_drvdata(codec
);
1742 /* Put device into active mode if previously pushed to standby */
1743 if (!da7219
->aad
->jack
)
1744 snd_soc_write(codec
, DA7219_SYSTEM_ACTIVE
,
1745 DA7219_SYSTEM_ACTIVE_MASK
);
1747 snd_soc_codec_force_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
1752 #define da7219_suspend NULL
1753 #define da7219_resume NULL
1756 static struct snd_soc_codec_driver soc_codec_dev_da7219
= {
1757 .probe
= da7219_probe
,
1758 .remove
= da7219_remove
,
1759 .suspend
= da7219_suspend
,
1760 .resume
= da7219_resume
,
1761 .set_bias_level
= da7219_set_bias_level
,
1763 .controls
= da7219_snd_controls
,
1764 .num_controls
= ARRAY_SIZE(da7219_snd_controls
),
1766 .dapm_widgets
= da7219_dapm_widgets
,
1767 .num_dapm_widgets
= ARRAY_SIZE(da7219_dapm_widgets
),
1768 .dapm_routes
= da7219_audio_map
,
1769 .num_dapm_routes
= ARRAY_SIZE(da7219_audio_map
),
1777 static struct reg_default da7219_reg_defaults
[] = {
1778 { DA7219_MIC_1_SELECT
, 0x00 },
1779 { DA7219_CIF_TIMEOUT_CTRL
, 0x01 },
1780 { DA7219_SR_24_48
, 0x00 },
1781 { DA7219_SR
, 0x0A },
1782 { DA7219_CIF_I2C_ADDR_CFG
, 0x02 },
1783 { DA7219_PLL_CTRL
, 0x10 },
1784 { DA7219_PLL_FRAC_TOP
, 0x00 },
1785 { DA7219_PLL_FRAC_BOT
, 0x00 },
1786 { DA7219_PLL_INTEGER
, 0x20 },
1787 { DA7219_DIG_ROUTING_DAI
, 0x10 },
1788 { DA7219_DAI_CLK_MODE
, 0x01 },
1789 { DA7219_DAI_CTRL
, 0x28 },
1790 { DA7219_DAI_TDM_CTRL
, 0x40 },
1791 { DA7219_DIG_ROUTING_DAC
, 0x32 },
1792 { DA7219_DAI_OFFSET_LOWER
, 0x00 },
1793 { DA7219_DAI_OFFSET_UPPER
, 0x00 },
1794 { DA7219_REFERENCES
, 0x08 },
1795 { DA7219_MIXIN_L_SELECT
, 0x00 },
1796 { DA7219_MIXIN_L_GAIN
, 0x03 },
1797 { DA7219_ADC_L_GAIN
, 0x6F },
1798 { DA7219_ADC_FILTERS1
, 0x80 },
1799 { DA7219_MIC_1_GAIN
, 0x01 },
1800 { DA7219_SIDETONE_CTRL
, 0x40 },
1801 { DA7219_SIDETONE_GAIN
, 0x0E },
1802 { DA7219_DROUTING_ST_OUTFILT_1L
, 0x01 },
1803 { DA7219_DROUTING_ST_OUTFILT_1R
, 0x02 },
1804 { DA7219_DAC_FILTERS5
, 0x00 },
1805 { DA7219_DAC_FILTERS2
, 0x88 },
1806 { DA7219_DAC_FILTERS3
, 0x88 },
1807 { DA7219_DAC_FILTERS4
, 0x08 },
1808 { DA7219_DAC_FILTERS1
, 0x80 },
1809 { DA7219_DAC_L_GAIN
, 0x6F },
1810 { DA7219_DAC_R_GAIN
, 0x6F },
1811 { DA7219_CP_CTRL
, 0x20 },
1812 { DA7219_HP_L_GAIN
, 0x39 },
1813 { DA7219_HP_R_GAIN
, 0x39 },
1814 { DA7219_MIXOUT_L_SELECT
, 0x00 },
1815 { DA7219_MIXOUT_R_SELECT
, 0x00 },
1816 { DA7219_MICBIAS_CTRL
, 0x03 },
1817 { DA7219_MIC_1_CTRL
, 0x40 },
1818 { DA7219_MIXIN_L_CTRL
, 0x40 },
1819 { DA7219_ADC_L_CTRL
, 0x40 },
1820 { DA7219_DAC_L_CTRL
, 0x40 },
1821 { DA7219_DAC_R_CTRL
, 0x40 },
1822 { DA7219_HP_L_CTRL
, 0x40 },
1823 { DA7219_HP_R_CTRL
, 0x40 },
1824 { DA7219_MIXOUT_L_CTRL
, 0x10 },
1825 { DA7219_MIXOUT_R_CTRL
, 0x10 },
1826 { DA7219_CHIP_ID1
, 0x23 },
1827 { DA7219_CHIP_ID2
, 0x93 },
1828 { DA7219_IO_CTRL
, 0x00 },
1829 { DA7219_GAIN_RAMP_CTRL
, 0x00 },
1830 { DA7219_PC_COUNT
, 0x02 },
1831 { DA7219_CP_VOL_THRESHOLD1
, 0x0E },
1832 { DA7219_DIG_CTRL
, 0x00 },
1833 { DA7219_ALC_CTRL2
, 0x00 },
1834 { DA7219_ALC_CTRL3
, 0x00 },
1835 { DA7219_ALC_NOISE
, 0x3F },
1836 { DA7219_ALC_TARGET_MIN
, 0x3F },
1837 { DA7219_ALC_TARGET_MAX
, 0x00 },
1838 { DA7219_ALC_GAIN_LIMITS
, 0xFF },
1839 { DA7219_ALC_ANA_GAIN_LIMITS
, 0x71 },
1840 { DA7219_ALC_ANTICLIP_CTRL
, 0x00 },
1841 { DA7219_ALC_ANTICLIP_LEVEL
, 0x00 },
1842 { DA7219_DAC_NG_SETUP_TIME
, 0x00 },
1843 { DA7219_DAC_NG_OFF_THRESH
, 0x00 },
1844 { DA7219_DAC_NG_ON_THRESH
, 0x00 },
1845 { DA7219_DAC_NG_CTRL
, 0x00 },
1846 { DA7219_TONE_GEN_CFG1
, 0x00 },
1847 { DA7219_TONE_GEN_CFG2
, 0x00 },
1848 { DA7219_TONE_GEN_CYCLES
, 0x00 },
1849 { DA7219_TONE_GEN_FREQ1_L
, 0x55 },
1850 { DA7219_TONE_GEN_FREQ1_U
, 0x15 },
1851 { DA7219_TONE_GEN_FREQ2_L
, 0x00 },
1852 { DA7219_TONE_GEN_FREQ2_U
, 0x40 },
1853 { DA7219_TONE_GEN_ON_PER
, 0x02 },
1854 { DA7219_TONE_GEN_OFF_PER
, 0x01 },
1855 { DA7219_ACCDET_IRQ_MASK_A
, 0x00 },
1856 { DA7219_ACCDET_IRQ_MASK_B
, 0x00 },
1857 { DA7219_ACCDET_CONFIG_1
, 0xD6 },
1858 { DA7219_ACCDET_CONFIG_2
, 0x34 },
1859 { DA7219_ACCDET_CONFIG_3
, 0x0A },
1860 { DA7219_ACCDET_CONFIG_4
, 0x16 },
1861 { DA7219_ACCDET_CONFIG_5
, 0x21 },
1862 { DA7219_ACCDET_CONFIG_6
, 0x3E },
1863 { DA7219_ACCDET_CONFIG_7
, 0x01 },
1864 { DA7219_SYSTEM_ACTIVE
, 0x00 },
1867 static bool da7219_volatile_register(struct device
*dev
, unsigned int reg
)
1870 case DA7219_MIC_1_GAIN_STATUS
:
1871 case DA7219_MIXIN_L_GAIN_STATUS
:
1872 case DA7219_ADC_L_GAIN_STATUS
:
1873 case DA7219_DAC_L_GAIN_STATUS
:
1874 case DA7219_DAC_R_GAIN_STATUS
:
1875 case DA7219_HP_L_GAIN_STATUS
:
1876 case DA7219_HP_R_GAIN_STATUS
:
1877 case DA7219_CIF_CTRL
:
1878 case DA7219_PLL_SRM_STS
:
1879 case DA7219_ALC_CTRL1
:
1880 case DA7219_SYSTEM_MODES_INPUT
:
1881 case DA7219_SYSTEM_MODES_OUTPUT
:
1882 case DA7219_ALC_OFFSET_AUTO_M_L
:
1883 case DA7219_ALC_OFFSET_AUTO_U_L
:
1884 case DA7219_TONE_GEN_CFG1
:
1885 case DA7219_ACCDET_STATUS_A
:
1886 case DA7219_ACCDET_STATUS_B
:
1887 case DA7219_ACCDET_IRQ_EVENT_A
:
1888 case DA7219_ACCDET_IRQ_EVENT_B
:
1889 case DA7219_ACCDET_CONFIG_8
:
1890 case DA7219_SYSTEM_STATUS
:
1897 static const struct regmap_config da7219_regmap_config
= {
1901 .max_register
= DA7219_SYSTEM_ACTIVE
,
1902 .reg_defaults
= da7219_reg_defaults
,
1903 .num_reg_defaults
= ARRAY_SIZE(da7219_reg_defaults
),
1904 .volatile_reg
= da7219_volatile_register
,
1905 .cache_type
= REGCACHE_RBTREE
,
1913 static int da7219_i2c_probe(struct i2c_client
*i2c
,
1914 const struct i2c_device_id
*id
)
1916 struct da7219_priv
*da7219
;
1919 da7219
= devm_kzalloc(&i2c
->dev
, sizeof(struct da7219_priv
),
1924 i2c_set_clientdata(i2c
, da7219
);
1926 da7219
->regmap
= devm_regmap_init_i2c(i2c
, &da7219_regmap_config
);
1927 if (IS_ERR(da7219
->regmap
)) {
1928 ret
= PTR_ERR(da7219
->regmap
);
1929 dev_err(&i2c
->dev
, "regmap_init() failed: %d\n", ret
);
1933 ret
= snd_soc_register_codec(&i2c
->dev
, &soc_codec_dev_da7219
,
1936 dev_err(&i2c
->dev
, "Failed to register da7219 codec: %d\n",
1942 static int da7219_i2c_remove(struct i2c_client
*client
)
1944 snd_soc_unregister_codec(&client
->dev
);
1948 static const struct i2c_device_id da7219_i2c_id
[] = {
1952 MODULE_DEVICE_TABLE(i2c
, da7219_i2c_id
);
1954 static struct i2c_driver da7219_i2c_driver
= {
1957 .of_match_table
= of_match_ptr(da7219_of_match
),
1959 .probe
= da7219_i2c_probe
,
1960 .remove
= da7219_i2c_remove
,
1961 .id_table
= da7219_i2c_id
,
1964 module_i2c_driver(da7219_i2c_driver
);
1966 MODULE_DESCRIPTION("ASoC DA7219 Codec Driver");
1967 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
1968 MODULE_LICENSE("GPL");