1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * da7218.c - DA7218 ALSA SoC Codec Driver |
4 | * |
5 | * Copyright (c) 2015 Dialog Semiconductor |
6 | * |
7 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> |
8 | */ |
9 | |
10 | #include <linux/clk.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/of.h> |
13 | #include <linux/regmap.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/pm.h> |
16 | #include <linux/module.h> |
17 | #include <linux/delay.h> |
18 | #include <linux/regulator/consumer.h> |
19 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> |
21 | #include <sound/soc.h> |
22 | #include <sound/soc-dapm.h> |
23 | #include <sound/jack.h> |
24 | #include <sound/initval.h> |
25 | #include <sound/tlv.h> |
26 | #include <asm/div64.h> |
27 | |
28 | #include <sound/da7218.h> |
29 | #include "da7218.h" |
30 | |
31 | |
32 | /* |
33 | * TLVs and Enums |
34 | */ |
35 | |
36 | /* Input TLVs */ |
37 | static const DECLARE_TLV_DB_SCALE(da7218_mic_gain_tlv, -600, 600, 0); |
38 | static const DECLARE_TLV_DB_SCALE(da7218_mixin_gain_tlv, -450, 150, 0); |
39 | static const DECLARE_TLV_DB_SCALE(da7218_in_dig_gain_tlv, -8325, 75, 0); |
40 | static const DECLARE_TLV_DB_SCALE(da7218_ags_trigger_tlv, -9000, 600, 0); |
41 | static const DECLARE_TLV_DB_SCALE(da7218_ags_att_max_tlv, 0, 600, 0); |
42 | static const DECLARE_TLV_DB_SCALE(da7218_alc_threshold_tlv, -9450, 150, 0); |
43 | static const DECLARE_TLV_DB_SCALE(da7218_alc_gain_tlv, 0, 600, 0); |
44 | static const DECLARE_TLV_DB_SCALE(da7218_alc_ana_gain_tlv, 0, 600, 0); |
45 | |
46 | /* Input/Output TLVs */ |
47 | static const DECLARE_TLV_DB_SCALE(da7218_dmix_gain_tlv, -4200, 150, 0); |
48 | |
49 | /* Output TLVs */ |
50 | static const DECLARE_TLV_DB_SCALE(da7218_dgs_trigger_tlv, -9450, 150, 0); |
51 | static const DECLARE_TLV_DB_SCALE(da7218_dgs_anticlip_tlv, -4200, 600, 0); |
52 | static const DECLARE_TLV_DB_SCALE(da7218_dgs_signal_tlv, -9000, 600, 0); |
53 | static const DECLARE_TLV_DB_SCALE(da7218_out_eq_band_tlv, -1050, 150, 0); |
54 | static const DECLARE_TLV_DB_SCALE(da7218_out_dig_gain_tlv, -8325, 75, 0); |
55 | static const DECLARE_TLV_DB_SCALE(da7218_dac_ng_threshold_tlv, -10200, 600, 0); |
56 | static const DECLARE_TLV_DB_SCALE(da7218_mixout_gain_tlv, -100, 50, 0); |
57 | static const DECLARE_TLV_DB_SCALE(da7218_hp_gain_tlv, -5700, 150, 0); |
58 | |
59 | /* Input Enums */ |
60 | static const char * const da7218_alc_attack_rate_txt[] = { |
61 | "7.33/fs" , "14.66/fs" , "29.32/fs" , "58.64/fs" , "117.3/fs" , "234.6/fs" , |
62 | "469.1/fs" , "938.2/fs" , "1876/fs" , "3753/fs" , "7506/fs" , "15012/fs" , |
63 | "30024/fs" , |
64 | }; |
65 | |
66 | static const struct soc_enum da7218_alc_attack_rate = |
67 | SOC_ENUM_SINGLE(DA7218_ALC_CTRL2, DA7218_ALC_ATTACK_SHIFT, |
68 | DA7218_ALC_ATTACK_MAX, da7218_alc_attack_rate_txt); |
69 | |
70 | static const char * const da7218_alc_release_rate_txt[] = { |
71 | "28.66/fs" , "57.33/fs" , "114.6/fs" , "229.3/fs" , "458.6/fs" , "917.1/fs" , |
72 | "1834/fs" , "3668/fs" , "7337/fs" , "14674/fs" , "29348/fs" , |
73 | }; |
74 | |
75 | static const struct soc_enum da7218_alc_release_rate = |
76 | SOC_ENUM_SINGLE(DA7218_ALC_CTRL2, DA7218_ALC_RELEASE_SHIFT, |
77 | DA7218_ALC_RELEASE_MAX, da7218_alc_release_rate_txt); |
78 | |
79 | static const char * const da7218_alc_hold_time_txt[] = { |
80 | "62/fs" , "124/fs" , "248/fs" , "496/fs" , "992/fs" , "1984/fs" , "3968/fs" , |
81 | "7936/fs" , "15872/fs" , "31744/fs" , "63488/fs" , "126976/fs" , |
82 | "253952/fs" , "507904/fs" , "1015808/fs" , "2031616/fs" |
83 | }; |
84 | |
85 | static const struct soc_enum da7218_alc_hold_time = |
86 | SOC_ENUM_SINGLE(DA7218_ALC_CTRL3, DA7218_ALC_HOLD_SHIFT, |
87 | DA7218_ALC_HOLD_MAX, da7218_alc_hold_time_txt); |
88 | |
89 | static const char * const da7218_alc_anticlip_step_txt[] = { |
90 | "0.034dB/fs" , "0.068dB/fs" , "0.136dB/fs" , "0.272dB/fs" , |
91 | }; |
92 | |
93 | static const struct soc_enum da7218_alc_anticlip_step = |
94 | SOC_ENUM_SINGLE(DA7218_ALC_ANTICLIP_CTRL, |
95 | DA7218_ALC_ANTICLIP_STEP_SHIFT, |
96 | DA7218_ALC_ANTICLIP_STEP_MAX, |
97 | da7218_alc_anticlip_step_txt); |
98 | |
99 | static const char * const da7218_integ_rate_txt[] = { |
100 | "1/4" , "1/16" , "1/256" , "1/65536" |
101 | }; |
102 | |
103 | static const struct soc_enum da7218_integ_attack_rate = |
104 | SOC_ENUM_SINGLE(DA7218_ENV_TRACK_CTRL, DA7218_INTEG_ATTACK_SHIFT, |
105 | DA7218_INTEG_MAX, da7218_integ_rate_txt); |
106 | |
107 | static const struct soc_enum da7218_integ_release_rate = |
108 | SOC_ENUM_SINGLE(DA7218_ENV_TRACK_CTRL, DA7218_INTEG_RELEASE_SHIFT, |
109 | DA7218_INTEG_MAX, da7218_integ_rate_txt); |
110 | |
111 | /* Input/Output Enums */ |
112 | static const char * const da7218_gain_ramp_rate_txt[] = { |
113 | "Nominal Rate * 8" , "Nominal Rate" , "Nominal Rate / 8" , |
114 | "Nominal Rate / 16" , |
115 | }; |
116 | |
117 | static const struct soc_enum da7218_gain_ramp_rate = |
118 | SOC_ENUM_SINGLE(DA7218_GAIN_RAMP_CTRL, DA7218_GAIN_RAMP_RATE_SHIFT, |
119 | DA7218_GAIN_RAMP_RATE_MAX, da7218_gain_ramp_rate_txt); |
120 | |
121 | static const char * const da7218_hpf_mode_txt[] = { |
122 | "Disabled" , "Audio" , "Voice" , |
123 | }; |
124 | |
125 | static const unsigned int da7218_hpf_mode_val[] = { |
126 | DA7218_HPF_DISABLED, DA7218_HPF_AUDIO_EN, DA7218_HPF_VOICE_EN, |
127 | }; |
128 | |
129 | static const struct soc_enum da7218_in1_hpf_mode = |
130 | SOC_VALUE_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL, |
131 | DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK, |
132 | DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt, |
133 | da7218_hpf_mode_val); |
134 | |
135 | static const struct soc_enum da7218_in2_hpf_mode = |
136 | SOC_VALUE_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL, |
137 | DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK, |
138 | DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt, |
139 | da7218_hpf_mode_val); |
140 | |
141 | static const struct soc_enum da7218_out1_hpf_mode = |
142 | SOC_VALUE_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL, |
143 | DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK, |
144 | DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt, |
145 | da7218_hpf_mode_val); |
146 | |
147 | static const char * const da7218_audio_hpf_corner_txt[] = { |
148 | "2Hz" , "4Hz" , "8Hz" , "16Hz" , |
149 | }; |
150 | |
151 | static const struct soc_enum da7218_in1_audio_hpf_corner = |
152 | SOC_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL, |
153 | DA7218_IN_1_AUDIO_HPF_CORNER_SHIFT, |
154 | DA7218_AUDIO_HPF_CORNER_MAX, |
155 | da7218_audio_hpf_corner_txt); |
156 | |
157 | static const struct soc_enum da7218_in2_audio_hpf_corner = |
158 | SOC_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL, |
159 | DA7218_IN_2_AUDIO_HPF_CORNER_SHIFT, |
160 | DA7218_AUDIO_HPF_CORNER_MAX, |
161 | da7218_audio_hpf_corner_txt); |
162 | |
163 | static const struct soc_enum da7218_out1_audio_hpf_corner = |
164 | SOC_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL, |
165 | DA7218_OUT_1_AUDIO_HPF_CORNER_SHIFT, |
166 | DA7218_AUDIO_HPF_CORNER_MAX, |
167 | da7218_audio_hpf_corner_txt); |
168 | |
169 | static const char * const da7218_voice_hpf_corner_txt[] = { |
170 | "2.5Hz" , "25Hz" , "50Hz" , "100Hz" , "150Hz" , "200Hz" , "300Hz" , "400Hz" , |
171 | }; |
172 | |
173 | static const struct soc_enum da7218_in1_voice_hpf_corner = |
174 | SOC_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL, |
175 | DA7218_IN_1_VOICE_HPF_CORNER_SHIFT, |
176 | DA7218_VOICE_HPF_CORNER_MAX, |
177 | da7218_voice_hpf_corner_txt); |
178 | |
179 | static const struct soc_enum da7218_in2_voice_hpf_corner = |
180 | SOC_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL, |
181 | DA7218_IN_2_VOICE_HPF_CORNER_SHIFT, |
182 | DA7218_VOICE_HPF_CORNER_MAX, |
183 | da7218_voice_hpf_corner_txt); |
184 | |
185 | static const struct soc_enum da7218_out1_voice_hpf_corner = |
186 | SOC_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL, |
187 | DA7218_OUT_1_VOICE_HPF_CORNER_SHIFT, |
188 | DA7218_VOICE_HPF_CORNER_MAX, |
189 | da7218_voice_hpf_corner_txt); |
190 | |
191 | static const char * const da7218_tonegen_dtmf_key_txt[] = { |
192 | "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , |
193 | "*" , "#" |
194 | }; |
195 | |
196 | static const struct soc_enum da7218_tonegen_dtmf_key = |
197 | SOC_ENUM_SINGLE(DA7218_TONE_GEN_CFG1, DA7218_DTMF_REG_SHIFT, |
198 | DA7218_DTMF_REG_MAX, da7218_tonegen_dtmf_key_txt); |
199 | |
200 | static const char * const da7218_tonegen_swg_sel_txt[] = { |
201 | "Sum" , "SWG1" , "SWG2" , "SWG1_1-Cos" |
202 | }; |
203 | |
204 | static const struct soc_enum da7218_tonegen_swg_sel = |
205 | SOC_ENUM_SINGLE(DA7218_TONE_GEN_CFG2, DA7218_SWG_SEL_SHIFT, |
206 | DA7218_SWG_SEL_MAX, da7218_tonegen_swg_sel_txt); |
207 | |
208 | /* Output Enums */ |
209 | static const char * const da7218_dgs_rise_coeff_txt[] = { |
210 | "1/1" , "1/16" , "1/64" , "1/256" , "1/1024" , "1/4096" , "1/16384" , |
211 | }; |
212 | |
213 | static const struct soc_enum da7218_dgs_rise_coeff = |
214 | SOC_ENUM_SINGLE(DA7218_DGS_RISE_FALL, DA7218_DGS_RISE_COEFF_SHIFT, |
215 | DA7218_DGS_RISE_COEFF_MAX, da7218_dgs_rise_coeff_txt); |
216 | |
217 | static const char * const da7218_dgs_fall_coeff_txt[] = { |
218 | "1/4" , "1/16" , "1/64" , "1/256" , "1/1024" , "1/4096" , "1/16384" , "1/65536" , |
219 | }; |
220 | |
221 | static const struct soc_enum da7218_dgs_fall_coeff = |
222 | SOC_ENUM_SINGLE(DA7218_DGS_RISE_FALL, DA7218_DGS_FALL_COEFF_SHIFT, |
223 | DA7218_DGS_FALL_COEFF_MAX, da7218_dgs_fall_coeff_txt); |
224 | |
225 | static const char * const da7218_dac_ng_setup_time_txt[] = { |
226 | "256 Samples" , "512 Samples" , "1024 Samples" , "2048 Samples" |
227 | }; |
228 | |
229 | static const struct soc_enum da7218_dac_ng_setup_time = |
230 | SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME, |
231 | DA7218_DAC_NG_SETUP_TIME_SHIFT, |
232 | DA7218_DAC_NG_SETUP_TIME_MAX, |
233 | da7218_dac_ng_setup_time_txt); |
234 | |
235 | static const char * const da7218_dac_ng_rampup_txt[] = { |
236 | "0.22ms/dB" , "0.0138ms/dB" |
237 | }; |
238 | |
239 | static const struct soc_enum da7218_dac_ng_rampup_rate = |
240 | SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME, |
241 | DA7218_DAC_NG_RAMPUP_RATE_SHIFT, |
242 | DA7218_DAC_NG_RAMPUP_RATE_MAX, |
243 | da7218_dac_ng_rampup_txt); |
244 | |
245 | static const char * const da7218_dac_ng_rampdown_txt[] = { |
246 | "0.88ms/dB" , "14.08ms/dB" |
247 | }; |
248 | |
249 | static const struct soc_enum da7218_dac_ng_rampdown_rate = |
250 | SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME, |
251 | DA7218_DAC_NG_RAMPDN_RATE_SHIFT, |
252 | DA7218_DAC_NG_RAMPDN_RATE_MAX, |
253 | da7218_dac_ng_rampdown_txt); |
254 | |
255 | static const char * const da7218_cp_mchange_txt[] = { |
256 | "Largest Volume" , "DAC Volume" , "Signal Magnitude" |
257 | }; |
258 | |
259 | static const unsigned int da7218_cp_mchange_val[] = { |
260 | DA7218_CP_MCHANGE_LARGEST_VOL, DA7218_CP_MCHANGE_DAC_VOL, |
261 | DA7218_CP_MCHANGE_SIG_MAG |
262 | }; |
263 | |
264 | static const struct soc_enum da7218_cp_mchange = |
265 | SOC_VALUE_ENUM_SINGLE(DA7218_CP_CTRL, DA7218_CP_MCHANGE_SHIFT, |
266 | DA7218_CP_MCHANGE_REL_MASK, DA7218_CP_MCHANGE_MAX, |
267 | da7218_cp_mchange_txt, da7218_cp_mchange_val); |
268 | |
269 | static const char * const da7218_cp_fcontrol_txt[] = { |
270 | "1MHz" , "500KHz" , "250KHz" , "125KHz" , "63KHz" , "0KHz" |
271 | }; |
272 | |
273 | static const struct soc_enum da7218_cp_fcontrol = |
274 | SOC_ENUM_SINGLE(DA7218_CP_DELAY, DA7218_CP_FCONTROL_SHIFT, |
275 | DA7218_CP_FCONTROL_MAX, da7218_cp_fcontrol_txt); |
276 | |
277 | static const char * const da7218_cp_tau_delay_txt[] = { |
278 | "0ms" , "2ms" , "4ms" , "16ms" , "64ms" , "128ms" , "256ms" , "512ms" |
279 | }; |
280 | |
281 | static const struct soc_enum da7218_cp_tau_delay = |
282 | SOC_ENUM_SINGLE(DA7218_CP_DELAY, DA7218_CP_TAU_DELAY_SHIFT, |
283 | DA7218_CP_TAU_DELAY_MAX, da7218_cp_tau_delay_txt); |
284 | |
285 | /* |
286 | * Control Functions |
287 | */ |
288 | |
289 | /* ALC */ |
290 | static void da7218_alc_calib(struct snd_soc_component *component) |
291 | { |
292 | u8 mic_1_ctrl, mic_2_ctrl; |
293 | u8 mixin_1_ctrl, mixin_2_ctrl; |
294 | u8 in_1l_filt_ctrl, in_1r_filt_ctrl, in_2l_filt_ctrl, in_2r_filt_ctrl; |
295 | u8 in_1_hpf_ctrl, in_2_hpf_ctrl; |
296 | u8 calib_ctrl; |
297 | int i = 0; |
298 | bool calibrated = false; |
299 | |
300 | /* Save current state of MIC control registers */ |
301 | mic_1_ctrl = snd_soc_component_read(component, DA7218_MIC_1_CTRL); |
302 | mic_2_ctrl = snd_soc_component_read(component, DA7218_MIC_2_CTRL); |
303 | |
304 | /* Save current state of input mixer control registers */ |
305 | mixin_1_ctrl = snd_soc_component_read(component, DA7218_MIXIN_1_CTRL); |
306 | mixin_2_ctrl = snd_soc_component_read(component, DA7218_MIXIN_2_CTRL); |
307 | |
308 | /* Save current state of input filter control registers */ |
309 | in_1l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1L_FILTER_CTRL); |
310 | in_1r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1R_FILTER_CTRL); |
311 | in_2l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2L_FILTER_CTRL); |
312 | in_2r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2R_FILTER_CTRL); |
313 | |
314 | /* Save current state of input HPF control registers */ |
315 | in_1_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_1_HPF_FILTER_CTRL); |
316 | in_2_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_2_HPF_FILTER_CTRL); |
317 | |
318 | /* Enable then Mute MIC PGAs */ |
319 | snd_soc_component_update_bits(component, DA7218_MIC_1_CTRL, DA7218_MIC_1_AMP_EN_MASK, |
320 | DA7218_MIC_1_AMP_EN_MASK); |
321 | snd_soc_component_update_bits(component, DA7218_MIC_2_CTRL, DA7218_MIC_2_AMP_EN_MASK, |
322 | DA7218_MIC_2_AMP_EN_MASK); |
323 | snd_soc_component_update_bits(component, DA7218_MIC_1_CTRL, |
324 | DA7218_MIC_1_AMP_MUTE_EN_MASK, |
325 | DA7218_MIC_1_AMP_MUTE_EN_MASK); |
326 | snd_soc_component_update_bits(component, DA7218_MIC_2_CTRL, |
327 | DA7218_MIC_2_AMP_MUTE_EN_MASK, |
328 | DA7218_MIC_2_AMP_MUTE_EN_MASK); |
329 | |
330 | /* Enable input mixers unmuted */ |
331 | snd_soc_component_update_bits(component, DA7218_MIXIN_1_CTRL, |
332 | DA7218_MIXIN_1_AMP_EN_MASK | |
333 | DA7218_MIXIN_1_AMP_MUTE_EN_MASK, |
334 | DA7218_MIXIN_1_AMP_EN_MASK); |
335 | snd_soc_component_update_bits(component, DA7218_MIXIN_2_CTRL, |
336 | DA7218_MIXIN_2_AMP_EN_MASK | |
337 | DA7218_MIXIN_2_AMP_MUTE_EN_MASK, |
338 | DA7218_MIXIN_2_AMP_EN_MASK); |
339 | |
340 | /* Enable input filters unmuted */ |
341 | snd_soc_component_update_bits(component, DA7218_IN_1L_FILTER_CTRL, |
342 | DA7218_IN_1L_FILTER_EN_MASK | |
343 | DA7218_IN_1L_MUTE_EN_MASK, |
344 | DA7218_IN_1L_FILTER_EN_MASK); |
345 | snd_soc_component_update_bits(component, DA7218_IN_1R_FILTER_CTRL, |
346 | DA7218_IN_1R_FILTER_EN_MASK | |
347 | DA7218_IN_1R_MUTE_EN_MASK, |
348 | DA7218_IN_1R_FILTER_EN_MASK); |
349 | snd_soc_component_update_bits(component, DA7218_IN_2L_FILTER_CTRL, |
350 | DA7218_IN_2L_FILTER_EN_MASK | |
351 | DA7218_IN_2L_MUTE_EN_MASK, |
352 | DA7218_IN_2L_FILTER_EN_MASK); |
353 | snd_soc_component_update_bits(component, DA7218_IN_2R_FILTER_CTRL, |
354 | DA7218_IN_2R_FILTER_EN_MASK | |
355 | DA7218_IN_2R_MUTE_EN_MASK, |
356 | DA7218_IN_2R_FILTER_EN_MASK); |
357 | |
358 | /* |
359 | * Make sure input HPFs voice mode is disabled, otherwise for sampling |
360 | * rates above 32KHz the ADC signals will be stopped and will cause |
361 | * calibration to lock up. |
362 | */ |
363 | snd_soc_component_update_bits(component, DA7218_IN_1_HPF_FILTER_CTRL, |
364 | DA7218_IN_1_VOICE_EN_MASK, val: 0); |
365 | snd_soc_component_update_bits(component, DA7218_IN_2_HPF_FILTER_CTRL, |
366 | DA7218_IN_2_VOICE_EN_MASK, val: 0); |
367 | |
368 | /* Perform auto calibration */ |
369 | snd_soc_component_update_bits(component, DA7218_CALIB_CTRL, DA7218_CALIB_AUTO_EN_MASK, |
370 | DA7218_CALIB_AUTO_EN_MASK); |
371 | do { |
372 | calib_ctrl = snd_soc_component_read(component, DA7218_CALIB_CTRL); |
373 | if (calib_ctrl & DA7218_CALIB_AUTO_EN_MASK) { |
374 | ++i; |
375 | usleep_range(DA7218_ALC_CALIB_DELAY_MIN, |
376 | DA7218_ALC_CALIB_DELAY_MAX); |
377 | } else { |
378 | calibrated = true; |
379 | } |
380 | |
381 | } while ((i < DA7218_ALC_CALIB_MAX_TRIES) && (!calibrated)); |
382 | |
383 | /* If auto calibration fails, disable DC offset, hybrid ALC */ |
384 | if ((!calibrated) || (calib_ctrl & DA7218_CALIB_OVERFLOW_MASK)) { |
385 | dev_warn(component->dev, |
386 | "ALC auto calibration failed - %s\n" , |
387 | (calibrated) ? "overflow" : "timeout" ); |
388 | snd_soc_component_update_bits(component, DA7218_CALIB_CTRL, |
389 | DA7218_CALIB_OFFSET_EN_MASK, val: 0); |
390 | snd_soc_component_update_bits(component, DA7218_ALC_CTRL1, |
391 | DA7218_ALC_SYNC_MODE_MASK, val: 0); |
392 | |
393 | } else { |
394 | /* Enable DC offset cancellation */ |
395 | snd_soc_component_update_bits(component, DA7218_CALIB_CTRL, |
396 | DA7218_CALIB_OFFSET_EN_MASK, |
397 | DA7218_CALIB_OFFSET_EN_MASK); |
398 | |
399 | /* Enable ALC hybrid mode */ |
400 | snd_soc_component_update_bits(component, DA7218_ALC_CTRL1, |
401 | DA7218_ALC_SYNC_MODE_MASK, |
402 | DA7218_ALC_SYNC_MODE_CH1 | |
403 | DA7218_ALC_SYNC_MODE_CH2); |
404 | } |
405 | |
406 | /* Restore input HPF control registers to original states */ |
407 | snd_soc_component_write(component, DA7218_IN_1_HPF_FILTER_CTRL, val: in_1_hpf_ctrl); |
408 | snd_soc_component_write(component, DA7218_IN_2_HPF_FILTER_CTRL, val: in_2_hpf_ctrl); |
409 | |
410 | /* Restore input filter control registers to original states */ |
411 | snd_soc_component_write(component, DA7218_IN_1L_FILTER_CTRL, val: in_1l_filt_ctrl); |
412 | snd_soc_component_write(component, DA7218_IN_1R_FILTER_CTRL, val: in_1r_filt_ctrl); |
413 | snd_soc_component_write(component, DA7218_IN_2L_FILTER_CTRL, val: in_2l_filt_ctrl); |
414 | snd_soc_component_write(component, DA7218_IN_2R_FILTER_CTRL, val: in_2r_filt_ctrl); |
415 | |
416 | /* Restore input mixer control registers to original state */ |
417 | snd_soc_component_write(component, DA7218_MIXIN_1_CTRL, val: mixin_1_ctrl); |
418 | snd_soc_component_write(component, DA7218_MIXIN_2_CTRL, val: mixin_2_ctrl); |
419 | |
420 | /* Restore MIC control registers to original states */ |
421 | snd_soc_component_write(component, DA7218_MIC_1_CTRL, val: mic_1_ctrl); |
422 | snd_soc_component_write(component, DA7218_MIC_2_CTRL, val: mic_2_ctrl); |
423 | } |
424 | |
425 | static int da7218_mixin_gain_put(struct snd_kcontrol *kcontrol, |
426 | struct snd_ctl_elem_value *ucontrol) |
427 | { |
428 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
429 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
430 | int ret; |
431 | |
432 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
433 | |
434 | /* |
435 | * If ALC in operation and value of control has been updated, |
436 | * make sure calibrated offsets are updated. |
437 | */ |
438 | if ((ret == 1) && (da7218->alc_en)) |
439 | da7218_alc_calib(component); |
440 | |
441 | return ret; |
442 | } |
443 | |
444 | static int da7218_alc_sw_put(struct snd_kcontrol *kcontrol, |
445 | struct snd_ctl_elem_value *ucontrol) |
446 | { |
447 | struct soc_mixer_control *mc = |
448 | (struct soc_mixer_control *) kcontrol->private_value; |
449 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
450 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
451 | unsigned int lvalue = ucontrol->value.integer.value[0]; |
452 | unsigned int rvalue = ucontrol->value.integer.value[1]; |
453 | unsigned int lshift = mc->shift; |
454 | unsigned int rshift = mc->rshift; |
455 | unsigned int mask = (mc->max << lshift) | (mc->max << rshift); |
456 | |
457 | /* Force ALC offset calibration if enabling ALC */ |
458 | if ((lvalue || rvalue) && (!da7218->alc_en)) |
459 | da7218_alc_calib(component); |
460 | |
461 | /* Update bits to detail which channels are enabled/disabled */ |
462 | da7218->alc_en &= ~mask; |
463 | da7218->alc_en |= (lvalue << lshift) | (rvalue << rshift); |
464 | |
465 | return snd_soc_put_volsw(kcontrol, ucontrol); |
466 | } |
467 | |
468 | /* ToneGen */ |
469 | static int da7218_tonegen_freq_get(struct snd_kcontrol *kcontrol, |
470 | struct snd_ctl_elem_value *ucontrol) |
471 | { |
472 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
473 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
474 | struct soc_mixer_control *mixer_ctrl = |
475 | (struct soc_mixer_control *) kcontrol->private_value; |
476 | unsigned int reg = mixer_ctrl->reg; |
477 | u16 val; |
478 | int ret; |
479 | |
480 | /* |
481 | * Frequency value spans two 8-bit registers, lower then upper byte. |
482 | * Therefore we need to convert to host endianness here. |
483 | */ |
484 | ret = regmap_raw_read(map: da7218->regmap, reg, val: &val, val_len: 2); |
485 | if (ret) |
486 | return ret; |
487 | |
488 | ucontrol->value.integer.value[0] = le16_to_cpu(val); |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | static int da7218_tonegen_freq_put(struct snd_kcontrol *kcontrol, |
494 | struct snd_ctl_elem_value *ucontrol) |
495 | { |
496 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
497 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
498 | struct soc_mixer_control *mixer_ctrl = |
499 | (struct soc_mixer_control *) kcontrol->private_value; |
500 | unsigned int reg = mixer_ctrl->reg; |
501 | u16 val; |
502 | |
503 | /* |
504 | * Frequency value spans two 8-bit registers, lower then upper byte. |
505 | * Therefore we need to convert to little endian here to align with |
506 | * HW registers. |
507 | */ |
508 | val = cpu_to_le16(ucontrol->value.integer.value[0]); |
509 | |
510 | return regmap_raw_write(map: da7218->regmap, reg, val: &val, val_len: 2); |
511 | } |
512 | |
513 | static int da7218_mic_lvl_det_sw_put(struct snd_kcontrol *kcontrol, |
514 | struct snd_ctl_elem_value *ucontrol) |
515 | { |
516 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
517 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
518 | struct soc_mixer_control *mixer_ctrl = |
519 | (struct soc_mixer_control *) kcontrol->private_value; |
520 | unsigned int lvalue = ucontrol->value.integer.value[0]; |
521 | unsigned int rvalue = ucontrol->value.integer.value[1]; |
522 | unsigned int lshift = mixer_ctrl->shift; |
523 | unsigned int rshift = mixer_ctrl->rshift; |
524 | unsigned int mask = (mixer_ctrl->max << lshift) | |
525 | (mixer_ctrl->max << rshift); |
526 | da7218->mic_lvl_det_en &= ~mask; |
527 | da7218->mic_lvl_det_en |= (lvalue << lshift) | (rvalue << rshift); |
528 | |
529 | /* |
530 | * Here we only enable the feature on paths which are already |
531 | * powered. If a channel is enabled here for level detect, but that path |
532 | * isn't powered, then the channel will actually be enabled when we do |
533 | * power the path (IN_FILTER widget events). This handling avoids |
534 | * unwanted level detect events. |
535 | */ |
536 | return snd_soc_component_write(component, reg: mixer_ctrl->reg, |
537 | val: (da7218->in_filt_en & da7218->mic_lvl_det_en)); |
538 | } |
539 | |
540 | static int da7218_mic_lvl_det_sw_get(struct snd_kcontrol *kcontrol, |
541 | struct snd_ctl_elem_value *ucontrol) |
542 | { |
543 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
544 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
545 | struct soc_mixer_control *mixer_ctrl = |
546 | (struct soc_mixer_control *) kcontrol->private_value; |
547 | unsigned int lshift = mixer_ctrl->shift; |
548 | unsigned int rshift = mixer_ctrl->rshift; |
549 | unsigned int lmask = (mixer_ctrl->max << lshift); |
550 | unsigned int rmask = (mixer_ctrl->max << rshift); |
551 | |
552 | ucontrol->value.integer.value[0] = |
553 | (da7218->mic_lvl_det_en & lmask) >> lshift; |
554 | ucontrol->value.integer.value[1] = |
555 | (da7218->mic_lvl_det_en & rmask) >> rshift; |
556 | |
557 | return 0; |
558 | } |
559 | |
560 | static int da7218_biquad_coeff_get(struct snd_kcontrol *kcontrol, |
561 | struct snd_ctl_elem_value *ucontrol) |
562 | { |
563 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
564 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
565 | struct soc_bytes_ext *bytes_ext = |
566 | (struct soc_bytes_ext *) kcontrol->private_value; |
567 | |
568 | /* Determine which BiQuads we're setting based on size of config data */ |
569 | switch (bytes_ext->max) { |
570 | case DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE: |
571 | memcpy(ucontrol->value.bytes.data, da7218->biq_5stage_coeff, |
572 | bytes_ext->max); |
573 | break; |
574 | case DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE: |
575 | memcpy(ucontrol->value.bytes.data, da7218->stbiq_3stage_coeff, |
576 | bytes_ext->max); |
577 | break; |
578 | default: |
579 | return -EINVAL; |
580 | } |
581 | |
582 | return 0; |
583 | } |
584 | |
585 | static int da7218_biquad_coeff_put(struct snd_kcontrol *kcontrol, |
586 | struct snd_ctl_elem_value *ucontrol) |
587 | { |
588 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
589 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
590 | struct soc_bytes_ext *bytes_ext = |
591 | (struct soc_bytes_ext *) kcontrol->private_value; |
592 | u8 reg, out_filt1l; |
593 | u8 cfg[DA7218_BIQ_CFG_SIZE]; |
594 | int i; |
595 | |
596 | /* |
597 | * Determine which BiQuads we're setting based on size of config data, |
598 | * and stored the data for use by get function. |
599 | */ |
600 | switch (bytes_ext->max) { |
601 | case DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE: |
602 | reg = DA7218_OUT_1_BIQ_5STAGE_DATA; |
603 | memcpy(da7218->biq_5stage_coeff, ucontrol->value.bytes.data, |
604 | bytes_ext->max); |
605 | break; |
606 | case DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE: |
607 | reg = DA7218_SIDETONE_BIQ_3STAGE_DATA; |
608 | memcpy(da7218->stbiq_3stage_coeff, ucontrol->value.bytes.data, |
609 | bytes_ext->max); |
610 | break; |
611 | default: |
612 | return -EINVAL; |
613 | } |
614 | |
615 | /* Make sure at least out filter1 enabled to allow programming */ |
616 | out_filt1l = snd_soc_component_read(component, DA7218_OUT_1L_FILTER_CTRL); |
617 | snd_soc_component_write(component, DA7218_OUT_1L_FILTER_CTRL, |
618 | val: out_filt1l | DA7218_OUT_1L_FILTER_EN_MASK); |
619 | |
620 | for (i = 0; i < bytes_ext->max; ++i) { |
621 | cfg[DA7218_BIQ_CFG_DATA] = ucontrol->value.bytes.data[i]; |
622 | cfg[DA7218_BIQ_CFG_ADDR] = i; |
623 | regmap_raw_write(map: da7218->regmap, reg, val: cfg, val_len: DA7218_BIQ_CFG_SIZE); |
624 | } |
625 | |
626 | /* Restore filter to previous setting */ |
627 | snd_soc_component_write(component, DA7218_OUT_1L_FILTER_CTRL, val: out_filt1l); |
628 | |
629 | return 0; |
630 | } |
631 | |
632 | |
633 | /* |
634 | * KControls |
635 | */ |
636 | |
637 | static const struct snd_kcontrol_new da7218_snd_controls[] = { |
638 | /* Mics */ |
639 | SOC_SINGLE_TLV("Mic1 Volume" , DA7218_MIC_1_GAIN, |
640 | DA7218_MIC_1_AMP_GAIN_SHIFT, DA7218_MIC_AMP_GAIN_MAX, |
641 | DA7218_NO_INVERT, da7218_mic_gain_tlv), |
642 | SOC_SINGLE("Mic1 Switch" , DA7218_MIC_1_CTRL, |
643 | DA7218_MIC_1_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
644 | DA7218_INVERT), |
645 | SOC_SINGLE_TLV("Mic2 Volume" , DA7218_MIC_2_GAIN, |
646 | DA7218_MIC_2_AMP_GAIN_SHIFT, DA7218_MIC_AMP_GAIN_MAX, |
647 | DA7218_NO_INVERT, da7218_mic_gain_tlv), |
648 | SOC_SINGLE("Mic2 Switch" , DA7218_MIC_2_CTRL, |
649 | DA7218_MIC_2_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
650 | DA7218_INVERT), |
651 | |
652 | /* Mixer Input */ |
653 | SOC_SINGLE_EXT_TLV("Mixin1 Volume" , DA7218_MIXIN_1_GAIN, |
654 | DA7218_MIXIN_1_AMP_GAIN_SHIFT, |
655 | DA7218_MIXIN_AMP_GAIN_MAX, DA7218_NO_INVERT, |
656 | snd_soc_get_volsw, da7218_mixin_gain_put, |
657 | da7218_mixin_gain_tlv), |
658 | SOC_SINGLE("Mixin1 Switch" , DA7218_MIXIN_1_CTRL, |
659 | DA7218_MIXIN_1_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
660 | DA7218_INVERT), |
661 | SOC_SINGLE("Mixin1 Gain Ramp Switch" , DA7218_MIXIN_1_CTRL, |
662 | DA7218_MIXIN_1_AMP_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
663 | DA7218_NO_INVERT), |
664 | SOC_SINGLE("Mixin1 ZC Gain Switch" , DA7218_MIXIN_1_CTRL, |
665 | DA7218_MIXIN_1_AMP_ZC_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
666 | DA7218_NO_INVERT), |
667 | SOC_SINGLE_EXT_TLV("Mixin2 Volume" , DA7218_MIXIN_2_GAIN, |
668 | DA7218_MIXIN_2_AMP_GAIN_SHIFT, |
669 | DA7218_MIXIN_AMP_GAIN_MAX, DA7218_NO_INVERT, |
670 | snd_soc_get_volsw, da7218_mixin_gain_put, |
671 | da7218_mixin_gain_tlv), |
672 | SOC_SINGLE("Mixin2 Switch" , DA7218_MIXIN_2_CTRL, |
673 | DA7218_MIXIN_2_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
674 | DA7218_INVERT), |
675 | SOC_SINGLE("Mixin2 Gain Ramp Switch" , DA7218_MIXIN_2_CTRL, |
676 | DA7218_MIXIN_2_AMP_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
677 | DA7218_NO_INVERT), |
678 | SOC_SINGLE("Mixin2 ZC Gain Switch" , DA7218_MIXIN_2_CTRL, |
679 | DA7218_MIXIN_2_AMP_ZC_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
680 | DA7218_NO_INVERT), |
681 | |
682 | /* ADCs */ |
683 | SOC_SINGLE("ADC1 AAF Switch" , DA7218_ADC_1_CTRL, |
684 | DA7218_ADC_1_AAF_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
685 | DA7218_NO_INVERT), |
686 | SOC_SINGLE("ADC2 AAF Switch" , DA7218_ADC_2_CTRL, |
687 | DA7218_ADC_2_AAF_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
688 | DA7218_NO_INVERT), |
689 | SOC_SINGLE("ADC LP Mode Switch" , DA7218_ADC_MODE, |
690 | DA7218_ADC_LP_MODE_SHIFT, DA7218_SWITCH_EN_MAX, |
691 | DA7218_NO_INVERT), |
692 | |
693 | /* Input Filters */ |
694 | SOC_SINGLE_TLV("In Filter1L Volume" , DA7218_IN_1L_GAIN, |
695 | DA7218_IN_1L_DIGITAL_GAIN_SHIFT, |
696 | DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT, |
697 | da7218_in_dig_gain_tlv), |
698 | SOC_SINGLE("In Filter1L Switch" , DA7218_IN_1L_FILTER_CTRL, |
699 | DA7218_IN_1L_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
700 | DA7218_INVERT), |
701 | SOC_SINGLE("In Filter1L Gain Ramp Switch" , DA7218_IN_1L_FILTER_CTRL, |
702 | DA7218_IN_1L_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
703 | DA7218_NO_INVERT), |
704 | SOC_SINGLE_TLV("In Filter1R Volume" , DA7218_IN_1R_GAIN, |
705 | DA7218_IN_1R_DIGITAL_GAIN_SHIFT, |
706 | DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT, |
707 | da7218_in_dig_gain_tlv), |
708 | SOC_SINGLE("In Filter1R Switch" , DA7218_IN_1R_FILTER_CTRL, |
709 | DA7218_IN_1R_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
710 | DA7218_INVERT), |
711 | SOC_SINGLE("In Filter1R Gain Ramp Switch" , |
712 | DA7218_IN_1R_FILTER_CTRL, DA7218_IN_1R_RAMP_EN_SHIFT, |
713 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
714 | SOC_SINGLE_TLV("In Filter2L Volume" , DA7218_IN_2L_GAIN, |
715 | DA7218_IN_2L_DIGITAL_GAIN_SHIFT, |
716 | DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT, |
717 | da7218_in_dig_gain_tlv), |
718 | SOC_SINGLE("In Filter2L Switch" , DA7218_IN_2L_FILTER_CTRL, |
719 | DA7218_IN_2L_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
720 | DA7218_INVERT), |
721 | SOC_SINGLE("In Filter2L Gain Ramp Switch" , DA7218_IN_2L_FILTER_CTRL, |
722 | DA7218_IN_2L_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
723 | DA7218_NO_INVERT), |
724 | SOC_SINGLE_TLV("In Filter2R Volume" , DA7218_IN_2R_GAIN, |
725 | DA7218_IN_2R_DIGITAL_GAIN_SHIFT, |
726 | DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT, |
727 | da7218_in_dig_gain_tlv), |
728 | SOC_SINGLE("In Filter2R Switch" , DA7218_IN_2R_FILTER_CTRL, |
729 | DA7218_IN_2R_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
730 | DA7218_INVERT), |
731 | SOC_SINGLE("In Filter2R Gain Ramp Switch" , |
732 | DA7218_IN_2R_FILTER_CTRL, DA7218_IN_2R_RAMP_EN_SHIFT, |
733 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
734 | |
735 | /* AGS */ |
736 | SOC_SINGLE_TLV("AGS Trigger" , DA7218_AGS_TRIGGER, |
737 | DA7218_AGS_TRIGGER_SHIFT, DA7218_AGS_TRIGGER_MAX, |
738 | DA7218_INVERT, da7218_ags_trigger_tlv), |
739 | SOC_SINGLE_TLV("AGS Max Attenuation" , DA7218_AGS_ATT_MAX, |
740 | DA7218_AGS_ATT_MAX_SHIFT, DA7218_AGS_ATT_MAX_MAX, |
741 | DA7218_NO_INVERT, da7218_ags_att_max_tlv), |
742 | SOC_SINGLE("AGS Anticlip Switch" , DA7218_AGS_ANTICLIP_CTRL, |
743 | DA7218_AGS_ANTICLIP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
744 | DA7218_NO_INVERT), |
745 | SOC_SINGLE("AGS Channel1 Switch" , DA7218_AGS_ENABLE, |
746 | DA7218_AGS_ENABLE_CHAN1_SHIFT, DA7218_SWITCH_EN_MAX, |
747 | DA7218_NO_INVERT), |
748 | SOC_SINGLE("AGS Channel2 Switch" , DA7218_AGS_ENABLE, |
749 | DA7218_AGS_ENABLE_CHAN2_SHIFT, DA7218_SWITCH_EN_MAX, |
750 | DA7218_NO_INVERT), |
751 | |
752 | /* ALC */ |
753 | SOC_ENUM("ALC Attack Rate" , da7218_alc_attack_rate), |
754 | SOC_ENUM("ALC Release Rate" , da7218_alc_release_rate), |
755 | SOC_ENUM("ALC Hold Time" , da7218_alc_hold_time), |
756 | SOC_SINGLE_TLV("ALC Noise Threshold" , DA7218_ALC_NOISE, |
757 | DA7218_ALC_NOISE_SHIFT, DA7218_ALC_THRESHOLD_MAX, |
758 | DA7218_INVERT, da7218_alc_threshold_tlv), |
759 | SOC_SINGLE_TLV("ALC Min Threshold" , DA7218_ALC_TARGET_MIN, |
760 | DA7218_ALC_THRESHOLD_MIN_SHIFT, DA7218_ALC_THRESHOLD_MAX, |
761 | DA7218_INVERT, da7218_alc_threshold_tlv), |
762 | SOC_SINGLE_TLV("ALC Max Threshold" , DA7218_ALC_TARGET_MAX, |
763 | DA7218_ALC_THRESHOLD_MAX_SHIFT, DA7218_ALC_THRESHOLD_MAX, |
764 | DA7218_INVERT, da7218_alc_threshold_tlv), |
765 | SOC_SINGLE_TLV("ALC Max Attenuation" , DA7218_ALC_GAIN_LIMITS, |
766 | DA7218_ALC_ATTEN_MAX_SHIFT, DA7218_ALC_ATTEN_GAIN_MAX, |
767 | DA7218_NO_INVERT, da7218_alc_gain_tlv), |
768 | SOC_SINGLE_TLV("ALC Max Gain" , DA7218_ALC_GAIN_LIMITS, |
769 | DA7218_ALC_GAIN_MAX_SHIFT, DA7218_ALC_ATTEN_GAIN_MAX, |
770 | DA7218_NO_INVERT, da7218_alc_gain_tlv), |
771 | SOC_SINGLE_RANGE_TLV("ALC Min Analog Gain" , DA7218_ALC_ANA_GAIN_LIMITS, |
772 | DA7218_ALC_ANA_GAIN_MIN_SHIFT, |
773 | DA7218_ALC_ANA_GAIN_MIN, DA7218_ALC_ANA_GAIN_MAX, |
774 | DA7218_NO_INVERT, da7218_alc_ana_gain_tlv), |
775 | SOC_SINGLE_RANGE_TLV("ALC Max Analog Gain" , DA7218_ALC_ANA_GAIN_LIMITS, |
776 | DA7218_ALC_ANA_GAIN_MAX_SHIFT, |
777 | DA7218_ALC_ANA_GAIN_MIN, DA7218_ALC_ANA_GAIN_MAX, |
778 | DA7218_NO_INVERT, da7218_alc_ana_gain_tlv), |
779 | SOC_ENUM("ALC Anticlip Step" , da7218_alc_anticlip_step), |
780 | SOC_SINGLE("ALC Anticlip Switch" , DA7218_ALC_ANTICLIP_CTRL, |
781 | DA7218_ALC_ANTICLIP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
782 | DA7218_NO_INVERT), |
783 | SOC_DOUBLE_EXT("ALC Channel1 Switch" , DA7218_ALC_CTRL1, |
784 | DA7218_ALC_CHAN1_L_EN_SHIFT, DA7218_ALC_CHAN1_R_EN_SHIFT, |
785 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT, |
786 | snd_soc_get_volsw, da7218_alc_sw_put), |
787 | SOC_DOUBLE_EXT("ALC Channel2 Switch" , DA7218_ALC_CTRL1, |
788 | DA7218_ALC_CHAN2_L_EN_SHIFT, DA7218_ALC_CHAN2_R_EN_SHIFT, |
789 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT, |
790 | snd_soc_get_volsw, da7218_alc_sw_put), |
791 | |
792 | /* Envelope Tracking */ |
793 | SOC_ENUM("Envelope Tracking Attack Rate" , da7218_integ_attack_rate), |
794 | SOC_ENUM("Envelope Tracking Release Rate" , da7218_integ_release_rate), |
795 | |
796 | /* Input High-Pass Filters */ |
797 | SOC_ENUM("In Filter1 HPF Mode" , da7218_in1_hpf_mode), |
798 | SOC_ENUM("In Filter1 HPF Corner Audio" , da7218_in1_audio_hpf_corner), |
799 | SOC_ENUM("In Filter1 HPF Corner Voice" , da7218_in1_voice_hpf_corner), |
800 | SOC_ENUM("In Filter2 HPF Mode" , da7218_in2_hpf_mode), |
801 | SOC_ENUM("In Filter2 HPF Corner Audio" , da7218_in2_audio_hpf_corner), |
802 | SOC_ENUM("In Filter2 HPF Corner Voice" , da7218_in2_voice_hpf_corner), |
803 | |
804 | /* Mic Level Detect */ |
805 | SOC_DOUBLE_EXT("Mic Level Detect Channel1 Switch" , DA7218_LVL_DET_CTRL, |
806 | DA7218_LVL_DET_EN_CHAN1L_SHIFT, |
807 | DA7218_LVL_DET_EN_CHAN1R_SHIFT, DA7218_SWITCH_EN_MAX, |
808 | DA7218_NO_INVERT, da7218_mic_lvl_det_sw_get, |
809 | da7218_mic_lvl_det_sw_put), |
810 | SOC_DOUBLE_EXT("Mic Level Detect Channel2 Switch" , DA7218_LVL_DET_CTRL, |
811 | DA7218_LVL_DET_EN_CHAN2L_SHIFT, |
812 | DA7218_LVL_DET_EN_CHAN2R_SHIFT, DA7218_SWITCH_EN_MAX, |
813 | DA7218_NO_INVERT, da7218_mic_lvl_det_sw_get, |
814 | da7218_mic_lvl_det_sw_put), |
815 | SOC_SINGLE("Mic Level Detect Level" , DA7218_LVL_DET_LEVEL, |
816 | DA7218_LVL_DET_LEVEL_SHIFT, DA7218_LVL_DET_LEVEL_MAX, |
817 | DA7218_NO_INVERT), |
818 | |
819 | /* Digital Mixer (Input) */ |
820 | SOC_SINGLE_TLV("DMix In Filter1L Out1 DAIL Volume" , |
821 | DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN, |
822 | DA7218_OUTDAI_1L_INFILT_1L_GAIN_SHIFT, |
823 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
824 | da7218_dmix_gain_tlv), |
825 | SOC_SINGLE_TLV("DMix In Filter1L Out1 DAIR Volume" , |
826 | DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN, |
827 | DA7218_OUTDAI_1R_INFILT_1L_GAIN_SHIFT, |
828 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
829 | da7218_dmix_gain_tlv), |
830 | SOC_SINGLE_TLV("DMix In Filter1L Out2 DAIL Volume" , |
831 | DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN, |
832 | DA7218_OUTDAI_2L_INFILT_1L_GAIN_SHIFT, |
833 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
834 | da7218_dmix_gain_tlv), |
835 | SOC_SINGLE_TLV("DMix In Filter1L Out2 DAIR Volume" , |
836 | DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN, |
837 | DA7218_OUTDAI_2R_INFILT_1L_GAIN_SHIFT, |
838 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
839 | da7218_dmix_gain_tlv), |
840 | |
841 | SOC_SINGLE_TLV("DMix In Filter1R Out1 DAIL Volume" , |
842 | DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN, |
843 | DA7218_OUTDAI_1L_INFILT_1R_GAIN_SHIFT, |
844 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
845 | da7218_dmix_gain_tlv), |
846 | SOC_SINGLE_TLV("DMix In Filter1R Out1 DAIR Volume" , |
847 | DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN, |
848 | DA7218_OUTDAI_1R_INFILT_1R_GAIN_SHIFT, |
849 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
850 | da7218_dmix_gain_tlv), |
851 | SOC_SINGLE_TLV("DMix In Filter1R Out2 DAIL Volume" , |
852 | DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN, |
853 | DA7218_OUTDAI_2L_INFILT_1R_GAIN_SHIFT, |
854 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
855 | da7218_dmix_gain_tlv), |
856 | SOC_SINGLE_TLV("DMix In Filter1R Out2 DAIR Volume" , |
857 | DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN, |
858 | DA7218_OUTDAI_2R_INFILT_1R_GAIN_SHIFT, |
859 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
860 | da7218_dmix_gain_tlv), |
861 | |
862 | SOC_SINGLE_TLV("DMix In Filter2L Out1 DAIL Volume" , |
863 | DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN, |
864 | DA7218_OUTDAI_1L_INFILT_2L_GAIN_SHIFT, |
865 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
866 | da7218_dmix_gain_tlv), |
867 | SOC_SINGLE_TLV("DMix In Filter2L Out1 DAIR Volume" , |
868 | DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN, |
869 | DA7218_OUTDAI_1R_INFILT_2L_GAIN_SHIFT, |
870 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
871 | da7218_dmix_gain_tlv), |
872 | SOC_SINGLE_TLV("DMix In Filter2L Out2 DAIL Volume" , |
873 | DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN, |
874 | DA7218_OUTDAI_2L_INFILT_2L_GAIN_SHIFT, |
875 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
876 | da7218_dmix_gain_tlv), |
877 | SOC_SINGLE_TLV("DMix In Filter2L Out2 DAIR Volume" , |
878 | DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN, |
879 | DA7218_OUTDAI_2R_INFILT_2L_GAIN_SHIFT, |
880 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
881 | da7218_dmix_gain_tlv), |
882 | |
883 | SOC_SINGLE_TLV("DMix In Filter2R Out1 DAIL Volume" , |
884 | DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN, |
885 | DA7218_OUTDAI_1L_INFILT_2R_GAIN_SHIFT, |
886 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
887 | da7218_dmix_gain_tlv), |
888 | SOC_SINGLE_TLV("DMix In Filter2R Out1 DAIR Volume" , |
889 | DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN, |
890 | DA7218_OUTDAI_1R_INFILT_2R_GAIN_SHIFT, |
891 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
892 | da7218_dmix_gain_tlv), |
893 | SOC_SINGLE_TLV("DMix In Filter2R Out2 DAIL Volume" , |
894 | DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN, |
895 | DA7218_OUTDAI_2L_INFILT_2R_GAIN_SHIFT, |
896 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
897 | da7218_dmix_gain_tlv), |
898 | SOC_SINGLE_TLV("DMix In Filter2R Out2 DAIR Volume" , |
899 | DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN, |
900 | DA7218_OUTDAI_2R_INFILT_2R_GAIN_SHIFT, |
901 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
902 | da7218_dmix_gain_tlv), |
903 | |
904 | SOC_SINGLE_TLV("DMix ToneGen Out1 DAIL Volume" , |
905 | DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN, |
906 | DA7218_OUTDAI_1L_TONEGEN_GAIN_SHIFT, |
907 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
908 | da7218_dmix_gain_tlv), |
909 | SOC_SINGLE_TLV("DMix ToneGen Out1 DAIR Volume" , |
910 | DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN, |
911 | DA7218_OUTDAI_1R_TONEGEN_GAIN_SHIFT, |
912 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
913 | da7218_dmix_gain_tlv), |
914 | SOC_SINGLE_TLV("DMix ToneGen Out2 DAIL Volume" , |
915 | DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN, |
916 | DA7218_OUTDAI_2L_TONEGEN_GAIN_SHIFT, |
917 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
918 | da7218_dmix_gain_tlv), |
919 | SOC_SINGLE_TLV("DMix ToneGen Out2 DAIR Volume" , |
920 | DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN, |
921 | DA7218_OUTDAI_2R_TONEGEN_GAIN_SHIFT, |
922 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
923 | da7218_dmix_gain_tlv), |
924 | |
925 | SOC_SINGLE_TLV("DMix In DAIL Out1 DAIL Volume" , |
926 | DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN, |
927 | DA7218_OUTDAI_1L_INDAI_1L_GAIN_SHIFT, |
928 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
929 | da7218_dmix_gain_tlv), |
930 | SOC_SINGLE_TLV("DMix In DAIL Out1 DAIR Volume" , |
931 | DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN, |
932 | DA7218_OUTDAI_1R_INDAI_1L_GAIN_SHIFT, |
933 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
934 | da7218_dmix_gain_tlv), |
935 | SOC_SINGLE_TLV("DMix In DAIL Out2 DAIL Volume" , |
936 | DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN, |
937 | DA7218_OUTDAI_2L_INDAI_1L_GAIN_SHIFT, |
938 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
939 | da7218_dmix_gain_tlv), |
940 | SOC_SINGLE_TLV("DMix In DAIL Out2 DAIR Volume" , |
941 | DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN, |
942 | DA7218_OUTDAI_2R_INDAI_1L_GAIN_SHIFT, |
943 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
944 | da7218_dmix_gain_tlv), |
945 | |
946 | SOC_SINGLE_TLV("DMix In DAIR Out1 DAIL Volume" , |
947 | DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN, |
948 | DA7218_OUTDAI_1L_INDAI_1R_GAIN_SHIFT, |
949 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
950 | da7218_dmix_gain_tlv), |
951 | SOC_SINGLE_TLV("DMix In DAIR Out1 DAIR Volume" , |
952 | DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN, |
953 | DA7218_OUTDAI_1R_INDAI_1R_GAIN_SHIFT, |
954 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
955 | da7218_dmix_gain_tlv), |
956 | SOC_SINGLE_TLV("DMix In DAIR Out2 DAIL Volume" , |
957 | DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN, |
958 | DA7218_OUTDAI_2L_INDAI_1R_GAIN_SHIFT, |
959 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
960 | da7218_dmix_gain_tlv), |
961 | SOC_SINGLE_TLV("DMix In DAIR Out2 DAIR Volume" , |
962 | DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN, |
963 | DA7218_OUTDAI_2R_INDAI_1R_GAIN_SHIFT, |
964 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
965 | da7218_dmix_gain_tlv), |
966 | |
967 | /* Digital Mixer (Output) */ |
968 | SOC_SINGLE_TLV("DMix In Filter1L Out FilterL Volume" , |
969 | DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN, |
970 | DA7218_OUTFILT_1L_INFILT_1L_GAIN_SHIFT, |
971 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
972 | da7218_dmix_gain_tlv), |
973 | SOC_SINGLE_TLV("DMix In Filter1L Out FilterR Volume" , |
974 | DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN, |
975 | DA7218_OUTFILT_1R_INFILT_1L_GAIN_SHIFT, |
976 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
977 | da7218_dmix_gain_tlv), |
978 | |
979 | SOC_SINGLE_TLV("DMix In Filter1R Out FilterL Volume" , |
980 | DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN, |
981 | DA7218_OUTFILT_1L_INFILT_1R_GAIN_SHIFT, |
982 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
983 | da7218_dmix_gain_tlv), |
984 | SOC_SINGLE_TLV("DMix In Filter1R Out FilterR Volume" , |
985 | DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN, |
986 | DA7218_OUTFILT_1R_INFILT_1R_GAIN_SHIFT, |
987 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
988 | da7218_dmix_gain_tlv), |
989 | |
990 | SOC_SINGLE_TLV("DMix In Filter2L Out FilterL Volume" , |
991 | DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN, |
992 | DA7218_OUTFILT_1L_INFILT_2L_GAIN_SHIFT, |
993 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
994 | da7218_dmix_gain_tlv), |
995 | SOC_SINGLE_TLV("DMix In Filter2L Out FilterR Volume" , |
996 | DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN, |
997 | DA7218_OUTFILT_1R_INFILT_2L_GAIN_SHIFT, |
998 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
999 | da7218_dmix_gain_tlv), |
1000 | |
1001 | SOC_SINGLE_TLV("DMix In Filter2R Out FilterL Volume" , |
1002 | DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN, |
1003 | DA7218_OUTFILT_1L_INFILT_2R_GAIN_SHIFT, |
1004 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1005 | da7218_dmix_gain_tlv), |
1006 | SOC_SINGLE_TLV("DMix In Filter2R Out FilterR Volume" , |
1007 | DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN, |
1008 | DA7218_OUTFILT_1R_INFILT_2R_GAIN_SHIFT, |
1009 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1010 | da7218_dmix_gain_tlv), |
1011 | |
1012 | SOC_SINGLE_TLV("DMix ToneGen Out FilterL Volume" , |
1013 | DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN, |
1014 | DA7218_OUTFILT_1L_TONEGEN_GAIN_SHIFT, |
1015 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1016 | da7218_dmix_gain_tlv), |
1017 | SOC_SINGLE_TLV("DMix ToneGen Out FilterR Volume" , |
1018 | DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN, |
1019 | DA7218_OUTFILT_1R_TONEGEN_GAIN_SHIFT, |
1020 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1021 | da7218_dmix_gain_tlv), |
1022 | |
1023 | SOC_SINGLE_TLV("DMix In DAIL Out FilterL Volume" , |
1024 | DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN, |
1025 | DA7218_OUTFILT_1L_INDAI_1L_GAIN_SHIFT, |
1026 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1027 | da7218_dmix_gain_tlv), |
1028 | SOC_SINGLE_TLV("DMix In DAIL Out FilterR Volume" , |
1029 | DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN, |
1030 | DA7218_OUTFILT_1R_INDAI_1L_GAIN_SHIFT, |
1031 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1032 | da7218_dmix_gain_tlv), |
1033 | |
1034 | SOC_SINGLE_TLV("DMix In DAIR Out FilterL Volume" , |
1035 | DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN, |
1036 | DA7218_OUTFILT_1L_INDAI_1R_GAIN_SHIFT, |
1037 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1038 | da7218_dmix_gain_tlv), |
1039 | SOC_SINGLE_TLV("DMix In DAIR Out FilterR Volume" , |
1040 | DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN, |
1041 | DA7218_OUTFILT_1R_INDAI_1R_GAIN_SHIFT, |
1042 | DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT, |
1043 | da7218_dmix_gain_tlv), |
1044 | |
1045 | /* Sidetone Filter */ |
1046 | SND_SOC_BYTES_EXT("Sidetone BiQuad Coefficients" , |
1047 | DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE, |
1048 | da7218_biquad_coeff_get, da7218_biquad_coeff_put), |
1049 | SOC_SINGLE_TLV("Sidetone Volume" , DA7218_SIDETONE_GAIN, |
1050 | DA7218_SIDETONE_GAIN_SHIFT, DA7218_DMIX_GAIN_MAX, |
1051 | DA7218_NO_INVERT, da7218_dmix_gain_tlv), |
1052 | SOC_SINGLE("Sidetone Switch" , DA7218_SIDETONE_CTRL, |
1053 | DA7218_SIDETONE_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1054 | DA7218_INVERT), |
1055 | |
1056 | /* Tone Generator */ |
1057 | SOC_ENUM("ToneGen DTMF Key" , da7218_tonegen_dtmf_key), |
1058 | SOC_SINGLE("ToneGen DTMF Switch" , DA7218_TONE_GEN_CFG1, |
1059 | DA7218_DTMF_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1060 | DA7218_NO_INVERT), |
1061 | SOC_ENUM("ToneGen Sinewave Gen Type" , da7218_tonegen_swg_sel), |
1062 | SOC_SINGLE_EXT("ToneGen Sinewave1 Freq" , DA7218_TONE_GEN_FREQ1_L, |
1063 | DA7218_FREQ1_L_SHIFT, DA7218_FREQ_MAX, DA7218_NO_INVERT, |
1064 | da7218_tonegen_freq_get, da7218_tonegen_freq_put), |
1065 | SOC_SINGLE_EXT("ToneGen Sinewave2 Freq" , DA7218_TONE_GEN_FREQ2_L, |
1066 | DA7218_FREQ2_L_SHIFT, DA7218_FREQ_MAX, DA7218_NO_INVERT, |
1067 | da7218_tonegen_freq_get, da7218_tonegen_freq_put), |
1068 | SOC_SINGLE("ToneGen On Time" , DA7218_TONE_GEN_ON_PER, |
1069 | DA7218_BEEP_ON_PER_SHIFT, DA7218_BEEP_ON_OFF_MAX, |
1070 | DA7218_NO_INVERT), |
1071 | SOC_SINGLE("ToneGen Off Time" , DA7218_TONE_GEN_OFF_PER, |
1072 | DA7218_BEEP_OFF_PER_SHIFT, DA7218_BEEP_ON_OFF_MAX, |
1073 | DA7218_NO_INVERT), |
1074 | |
1075 | /* Gain ramping */ |
1076 | SOC_ENUM("Gain Ramp Rate" , da7218_gain_ramp_rate), |
1077 | |
1078 | /* DGS */ |
1079 | SOC_SINGLE_TLV("DGS Trigger" , DA7218_DGS_TRIGGER, |
1080 | DA7218_DGS_TRIGGER_LVL_SHIFT, DA7218_DGS_TRIGGER_MAX, |
1081 | DA7218_INVERT, da7218_dgs_trigger_tlv), |
1082 | SOC_ENUM("DGS Rise Coefficient" , da7218_dgs_rise_coeff), |
1083 | SOC_ENUM("DGS Fall Coefficient" , da7218_dgs_fall_coeff), |
1084 | SOC_SINGLE("DGS Sync Delay" , DA7218_DGS_SYNC_DELAY, |
1085 | DA7218_DGS_SYNC_DELAY_SHIFT, DA7218_DGS_SYNC_DELAY_MAX, |
1086 | DA7218_NO_INVERT), |
1087 | SOC_SINGLE("DGS Fast SR Sync Delay" , DA7218_DGS_SYNC_DELAY2, |
1088 | DA7218_DGS_SYNC_DELAY2_SHIFT, DA7218_DGS_SYNC_DELAY_MAX, |
1089 | DA7218_NO_INVERT), |
1090 | SOC_SINGLE("DGS Voice Filter Sync Delay" , DA7218_DGS_SYNC_DELAY3, |
1091 | DA7218_DGS_SYNC_DELAY3_SHIFT, DA7218_DGS_SYNC_DELAY3_MAX, |
1092 | DA7218_NO_INVERT), |
1093 | SOC_SINGLE_TLV("DGS Anticlip Level" , DA7218_DGS_LEVELS, |
1094 | DA7218_DGS_ANTICLIP_LVL_SHIFT, |
1095 | DA7218_DGS_ANTICLIP_LVL_MAX, DA7218_INVERT, |
1096 | da7218_dgs_anticlip_tlv), |
1097 | SOC_SINGLE_TLV("DGS Signal Level" , DA7218_DGS_LEVELS, |
1098 | DA7218_DGS_SIGNAL_LVL_SHIFT, DA7218_DGS_SIGNAL_LVL_MAX, |
1099 | DA7218_INVERT, da7218_dgs_signal_tlv), |
1100 | SOC_SINGLE("DGS Gain Subrange Switch" , DA7218_DGS_GAIN_CTRL, |
1101 | DA7218_DGS_SUBR_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1102 | DA7218_NO_INVERT), |
1103 | SOC_SINGLE("DGS Gain Ramp Switch" , DA7218_DGS_GAIN_CTRL, |
1104 | DA7218_DGS_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1105 | DA7218_NO_INVERT), |
1106 | SOC_SINGLE("DGS Gain Steps" , DA7218_DGS_GAIN_CTRL, |
1107 | DA7218_DGS_STEPS_SHIFT, DA7218_DGS_STEPS_MAX, |
1108 | DA7218_NO_INVERT), |
1109 | SOC_DOUBLE("DGS Switch" , DA7218_DGS_ENABLE, DA7218_DGS_ENABLE_L_SHIFT, |
1110 | DA7218_DGS_ENABLE_R_SHIFT, DA7218_SWITCH_EN_MAX, |
1111 | DA7218_NO_INVERT), |
1112 | |
1113 | /* Output High-Pass Filter */ |
1114 | SOC_ENUM("Out Filter HPF Mode" , da7218_out1_hpf_mode), |
1115 | SOC_ENUM("Out Filter HPF Corner Audio" , da7218_out1_audio_hpf_corner), |
1116 | SOC_ENUM("Out Filter HPF Corner Voice" , da7218_out1_voice_hpf_corner), |
1117 | |
1118 | /* 5-Band Equaliser */ |
1119 | SOC_SINGLE_TLV("Out EQ Band1 Volume" , DA7218_OUT_1_EQ_12_FILTER_CTRL, |
1120 | DA7218_OUT_1_EQ_BAND1_SHIFT, DA7218_OUT_EQ_BAND_MAX, |
1121 | DA7218_NO_INVERT, da7218_out_eq_band_tlv), |
1122 | SOC_SINGLE_TLV("Out EQ Band2 Volume" , DA7218_OUT_1_EQ_12_FILTER_CTRL, |
1123 | DA7218_OUT_1_EQ_BAND2_SHIFT, DA7218_OUT_EQ_BAND_MAX, |
1124 | DA7218_NO_INVERT, da7218_out_eq_band_tlv), |
1125 | SOC_SINGLE_TLV("Out EQ Band3 Volume" , DA7218_OUT_1_EQ_34_FILTER_CTRL, |
1126 | DA7218_OUT_1_EQ_BAND3_SHIFT, DA7218_OUT_EQ_BAND_MAX, |
1127 | DA7218_NO_INVERT, da7218_out_eq_band_tlv), |
1128 | SOC_SINGLE_TLV("Out EQ Band4 Volume" , DA7218_OUT_1_EQ_34_FILTER_CTRL, |
1129 | DA7218_OUT_1_EQ_BAND4_SHIFT, DA7218_OUT_EQ_BAND_MAX, |
1130 | DA7218_NO_INVERT, da7218_out_eq_band_tlv), |
1131 | SOC_SINGLE_TLV("Out EQ Band5 Volume" , DA7218_OUT_1_EQ_5_FILTER_CTRL, |
1132 | DA7218_OUT_1_EQ_BAND5_SHIFT, DA7218_OUT_EQ_BAND_MAX, |
1133 | DA7218_NO_INVERT, da7218_out_eq_band_tlv), |
1134 | SOC_SINGLE("Out EQ Switch" , DA7218_OUT_1_EQ_5_FILTER_CTRL, |
1135 | DA7218_OUT_1_EQ_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1136 | DA7218_NO_INVERT), |
1137 | |
1138 | /* BiQuad Filters */ |
1139 | SND_SOC_BYTES_EXT("BiQuad Coefficients" , |
1140 | DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE, |
1141 | da7218_biquad_coeff_get, da7218_biquad_coeff_put), |
1142 | SOC_SINGLE("BiQuad Filter Switch" , DA7218_OUT_1_BIQ_5STAGE_CTRL, |
1143 | DA7218_OUT_1_BIQ_5STAGE_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1144 | DA7218_INVERT), |
1145 | |
1146 | /* Output Filters */ |
1147 | SOC_DOUBLE_R_RANGE_TLV("Out Filter Volume" , DA7218_OUT_1L_GAIN, |
1148 | DA7218_OUT_1R_GAIN, |
1149 | DA7218_OUT_1L_DIGITAL_GAIN_SHIFT, |
1150 | DA7218_OUT_DIGITAL_GAIN_MIN, |
1151 | DA7218_OUT_DIGITAL_GAIN_MAX, DA7218_NO_INVERT, |
1152 | da7218_out_dig_gain_tlv), |
1153 | SOC_DOUBLE_R("Out Filter Switch" , DA7218_OUT_1L_FILTER_CTRL, |
1154 | DA7218_OUT_1R_FILTER_CTRL, DA7218_OUT_1L_MUTE_EN_SHIFT, |
1155 | DA7218_SWITCH_EN_MAX, DA7218_INVERT), |
1156 | SOC_DOUBLE_R("Out Filter Gain Subrange Switch" , |
1157 | DA7218_OUT_1L_FILTER_CTRL, DA7218_OUT_1R_FILTER_CTRL, |
1158 | DA7218_OUT_1L_SUBRANGE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1159 | DA7218_NO_INVERT), |
1160 | SOC_DOUBLE_R("Out Filter Gain Ramp Switch" , DA7218_OUT_1L_FILTER_CTRL, |
1161 | DA7218_OUT_1R_FILTER_CTRL, DA7218_OUT_1L_RAMP_EN_SHIFT, |
1162 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
1163 | |
1164 | /* Mixer Output */ |
1165 | SOC_DOUBLE_R_RANGE_TLV("Mixout Volume" , DA7218_MIXOUT_L_GAIN, |
1166 | DA7218_MIXOUT_R_GAIN, |
1167 | DA7218_MIXOUT_L_AMP_GAIN_SHIFT, |
1168 | DA7218_MIXOUT_AMP_GAIN_MIN, |
1169 | DA7218_MIXOUT_AMP_GAIN_MAX, DA7218_NO_INVERT, |
1170 | da7218_mixout_gain_tlv), |
1171 | |
1172 | /* DAC Noise Gate */ |
1173 | SOC_ENUM("DAC NG Setup Time" , da7218_dac_ng_setup_time), |
1174 | SOC_ENUM("DAC NG Rampup Rate" , da7218_dac_ng_rampup_rate), |
1175 | SOC_ENUM("DAC NG Rampdown Rate" , da7218_dac_ng_rampdown_rate), |
1176 | SOC_SINGLE_TLV("DAC NG Off Threshold" , DA7218_DAC_NG_OFF_THRESH, |
1177 | DA7218_DAC_NG_OFF_THRESHOLD_SHIFT, |
1178 | DA7218_DAC_NG_THRESHOLD_MAX, DA7218_NO_INVERT, |
1179 | da7218_dac_ng_threshold_tlv), |
1180 | SOC_SINGLE_TLV("DAC NG On Threshold" , DA7218_DAC_NG_ON_THRESH, |
1181 | DA7218_DAC_NG_ON_THRESHOLD_SHIFT, |
1182 | DA7218_DAC_NG_THRESHOLD_MAX, DA7218_NO_INVERT, |
1183 | da7218_dac_ng_threshold_tlv), |
1184 | SOC_SINGLE("DAC NG Switch" , DA7218_DAC_NG_CTRL, DA7218_DAC_NG_EN_SHIFT, |
1185 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
1186 | |
1187 | /* CP */ |
1188 | SOC_ENUM("Charge Pump Track Mode" , da7218_cp_mchange), |
1189 | SOC_ENUM("Charge Pump Frequency" , da7218_cp_fcontrol), |
1190 | SOC_ENUM("Charge Pump Decay Rate" , da7218_cp_tau_delay), |
1191 | SOC_SINGLE("Charge Pump Threshold" , DA7218_CP_VOL_THRESHOLD1, |
1192 | DA7218_CP_THRESH_VDD2_SHIFT, DA7218_CP_THRESH_VDD2_MAX, |
1193 | DA7218_NO_INVERT), |
1194 | |
1195 | /* Headphones */ |
1196 | SOC_DOUBLE_R_RANGE_TLV("Headphone Volume" , DA7218_HP_L_GAIN, |
1197 | DA7218_HP_R_GAIN, DA7218_HP_L_AMP_GAIN_SHIFT, |
1198 | DA7218_HP_AMP_GAIN_MIN, DA7218_HP_AMP_GAIN_MAX, |
1199 | DA7218_NO_INVERT, da7218_hp_gain_tlv), |
1200 | SOC_DOUBLE_R("Headphone Switch" , DA7218_HP_L_CTRL, DA7218_HP_R_CTRL, |
1201 | DA7218_HP_L_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX, |
1202 | DA7218_INVERT), |
1203 | SOC_DOUBLE_R("Headphone Gain Ramp Switch" , DA7218_HP_L_CTRL, |
1204 | DA7218_HP_R_CTRL, DA7218_HP_L_AMP_RAMP_EN_SHIFT, |
1205 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
1206 | SOC_DOUBLE_R("Headphone ZC Gain Switch" , DA7218_HP_L_CTRL, |
1207 | DA7218_HP_R_CTRL, DA7218_HP_L_AMP_ZC_EN_SHIFT, |
1208 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), |
1209 | }; |
1210 | |
1211 | |
1212 | /* |
1213 | * DAPM Mux Controls |
1214 | */ |
1215 | |
1216 | static const char * const da7218_mic_sel_text[] = { "Analog" , "Digital" }; |
1217 | |
1218 | static const struct soc_enum da7218_mic1_sel = |
1219 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(da7218_mic_sel_text), |
1220 | da7218_mic_sel_text); |
1221 | |
1222 | static const struct snd_kcontrol_new da7218_mic1_sel_mux = |
1223 | SOC_DAPM_ENUM("Mic1 Mux" , da7218_mic1_sel); |
1224 | |
1225 | static const struct soc_enum da7218_mic2_sel = |
1226 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(da7218_mic_sel_text), |
1227 | da7218_mic_sel_text); |
1228 | |
1229 | static const struct snd_kcontrol_new da7218_mic2_sel_mux = |
1230 | SOC_DAPM_ENUM("Mic2 Mux" , da7218_mic2_sel); |
1231 | |
1232 | static const char * const da7218_sidetone_in_sel_txt[] = { |
1233 | "In Filter1L" , "In Filter1R" , "In Filter2L" , "In Filter2R" |
1234 | }; |
1235 | |
1236 | static const struct soc_enum da7218_sidetone_in_sel = |
1237 | SOC_ENUM_SINGLE(DA7218_SIDETONE_IN_SELECT, |
1238 | DA7218_SIDETONE_IN_SELECT_SHIFT, |
1239 | DA7218_SIDETONE_IN_SELECT_MAX, |
1240 | da7218_sidetone_in_sel_txt); |
1241 | |
1242 | static const struct snd_kcontrol_new da7218_sidetone_in_sel_mux = |
1243 | SOC_DAPM_ENUM("Sidetone Mux" , da7218_sidetone_in_sel); |
1244 | |
1245 | static const char * const da7218_out_filt_biq_sel_txt[] = { |
1246 | "Bypass" , "Enabled" |
1247 | }; |
1248 | |
1249 | static const struct soc_enum da7218_out_filtl_biq_sel = |
1250 | SOC_ENUM_SINGLE(DA7218_OUT_1L_FILTER_CTRL, |
1251 | DA7218_OUT_1L_BIQ_5STAGE_SEL_SHIFT, |
1252 | DA7218_OUT_BIQ_5STAGE_SEL_MAX, |
1253 | da7218_out_filt_biq_sel_txt); |
1254 | |
1255 | static const struct snd_kcontrol_new da7218_out_filtl_biq_sel_mux = |
1256 | SOC_DAPM_ENUM("Out FilterL BiQuad Mux" , da7218_out_filtl_biq_sel); |
1257 | |
1258 | static const struct soc_enum da7218_out_filtr_biq_sel = |
1259 | SOC_ENUM_SINGLE(DA7218_OUT_1R_FILTER_CTRL, |
1260 | DA7218_OUT_1R_BIQ_5STAGE_SEL_SHIFT, |
1261 | DA7218_OUT_BIQ_5STAGE_SEL_MAX, |
1262 | da7218_out_filt_biq_sel_txt); |
1263 | |
1264 | static const struct snd_kcontrol_new da7218_out_filtr_biq_sel_mux = |
1265 | SOC_DAPM_ENUM("Out FilterR BiQuad Mux" , da7218_out_filtr_biq_sel); |
1266 | |
1267 | |
1268 | /* |
1269 | * DAPM Mixer Controls |
1270 | */ |
1271 | |
1272 | #define DA7218_DMIX_CTRLS(reg) \ |
1273 | SOC_DAPM_SINGLE("In Filter1L Switch", reg, \ |
1274 | DA7218_DMIX_SRC_INFILT1L, \ |
1275 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1276 | SOC_DAPM_SINGLE("In Filter1R Switch", reg, \ |
1277 | DA7218_DMIX_SRC_INFILT1R, \ |
1278 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1279 | SOC_DAPM_SINGLE("In Filter2L Switch", reg, \ |
1280 | DA7218_DMIX_SRC_INFILT2L, \ |
1281 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1282 | SOC_DAPM_SINGLE("In Filter2R Switch", reg, \ |
1283 | DA7218_DMIX_SRC_INFILT2R, \ |
1284 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1285 | SOC_DAPM_SINGLE("ToneGen Switch", reg, \ |
1286 | DA7218_DMIX_SRC_TONEGEN, \ |
1287 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1288 | SOC_DAPM_SINGLE("DAIL Switch", reg, DA7218_DMIX_SRC_DAIL, \ |
1289 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1290 | SOC_DAPM_SINGLE("DAIR Switch", reg, DA7218_DMIX_SRC_DAIR, \ |
1291 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT) |
1292 | |
1293 | static const struct snd_kcontrol_new da7218_out_dai1l_mix_controls[] = { |
1294 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_1L), |
1295 | }; |
1296 | |
1297 | static const struct snd_kcontrol_new da7218_out_dai1r_mix_controls[] = { |
1298 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_1R), |
1299 | }; |
1300 | |
1301 | static const struct snd_kcontrol_new da7218_out_dai2l_mix_controls[] = { |
1302 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_2L), |
1303 | }; |
1304 | |
1305 | static const struct snd_kcontrol_new da7218_out_dai2r_mix_controls[] = { |
1306 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_2R), |
1307 | }; |
1308 | |
1309 | static const struct snd_kcontrol_new da7218_out_filtl_mix_controls[] = { |
1310 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTFILT_1L), |
1311 | }; |
1312 | |
1313 | static const struct snd_kcontrol_new da7218_out_filtr_mix_controls[] = { |
1314 | DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTFILT_1R), |
1315 | }; |
1316 | |
1317 | #define DA7218_DMIX_ST_CTRLS(reg) \ |
1318 | SOC_DAPM_SINGLE("Out FilterL Switch", reg, \ |
1319 | DA7218_DMIX_ST_SRC_OUTFILT1L, \ |
1320 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1321 | SOC_DAPM_SINGLE("Out FilterR Switch", reg, \ |
1322 | DA7218_DMIX_ST_SRC_OUTFILT1R, \ |
1323 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \ |
1324 | SOC_DAPM_SINGLE("Sidetone Switch", reg, \ |
1325 | DA7218_DMIX_ST_SRC_SIDETONE, \ |
1326 | DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT) \ |
1327 | |
1328 | static const struct snd_kcontrol_new da7218_st_out_filtl_mix_controls[] = { |
1329 | DA7218_DMIX_ST_CTRLS(DA7218_DROUTING_ST_OUTFILT_1L), |
1330 | }; |
1331 | |
1332 | static const struct snd_kcontrol_new da7218_st_out_filtr_mix_controls[] = { |
1333 | DA7218_DMIX_ST_CTRLS(DA7218_DROUTING_ST_OUTFILT_1R), |
1334 | }; |
1335 | |
1336 | |
1337 | /* |
1338 | * DAPM Events |
1339 | */ |
1340 | |
1341 | /* |
1342 | * We keep track of which input filters are enabled. This is used in the logic |
1343 | * for controlling the mic level detect feature. |
1344 | */ |
1345 | static int da7218_in_filter_event(struct snd_soc_dapm_widget *w, |
1346 | struct snd_kcontrol *kcontrol, int event) |
1347 | { |
1348 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1349 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1350 | u8 mask; |
1351 | |
1352 | switch (w->reg) { |
1353 | case DA7218_IN_1L_FILTER_CTRL: |
1354 | mask = (1 << DA7218_LVL_DET_EN_CHAN1L_SHIFT); |
1355 | break; |
1356 | case DA7218_IN_1R_FILTER_CTRL: |
1357 | mask = (1 << DA7218_LVL_DET_EN_CHAN1R_SHIFT); |
1358 | break; |
1359 | case DA7218_IN_2L_FILTER_CTRL: |
1360 | mask = (1 << DA7218_LVL_DET_EN_CHAN2L_SHIFT); |
1361 | break; |
1362 | case DA7218_IN_2R_FILTER_CTRL: |
1363 | mask = (1 << DA7218_LVL_DET_EN_CHAN2R_SHIFT); |
1364 | break; |
1365 | default: |
1366 | return -EINVAL; |
1367 | } |
1368 | |
1369 | switch (event) { |
1370 | case SND_SOC_DAPM_POST_PMU: |
1371 | da7218->in_filt_en |= mask; |
1372 | /* |
1373 | * If we're enabling path for mic level detect, wait for path |
1374 | * to settle before enabling feature to avoid incorrect and |
1375 | * unwanted detect events. |
1376 | */ |
1377 | if (mask & da7218->mic_lvl_det_en) |
1378 | msleep(DA7218_MIC_LVL_DET_DELAY); |
1379 | break; |
1380 | case SND_SOC_DAPM_PRE_PMD: |
1381 | da7218->in_filt_en &= ~mask; |
1382 | break; |
1383 | default: |
1384 | return -EINVAL; |
1385 | } |
1386 | |
1387 | /* Enable configured level detection paths */ |
1388 | snd_soc_component_write(component, DA7218_LVL_DET_CTRL, |
1389 | val: (da7218->in_filt_en & da7218->mic_lvl_det_en)); |
1390 | |
1391 | return 0; |
1392 | } |
1393 | |
1394 | static int da7218_dai_event(struct snd_soc_dapm_widget *w, |
1395 | struct snd_kcontrol *kcontrol, int event) |
1396 | { |
1397 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1398 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1399 | u8 pll_ctrl, pll_status, refosc_cal; |
1400 | int i; |
1401 | bool success; |
1402 | |
1403 | switch (event) { |
1404 | case SND_SOC_DAPM_POST_PMU: |
1405 | if (da7218->master) |
1406 | /* Enable DAI clks for master mode */ |
1407 | snd_soc_component_update_bits(component, DA7218_DAI_CLK_MODE, |
1408 | DA7218_DAI_CLK_EN_MASK, |
1409 | DA7218_DAI_CLK_EN_MASK); |
1410 | |
1411 | /* Tune reference oscillator */ |
1412 | snd_soc_component_write(component, DA7218_PLL_REFOSC_CAL, |
1413 | DA7218_PLL_REFOSC_CAL_START_MASK); |
1414 | snd_soc_component_write(component, DA7218_PLL_REFOSC_CAL, |
1415 | DA7218_PLL_REFOSC_CAL_START_MASK | |
1416 | DA7218_PLL_REFOSC_CAL_EN_MASK); |
1417 | |
1418 | /* Check tuning complete */ |
1419 | i = 0; |
1420 | success = false; |
1421 | do { |
1422 | refosc_cal = snd_soc_component_read(component, DA7218_PLL_REFOSC_CAL); |
1423 | if (!(refosc_cal & DA7218_PLL_REFOSC_CAL_START_MASK)) { |
1424 | success = true; |
1425 | } else { |
1426 | ++i; |
1427 | usleep_range(DA7218_REF_OSC_CHECK_DELAY_MIN, |
1428 | DA7218_REF_OSC_CHECK_DELAY_MAX); |
1429 | } |
1430 | } while ((i < DA7218_REF_OSC_CHECK_TRIES) && (!success)); |
1431 | |
1432 | if (!success) |
1433 | dev_warn(component->dev, |
1434 | "Reference oscillator failed calibration\n" ); |
1435 | |
1436 | /* PC synchronised to DAI */ |
1437 | snd_soc_component_write(component, DA7218_PC_COUNT, |
1438 | DA7218_PC_RESYNC_AUTO_MASK); |
1439 | |
1440 | /* If SRM not enabled, we don't need to check status */ |
1441 | pll_ctrl = snd_soc_component_read(component, DA7218_PLL_CTRL); |
1442 | if ((pll_ctrl & DA7218_PLL_MODE_MASK) != DA7218_PLL_MODE_SRM) |
1443 | return 0; |
1444 | |
1445 | /* Check SRM has locked */ |
1446 | i = 0; |
1447 | success = false; |
1448 | do { |
1449 | pll_status = snd_soc_component_read(component, DA7218_PLL_STATUS); |
1450 | if (pll_status & DA7218_PLL_SRM_STATUS_SRM_LOCK) { |
1451 | success = true; |
1452 | } else { |
1453 | ++i; |
1454 | msleep(DA7218_SRM_CHECK_DELAY); |
1455 | } |
1456 | } while ((i < DA7218_SRM_CHECK_TRIES) && (!success)); |
1457 | |
1458 | if (!success) |
1459 | dev_warn(component->dev, "SRM failed to lock\n" ); |
1460 | |
1461 | return 0; |
1462 | case SND_SOC_DAPM_POST_PMD: |
1463 | /* PC free-running */ |
1464 | snd_soc_component_write(component, DA7218_PC_COUNT, DA7218_PC_FREERUN_MASK); |
1465 | |
1466 | if (da7218->master) |
1467 | /* Disable DAI clks for master mode */ |
1468 | snd_soc_component_update_bits(component, DA7218_DAI_CLK_MODE, |
1469 | DA7218_DAI_CLK_EN_MASK, val: 0); |
1470 | |
1471 | return 0; |
1472 | default: |
1473 | return -EINVAL; |
1474 | } |
1475 | } |
1476 | |
1477 | static int da7218_cp_event(struct snd_soc_dapm_widget *w, |
1478 | struct snd_kcontrol *kcontrol, int event) |
1479 | { |
1480 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1481 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1482 | |
1483 | /* |
1484 | * If this is DA7217 and we're using single supply for differential |
1485 | * output, we really don't want to touch the charge pump. |
1486 | */ |
1487 | if (da7218->hp_single_supply) |
1488 | return 0; |
1489 | |
1490 | switch (event) { |
1491 | case SND_SOC_DAPM_PRE_PMU: |
1492 | snd_soc_component_update_bits(component, DA7218_CP_CTRL, DA7218_CP_EN_MASK, |
1493 | DA7218_CP_EN_MASK); |
1494 | return 0; |
1495 | case SND_SOC_DAPM_PRE_PMD: |
1496 | snd_soc_component_update_bits(component, DA7218_CP_CTRL, DA7218_CP_EN_MASK, |
1497 | val: 0); |
1498 | return 0; |
1499 | default: |
1500 | return -EINVAL; |
1501 | } |
1502 | } |
1503 | |
1504 | static int da7218_hp_pga_event(struct snd_soc_dapm_widget *w, |
1505 | struct snd_kcontrol *kcontrol, int event) |
1506 | { |
1507 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1508 | |
1509 | switch (event) { |
1510 | case SND_SOC_DAPM_POST_PMU: |
1511 | /* Enable headphone output */ |
1512 | snd_soc_component_update_bits(component, reg: w->reg, DA7218_HP_AMP_OE_MASK, |
1513 | DA7218_HP_AMP_OE_MASK); |
1514 | return 0; |
1515 | case SND_SOC_DAPM_PRE_PMD: |
1516 | /* Headphone output high impedance */ |
1517 | snd_soc_component_update_bits(component, reg: w->reg, DA7218_HP_AMP_OE_MASK, val: 0); |
1518 | return 0; |
1519 | default: |
1520 | return -EINVAL; |
1521 | } |
1522 | } |
1523 | |
1524 | |
1525 | /* |
1526 | * DAPM Widgets |
1527 | */ |
1528 | |
1529 | static const struct snd_soc_dapm_widget da7218_dapm_widgets[] = { |
1530 | /* Input Supplies */ |
1531 | SND_SOC_DAPM_SUPPLY("Mic Bias1" , DA7218_MICBIAS_EN, |
1532 | DA7218_MICBIAS_1_EN_SHIFT, DA7218_NO_INVERT, |
1533 | NULL, 0), |
1534 | SND_SOC_DAPM_SUPPLY("Mic Bias2" , DA7218_MICBIAS_EN, |
1535 | DA7218_MICBIAS_2_EN_SHIFT, DA7218_NO_INVERT, |
1536 | NULL, 0), |
1537 | SND_SOC_DAPM_SUPPLY("DMic1 Left" , DA7218_DMIC_1_CTRL, |
1538 | DA7218_DMIC_1L_EN_SHIFT, DA7218_NO_INVERT, |
1539 | NULL, 0), |
1540 | SND_SOC_DAPM_SUPPLY("DMic1 Right" , DA7218_DMIC_1_CTRL, |
1541 | DA7218_DMIC_1R_EN_SHIFT, DA7218_NO_INVERT, |
1542 | NULL, 0), |
1543 | SND_SOC_DAPM_SUPPLY("DMic2 Left" , DA7218_DMIC_2_CTRL, |
1544 | DA7218_DMIC_2L_EN_SHIFT, DA7218_NO_INVERT, |
1545 | NULL, 0), |
1546 | SND_SOC_DAPM_SUPPLY("DMic2 Right" , DA7218_DMIC_2_CTRL, |
1547 | DA7218_DMIC_2R_EN_SHIFT, DA7218_NO_INVERT, |
1548 | NULL, 0), |
1549 | |
1550 | /* Inputs */ |
1551 | SND_SOC_DAPM_INPUT("MIC1" ), |
1552 | SND_SOC_DAPM_INPUT("MIC2" ), |
1553 | SND_SOC_DAPM_INPUT("DMIC1L" ), |
1554 | SND_SOC_DAPM_INPUT("DMIC1R" ), |
1555 | SND_SOC_DAPM_INPUT("DMIC2L" ), |
1556 | SND_SOC_DAPM_INPUT("DMIC2R" ), |
1557 | |
1558 | /* Input Mixer Supplies */ |
1559 | SND_SOC_DAPM_SUPPLY("Mixin1 Supply" , DA7218_MIXIN_1_CTRL, |
1560 | DA7218_MIXIN_1_MIX_SEL_SHIFT, DA7218_NO_INVERT, |
1561 | NULL, 0), |
1562 | SND_SOC_DAPM_SUPPLY("Mixin2 Supply" , DA7218_MIXIN_2_CTRL, |
1563 | DA7218_MIXIN_2_MIX_SEL_SHIFT, DA7218_NO_INVERT, |
1564 | NULL, 0), |
1565 | |
1566 | /* Input PGAs */ |
1567 | SND_SOC_DAPM_PGA("Mic1 PGA" , DA7218_MIC_1_CTRL, |
1568 | DA7218_MIC_1_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1569 | NULL, 0), |
1570 | SND_SOC_DAPM_PGA("Mic2 PGA" , DA7218_MIC_2_CTRL, |
1571 | DA7218_MIC_2_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1572 | NULL, 0), |
1573 | SND_SOC_DAPM_PGA("Mixin1 PGA" , DA7218_MIXIN_1_CTRL, |
1574 | DA7218_MIXIN_1_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1575 | NULL, 0), |
1576 | SND_SOC_DAPM_PGA("Mixin2 PGA" , DA7218_MIXIN_2_CTRL, |
1577 | DA7218_MIXIN_2_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1578 | NULL, 0), |
1579 | |
1580 | /* Mic/DMic Muxes */ |
1581 | SND_SOC_DAPM_MUX("Mic1 Mux" , SND_SOC_NOPM, 0, 0, &da7218_mic1_sel_mux), |
1582 | SND_SOC_DAPM_MUX("Mic2 Mux" , SND_SOC_NOPM, 0, 0, &da7218_mic2_sel_mux), |
1583 | |
1584 | /* Input Filters */ |
1585 | SND_SOC_DAPM_ADC_E("In Filter1L" , NULL, DA7218_IN_1L_FILTER_CTRL, |
1586 | DA7218_IN_1L_FILTER_EN_SHIFT, DA7218_NO_INVERT, |
1587 | da7218_in_filter_event, |
1588 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1589 | SND_SOC_DAPM_ADC_E("In Filter1R" , NULL, DA7218_IN_1R_FILTER_CTRL, |
1590 | DA7218_IN_1R_FILTER_EN_SHIFT, DA7218_NO_INVERT, |
1591 | da7218_in_filter_event, |
1592 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1593 | SND_SOC_DAPM_ADC_E("In Filter2L" , NULL, DA7218_IN_2L_FILTER_CTRL, |
1594 | DA7218_IN_2L_FILTER_EN_SHIFT, DA7218_NO_INVERT, |
1595 | da7218_in_filter_event, |
1596 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1597 | SND_SOC_DAPM_ADC_E("In Filter2R" , NULL, DA7218_IN_2R_FILTER_CTRL, |
1598 | DA7218_IN_2R_FILTER_EN_SHIFT, DA7218_NO_INVERT, |
1599 | da7218_in_filter_event, |
1600 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1601 | |
1602 | /* Tone Generator */ |
1603 | SND_SOC_DAPM_SIGGEN("TONE" ), |
1604 | SND_SOC_DAPM_PGA("Tone Generator" , DA7218_TONE_GEN_CFG1, |
1605 | DA7218_START_STOPN_SHIFT, DA7218_NO_INVERT, NULL, 0), |
1606 | |
1607 | /* Sidetone Input */ |
1608 | SND_SOC_DAPM_MUX("Sidetone Mux" , SND_SOC_NOPM, 0, 0, |
1609 | &da7218_sidetone_in_sel_mux), |
1610 | SND_SOC_DAPM_ADC("Sidetone Filter" , NULL, DA7218_SIDETONE_CTRL, |
1611 | DA7218_SIDETONE_FILTER_EN_SHIFT, DA7218_NO_INVERT), |
1612 | |
1613 | /* Input Mixers */ |
1614 | SND_SOC_DAPM_MIXER("Mixer DAI1L" , SND_SOC_NOPM, 0, 0, |
1615 | da7218_out_dai1l_mix_controls, |
1616 | ARRAY_SIZE(da7218_out_dai1l_mix_controls)), |
1617 | SND_SOC_DAPM_MIXER("Mixer DAI1R" , SND_SOC_NOPM, 0, 0, |
1618 | da7218_out_dai1r_mix_controls, |
1619 | ARRAY_SIZE(da7218_out_dai1r_mix_controls)), |
1620 | SND_SOC_DAPM_MIXER("Mixer DAI2L" , SND_SOC_NOPM, 0, 0, |
1621 | da7218_out_dai2l_mix_controls, |
1622 | ARRAY_SIZE(da7218_out_dai2l_mix_controls)), |
1623 | SND_SOC_DAPM_MIXER("Mixer DAI2R" , SND_SOC_NOPM, 0, 0, |
1624 | da7218_out_dai2r_mix_controls, |
1625 | ARRAY_SIZE(da7218_out_dai2r_mix_controls)), |
1626 | |
1627 | /* DAI Supply */ |
1628 | SND_SOC_DAPM_SUPPLY("DAI" , DA7218_DAI_CTRL, DA7218_DAI_EN_SHIFT, |
1629 | DA7218_NO_INVERT, da7218_dai_event, |
1630 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1631 | |
1632 | /* DAI */ |
1633 | SND_SOC_DAPM_AIF_OUT("DAIOUT" , "Capture" , 0, DA7218_DAI_TDM_CTRL, |
1634 | DA7218_DAI_OE_SHIFT, DA7218_NO_INVERT), |
1635 | SND_SOC_DAPM_AIF_IN("DAIIN" , "Playback" , 0, SND_SOC_NOPM, 0, 0), |
1636 | |
1637 | /* Output Mixers */ |
1638 | SND_SOC_DAPM_MIXER("Mixer Out FilterL" , SND_SOC_NOPM, 0, 0, |
1639 | da7218_out_filtl_mix_controls, |
1640 | ARRAY_SIZE(da7218_out_filtl_mix_controls)), |
1641 | SND_SOC_DAPM_MIXER("Mixer Out FilterR" , SND_SOC_NOPM, 0, 0, |
1642 | da7218_out_filtr_mix_controls, |
1643 | ARRAY_SIZE(da7218_out_filtr_mix_controls)), |
1644 | |
1645 | /* BiQuad Filters */ |
1646 | SND_SOC_DAPM_MUX("Out FilterL BiQuad Mux" , SND_SOC_NOPM, 0, 0, |
1647 | &da7218_out_filtl_biq_sel_mux), |
1648 | SND_SOC_DAPM_MUX("Out FilterR BiQuad Mux" , SND_SOC_NOPM, 0, 0, |
1649 | &da7218_out_filtr_biq_sel_mux), |
1650 | SND_SOC_DAPM_DAC("BiQuad Filter" , NULL, DA7218_OUT_1_BIQ_5STAGE_CTRL, |
1651 | DA7218_OUT_1_BIQ_5STAGE_FILTER_EN_SHIFT, |
1652 | DA7218_NO_INVERT), |
1653 | |
1654 | /* Sidetone Mixers */ |
1655 | SND_SOC_DAPM_MIXER("ST Mixer Out FilterL" , SND_SOC_NOPM, 0, 0, |
1656 | da7218_st_out_filtl_mix_controls, |
1657 | ARRAY_SIZE(da7218_st_out_filtl_mix_controls)), |
1658 | SND_SOC_DAPM_MIXER("ST Mixer Out FilterR" , SND_SOC_NOPM, 0, 0, |
1659 | da7218_st_out_filtr_mix_controls, |
1660 | ARRAY_SIZE(da7218_st_out_filtr_mix_controls)), |
1661 | |
1662 | /* Output Filters */ |
1663 | SND_SOC_DAPM_DAC("Out FilterL" , NULL, DA7218_OUT_1L_FILTER_CTRL, |
1664 | DA7218_OUT_1L_FILTER_EN_SHIFT, DA7218_NO_INVERT), |
1665 | SND_SOC_DAPM_DAC("Out FilterR" , NULL, DA7218_OUT_1R_FILTER_CTRL, |
1666 | DA7218_IN_1R_FILTER_EN_SHIFT, DA7218_NO_INVERT), |
1667 | |
1668 | /* Output PGAs */ |
1669 | SND_SOC_DAPM_PGA("Mixout Left PGA" , DA7218_MIXOUT_L_CTRL, |
1670 | DA7218_MIXOUT_L_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1671 | NULL, 0), |
1672 | SND_SOC_DAPM_PGA("Mixout Right PGA" , DA7218_MIXOUT_R_CTRL, |
1673 | DA7218_MIXOUT_R_AMP_EN_SHIFT, DA7218_NO_INVERT, |
1674 | NULL, 0), |
1675 | SND_SOC_DAPM_PGA_E("Headphone Left PGA" , DA7218_HP_L_CTRL, |
1676 | DA7218_HP_L_AMP_EN_SHIFT, DA7218_NO_INVERT, NULL, 0, |
1677 | da7218_hp_pga_event, |
1678 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1679 | SND_SOC_DAPM_PGA_E("Headphone Right PGA" , DA7218_HP_R_CTRL, |
1680 | DA7218_HP_R_AMP_EN_SHIFT, DA7218_NO_INVERT, NULL, 0, |
1681 | da7218_hp_pga_event, |
1682 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1683 | |
1684 | /* Output Supplies */ |
1685 | SND_SOC_DAPM_SUPPLY("Charge Pump" , SND_SOC_NOPM, 0, 0, da7218_cp_event, |
1686 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), |
1687 | |
1688 | /* Outputs */ |
1689 | SND_SOC_DAPM_OUTPUT("HPL" ), |
1690 | SND_SOC_DAPM_OUTPUT("HPR" ), |
1691 | }; |
1692 | |
1693 | |
1694 | /* |
1695 | * DAPM Mixer Routes |
1696 | */ |
1697 | |
1698 | #define DA7218_DMIX_ROUTES(name) \ |
1699 | {name, "In Filter1L Switch", "In Filter1L"}, \ |
1700 | {name, "In Filter1R Switch", "In Filter1R"}, \ |
1701 | {name, "In Filter2L Switch", "In Filter2L"}, \ |
1702 | {name, "In Filter2R Switch", "In Filter2R"}, \ |
1703 | {name, "ToneGen Switch", "Tone Generator"}, \ |
1704 | {name, "DAIL Switch", "DAIIN"}, \ |
1705 | {name, "DAIR Switch", "DAIIN"} |
1706 | |
1707 | #define DA7218_DMIX_ST_ROUTES(name) \ |
1708 | {name, "Out FilterL Switch", "Out FilterL BiQuad Mux"}, \ |
1709 | {name, "Out FilterR Switch", "Out FilterR BiQuad Mux"}, \ |
1710 | {name, "Sidetone Switch", "Sidetone Filter"} |
1711 | |
1712 | |
1713 | /* |
1714 | * DAPM audio route definition |
1715 | */ |
1716 | |
1717 | static const struct snd_soc_dapm_route da7218_audio_map[] = { |
1718 | /* Input paths */ |
1719 | {"MIC1" , NULL, "Mic Bias1" }, |
1720 | {"MIC2" , NULL, "Mic Bias2" }, |
1721 | {"DMIC1L" , NULL, "Mic Bias1" }, |
1722 | {"DMIC1L" , NULL, "DMic1 Left" }, |
1723 | {"DMIC1R" , NULL, "Mic Bias1" }, |
1724 | {"DMIC1R" , NULL, "DMic1 Right" }, |
1725 | {"DMIC2L" , NULL, "Mic Bias2" }, |
1726 | {"DMIC2L" , NULL, "DMic2 Left" }, |
1727 | {"DMIC2R" , NULL, "Mic Bias2" }, |
1728 | {"DMIC2R" , NULL, "DMic2 Right" }, |
1729 | |
1730 | {"Mic1 PGA" , NULL, "MIC1" }, |
1731 | {"Mic2 PGA" , NULL, "MIC2" }, |
1732 | |
1733 | {"Mixin1 PGA" , NULL, "Mixin1 Supply" }, |
1734 | {"Mixin2 PGA" , NULL, "Mixin2 Supply" }, |
1735 | |
1736 | {"Mixin1 PGA" , NULL, "Mic1 PGA" }, |
1737 | {"Mixin2 PGA" , NULL, "Mic2 PGA" }, |
1738 | |
1739 | {"Mic1 Mux" , "Analog" , "Mixin1 PGA" }, |
1740 | {"Mic1 Mux" , "Digital" , "DMIC1L" }, |
1741 | {"Mic1 Mux" , "Digital" , "DMIC1R" }, |
1742 | {"Mic2 Mux" , "Analog" , "Mixin2 PGA" }, |
1743 | {"Mic2 Mux" , "Digital" , "DMIC2L" }, |
1744 | {"Mic2 Mux" , "Digital" , "DMIC2R" }, |
1745 | |
1746 | {"In Filter1L" , NULL, "Mic1 Mux" }, |
1747 | {"In Filter1R" , NULL, "Mic1 Mux" }, |
1748 | {"In Filter2L" , NULL, "Mic2 Mux" }, |
1749 | {"In Filter2R" , NULL, "Mic2 Mux" }, |
1750 | |
1751 | {"Tone Generator" , NULL, "TONE" }, |
1752 | |
1753 | {"Sidetone Mux" , "In Filter1L" , "In Filter1L" }, |
1754 | {"Sidetone Mux" , "In Filter1R" , "In Filter1R" }, |
1755 | {"Sidetone Mux" , "In Filter2L" , "In Filter2L" }, |
1756 | {"Sidetone Mux" , "In Filter2R" , "In Filter2R" }, |
1757 | {"Sidetone Filter" , NULL, "Sidetone Mux" }, |
1758 | |
1759 | DA7218_DMIX_ROUTES("Mixer DAI1L" ), |
1760 | DA7218_DMIX_ROUTES("Mixer DAI1R" ), |
1761 | DA7218_DMIX_ROUTES("Mixer DAI2L" ), |
1762 | DA7218_DMIX_ROUTES("Mixer DAI2R" ), |
1763 | |
1764 | {"DAIOUT" , NULL, "Mixer DAI1L" }, |
1765 | {"DAIOUT" , NULL, "Mixer DAI1R" }, |
1766 | {"DAIOUT" , NULL, "Mixer DAI2L" }, |
1767 | {"DAIOUT" , NULL, "Mixer DAI2R" }, |
1768 | |
1769 | {"DAIOUT" , NULL, "DAI" }, |
1770 | |
1771 | /* Output paths */ |
1772 | {"DAIIN" , NULL, "DAI" }, |
1773 | |
1774 | DA7218_DMIX_ROUTES("Mixer Out FilterL" ), |
1775 | DA7218_DMIX_ROUTES("Mixer Out FilterR" ), |
1776 | |
1777 | {"BiQuad Filter" , NULL, "Mixer Out FilterL" }, |
1778 | {"BiQuad Filter" , NULL, "Mixer Out FilterR" }, |
1779 | |
1780 | {"Out FilterL BiQuad Mux" , "Bypass" , "Mixer Out FilterL" }, |
1781 | {"Out FilterL BiQuad Mux" , "Enabled" , "BiQuad Filter" }, |
1782 | {"Out FilterR BiQuad Mux" , "Bypass" , "Mixer Out FilterR" }, |
1783 | {"Out FilterR BiQuad Mux" , "Enabled" , "BiQuad Filter" }, |
1784 | |
1785 | DA7218_DMIX_ST_ROUTES("ST Mixer Out FilterL" ), |
1786 | DA7218_DMIX_ST_ROUTES("ST Mixer Out FilterR" ), |
1787 | |
1788 | {"Out FilterL" , NULL, "ST Mixer Out FilterL" }, |
1789 | {"Out FilterR" , NULL, "ST Mixer Out FilterR" }, |
1790 | |
1791 | {"Mixout Left PGA" , NULL, "Out FilterL" }, |
1792 | {"Mixout Right PGA" , NULL, "Out FilterR" }, |
1793 | |
1794 | {"Headphone Left PGA" , NULL, "Mixout Left PGA" }, |
1795 | {"Headphone Right PGA" , NULL, "Mixout Right PGA" }, |
1796 | |
1797 | {"HPL" , NULL, "Headphone Left PGA" }, |
1798 | {"HPR" , NULL, "Headphone Right PGA" }, |
1799 | |
1800 | {"HPL" , NULL, "Charge Pump" }, |
1801 | {"HPR" , NULL, "Charge Pump" }, |
1802 | }; |
1803 | |
1804 | |
1805 | /* |
1806 | * DAI operations |
1807 | */ |
1808 | |
1809 | static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
1810 | int clk_id, unsigned int freq, int dir) |
1811 | { |
1812 | struct snd_soc_component *component = codec_dai->component; |
1813 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1814 | int ret; |
1815 | |
1816 | if (da7218->mclk_rate == freq) |
1817 | return 0; |
1818 | |
1819 | if ((freq < 2000000) || (freq > 54000000)) { |
1820 | dev_err(codec_dai->dev, "Unsupported MCLK value %d\n" , |
1821 | freq); |
1822 | return -EINVAL; |
1823 | } |
1824 | |
1825 | switch (clk_id) { |
1826 | case DA7218_CLKSRC_MCLK_SQR: |
1827 | snd_soc_component_update_bits(component, DA7218_PLL_CTRL, |
1828 | DA7218_PLL_MCLK_SQR_EN_MASK, |
1829 | DA7218_PLL_MCLK_SQR_EN_MASK); |
1830 | break; |
1831 | case DA7218_CLKSRC_MCLK: |
1832 | snd_soc_component_update_bits(component, DA7218_PLL_CTRL, |
1833 | DA7218_PLL_MCLK_SQR_EN_MASK, val: 0); |
1834 | break; |
1835 | default: |
1836 | dev_err(codec_dai->dev, "Unknown clock source %d\n" , clk_id); |
1837 | return -EINVAL; |
1838 | } |
1839 | |
1840 | if (da7218->mclk) { |
1841 | freq = clk_round_rate(clk: da7218->mclk, rate: freq); |
1842 | ret = clk_set_rate(clk: da7218->mclk, rate: freq); |
1843 | if (ret) { |
1844 | dev_err(codec_dai->dev, "Failed to set clock rate %d\n" , |
1845 | freq); |
1846 | return ret; |
1847 | } |
1848 | } |
1849 | |
1850 | da7218->mclk_rate = freq; |
1851 | |
1852 | return 0; |
1853 | } |
1854 | |
1855 | static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
1856 | int source, unsigned int fref, unsigned int fout) |
1857 | { |
1858 | struct snd_soc_component *component = codec_dai->component; |
1859 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1860 | |
1861 | u8 pll_ctrl, indiv_bits, indiv; |
1862 | u8 pll_frac_top, pll_frac_bot, pll_integer; |
1863 | u32 freq_ref; |
1864 | u64 frac_div; |
1865 | |
1866 | /* Verify 2MHz - 54MHz MCLK provided, and set input divider */ |
1867 | if (da7218->mclk_rate < 2000000) { |
1868 | dev_err(component->dev, "PLL input clock %d below valid range\n" , |
1869 | da7218->mclk_rate); |
1870 | return -EINVAL; |
1871 | } else if (da7218->mclk_rate <= 4500000) { |
1872 | indiv_bits = DA7218_PLL_INDIV_2_TO_4_5_MHZ; |
1873 | indiv = DA7218_PLL_INDIV_2_TO_4_5_MHZ_VAL; |
1874 | } else if (da7218->mclk_rate <= 9000000) { |
1875 | indiv_bits = DA7218_PLL_INDIV_4_5_TO_9_MHZ; |
1876 | indiv = DA7218_PLL_INDIV_4_5_TO_9_MHZ_VAL; |
1877 | } else if (da7218->mclk_rate <= 18000000) { |
1878 | indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; |
1879 | indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; |
1880 | } else if (da7218->mclk_rate <= 36000000) { |
1881 | indiv_bits = DA7218_PLL_INDIV_18_TO_36_MHZ; |
1882 | indiv = DA7218_PLL_INDIV_18_TO_36_MHZ_VAL; |
1883 | } else if (da7218->mclk_rate <= 54000000) { |
1884 | indiv_bits = DA7218_PLL_INDIV_36_TO_54_MHZ; |
1885 | indiv = DA7218_PLL_INDIV_36_TO_54_MHZ_VAL; |
1886 | } else { |
1887 | dev_err(component->dev, "PLL input clock %d above valid range\n" , |
1888 | da7218->mclk_rate); |
1889 | return -EINVAL; |
1890 | } |
1891 | freq_ref = (da7218->mclk_rate / indiv); |
1892 | pll_ctrl = indiv_bits; |
1893 | |
1894 | /* Configure PLL */ |
1895 | switch (source) { |
1896 | case DA7218_SYSCLK_MCLK: |
1897 | pll_ctrl |= DA7218_PLL_MODE_BYPASS; |
1898 | snd_soc_component_update_bits(component, DA7218_PLL_CTRL, |
1899 | DA7218_PLL_INDIV_MASK | |
1900 | DA7218_PLL_MODE_MASK, val: pll_ctrl); |
1901 | return 0; |
1902 | case DA7218_SYSCLK_PLL: |
1903 | pll_ctrl |= DA7218_PLL_MODE_NORMAL; |
1904 | break; |
1905 | case DA7218_SYSCLK_PLL_SRM: |
1906 | pll_ctrl |= DA7218_PLL_MODE_SRM; |
1907 | break; |
1908 | default: |
1909 | dev_err(component->dev, "Invalid PLL config\n" ); |
1910 | return -EINVAL; |
1911 | } |
1912 | |
1913 | /* Calculate dividers for PLL */ |
1914 | pll_integer = fout / freq_ref; |
1915 | frac_div = (u64)(fout % freq_ref) * 8192ULL; |
1916 | do_div(frac_div, freq_ref); |
1917 | pll_frac_top = (frac_div >> DA7218_BYTE_SHIFT) & DA7218_BYTE_MASK; |
1918 | pll_frac_bot = (frac_div) & DA7218_BYTE_MASK; |
1919 | |
1920 | /* Write PLL config & dividers */ |
1921 | snd_soc_component_write(component, DA7218_PLL_FRAC_TOP, val: pll_frac_top); |
1922 | snd_soc_component_write(component, DA7218_PLL_FRAC_BOT, val: pll_frac_bot); |
1923 | snd_soc_component_write(component, DA7218_PLL_INTEGER, val: pll_integer); |
1924 | snd_soc_component_update_bits(component, DA7218_PLL_CTRL, |
1925 | DA7218_PLL_MODE_MASK | DA7218_PLL_INDIV_MASK, |
1926 | val: pll_ctrl); |
1927 | |
1928 | return 0; |
1929 | } |
1930 | |
1931 | static int da7218_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
1932 | { |
1933 | struct snd_soc_component *component = codec_dai->component; |
1934 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
1935 | u8 dai_clk_mode = 0, dai_ctrl = 0; |
1936 | |
1937 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
1938 | case SND_SOC_DAIFMT_CBM_CFM: |
1939 | da7218->master = true; |
1940 | break; |
1941 | case SND_SOC_DAIFMT_CBS_CFS: |
1942 | da7218->master = false; |
1943 | break; |
1944 | default: |
1945 | return -EINVAL; |
1946 | } |
1947 | |
1948 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
1949 | case SND_SOC_DAIFMT_I2S: |
1950 | case SND_SOC_DAIFMT_LEFT_J: |
1951 | case SND_SOC_DAIFMT_RIGHT_J: |
1952 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
1953 | case SND_SOC_DAIFMT_NB_NF: |
1954 | break; |
1955 | case SND_SOC_DAIFMT_NB_IF: |
1956 | dai_clk_mode |= DA7218_DAI_WCLK_POL_INV; |
1957 | break; |
1958 | case SND_SOC_DAIFMT_IB_NF: |
1959 | dai_clk_mode |= DA7218_DAI_CLK_POL_INV; |
1960 | break; |
1961 | case SND_SOC_DAIFMT_IB_IF: |
1962 | dai_clk_mode |= DA7218_DAI_WCLK_POL_INV | |
1963 | DA7218_DAI_CLK_POL_INV; |
1964 | break; |
1965 | default: |
1966 | return -EINVAL; |
1967 | } |
1968 | break; |
1969 | case SND_SOC_DAIFMT_DSP_B: |
1970 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
1971 | case SND_SOC_DAIFMT_NB_NF: |
1972 | dai_clk_mode |= DA7218_DAI_CLK_POL_INV; |
1973 | break; |
1974 | case SND_SOC_DAIFMT_NB_IF: |
1975 | dai_clk_mode |= DA7218_DAI_WCLK_POL_INV | |
1976 | DA7218_DAI_CLK_POL_INV; |
1977 | break; |
1978 | case SND_SOC_DAIFMT_IB_NF: |
1979 | break; |
1980 | case SND_SOC_DAIFMT_IB_IF: |
1981 | dai_clk_mode |= DA7218_DAI_WCLK_POL_INV; |
1982 | break; |
1983 | default: |
1984 | return -EINVAL; |
1985 | } |
1986 | break; |
1987 | default: |
1988 | return -EINVAL; |
1989 | } |
1990 | |
1991 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
1992 | case SND_SOC_DAIFMT_I2S: |
1993 | dai_ctrl |= DA7218_DAI_FORMAT_I2S; |
1994 | break; |
1995 | case SND_SOC_DAIFMT_LEFT_J: |
1996 | dai_ctrl |= DA7218_DAI_FORMAT_LEFT_J; |
1997 | break; |
1998 | case SND_SOC_DAIFMT_RIGHT_J: |
1999 | dai_ctrl |= DA7218_DAI_FORMAT_RIGHT_J; |
2000 | break; |
2001 | case SND_SOC_DAIFMT_DSP_B: |
2002 | dai_ctrl |= DA7218_DAI_FORMAT_DSP; |
2003 | break; |
2004 | default: |
2005 | return -EINVAL; |
2006 | } |
2007 | |
2008 | /* By default 64 BCLKs per WCLK is supported */ |
2009 | dai_clk_mode |= DA7218_DAI_BCLKS_PER_WCLK_64; |
2010 | |
2011 | snd_soc_component_write(component, DA7218_DAI_CLK_MODE, val: dai_clk_mode); |
2012 | snd_soc_component_update_bits(component, DA7218_DAI_CTRL, DA7218_DAI_FORMAT_MASK, |
2013 | val: dai_ctrl); |
2014 | |
2015 | return 0; |
2016 | } |
2017 | |
2018 | static int da7218_set_dai_tdm_slot(struct snd_soc_dai *dai, |
2019 | unsigned int tx_mask, unsigned int rx_mask, |
2020 | int slots, int slot_width) |
2021 | { |
2022 | struct snd_soc_component *component = dai->component; |
2023 | u8 dai_bclks_per_wclk; |
2024 | u32 frame_size; |
2025 | |
2026 | /* No channels enabled so disable TDM, revert to 64-bit frames */ |
2027 | if (!tx_mask) { |
2028 | snd_soc_component_update_bits(component, DA7218_DAI_TDM_CTRL, |
2029 | DA7218_DAI_TDM_CH_EN_MASK | |
2030 | DA7218_DAI_TDM_MODE_EN_MASK, val: 0); |
2031 | snd_soc_component_update_bits(component, DA7218_DAI_CLK_MODE, |
2032 | DA7218_DAI_BCLKS_PER_WCLK_MASK, |
2033 | DA7218_DAI_BCLKS_PER_WCLK_64); |
2034 | return 0; |
2035 | } |
2036 | |
2037 | /* Check we have valid slots */ |
2038 | if (fls(x: tx_mask) > DA7218_DAI_TDM_MAX_SLOTS) { |
2039 | dev_err(component->dev, "Invalid number of slots, max = %d\n" , |
2040 | DA7218_DAI_TDM_MAX_SLOTS); |
2041 | return -EINVAL; |
2042 | } |
2043 | |
2044 | /* Check we have a valid offset given (first 2 bytes of rx_mask) */ |
2045 | if (rx_mask >> DA7218_2BYTE_SHIFT) { |
2046 | dev_err(component->dev, "Invalid slot offset, max = %d\n" , |
2047 | DA7218_2BYTE_MASK); |
2048 | return -EINVAL; |
2049 | } |
2050 | |
2051 | /* Calculate & validate frame size based on slot info provided. */ |
2052 | frame_size = slots * slot_width; |
2053 | switch (frame_size) { |
2054 | case 32: |
2055 | dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_32; |
2056 | break; |
2057 | case 64: |
2058 | dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_64; |
2059 | break; |
2060 | case 128: |
2061 | dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_128; |
2062 | break; |
2063 | case 256: |
2064 | dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_256; |
2065 | break; |
2066 | default: |
2067 | dev_err(component->dev, "Invalid frame size\n" ); |
2068 | return -EINVAL; |
2069 | } |
2070 | |
2071 | snd_soc_component_update_bits(component, DA7218_DAI_CLK_MODE, |
2072 | DA7218_DAI_BCLKS_PER_WCLK_MASK, |
2073 | val: dai_bclks_per_wclk); |
2074 | snd_soc_component_write(component, DA7218_DAI_OFFSET_LOWER, |
2075 | val: (rx_mask & DA7218_BYTE_MASK)); |
2076 | snd_soc_component_write(component, DA7218_DAI_OFFSET_UPPER, |
2077 | val: ((rx_mask >> DA7218_BYTE_SHIFT) & DA7218_BYTE_MASK)); |
2078 | snd_soc_component_update_bits(component, DA7218_DAI_TDM_CTRL, |
2079 | DA7218_DAI_TDM_CH_EN_MASK | |
2080 | DA7218_DAI_TDM_MODE_EN_MASK, |
2081 | val: (tx_mask << DA7218_DAI_TDM_CH_EN_SHIFT) | |
2082 | DA7218_DAI_TDM_MODE_EN_MASK); |
2083 | |
2084 | return 0; |
2085 | } |
2086 | |
2087 | static int da7218_hw_params(struct snd_pcm_substream *substream, |
2088 | struct snd_pcm_hw_params *params, |
2089 | struct snd_soc_dai *dai) |
2090 | { |
2091 | struct snd_soc_component *component = dai->component; |
2092 | u8 dai_ctrl = 0, fs; |
2093 | unsigned int channels; |
2094 | |
2095 | switch (params_width(p: params)) { |
2096 | case 16: |
2097 | dai_ctrl |= DA7218_DAI_WORD_LENGTH_S16_LE; |
2098 | break; |
2099 | case 20: |
2100 | dai_ctrl |= DA7218_DAI_WORD_LENGTH_S20_LE; |
2101 | break; |
2102 | case 24: |
2103 | dai_ctrl |= DA7218_DAI_WORD_LENGTH_S24_LE; |
2104 | break; |
2105 | case 32: |
2106 | dai_ctrl |= DA7218_DAI_WORD_LENGTH_S32_LE; |
2107 | break; |
2108 | default: |
2109 | return -EINVAL; |
2110 | } |
2111 | |
2112 | channels = params_channels(p: params); |
2113 | if ((channels < 1) || (channels > DA7218_DAI_CH_NUM_MAX)) { |
2114 | dev_err(component->dev, |
2115 | "Invalid number of channels, only 1 to %d supported\n" , |
2116 | DA7218_DAI_CH_NUM_MAX); |
2117 | return -EINVAL; |
2118 | } |
2119 | dai_ctrl |= channels << DA7218_DAI_CH_NUM_SHIFT; |
2120 | |
2121 | switch (params_rate(p: params)) { |
2122 | case 8000: |
2123 | fs = DA7218_SR_8000; |
2124 | break; |
2125 | case 11025: |
2126 | fs = DA7218_SR_11025; |
2127 | break; |
2128 | case 12000: |
2129 | fs = DA7218_SR_12000; |
2130 | break; |
2131 | case 16000: |
2132 | fs = DA7218_SR_16000; |
2133 | break; |
2134 | case 22050: |
2135 | fs = DA7218_SR_22050; |
2136 | break; |
2137 | case 24000: |
2138 | fs = DA7218_SR_24000; |
2139 | break; |
2140 | case 32000: |
2141 | fs = DA7218_SR_32000; |
2142 | break; |
2143 | case 44100: |
2144 | fs = DA7218_SR_44100; |
2145 | break; |
2146 | case 48000: |
2147 | fs = DA7218_SR_48000; |
2148 | break; |
2149 | case 88200: |
2150 | fs = DA7218_SR_88200; |
2151 | break; |
2152 | case 96000: |
2153 | fs = DA7218_SR_96000; |
2154 | break; |
2155 | default: |
2156 | return -EINVAL; |
2157 | } |
2158 | |
2159 | snd_soc_component_update_bits(component, DA7218_DAI_CTRL, |
2160 | DA7218_DAI_WORD_LENGTH_MASK | DA7218_DAI_CH_NUM_MASK, |
2161 | val: dai_ctrl); |
2162 | /* SRs tied for ADCs and DACs. */ |
2163 | snd_soc_component_write(component, DA7218_SR, |
2164 | val: (fs << DA7218_SR_DAC_SHIFT) | (fs << DA7218_SR_ADC_SHIFT)); |
2165 | |
2166 | return 0; |
2167 | } |
2168 | |
2169 | static const struct snd_soc_dai_ops da7218_dai_ops = { |
2170 | .hw_params = da7218_hw_params, |
2171 | .set_sysclk = da7218_set_dai_sysclk, |
2172 | .set_pll = da7218_set_dai_pll, |
2173 | .set_fmt = da7218_set_dai_fmt, |
2174 | .set_tdm_slot = da7218_set_dai_tdm_slot, |
2175 | }; |
2176 | |
2177 | #define DA7218_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
2178 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
2179 | |
2180 | static struct snd_soc_dai_driver da7218_dai = { |
2181 | .name = "da7218-hifi" , |
2182 | .playback = { |
2183 | .stream_name = "Playback" , |
2184 | .channels_min = 1, |
2185 | .channels_max = 4, /* Only 2 channels of data */ |
2186 | .rates = SNDRV_PCM_RATE_8000_96000, |
2187 | .formats = DA7218_FORMATS, |
2188 | }, |
2189 | .capture = { |
2190 | .stream_name = "Capture" , |
2191 | .channels_min = 1, |
2192 | .channels_max = 4, |
2193 | .rates = SNDRV_PCM_RATE_8000_96000, |
2194 | .formats = DA7218_FORMATS, |
2195 | }, |
2196 | .ops = &da7218_dai_ops, |
2197 | .symmetric_rate = 1, |
2198 | .symmetric_channels = 1, |
2199 | .symmetric_sample_bits = 1, |
2200 | }; |
2201 | |
2202 | |
2203 | /* |
2204 | * HP Detect |
2205 | */ |
2206 | |
2207 | int da7218_hpldet(struct snd_soc_component *component, struct snd_soc_jack *jack) |
2208 | { |
2209 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2210 | |
2211 | if (da7218->dev_id == DA7217_DEV_ID) |
2212 | return -EINVAL; |
2213 | |
2214 | da7218->jack = jack; |
2215 | snd_soc_component_update_bits(component, DA7218_HPLDET_JACK, |
2216 | DA7218_HPLDET_JACK_EN_MASK, |
2217 | val: jack ? DA7218_HPLDET_JACK_EN_MASK : 0); |
2218 | |
2219 | return 0; |
2220 | } |
2221 | EXPORT_SYMBOL_GPL(da7218_hpldet); |
2222 | |
2223 | static void da7218_micldet_irq(struct snd_soc_component *component) |
2224 | { |
2225 | char *envp[] = { |
2226 | "EVENT=MIC_LEVEL_DETECT" , |
2227 | NULL, |
2228 | }; |
2229 | |
2230 | kobject_uevent_env(kobj: &component->dev->kobj, action: KOBJ_CHANGE, envp); |
2231 | } |
2232 | |
2233 | static void da7218_hpldet_irq(struct snd_soc_component *component) |
2234 | { |
2235 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2236 | u8 jack_status; |
2237 | int report; |
2238 | |
2239 | jack_status = snd_soc_component_read(component, DA7218_EVENT_STATUS); |
2240 | |
2241 | if (jack_status & DA7218_HPLDET_JACK_STS_MASK) |
2242 | report = SND_JACK_HEADPHONE; |
2243 | else |
2244 | report = 0; |
2245 | |
2246 | snd_soc_jack_report(jack: da7218->jack, status: report, mask: SND_JACK_HEADPHONE); |
2247 | } |
2248 | |
2249 | /* |
2250 | * IRQ |
2251 | */ |
2252 | |
2253 | static irqreturn_t da7218_irq_thread(int irq, void *data) |
2254 | { |
2255 | struct snd_soc_component *component = data; |
2256 | u8 status; |
2257 | |
2258 | /* Read IRQ status reg */ |
2259 | status = snd_soc_component_read(component, DA7218_EVENT); |
2260 | if (!status) |
2261 | return IRQ_NONE; |
2262 | |
2263 | /* Mic level detect */ |
2264 | if (status & DA7218_LVL_DET_EVENT_MASK) |
2265 | da7218_micldet_irq(component); |
2266 | |
2267 | /* HP detect */ |
2268 | if (status & DA7218_HPLDET_JACK_EVENT_MASK) |
2269 | da7218_hpldet_irq(component); |
2270 | |
2271 | /* Clear interrupts */ |
2272 | snd_soc_component_write(component, DA7218_EVENT, val: status); |
2273 | |
2274 | return IRQ_HANDLED; |
2275 | } |
2276 | |
2277 | /* |
2278 | * DT |
2279 | */ |
2280 | |
2281 | static const struct of_device_id da7218_of_match[] = { |
2282 | { .compatible = "dlg,da7217" , .data = (void *) DA7217_DEV_ID }, |
2283 | { .compatible = "dlg,da7218" , .data = (void *) DA7218_DEV_ID }, |
2284 | { } |
2285 | }; |
2286 | MODULE_DEVICE_TABLE(of, da7218_of_match); |
2287 | |
2288 | static enum da7218_micbias_voltage |
2289 | da7218_of_micbias_lvl(struct snd_soc_component *component, u32 val) |
2290 | { |
2291 | switch (val) { |
2292 | case 1200: |
2293 | return DA7218_MICBIAS_1_2V; |
2294 | case 1600: |
2295 | return DA7218_MICBIAS_1_6V; |
2296 | case 1800: |
2297 | return DA7218_MICBIAS_1_8V; |
2298 | case 2000: |
2299 | return DA7218_MICBIAS_2_0V; |
2300 | case 2200: |
2301 | return DA7218_MICBIAS_2_2V; |
2302 | case 2400: |
2303 | return DA7218_MICBIAS_2_4V; |
2304 | case 2600: |
2305 | return DA7218_MICBIAS_2_6V; |
2306 | case 2800: |
2307 | return DA7218_MICBIAS_2_8V; |
2308 | case 3000: |
2309 | return DA7218_MICBIAS_3_0V; |
2310 | default: |
2311 | dev_warn(component->dev, "Invalid micbias level" ); |
2312 | return DA7218_MICBIAS_1_6V; |
2313 | } |
2314 | } |
2315 | |
2316 | static enum da7218_mic_amp_in_sel |
2317 | da7218_of_mic_amp_in_sel(struct snd_soc_component *component, const char *str) |
2318 | { |
2319 | if (!strcmp(str, "diff" )) { |
2320 | return DA7218_MIC_AMP_IN_SEL_DIFF; |
2321 | } else if (!strcmp(str, "se_p" )) { |
2322 | return DA7218_MIC_AMP_IN_SEL_SE_P; |
2323 | } else if (!strcmp(str, "se_n" )) { |
2324 | return DA7218_MIC_AMP_IN_SEL_SE_N; |
2325 | } else { |
2326 | dev_warn(component->dev, "Invalid mic input type selection" ); |
2327 | return DA7218_MIC_AMP_IN_SEL_DIFF; |
2328 | } |
2329 | } |
2330 | |
2331 | static enum da7218_dmic_data_sel |
2332 | da7218_of_dmic_data_sel(struct snd_soc_component *component, const char *str) |
2333 | { |
2334 | if (!strcmp(str, "lrise_rfall" )) { |
2335 | return DA7218_DMIC_DATA_LRISE_RFALL; |
2336 | } else if (!strcmp(str, "lfall_rrise" )) { |
2337 | return DA7218_DMIC_DATA_LFALL_RRISE; |
2338 | } else { |
2339 | dev_warn(component->dev, "Invalid DMIC data type selection" ); |
2340 | return DA7218_DMIC_DATA_LRISE_RFALL; |
2341 | } |
2342 | } |
2343 | |
2344 | static enum da7218_dmic_samplephase |
2345 | da7218_of_dmic_samplephase(struct snd_soc_component *component, const char *str) |
2346 | { |
2347 | if (!strcmp(str, "on_clkedge" )) { |
2348 | return DA7218_DMIC_SAMPLE_ON_CLKEDGE; |
2349 | } else if (!strcmp(str, "between_clkedge" )) { |
2350 | return DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE; |
2351 | } else { |
2352 | dev_warn(component->dev, "Invalid DMIC sample phase" ); |
2353 | return DA7218_DMIC_SAMPLE_ON_CLKEDGE; |
2354 | } |
2355 | } |
2356 | |
2357 | static enum da7218_dmic_clk_rate |
2358 | da7218_of_dmic_clkrate(struct snd_soc_component *component, u32 val) |
2359 | { |
2360 | switch (val) { |
2361 | case 1500000: |
2362 | return DA7218_DMIC_CLK_1_5MHZ; |
2363 | case 3000000: |
2364 | return DA7218_DMIC_CLK_3_0MHZ; |
2365 | default: |
2366 | dev_warn(component->dev, "Invalid DMIC clock rate" ); |
2367 | return DA7218_DMIC_CLK_3_0MHZ; |
2368 | } |
2369 | } |
2370 | |
2371 | static enum da7218_hpldet_jack_rate |
2372 | da7218_of_jack_rate(struct snd_soc_component *component, u32 val) |
2373 | { |
2374 | switch (val) { |
2375 | case 5: |
2376 | return DA7218_HPLDET_JACK_RATE_5US; |
2377 | case 10: |
2378 | return DA7218_HPLDET_JACK_RATE_10US; |
2379 | case 20: |
2380 | return DA7218_HPLDET_JACK_RATE_20US; |
2381 | case 40: |
2382 | return DA7218_HPLDET_JACK_RATE_40US; |
2383 | case 80: |
2384 | return DA7218_HPLDET_JACK_RATE_80US; |
2385 | case 160: |
2386 | return DA7218_HPLDET_JACK_RATE_160US; |
2387 | case 320: |
2388 | return DA7218_HPLDET_JACK_RATE_320US; |
2389 | case 640: |
2390 | return DA7218_HPLDET_JACK_RATE_640US; |
2391 | default: |
2392 | dev_warn(component->dev, "Invalid jack detect rate" ); |
2393 | return DA7218_HPLDET_JACK_RATE_40US; |
2394 | } |
2395 | } |
2396 | |
2397 | static enum da7218_hpldet_jack_debounce |
2398 | da7218_of_jack_debounce(struct snd_soc_component *component, u32 val) |
2399 | { |
2400 | switch (val) { |
2401 | case 0: |
2402 | return DA7218_HPLDET_JACK_DEBOUNCE_OFF; |
2403 | case 2: |
2404 | return DA7218_HPLDET_JACK_DEBOUNCE_2; |
2405 | case 3: |
2406 | return DA7218_HPLDET_JACK_DEBOUNCE_3; |
2407 | case 4: |
2408 | return DA7218_HPLDET_JACK_DEBOUNCE_4; |
2409 | default: |
2410 | dev_warn(component->dev, "Invalid jack debounce" ); |
2411 | return DA7218_HPLDET_JACK_DEBOUNCE_2; |
2412 | } |
2413 | } |
2414 | |
2415 | static enum da7218_hpldet_jack_thr |
2416 | da7218_of_jack_thr(struct snd_soc_component *component, u32 val) |
2417 | { |
2418 | switch (val) { |
2419 | case 84: |
2420 | return DA7218_HPLDET_JACK_THR_84PCT; |
2421 | case 88: |
2422 | return DA7218_HPLDET_JACK_THR_88PCT; |
2423 | case 92: |
2424 | return DA7218_HPLDET_JACK_THR_92PCT; |
2425 | case 96: |
2426 | return DA7218_HPLDET_JACK_THR_96PCT; |
2427 | default: |
2428 | dev_warn(component->dev, "Invalid jack threshold level" ); |
2429 | return DA7218_HPLDET_JACK_THR_84PCT; |
2430 | } |
2431 | } |
2432 | |
2433 | static struct da7218_pdata *da7218_of_to_pdata(struct snd_soc_component *component) |
2434 | { |
2435 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2436 | struct device_node *np = component->dev->of_node; |
2437 | struct device_node *hpldet_np; |
2438 | struct da7218_pdata *pdata; |
2439 | struct da7218_hpldet_pdata *hpldet_pdata; |
2440 | const char *of_str; |
2441 | u32 of_val32; |
2442 | |
2443 | pdata = devm_kzalloc(dev: component->dev, size: sizeof(*pdata), GFP_KERNEL); |
2444 | if (!pdata) |
2445 | return NULL; |
2446 | |
2447 | if (of_property_read_u32(np, propname: "dlg,micbias1-lvl-millivolt" , out_value: &of_val32) >= 0) |
2448 | pdata->micbias1_lvl = da7218_of_micbias_lvl(component, val: of_val32); |
2449 | else |
2450 | pdata->micbias1_lvl = DA7218_MICBIAS_1_6V; |
2451 | |
2452 | if (of_property_read_u32(np, propname: "dlg,micbias2-lvl-millivolt" , out_value: &of_val32) >= 0) |
2453 | pdata->micbias2_lvl = da7218_of_micbias_lvl(component, val: of_val32); |
2454 | else |
2455 | pdata->micbias2_lvl = DA7218_MICBIAS_1_6V; |
2456 | |
2457 | if (!of_property_read_string(np, propname: "dlg,mic1-amp-in-sel" , out_string: &of_str)) |
2458 | pdata->mic1_amp_in_sel = |
2459 | da7218_of_mic_amp_in_sel(component, str: of_str); |
2460 | else |
2461 | pdata->mic1_amp_in_sel = DA7218_MIC_AMP_IN_SEL_DIFF; |
2462 | |
2463 | if (!of_property_read_string(np, propname: "dlg,mic2-amp-in-sel" , out_string: &of_str)) |
2464 | pdata->mic2_amp_in_sel = |
2465 | da7218_of_mic_amp_in_sel(component, str: of_str); |
2466 | else |
2467 | pdata->mic2_amp_in_sel = DA7218_MIC_AMP_IN_SEL_DIFF; |
2468 | |
2469 | if (!of_property_read_string(np, propname: "dlg,dmic1-data-sel" , out_string: &of_str)) |
2470 | pdata->dmic1_data_sel = da7218_of_dmic_data_sel(component, str: of_str); |
2471 | else |
2472 | pdata->dmic1_data_sel = DA7218_DMIC_DATA_LRISE_RFALL; |
2473 | |
2474 | if (!of_property_read_string(np, propname: "dlg,dmic1-samplephase" , out_string: &of_str)) |
2475 | pdata->dmic1_samplephase = |
2476 | da7218_of_dmic_samplephase(component, str: of_str); |
2477 | else |
2478 | pdata->dmic1_samplephase = DA7218_DMIC_SAMPLE_ON_CLKEDGE; |
2479 | |
2480 | if (of_property_read_u32(np, propname: "dlg,dmic1-clkrate-hz" , out_value: &of_val32) >= 0) |
2481 | pdata->dmic1_clk_rate = da7218_of_dmic_clkrate(component, val: of_val32); |
2482 | else |
2483 | pdata->dmic1_clk_rate = DA7218_DMIC_CLK_3_0MHZ; |
2484 | |
2485 | if (!of_property_read_string(np, propname: "dlg,dmic2-data-sel" , out_string: &of_str)) |
2486 | pdata->dmic2_data_sel = da7218_of_dmic_data_sel(component, str: of_str); |
2487 | else |
2488 | pdata->dmic2_data_sel = DA7218_DMIC_DATA_LRISE_RFALL; |
2489 | |
2490 | if (!of_property_read_string(np, propname: "dlg,dmic2-samplephase" , out_string: &of_str)) |
2491 | pdata->dmic2_samplephase = |
2492 | da7218_of_dmic_samplephase(component, str: of_str); |
2493 | else |
2494 | pdata->dmic2_samplephase = DA7218_DMIC_SAMPLE_ON_CLKEDGE; |
2495 | |
2496 | if (of_property_read_u32(np, propname: "dlg,dmic2-clkrate-hz" , out_value: &of_val32) >= 0) |
2497 | pdata->dmic2_clk_rate = da7218_of_dmic_clkrate(component, val: of_val32); |
2498 | else |
2499 | pdata->dmic2_clk_rate = DA7218_DMIC_CLK_3_0MHZ; |
2500 | |
2501 | if (da7218->dev_id == DA7217_DEV_ID) { |
2502 | if (of_property_read_bool(np, propname: "dlg,hp-diff-single-supply" )) |
2503 | pdata->hp_diff_single_supply = true; |
2504 | } |
2505 | |
2506 | if (da7218->dev_id == DA7218_DEV_ID) { |
2507 | hpldet_np = of_get_child_by_name(node: np, name: "da7218_hpldet" ); |
2508 | if (!hpldet_np) |
2509 | return pdata; |
2510 | |
2511 | hpldet_pdata = devm_kzalloc(dev: component->dev, size: sizeof(*hpldet_pdata), |
2512 | GFP_KERNEL); |
2513 | if (!hpldet_pdata) { |
2514 | of_node_put(node: hpldet_np); |
2515 | return pdata; |
2516 | } |
2517 | pdata->hpldet_pdata = hpldet_pdata; |
2518 | |
2519 | if (of_property_read_u32(np: hpldet_np, propname: "dlg,jack-rate-us" , |
2520 | out_value: &of_val32) >= 0) |
2521 | hpldet_pdata->jack_rate = |
2522 | da7218_of_jack_rate(component, val: of_val32); |
2523 | else |
2524 | hpldet_pdata->jack_rate = DA7218_HPLDET_JACK_RATE_40US; |
2525 | |
2526 | if (of_property_read_u32(np: hpldet_np, propname: "dlg,jack-debounce" , |
2527 | out_value: &of_val32) >= 0) |
2528 | hpldet_pdata->jack_debounce = |
2529 | da7218_of_jack_debounce(component, val: of_val32); |
2530 | else |
2531 | hpldet_pdata->jack_debounce = |
2532 | DA7218_HPLDET_JACK_DEBOUNCE_2; |
2533 | |
2534 | if (of_property_read_u32(np: hpldet_np, propname: "dlg,jack-threshold-pct" , |
2535 | out_value: &of_val32) >= 0) |
2536 | hpldet_pdata->jack_thr = |
2537 | da7218_of_jack_thr(component, val: of_val32); |
2538 | else |
2539 | hpldet_pdata->jack_thr = DA7218_HPLDET_JACK_THR_84PCT; |
2540 | |
2541 | if (of_property_read_bool(np: hpldet_np, propname: "dlg,comp-inv" )) |
2542 | hpldet_pdata->comp_inv = true; |
2543 | |
2544 | if (of_property_read_bool(np: hpldet_np, propname: "dlg,hyst" )) |
2545 | hpldet_pdata->hyst = true; |
2546 | |
2547 | if (of_property_read_bool(np: hpldet_np, propname: "dlg,discharge" )) |
2548 | hpldet_pdata->discharge = true; |
2549 | |
2550 | of_node_put(node: hpldet_np); |
2551 | } |
2552 | |
2553 | return pdata; |
2554 | } |
2555 | |
2556 | |
2557 | /* |
2558 | * Codec driver functions |
2559 | */ |
2560 | |
2561 | static int da7218_set_bias_level(struct snd_soc_component *component, |
2562 | enum snd_soc_bias_level level) |
2563 | { |
2564 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2565 | int ret; |
2566 | |
2567 | switch (level) { |
2568 | case SND_SOC_BIAS_ON: |
2569 | break; |
2570 | case SND_SOC_BIAS_PREPARE: |
2571 | /* Enable MCLK for transition to ON state */ |
2572 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) { |
2573 | if (da7218->mclk) { |
2574 | ret = clk_prepare_enable(clk: da7218->mclk); |
2575 | if (ret) { |
2576 | dev_err(component->dev, "Failed to enable mclk\n" ); |
2577 | return ret; |
2578 | } |
2579 | } |
2580 | } |
2581 | |
2582 | break; |
2583 | case SND_SOC_BIAS_STANDBY: |
2584 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { |
2585 | /* Master bias */ |
2586 | snd_soc_component_update_bits(component, DA7218_REFERENCES, |
2587 | DA7218_BIAS_EN_MASK, |
2588 | DA7218_BIAS_EN_MASK); |
2589 | |
2590 | /* Internal LDO */ |
2591 | snd_soc_component_update_bits(component, DA7218_LDO_CTRL, |
2592 | DA7218_LDO_EN_MASK, |
2593 | DA7218_LDO_EN_MASK); |
2594 | } else { |
2595 | /* Remove MCLK */ |
2596 | if (da7218->mclk) |
2597 | clk_disable_unprepare(clk: da7218->mclk); |
2598 | } |
2599 | break; |
2600 | case SND_SOC_BIAS_OFF: |
2601 | /* Only disable if jack detection disabled */ |
2602 | if (!da7218->jack) { |
2603 | /* Internal LDO */ |
2604 | snd_soc_component_update_bits(component, DA7218_LDO_CTRL, |
2605 | DA7218_LDO_EN_MASK, val: 0); |
2606 | |
2607 | /* Master bias */ |
2608 | snd_soc_component_update_bits(component, DA7218_REFERENCES, |
2609 | DA7218_BIAS_EN_MASK, val: 0); |
2610 | } |
2611 | break; |
2612 | } |
2613 | |
2614 | return 0; |
2615 | } |
2616 | |
2617 | static const char *da7218_supply_names[DA7218_NUM_SUPPLIES] = { |
2618 | [DA7218_SUPPLY_VDD] = "VDD" , |
2619 | [DA7218_SUPPLY_VDDMIC] = "VDDMIC" , |
2620 | [DA7218_SUPPLY_VDDIO] = "VDDIO" , |
2621 | }; |
2622 | |
2623 | static int da7218_handle_supplies(struct snd_soc_component *component) |
2624 | { |
2625 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2626 | struct regulator *vddio; |
2627 | u8 io_voltage_lvl = DA7218_IO_VOLTAGE_LEVEL_2_5V_3_6V; |
2628 | int i, ret; |
2629 | |
2630 | /* Get required supplies */ |
2631 | for (i = 0; i < DA7218_NUM_SUPPLIES; ++i) |
2632 | da7218->supplies[i].supply = da7218_supply_names[i]; |
2633 | |
2634 | ret = devm_regulator_bulk_get(dev: component->dev, num_consumers: DA7218_NUM_SUPPLIES, |
2635 | consumers: da7218->supplies); |
2636 | if (ret) { |
2637 | dev_err(component->dev, "Failed to get supplies\n" ); |
2638 | return ret; |
2639 | } |
2640 | |
2641 | /* Determine VDDIO voltage provided */ |
2642 | vddio = da7218->supplies[DA7218_SUPPLY_VDDIO].consumer; |
2643 | ret = regulator_get_voltage(regulator: vddio); |
2644 | if (ret < 1500000) |
2645 | dev_warn(component->dev, "Invalid VDDIO voltage\n" ); |
2646 | else if (ret < 2500000) |
2647 | io_voltage_lvl = DA7218_IO_VOLTAGE_LEVEL_1_5V_2_5V; |
2648 | |
2649 | /* Enable main supplies */ |
2650 | ret = regulator_bulk_enable(num_consumers: DA7218_NUM_SUPPLIES, consumers: da7218->supplies); |
2651 | if (ret) { |
2652 | dev_err(component->dev, "Failed to enable supplies\n" ); |
2653 | return ret; |
2654 | } |
2655 | |
2656 | /* Ensure device in active mode */ |
2657 | snd_soc_component_write(component, DA7218_SYSTEM_ACTIVE, DA7218_SYSTEM_ACTIVE_MASK); |
2658 | |
2659 | /* Update IO voltage level range */ |
2660 | snd_soc_component_write(component, DA7218_IO_CTRL, val: io_voltage_lvl); |
2661 | |
2662 | return 0; |
2663 | } |
2664 | |
2665 | static void da7218_handle_pdata(struct snd_soc_component *component) |
2666 | { |
2667 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2668 | struct da7218_pdata *pdata = da7218->pdata; |
2669 | |
2670 | if (pdata) { |
2671 | u8 micbias_lvl = 0, dmic_cfg = 0; |
2672 | |
2673 | /* Mic Bias voltages */ |
2674 | switch (pdata->micbias1_lvl) { |
2675 | case DA7218_MICBIAS_1_2V: |
2676 | micbias_lvl |= DA7218_MICBIAS_1_LP_MODE_MASK; |
2677 | break; |
2678 | case DA7218_MICBIAS_1_6V: |
2679 | case DA7218_MICBIAS_1_8V: |
2680 | case DA7218_MICBIAS_2_0V: |
2681 | case DA7218_MICBIAS_2_2V: |
2682 | case DA7218_MICBIAS_2_4V: |
2683 | case DA7218_MICBIAS_2_6V: |
2684 | case DA7218_MICBIAS_2_8V: |
2685 | case DA7218_MICBIAS_3_0V: |
2686 | micbias_lvl |= (pdata->micbias1_lvl << |
2687 | DA7218_MICBIAS_1_LEVEL_SHIFT); |
2688 | break; |
2689 | } |
2690 | |
2691 | switch (pdata->micbias2_lvl) { |
2692 | case DA7218_MICBIAS_1_2V: |
2693 | micbias_lvl |= DA7218_MICBIAS_2_LP_MODE_MASK; |
2694 | break; |
2695 | case DA7218_MICBIAS_1_6V: |
2696 | case DA7218_MICBIAS_1_8V: |
2697 | case DA7218_MICBIAS_2_0V: |
2698 | case DA7218_MICBIAS_2_2V: |
2699 | case DA7218_MICBIAS_2_4V: |
2700 | case DA7218_MICBIAS_2_6V: |
2701 | case DA7218_MICBIAS_2_8V: |
2702 | case DA7218_MICBIAS_3_0V: |
2703 | micbias_lvl |= (pdata->micbias2_lvl << |
2704 | DA7218_MICBIAS_2_LEVEL_SHIFT); |
2705 | break; |
2706 | } |
2707 | |
2708 | snd_soc_component_write(component, DA7218_MICBIAS_CTRL, val: micbias_lvl); |
2709 | |
2710 | /* Mic */ |
2711 | switch (pdata->mic1_amp_in_sel) { |
2712 | case DA7218_MIC_AMP_IN_SEL_DIFF: |
2713 | case DA7218_MIC_AMP_IN_SEL_SE_P: |
2714 | case DA7218_MIC_AMP_IN_SEL_SE_N: |
2715 | snd_soc_component_write(component, DA7218_MIC_1_SELECT, |
2716 | val: pdata->mic1_amp_in_sel); |
2717 | break; |
2718 | } |
2719 | |
2720 | switch (pdata->mic2_amp_in_sel) { |
2721 | case DA7218_MIC_AMP_IN_SEL_DIFF: |
2722 | case DA7218_MIC_AMP_IN_SEL_SE_P: |
2723 | case DA7218_MIC_AMP_IN_SEL_SE_N: |
2724 | snd_soc_component_write(component, DA7218_MIC_2_SELECT, |
2725 | val: pdata->mic2_amp_in_sel); |
2726 | break; |
2727 | } |
2728 | |
2729 | /* DMic */ |
2730 | switch (pdata->dmic1_data_sel) { |
2731 | case DA7218_DMIC_DATA_LFALL_RRISE: |
2732 | case DA7218_DMIC_DATA_LRISE_RFALL: |
2733 | dmic_cfg |= (pdata->dmic1_data_sel << |
2734 | DA7218_DMIC_1_DATA_SEL_SHIFT); |
2735 | break; |
2736 | } |
2737 | |
2738 | switch (pdata->dmic1_samplephase) { |
2739 | case DA7218_DMIC_SAMPLE_ON_CLKEDGE: |
2740 | case DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE: |
2741 | dmic_cfg |= (pdata->dmic1_samplephase << |
2742 | DA7218_DMIC_1_SAMPLEPHASE_SHIFT); |
2743 | break; |
2744 | } |
2745 | |
2746 | switch (pdata->dmic1_clk_rate) { |
2747 | case DA7218_DMIC_CLK_3_0MHZ: |
2748 | case DA7218_DMIC_CLK_1_5MHZ: |
2749 | dmic_cfg |= (pdata->dmic1_clk_rate << |
2750 | DA7218_DMIC_1_CLK_RATE_SHIFT); |
2751 | break; |
2752 | } |
2753 | |
2754 | snd_soc_component_update_bits(component, DA7218_DMIC_1_CTRL, |
2755 | DA7218_DMIC_1_DATA_SEL_MASK | |
2756 | DA7218_DMIC_1_SAMPLEPHASE_MASK | |
2757 | DA7218_DMIC_1_CLK_RATE_MASK, val: dmic_cfg); |
2758 | |
2759 | dmic_cfg = 0; |
2760 | switch (pdata->dmic2_data_sel) { |
2761 | case DA7218_DMIC_DATA_LFALL_RRISE: |
2762 | case DA7218_DMIC_DATA_LRISE_RFALL: |
2763 | dmic_cfg |= (pdata->dmic2_data_sel << |
2764 | DA7218_DMIC_2_DATA_SEL_SHIFT); |
2765 | break; |
2766 | } |
2767 | |
2768 | switch (pdata->dmic2_samplephase) { |
2769 | case DA7218_DMIC_SAMPLE_ON_CLKEDGE: |
2770 | case DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE: |
2771 | dmic_cfg |= (pdata->dmic2_samplephase << |
2772 | DA7218_DMIC_2_SAMPLEPHASE_SHIFT); |
2773 | break; |
2774 | } |
2775 | |
2776 | switch (pdata->dmic2_clk_rate) { |
2777 | case DA7218_DMIC_CLK_3_0MHZ: |
2778 | case DA7218_DMIC_CLK_1_5MHZ: |
2779 | dmic_cfg |= (pdata->dmic2_clk_rate << |
2780 | DA7218_DMIC_2_CLK_RATE_SHIFT); |
2781 | break; |
2782 | } |
2783 | |
2784 | snd_soc_component_update_bits(component, DA7218_DMIC_2_CTRL, |
2785 | DA7218_DMIC_2_DATA_SEL_MASK | |
2786 | DA7218_DMIC_2_SAMPLEPHASE_MASK | |
2787 | DA7218_DMIC_2_CLK_RATE_MASK, val: dmic_cfg); |
2788 | |
2789 | /* DA7217 Specific */ |
2790 | if (da7218->dev_id == DA7217_DEV_ID) { |
2791 | da7218->hp_single_supply = |
2792 | pdata->hp_diff_single_supply; |
2793 | |
2794 | if (da7218->hp_single_supply) { |
2795 | snd_soc_component_write(component, DA7218_HP_DIFF_UNLOCK, |
2796 | DA7218_HP_DIFF_UNLOCK_VAL); |
2797 | snd_soc_component_update_bits(component, DA7218_HP_DIFF_CTRL, |
2798 | DA7218_HP_AMP_SINGLE_SUPPLY_EN_MASK, |
2799 | DA7218_HP_AMP_SINGLE_SUPPLY_EN_MASK); |
2800 | } |
2801 | } |
2802 | |
2803 | /* DA7218 Specific */ |
2804 | if ((da7218->dev_id == DA7218_DEV_ID) && |
2805 | (pdata->hpldet_pdata)) { |
2806 | struct da7218_hpldet_pdata *hpldet_pdata = |
2807 | pdata->hpldet_pdata; |
2808 | u8 hpldet_cfg = 0; |
2809 | |
2810 | switch (hpldet_pdata->jack_rate) { |
2811 | case DA7218_HPLDET_JACK_RATE_5US: |
2812 | case DA7218_HPLDET_JACK_RATE_10US: |
2813 | case DA7218_HPLDET_JACK_RATE_20US: |
2814 | case DA7218_HPLDET_JACK_RATE_40US: |
2815 | case DA7218_HPLDET_JACK_RATE_80US: |
2816 | case DA7218_HPLDET_JACK_RATE_160US: |
2817 | case DA7218_HPLDET_JACK_RATE_320US: |
2818 | case DA7218_HPLDET_JACK_RATE_640US: |
2819 | hpldet_cfg |= |
2820 | (hpldet_pdata->jack_rate << |
2821 | DA7218_HPLDET_JACK_RATE_SHIFT); |
2822 | break; |
2823 | } |
2824 | |
2825 | switch (hpldet_pdata->jack_debounce) { |
2826 | case DA7218_HPLDET_JACK_DEBOUNCE_OFF: |
2827 | case DA7218_HPLDET_JACK_DEBOUNCE_2: |
2828 | case DA7218_HPLDET_JACK_DEBOUNCE_3: |
2829 | case DA7218_HPLDET_JACK_DEBOUNCE_4: |
2830 | hpldet_cfg |= |
2831 | (hpldet_pdata->jack_debounce << |
2832 | DA7218_HPLDET_JACK_DEBOUNCE_SHIFT); |
2833 | break; |
2834 | } |
2835 | |
2836 | switch (hpldet_pdata->jack_thr) { |
2837 | case DA7218_HPLDET_JACK_THR_84PCT: |
2838 | case DA7218_HPLDET_JACK_THR_88PCT: |
2839 | case DA7218_HPLDET_JACK_THR_92PCT: |
2840 | case DA7218_HPLDET_JACK_THR_96PCT: |
2841 | hpldet_cfg |= |
2842 | (hpldet_pdata->jack_thr << |
2843 | DA7218_HPLDET_JACK_THR_SHIFT); |
2844 | break; |
2845 | } |
2846 | snd_soc_component_update_bits(component, DA7218_HPLDET_JACK, |
2847 | DA7218_HPLDET_JACK_RATE_MASK | |
2848 | DA7218_HPLDET_JACK_DEBOUNCE_MASK | |
2849 | DA7218_HPLDET_JACK_THR_MASK, |
2850 | val: hpldet_cfg); |
2851 | |
2852 | hpldet_cfg = 0; |
2853 | if (hpldet_pdata->comp_inv) |
2854 | hpldet_cfg |= DA7218_HPLDET_COMP_INV_MASK; |
2855 | |
2856 | if (hpldet_pdata->hyst) |
2857 | hpldet_cfg |= DA7218_HPLDET_HYST_EN_MASK; |
2858 | |
2859 | if (hpldet_pdata->discharge) |
2860 | hpldet_cfg |= DA7218_HPLDET_DISCHARGE_EN_MASK; |
2861 | |
2862 | snd_soc_component_write(component, DA7218_HPLDET_CTRL, val: hpldet_cfg); |
2863 | } |
2864 | } |
2865 | } |
2866 | |
2867 | static int da7218_probe(struct snd_soc_component *component) |
2868 | { |
2869 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2870 | int ret; |
2871 | |
2872 | /* Regulator configuration */ |
2873 | ret = da7218_handle_supplies(component); |
2874 | if (ret) |
2875 | return ret; |
2876 | |
2877 | /* Handle DT/Platform data */ |
2878 | if (component->dev->of_node) |
2879 | da7218->pdata = da7218_of_to_pdata(component); |
2880 | else |
2881 | da7218->pdata = dev_get_platdata(dev: component->dev); |
2882 | |
2883 | da7218_handle_pdata(component); |
2884 | |
2885 | /* Check if MCLK provided, if not the clock is NULL */ |
2886 | da7218->mclk = devm_clk_get_optional(dev: component->dev, id: "mclk" ); |
2887 | if (IS_ERR(ptr: da7218->mclk)) { |
2888 | ret = PTR_ERR(ptr: da7218->mclk); |
2889 | goto err_disable_reg; |
2890 | } |
2891 | |
2892 | /* Default PC to free-running */ |
2893 | snd_soc_component_write(component, DA7218_PC_COUNT, DA7218_PC_FREERUN_MASK); |
2894 | |
2895 | /* |
2896 | * Default Output Filter mixers to off otherwise DAPM will power |
2897 | * Mic to HP passthrough paths by default at startup. |
2898 | */ |
2899 | snd_soc_component_write(component, DA7218_DROUTING_OUTFILT_1L, val: 0); |
2900 | snd_soc_component_write(component, DA7218_DROUTING_OUTFILT_1R, val: 0); |
2901 | |
2902 | /* Default CP to normal load, power mode */ |
2903 | snd_soc_component_update_bits(component, DA7218_CP_CTRL, |
2904 | DA7218_CP_SMALL_SWITCH_FREQ_EN_MASK, val: 0); |
2905 | |
2906 | /* Default gain ramping */ |
2907 | snd_soc_component_update_bits(component, DA7218_MIXIN_1_CTRL, |
2908 | DA7218_MIXIN_1_AMP_RAMP_EN_MASK, |
2909 | DA7218_MIXIN_1_AMP_RAMP_EN_MASK); |
2910 | snd_soc_component_update_bits(component, DA7218_MIXIN_2_CTRL, |
2911 | DA7218_MIXIN_2_AMP_RAMP_EN_MASK, |
2912 | DA7218_MIXIN_2_AMP_RAMP_EN_MASK); |
2913 | snd_soc_component_update_bits(component, DA7218_IN_1L_FILTER_CTRL, |
2914 | DA7218_IN_1L_RAMP_EN_MASK, |
2915 | DA7218_IN_1L_RAMP_EN_MASK); |
2916 | snd_soc_component_update_bits(component, DA7218_IN_1R_FILTER_CTRL, |
2917 | DA7218_IN_1R_RAMP_EN_MASK, |
2918 | DA7218_IN_1R_RAMP_EN_MASK); |
2919 | snd_soc_component_update_bits(component, DA7218_IN_2L_FILTER_CTRL, |
2920 | DA7218_IN_2L_RAMP_EN_MASK, |
2921 | DA7218_IN_2L_RAMP_EN_MASK); |
2922 | snd_soc_component_update_bits(component, DA7218_IN_2R_FILTER_CTRL, |
2923 | DA7218_IN_2R_RAMP_EN_MASK, |
2924 | DA7218_IN_2R_RAMP_EN_MASK); |
2925 | snd_soc_component_update_bits(component, DA7218_DGS_GAIN_CTRL, |
2926 | DA7218_DGS_RAMP_EN_MASK, DA7218_DGS_RAMP_EN_MASK); |
2927 | snd_soc_component_update_bits(component, DA7218_OUT_1L_FILTER_CTRL, |
2928 | DA7218_OUT_1L_RAMP_EN_MASK, |
2929 | DA7218_OUT_1L_RAMP_EN_MASK); |
2930 | snd_soc_component_update_bits(component, DA7218_OUT_1R_FILTER_CTRL, |
2931 | DA7218_OUT_1R_RAMP_EN_MASK, |
2932 | DA7218_OUT_1R_RAMP_EN_MASK); |
2933 | snd_soc_component_update_bits(component, DA7218_HP_L_CTRL, |
2934 | DA7218_HP_L_AMP_RAMP_EN_MASK, |
2935 | DA7218_HP_L_AMP_RAMP_EN_MASK); |
2936 | snd_soc_component_update_bits(component, DA7218_HP_R_CTRL, |
2937 | DA7218_HP_R_AMP_RAMP_EN_MASK, |
2938 | DA7218_HP_R_AMP_RAMP_EN_MASK); |
2939 | |
2940 | /* Default infinite tone gen, start/stop by Kcontrol */ |
2941 | snd_soc_component_write(component, DA7218_TONE_GEN_CYCLES, DA7218_BEEP_CYCLES_MASK); |
2942 | |
2943 | /* DA7217 specific config */ |
2944 | if (da7218->dev_id == DA7217_DEV_ID) { |
2945 | snd_soc_component_update_bits(component, DA7218_HP_DIFF_CTRL, |
2946 | DA7218_HP_AMP_DIFF_MODE_EN_MASK, |
2947 | DA7218_HP_AMP_DIFF_MODE_EN_MASK); |
2948 | |
2949 | /* Only DA7218 supports HP detect, mask off for DA7217 */ |
2950 | snd_soc_component_write(component, DA7218_EVENT_MASK, |
2951 | DA7218_HPLDET_JACK_EVENT_IRQ_MSK_MASK); |
2952 | } |
2953 | |
2954 | if (da7218->irq) { |
2955 | ret = devm_request_threaded_irq(dev: component->dev, irq: da7218->irq, NULL, |
2956 | thread_fn: da7218_irq_thread, |
2957 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
2958 | devname: "da7218" , dev_id: component); |
2959 | if (ret != 0) { |
2960 | dev_err(component->dev, "Failed to request IRQ %d: %d\n" , |
2961 | da7218->irq, ret); |
2962 | goto err_disable_reg; |
2963 | } |
2964 | |
2965 | } |
2966 | |
2967 | return 0; |
2968 | |
2969 | err_disable_reg: |
2970 | regulator_bulk_disable(num_consumers: DA7218_NUM_SUPPLIES, consumers: da7218->supplies); |
2971 | |
2972 | return ret; |
2973 | } |
2974 | |
2975 | static void da7218_remove(struct snd_soc_component *component) |
2976 | { |
2977 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2978 | |
2979 | regulator_bulk_disable(num_consumers: DA7218_NUM_SUPPLIES, consumers: da7218->supplies); |
2980 | } |
2981 | |
2982 | #ifdef CONFIG_PM |
2983 | static int da7218_suspend(struct snd_soc_component *component) |
2984 | { |
2985 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2986 | |
2987 | da7218_set_bias_level(component, level: SND_SOC_BIAS_OFF); |
2988 | |
2989 | /* Put device into standby mode if jack detection disabled */ |
2990 | if (!da7218->jack) |
2991 | snd_soc_component_write(component, DA7218_SYSTEM_ACTIVE, val: 0); |
2992 | |
2993 | return 0; |
2994 | } |
2995 | |
2996 | static int da7218_resume(struct snd_soc_component *component) |
2997 | { |
2998 | struct da7218_priv *da7218 = snd_soc_component_get_drvdata(c: component); |
2999 | |
3000 | /* Put device into active mode if previously moved to standby */ |
3001 | if (!da7218->jack) |
3002 | snd_soc_component_write(component, DA7218_SYSTEM_ACTIVE, |
3003 | DA7218_SYSTEM_ACTIVE_MASK); |
3004 | |
3005 | da7218_set_bias_level(component, level: SND_SOC_BIAS_STANDBY); |
3006 | |
3007 | return 0; |
3008 | } |
3009 | #else |
3010 | #define da7218_suspend NULL |
3011 | #define da7218_resume NULL |
3012 | #endif |
3013 | |
3014 | static const struct snd_soc_component_driver soc_component_dev_da7218 = { |
3015 | .probe = da7218_probe, |
3016 | .remove = da7218_remove, |
3017 | .suspend = da7218_suspend, |
3018 | .resume = da7218_resume, |
3019 | .set_bias_level = da7218_set_bias_level, |
3020 | .controls = da7218_snd_controls, |
3021 | .num_controls = ARRAY_SIZE(da7218_snd_controls), |
3022 | .dapm_widgets = da7218_dapm_widgets, |
3023 | .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets), |
3024 | .dapm_routes = da7218_audio_map, |
3025 | .num_dapm_routes = ARRAY_SIZE(da7218_audio_map), |
3026 | .idle_bias_on = 1, |
3027 | .use_pmdown_time = 1, |
3028 | .endianness = 1, |
3029 | }; |
3030 | |
3031 | |
3032 | /* |
3033 | * Regmap configs |
3034 | */ |
3035 | |
3036 | static struct reg_default da7218_reg_defaults[] = { |
3037 | { DA7218_SYSTEM_ACTIVE, 0x00 }, |
3038 | { DA7218_CIF_CTRL, 0x00 }, |
3039 | { DA7218_SPARE1, 0x00 }, |
3040 | { DA7218_SR, 0xAA }, |
3041 | { DA7218_PC_COUNT, 0x02 }, |
3042 | { DA7218_GAIN_RAMP_CTRL, 0x00 }, |
3043 | { DA7218_CIF_TIMEOUT_CTRL, 0x01 }, |
3044 | { DA7218_SYSTEM_MODES_INPUT, 0x00 }, |
3045 | { DA7218_SYSTEM_MODES_OUTPUT, 0x00 }, |
3046 | { DA7218_IN_1L_FILTER_CTRL, 0x00 }, |
3047 | { DA7218_IN_1R_FILTER_CTRL, 0x00 }, |
3048 | { DA7218_IN_2L_FILTER_CTRL, 0x00 }, |
3049 | { DA7218_IN_2R_FILTER_CTRL, 0x00 }, |
3050 | { DA7218_OUT_1L_FILTER_CTRL, 0x40 }, |
3051 | { DA7218_OUT_1R_FILTER_CTRL, 0x40 }, |
3052 | { DA7218_OUT_1_HPF_FILTER_CTRL, 0x80 }, |
3053 | { DA7218_OUT_1_EQ_12_FILTER_CTRL, 0x77 }, |
3054 | { DA7218_OUT_1_EQ_34_FILTER_CTRL, 0x77 }, |
3055 | { DA7218_OUT_1_EQ_5_FILTER_CTRL, 0x07 }, |
3056 | { DA7218_OUT_1_BIQ_5STAGE_CTRL, 0x40 }, |
3057 | { DA7218_OUT_1_BIQ_5STAGE_DATA, 0x00 }, |
3058 | { DA7218_OUT_1_BIQ_5STAGE_ADDR, 0x00 }, |
3059 | { DA7218_MIXIN_1_CTRL, 0x48 }, |
3060 | { DA7218_MIXIN_1_GAIN, 0x03 }, |
3061 | { DA7218_MIXIN_2_CTRL, 0x48 }, |
3062 | { DA7218_MIXIN_2_GAIN, 0x03 }, |
3063 | { DA7218_ALC_CTRL1, 0x00 }, |
3064 | { DA7218_ALC_CTRL2, 0x00 }, |
3065 | { DA7218_ALC_CTRL3, 0x00 }, |
3066 | { DA7218_ALC_NOISE, 0x3F }, |
3067 | { DA7218_ALC_TARGET_MIN, 0x3F }, |
3068 | { DA7218_ALC_TARGET_MAX, 0x00 }, |
3069 | { DA7218_ALC_GAIN_LIMITS, 0xFF }, |
3070 | { DA7218_ALC_ANA_GAIN_LIMITS, 0x71 }, |
3071 | { DA7218_ALC_ANTICLIP_CTRL, 0x00 }, |
3072 | { DA7218_AGS_ENABLE, 0x00 }, |
3073 | { DA7218_AGS_TRIGGER, 0x09 }, |
3074 | { DA7218_AGS_ATT_MAX, 0x00 }, |
3075 | { DA7218_AGS_TIMEOUT, 0x00 }, |
3076 | { DA7218_AGS_ANTICLIP_CTRL, 0x00 }, |
3077 | { DA7218_ENV_TRACK_CTRL, 0x00 }, |
3078 | { DA7218_LVL_DET_CTRL, 0x00 }, |
3079 | { DA7218_LVL_DET_LEVEL, 0x7F }, |
3080 | { DA7218_DGS_TRIGGER, 0x24 }, |
3081 | { DA7218_DGS_ENABLE, 0x00 }, |
3082 | { DA7218_DGS_RISE_FALL, 0x50 }, |
3083 | { DA7218_DGS_SYNC_DELAY, 0xA3 }, |
3084 | { DA7218_DGS_SYNC_DELAY2, 0x31 }, |
3085 | { DA7218_DGS_SYNC_DELAY3, 0x11 }, |
3086 | { DA7218_DGS_LEVELS, 0x01 }, |
3087 | { DA7218_DGS_GAIN_CTRL, 0x74 }, |
3088 | { DA7218_DROUTING_OUTDAI_1L, 0x01 }, |
3089 | { DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN, 0x1C }, |
3090 | { DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN, 0x1C }, |
3091 | { DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN, 0x1C }, |
3092 | { DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN, 0x1C }, |
3093 | { DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN, 0x1C }, |
3094 | { DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN, 0x1C }, |
3095 | { DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN, 0x1C }, |
3096 | { DA7218_DROUTING_OUTDAI_1R, 0x04 }, |
3097 | { DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN, 0x1C }, |
3098 | { DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN, 0x1C }, |
3099 | { DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN, 0x1C }, |
3100 | { DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN, 0x1C }, |
3101 | { DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN, 0x1C }, |
3102 | { DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN, 0x1C }, |
3103 | { DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN, 0x1C }, |
3104 | { DA7218_DROUTING_OUTFILT_1L, 0x01 }, |
3105 | { DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN, 0x1C }, |
3106 | { DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN, 0x1C }, |
3107 | { DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN, 0x1C }, |
3108 | { DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN, 0x1C }, |
3109 | { DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN, 0x1C }, |
3110 | { DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN, 0x1C }, |
3111 | { DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN, 0x1C }, |
3112 | { DA7218_DROUTING_OUTFILT_1R, 0x04 }, |
3113 | { DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN, 0x1C }, |
3114 | { DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN, 0x1C }, |
3115 | { DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN, 0x1C }, |
3116 | { DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN, 0x1C }, |
3117 | { DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN, 0x1C }, |
3118 | { DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN, 0x1C }, |
3119 | { DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN, 0x1C }, |
3120 | { DA7218_DROUTING_OUTDAI_2L, 0x04 }, |
3121 | { DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN, 0x1C }, |
3122 | { DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN, 0x1C }, |
3123 | { DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN, 0x1C }, |
3124 | { DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN, 0x1C }, |
3125 | { DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN, 0x1C }, |
3126 | { DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN, 0x1C }, |
3127 | { DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN, 0x1C }, |
3128 | { DA7218_DROUTING_OUTDAI_2R, 0x08 }, |
3129 | { DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN, 0x1C }, |
3130 | { DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN, 0x1C }, |
3131 | { DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN, 0x1C }, |
3132 | { DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN, 0x1C }, |
3133 | { DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN, 0x1C }, |
3134 | { DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN, 0x1C }, |
3135 | { DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN, 0x1C }, |
3136 | { DA7218_DAI_CTRL, 0x28 }, |
3137 | { DA7218_DAI_TDM_CTRL, 0x40 }, |
3138 | { DA7218_DAI_OFFSET_LOWER, 0x00 }, |
3139 | { DA7218_DAI_OFFSET_UPPER, 0x00 }, |
3140 | { DA7218_DAI_CLK_MODE, 0x01 }, |
3141 | { DA7218_PLL_CTRL, 0x04 }, |
3142 | { DA7218_PLL_FRAC_TOP, 0x00 }, |
3143 | { DA7218_PLL_FRAC_BOT, 0x00 }, |
3144 | { DA7218_PLL_INTEGER, 0x20 }, |
3145 | { DA7218_DAC_NG_CTRL, 0x00 }, |
3146 | { DA7218_DAC_NG_SETUP_TIME, 0x00 }, |
3147 | { DA7218_DAC_NG_OFF_THRESH, 0x00 }, |
3148 | { DA7218_DAC_NG_ON_THRESH, 0x00 }, |
3149 | { DA7218_TONE_GEN_CFG2, 0x00 }, |
3150 | { DA7218_TONE_GEN_FREQ1_L, 0x55 }, |
3151 | { DA7218_TONE_GEN_FREQ1_U, 0x15 }, |
3152 | { DA7218_TONE_GEN_FREQ2_L, 0x00 }, |
3153 | { DA7218_TONE_GEN_FREQ2_U, 0x40 }, |
3154 | { DA7218_TONE_GEN_CYCLES, 0x00 }, |
3155 | { DA7218_TONE_GEN_ON_PER, 0x02 }, |
3156 | { DA7218_TONE_GEN_OFF_PER, 0x01 }, |
3157 | { DA7218_CP_CTRL, 0x60 }, |
3158 | { DA7218_CP_DELAY, 0x11 }, |
3159 | { DA7218_CP_VOL_THRESHOLD1, 0x0E }, |
3160 | { DA7218_MIC_1_CTRL, 0x40 }, |
3161 | { DA7218_MIC_1_GAIN, 0x01 }, |
3162 | { DA7218_MIC_1_SELECT, 0x00 }, |
3163 | { DA7218_MIC_2_CTRL, 0x40 }, |
3164 | { DA7218_MIC_2_GAIN, 0x01 }, |
3165 | { DA7218_MIC_2_SELECT, 0x00 }, |
3166 | { DA7218_IN_1_HPF_FILTER_CTRL, 0x80 }, |
3167 | { DA7218_IN_2_HPF_FILTER_CTRL, 0x80 }, |
3168 | { DA7218_ADC_1_CTRL, 0x07 }, |
3169 | { DA7218_ADC_2_CTRL, 0x07 }, |
3170 | { DA7218_MIXOUT_L_CTRL, 0x00 }, |
3171 | { DA7218_MIXOUT_L_GAIN, 0x03 }, |
3172 | { DA7218_MIXOUT_R_CTRL, 0x00 }, |
3173 | { DA7218_MIXOUT_R_GAIN, 0x03 }, |
3174 | { DA7218_HP_L_CTRL, 0x40 }, |
3175 | { DA7218_HP_L_GAIN, 0x3B }, |
3176 | { DA7218_HP_R_CTRL, 0x40 }, |
3177 | { DA7218_HP_R_GAIN, 0x3B }, |
3178 | { DA7218_HP_DIFF_CTRL, 0x00 }, |
3179 | { DA7218_HP_DIFF_UNLOCK, 0xC3 }, |
3180 | { DA7218_HPLDET_JACK, 0x0B }, |
3181 | { DA7218_HPLDET_CTRL, 0x00 }, |
3182 | { DA7218_REFERENCES, 0x08 }, |
3183 | { DA7218_IO_CTRL, 0x00 }, |
3184 | { DA7218_LDO_CTRL, 0x00 }, |
3185 | { DA7218_SIDETONE_CTRL, 0x40 }, |
3186 | { DA7218_SIDETONE_IN_SELECT, 0x00 }, |
3187 | { DA7218_SIDETONE_GAIN, 0x1C }, |
3188 | { DA7218_DROUTING_ST_OUTFILT_1L, 0x01 }, |
3189 | { DA7218_DROUTING_ST_OUTFILT_1R, 0x02 }, |
3190 | { DA7218_SIDETONE_BIQ_3STAGE_DATA, 0x00 }, |
3191 | { DA7218_SIDETONE_BIQ_3STAGE_ADDR, 0x00 }, |
3192 | { DA7218_EVENT_MASK, 0x00 }, |
3193 | { DA7218_DMIC_1_CTRL, 0x00 }, |
3194 | { DA7218_DMIC_2_CTRL, 0x00 }, |
3195 | { DA7218_IN_1L_GAIN, 0x6F }, |
3196 | { DA7218_IN_1R_GAIN, 0x6F }, |
3197 | { DA7218_IN_2L_GAIN, 0x6F }, |
3198 | { DA7218_IN_2R_GAIN, 0x6F }, |
3199 | { DA7218_OUT_1L_GAIN, 0x6F }, |
3200 | { DA7218_OUT_1R_GAIN, 0x6F }, |
3201 | { DA7218_MICBIAS_CTRL, 0x00 }, |
3202 | { DA7218_MICBIAS_EN, 0x00 }, |
3203 | }; |
3204 | |
3205 | static bool da7218_volatile_register(struct device *dev, unsigned int reg) |
3206 | { |
3207 | switch (reg) { |
3208 | case DA7218_STATUS1: |
3209 | case DA7218_SOFT_RESET: |
3210 | case DA7218_SYSTEM_STATUS: |
3211 | case DA7218_CALIB_CTRL: |
3212 | case DA7218_CALIB_OFFSET_AUTO_M_1: |
3213 | case DA7218_CALIB_OFFSET_AUTO_U_1: |
3214 | case DA7218_CALIB_OFFSET_AUTO_M_2: |
3215 | case DA7218_CALIB_OFFSET_AUTO_U_2: |
3216 | case DA7218_PLL_STATUS: |
3217 | case DA7218_PLL_REFOSC_CAL: |
3218 | case DA7218_TONE_GEN_CFG1: |
3219 | case DA7218_ADC_MODE: |
3220 | case DA7218_HP_SNGL_CTRL: |
3221 | case DA7218_HPLDET_TEST: |
3222 | case DA7218_EVENT_STATUS: |
3223 | case DA7218_EVENT: |
3224 | return true; |
3225 | default: |
3226 | return false; |
3227 | } |
3228 | } |
3229 | |
3230 | static const struct regmap_config da7218_regmap_config = { |
3231 | .reg_bits = 8, |
3232 | .val_bits = 8, |
3233 | |
3234 | .max_register = DA7218_MICBIAS_EN, |
3235 | .reg_defaults = da7218_reg_defaults, |
3236 | .num_reg_defaults = ARRAY_SIZE(da7218_reg_defaults), |
3237 | .volatile_reg = da7218_volatile_register, |
3238 | .cache_type = REGCACHE_RBTREE, |
3239 | }; |
3240 | |
3241 | |
3242 | /* |
3243 | * I2C layer |
3244 | */ |
3245 | |
3246 | static int da7218_i2c_probe(struct i2c_client *i2c) |
3247 | { |
3248 | struct da7218_priv *da7218; |
3249 | int ret; |
3250 | |
3251 | da7218 = devm_kzalloc(dev: &i2c->dev, size: sizeof(*da7218), GFP_KERNEL); |
3252 | if (!da7218) |
3253 | return -ENOMEM; |
3254 | |
3255 | i2c_set_clientdata(client: i2c, data: da7218); |
3256 | |
3257 | da7218->dev_id = (uintptr_t)i2c_get_match_data(client: i2c); |
3258 | |
3259 | if ((da7218->dev_id != DA7217_DEV_ID) && |
3260 | (da7218->dev_id != DA7218_DEV_ID)) { |
3261 | dev_err(&i2c->dev, "Invalid device Id\n" ); |
3262 | return -EINVAL; |
3263 | } |
3264 | |
3265 | da7218->irq = i2c->irq; |
3266 | |
3267 | da7218->regmap = devm_regmap_init_i2c(i2c, &da7218_regmap_config); |
3268 | if (IS_ERR(ptr: da7218->regmap)) { |
3269 | ret = PTR_ERR(ptr: da7218->regmap); |
3270 | dev_err(&i2c->dev, "regmap_init() failed: %d\n" , ret); |
3271 | return ret; |
3272 | } |
3273 | |
3274 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
3275 | component_driver: &soc_component_dev_da7218, dai_drv: &da7218_dai, num_dai: 1); |
3276 | if (ret < 0) { |
3277 | dev_err(&i2c->dev, "Failed to register da7218 component: %d\n" , |
3278 | ret); |
3279 | } |
3280 | return ret; |
3281 | } |
3282 | |
3283 | static const struct i2c_device_id da7218_i2c_id[] = { |
3284 | { "da7217" , DA7217_DEV_ID }, |
3285 | { "da7218" , DA7218_DEV_ID }, |
3286 | { } |
3287 | }; |
3288 | MODULE_DEVICE_TABLE(i2c, da7218_i2c_id); |
3289 | |
3290 | static struct i2c_driver da7218_i2c_driver = { |
3291 | .driver = { |
3292 | .name = "da7218" , |
3293 | .of_match_table = da7218_of_match, |
3294 | }, |
3295 | .probe = da7218_i2c_probe, |
3296 | .id_table = da7218_i2c_id, |
3297 | }; |
3298 | |
3299 | module_i2c_driver(da7218_i2c_driver); |
3300 | |
3301 | MODULE_DESCRIPTION("ASoC DA7218 Codec driver" ); |
3302 | MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>" ); |
3303 | MODULE_LICENSE("GPL" ); |
3304 | |