1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* ALSA SoC TLV320AIC3X codec driver |
3 | * |
4 | * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> |
5 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> |
6 | * |
7 | * Based on sound/soc/codecs/wm8753.c by Liam Girdwood |
8 | * |
9 | * Notes: |
10 | * The AIC3X is a driver for a low power stereo audio |
11 | * codecs aic31, aic32, aic33, aic3007. |
12 | * |
13 | * It supports full aic33 codec functionality. |
14 | * The compatibility with aic32, aic31 and aic3007 is as follows: |
15 | * aic32/aic3007 | aic31 |
16 | * --------------------------------------- |
17 | * MONO_LOUT -> N/A | MONO_LOUT -> N/A |
18 | * | IN1L -> LINE1L |
19 | * | IN1R -> LINE1R |
20 | * | IN2L -> LINE2L |
21 | * | IN2R -> LINE2R |
22 | * | MIC3L/R -> N/A |
23 | * truncated internal functionality in |
24 | * accordance with documentation |
25 | * --------------------------------------- |
26 | * |
27 | * Hence the machine layer should disable unsupported inputs/outputs by |
28 | * snd_soc_dapm_disable_pin(codec, "MONO_LOUT"), etc. |
29 | */ |
30 | |
31 | #include <linux/module.h> |
32 | #include <linux/moduleparam.h> |
33 | #include <linux/init.h> |
34 | #include <linux/delay.h> |
35 | #include <linux/err.h> |
36 | #include <linux/pm.h> |
37 | #include <linux/i2c.h> |
38 | #include <linux/gpio/consumer.h> |
39 | #include <linux/regulator/consumer.h> |
40 | #include <linux/of.h> |
41 | #include <linux/slab.h> |
42 | #include <sound/core.h> |
43 | #include <sound/pcm.h> |
44 | #include <sound/pcm_params.h> |
45 | #include <sound/soc.h> |
46 | #include <sound/initval.h> |
47 | #include <sound/tlv.h> |
48 | |
49 | #include "tlv320aic3x.h" |
50 | |
51 | #define AIC3X_NUM_SUPPLIES 4 |
52 | static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { |
53 | "IOVDD" , /* I/O Voltage */ |
54 | "DVDD" , /* Digital Core Voltage */ |
55 | "AVDD" , /* Analog DAC Voltage */ |
56 | "DRVDD" , /* ADC Analog and Output Driver Voltage */ |
57 | }; |
58 | |
59 | struct aic3x_priv; |
60 | |
61 | struct aic3x_disable_nb { |
62 | struct notifier_block nb; |
63 | struct aic3x_priv *aic3x; |
64 | }; |
65 | |
66 | struct aic3x_setup_data { |
67 | unsigned int gpio_func[2]; |
68 | }; |
69 | |
70 | /* codec private data */ |
71 | struct aic3x_priv { |
72 | struct snd_soc_component *component; |
73 | struct regmap *regmap; |
74 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; |
75 | struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; |
76 | struct aic3x_setup_data *setup; |
77 | unsigned int sysclk; |
78 | unsigned int dai_fmt; |
79 | unsigned int tdm_delay; |
80 | unsigned int slot_width; |
81 | int master; |
82 | struct gpio_desc *gpio_reset; |
83 | bool shared_reset; |
84 | int power; |
85 | u16 model; |
86 | |
87 | /* Selects the micbias voltage */ |
88 | enum aic3x_micbias_voltage micbias_vg; |
89 | /* Output Common-Mode Voltage */ |
90 | u8 ocmv; |
91 | }; |
92 | |
93 | static const struct reg_default aic3x_reg[] = { |
94 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x10 }, |
95 | { 4, 0x04 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
96 | { 8, 0x00 }, { 9, 0x00 }, { 10, 0x00 }, { 11, 0x01 }, |
97 | { 12, 0x00 }, { 13, 0x00 }, { 14, 0x00 }, { 15, 0x80 }, |
98 | { 16, 0x80 }, { 17, 0xff }, { 18, 0xff }, { 19, 0x78 }, |
99 | { 20, 0x78 }, { 21, 0x78 }, { 22, 0x78 }, { 23, 0x78 }, |
100 | { 24, 0x78 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0xfe }, |
101 | { 28, 0x00 }, { 29, 0x00 }, { 30, 0xfe }, { 31, 0x00 }, |
102 | { 32, 0x18 }, { 33, 0x18 }, { 34, 0x00 }, { 35, 0x00 }, |
103 | { 36, 0x00 }, { 37, 0x00 }, { 38, 0x00 }, { 39, 0x00 }, |
104 | { 40, 0x00 }, { 41, 0x00 }, { 42, 0x00 }, { 43, 0x80 }, |
105 | { 44, 0x80 }, { 45, 0x00 }, { 46, 0x00 }, { 47, 0x00 }, |
106 | { 48, 0x00 }, { 49, 0x00 }, { 50, 0x00 }, { 51, 0x04 }, |
107 | { 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, { 55, 0x00 }, |
108 | { 56, 0x00 }, { 57, 0x00 }, { 58, 0x04 }, { 59, 0x00 }, |
109 | { 60, 0x00 }, { 61, 0x00 }, { 62, 0x00 }, { 63, 0x00 }, |
110 | { 64, 0x00 }, { 65, 0x04 }, { 66, 0x00 }, { 67, 0x00 }, |
111 | { 68, 0x00 }, { 69, 0x00 }, { 70, 0x00 }, { 71, 0x00 }, |
112 | { 72, 0x04 }, { 73, 0x00 }, { 74, 0x00 }, { 75, 0x00 }, |
113 | { 76, 0x00 }, { 77, 0x00 }, { 78, 0x00 }, { 79, 0x00 }, |
114 | { 80, 0x00 }, { 81, 0x00 }, { 82, 0x00 }, { 83, 0x00 }, |
115 | { 84, 0x00 }, { 85, 0x00 }, { 86, 0x00 }, { 87, 0x00 }, |
116 | { 88, 0x00 }, { 89, 0x00 }, { 90, 0x00 }, { 91, 0x00 }, |
117 | { 92, 0x00 }, { 93, 0x00 }, { 94, 0x00 }, { 95, 0x00 }, |
118 | { 96, 0x00 }, { 97, 0x00 }, { 98, 0x00 }, { 99, 0x00 }, |
119 | { 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 }, |
120 | { 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 }, |
121 | { 108, 0x00 }, { 109, 0x00 }, |
122 | }; |
123 | |
124 | static bool aic3x_volatile_reg(struct device *dev, unsigned int reg) |
125 | { |
126 | switch (reg) { |
127 | case AIC3X_RESET: |
128 | return true; |
129 | default: |
130 | return false; |
131 | } |
132 | } |
133 | |
134 | const struct regmap_config aic3x_regmap = { |
135 | .max_register = DAC_ICC_ADJ, |
136 | .reg_defaults = aic3x_reg, |
137 | .num_reg_defaults = ARRAY_SIZE(aic3x_reg), |
138 | |
139 | .volatile_reg = aic3x_volatile_reg, |
140 | |
141 | .cache_type = REGCACHE_RBTREE, |
142 | }; |
143 | EXPORT_SYMBOL_GPL(aic3x_regmap); |
144 | |
145 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
146 | SOC_SINGLE_EXT(xname, reg, shift, mask, invert, \ |
147 | snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw_aic3x) |
148 | |
149 | /* |
150 | * All input lines are connected when !0xf and disconnected with 0xf bit field, |
151 | * so we have to use specific dapm_put call for input mixer |
152 | */ |
153 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, |
154 | struct snd_ctl_elem_value *ucontrol) |
155 | { |
156 | struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); |
157 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
158 | struct soc_mixer_control *mc = |
159 | (struct soc_mixer_control *)kcontrol->private_value; |
160 | unsigned int reg = mc->reg; |
161 | unsigned int shift = mc->shift; |
162 | int max = mc->max; |
163 | unsigned int mask = (1 << fls(x: max)) - 1; |
164 | unsigned int invert = mc->invert; |
165 | unsigned short val; |
166 | struct snd_soc_dapm_update update = {}; |
167 | int connect, change; |
168 | |
169 | val = (ucontrol->value.integer.value[0] & mask); |
170 | |
171 | mask = 0xf; |
172 | if (val) |
173 | val = mask; |
174 | |
175 | connect = !!val; |
176 | |
177 | if (invert) |
178 | val = mask - val; |
179 | |
180 | mask <<= shift; |
181 | val <<= shift; |
182 | |
183 | change = snd_soc_component_test_bits(component, reg, mask, value: val); |
184 | if (change) { |
185 | update.kcontrol = kcontrol; |
186 | update.reg = reg; |
187 | update.mask = mask; |
188 | update.val = val; |
189 | |
190 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, connect, |
191 | update: &update); |
192 | } |
193 | |
194 | return change; |
195 | } |
196 | |
197 | /* |
198 | * mic bias power on/off share the same register bits with |
199 | * output voltage of mic bias. when power on mic bias, we |
200 | * need reclaim it to voltage value. |
201 | * 0x0 = Powered off |
202 | * 0x1 = MICBIAS output is powered to 2.0V, |
203 | * 0x2 = MICBIAS output is powered to 2.5V |
204 | * 0x3 = MICBIAS output is connected to AVDD |
205 | */ |
206 | static int mic_bias_event(struct snd_soc_dapm_widget *w, |
207 | struct snd_kcontrol *kcontrol, int event) |
208 | { |
209 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
210 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
211 | |
212 | switch (event) { |
213 | case SND_SOC_DAPM_POST_PMU: |
214 | /* change mic bias voltage to user defined */ |
215 | snd_soc_component_update_bits(component, MICBIAS_CTRL, |
216 | MICBIAS_LEVEL_MASK, |
217 | val: aic3x->micbias_vg << MICBIAS_LEVEL_SHIFT); |
218 | break; |
219 | |
220 | case SND_SOC_DAPM_PRE_PMD: |
221 | snd_soc_component_update_bits(component, MICBIAS_CTRL, |
222 | MICBIAS_LEVEL_MASK, val: 0); |
223 | break; |
224 | } |
225 | return 0; |
226 | } |
227 | |
228 | static const char * const aic3x_left_dac_mux[] = { |
229 | "DAC_L1" , "DAC_L3" , "DAC_L2" }; |
230 | static SOC_ENUM_SINGLE_DECL(aic3x_left_dac_enum, DAC_LINE_MUX, 6, |
231 | aic3x_left_dac_mux); |
232 | |
233 | static const char * const aic3x_right_dac_mux[] = { |
234 | "DAC_R1" , "DAC_R3" , "DAC_R2" }; |
235 | static SOC_ENUM_SINGLE_DECL(aic3x_right_dac_enum, DAC_LINE_MUX, 4, |
236 | aic3x_right_dac_mux); |
237 | |
238 | static const char * const aic3x_left_hpcom_mux[] = { |
239 | "differential of HPLOUT" , "constant VCM" , "single-ended" }; |
240 | static SOC_ENUM_SINGLE_DECL(aic3x_left_hpcom_enum, HPLCOM_CFG, 4, |
241 | aic3x_left_hpcom_mux); |
242 | |
243 | static const char * const aic3x_right_hpcom_mux[] = { |
244 | "differential of HPROUT" , "constant VCM" , "single-ended" , |
245 | "differential of HPLCOM" , "external feedback" }; |
246 | static SOC_ENUM_SINGLE_DECL(aic3x_right_hpcom_enum, HPRCOM_CFG, 3, |
247 | aic3x_right_hpcom_mux); |
248 | |
249 | static const char * const aic3x_linein_mode_mux[] = { |
250 | "single-ended" , "differential" }; |
251 | static SOC_ENUM_SINGLE_DECL(aic3x_line1l_2_l_enum, LINE1L_2_LADC_CTRL, 7, |
252 | aic3x_linein_mode_mux); |
253 | static SOC_ENUM_SINGLE_DECL(aic3x_line1l_2_r_enum, LINE1L_2_RADC_CTRL, 7, |
254 | aic3x_linein_mode_mux); |
255 | static SOC_ENUM_SINGLE_DECL(aic3x_line1r_2_l_enum, LINE1R_2_LADC_CTRL, 7, |
256 | aic3x_linein_mode_mux); |
257 | static SOC_ENUM_SINGLE_DECL(aic3x_line1r_2_r_enum, LINE1R_2_RADC_CTRL, 7, |
258 | aic3x_linein_mode_mux); |
259 | static SOC_ENUM_SINGLE_DECL(aic3x_line2l_2_ldac_enum, LINE2L_2_LADC_CTRL, 7, |
260 | aic3x_linein_mode_mux); |
261 | static SOC_ENUM_SINGLE_DECL(aic3x_line2r_2_rdac_enum, LINE2R_2_RADC_CTRL, 7, |
262 | aic3x_linein_mode_mux); |
263 | |
264 | static const char * const aic3x_adc_hpf[] = { |
265 | "Disabled" , "0.0045xFs" , "0.0125xFs" , "0.025xFs" }; |
266 | static SOC_ENUM_DOUBLE_DECL(aic3x_adc_hpf_enum, AIC3X_CODEC_DFILT_CTRL, 6, 4, |
267 | aic3x_adc_hpf); |
268 | |
269 | static const char * const aic3x_agc_level[] = { |
270 | "-5.5dB" , "-8dB" , "-10dB" , "-12dB" , |
271 | "-14dB" , "-17dB" , "-20dB" , "-24dB" }; |
272 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_level_enum, LAGC_CTRL_A, 4, |
273 | aic3x_agc_level); |
274 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_level_enum, RAGC_CTRL_A, 4, |
275 | aic3x_agc_level); |
276 | |
277 | static const char * const aic3x_agc_attack[] = { |
278 | "8ms" , "11ms" , "16ms" , "20ms" }; |
279 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_attack_enum, LAGC_CTRL_A, 2, |
280 | aic3x_agc_attack); |
281 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_attack_enum, RAGC_CTRL_A, 2, |
282 | aic3x_agc_attack); |
283 | |
284 | static const char * const aic3x_agc_decay[] = { |
285 | "100ms" , "200ms" , "400ms" , "500ms" }; |
286 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_decay_enum, LAGC_CTRL_A, 0, |
287 | aic3x_agc_decay); |
288 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_decay_enum, RAGC_CTRL_A, 0, |
289 | aic3x_agc_decay); |
290 | |
291 | static const char * const aic3x_poweron_time[] = { |
292 | "0us" , "10us" , "100us" , "1ms" , "10ms" , "50ms" , |
293 | "100ms" , "200ms" , "400ms" , "800ms" , "2s" , "4s" }; |
294 | static SOC_ENUM_SINGLE_DECL(aic3x_poweron_time_enum, HPOUT_POP_REDUCTION, 4, |
295 | aic3x_poweron_time); |
296 | |
297 | static const char * const aic3x_rampup_step[] = { "0ms" , "1ms" , "2ms" , "4ms" }; |
298 | static SOC_ENUM_SINGLE_DECL(aic3x_rampup_step_enum, HPOUT_POP_REDUCTION, 2, |
299 | aic3x_rampup_step); |
300 | |
301 | /* |
302 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps |
303 | */ |
304 | static DECLARE_TLV_DB_SCALE(dac_tlv, -6350, 50, 0); |
305 | /* ADC PGA gain volumes. From 0 to 59.5 dB in 0.5 dB steps */ |
306 | static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0); |
307 | /* |
308 | * Output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB. |
309 | * Step size is approximately 0.5 dB over most of the scale but increasing |
310 | * near the very low levels. |
311 | * Define dB scale so that it is mostly correct for range about -55 to 0 dB |
312 | * but having increasing dB difference below that (and where it doesn't count |
313 | * so much). This setting shows -50 dB (actual is -50.3 dB) for register |
314 | * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117. |
315 | */ |
316 | static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); |
317 | |
318 | /* Output volumes. From 0 to 9 dB in 1 dB steps */ |
319 | static const DECLARE_TLV_DB_SCALE(out_tlv, 0, 100, 0); |
320 | |
321 | static const struct snd_kcontrol_new aic3x_snd_controls[] = { |
322 | /* Output */ |
323 | SOC_DOUBLE_R_TLV("PCM Playback Volume" , |
324 | LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), |
325 | |
326 | /* |
327 | * Output controls that map to output mixer switches. Note these are |
328 | * only for swapped L-to-R and R-to-L routes. See below stereo controls |
329 | * for direct L-to-L and R-to-R routes. |
330 | */ |
331 | SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume" , |
332 | PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
333 | SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume" , |
334 | DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
335 | |
336 | SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume" , |
337 | PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
338 | SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume" , |
339 | DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
340 | |
341 | SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume" , |
342 | PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
343 | SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume" , |
344 | DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
345 | |
346 | SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume" , |
347 | PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
348 | SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume" , |
349 | DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
350 | |
351 | SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume" , |
352 | PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
353 | SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume" , |
354 | DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
355 | |
356 | SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume" , |
357 | PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
358 | SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume" , |
359 | DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
360 | |
361 | /* Stereo output controls for direct L-to-L and R-to-R routes */ |
362 | SOC_DOUBLE_R_TLV("Line PGA Bypass Volume" , |
363 | PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL, |
364 | 0, 118, 1, output_stage_tlv), |
365 | SOC_DOUBLE_R_TLV("Line DAC Playback Volume" , |
366 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, |
367 | 0, 118, 1, output_stage_tlv), |
368 | |
369 | SOC_DOUBLE_R_TLV("HP PGA Bypass Volume" , |
370 | PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, |
371 | 0, 118, 1, output_stage_tlv), |
372 | SOC_DOUBLE_R_TLV("HP DAC Playback Volume" , |
373 | DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, |
374 | 0, 118, 1, output_stage_tlv), |
375 | |
376 | SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume" , |
377 | PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL, |
378 | 0, 118, 1, output_stage_tlv), |
379 | SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume" , |
380 | DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, |
381 | 0, 118, 1, output_stage_tlv), |
382 | |
383 | /* Output pin controls */ |
384 | SOC_DOUBLE_R_TLV("Line Playback Volume" , LLOPM_CTRL, RLOPM_CTRL, 4, |
385 | 9, 0, out_tlv), |
386 | SOC_DOUBLE_R("Line Playback Switch" , LLOPM_CTRL, RLOPM_CTRL, 3, |
387 | 0x01, 0), |
388 | SOC_DOUBLE_R_TLV("HP Playback Volume" , HPLOUT_CTRL, HPROUT_CTRL, 4, |
389 | 9, 0, out_tlv), |
390 | SOC_DOUBLE_R("HP Playback Switch" , HPLOUT_CTRL, HPROUT_CTRL, 3, |
391 | 0x01, 0), |
392 | SOC_DOUBLE_R_TLV("HPCOM Playback Volume" , HPLCOM_CTRL, HPRCOM_CTRL, |
393 | 4, 9, 0, out_tlv), |
394 | SOC_DOUBLE_R("HPCOM Playback Switch" , HPLCOM_CTRL, HPRCOM_CTRL, 3, |
395 | 0x01, 0), |
396 | |
397 | /* |
398 | * Note: enable Automatic input Gain Controller with care. It can |
399 | * adjust PGA to max value when ADC is on and will never go back. |
400 | */ |
401 | SOC_DOUBLE_R("AGC Switch" , LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), |
402 | SOC_ENUM("Left AGC Target level" , aic3x_lagc_level_enum), |
403 | SOC_ENUM("Right AGC Target level" , aic3x_ragc_level_enum), |
404 | SOC_ENUM("Left AGC Attack time" , aic3x_lagc_attack_enum), |
405 | SOC_ENUM("Right AGC Attack time" , aic3x_ragc_attack_enum), |
406 | SOC_ENUM("Left AGC Decay time" , aic3x_lagc_decay_enum), |
407 | SOC_ENUM("Right AGC Decay time" , aic3x_ragc_decay_enum), |
408 | |
409 | /* De-emphasis */ |
410 | SOC_DOUBLE("De-emphasis Switch" , AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), |
411 | |
412 | /* Input */ |
413 | SOC_DOUBLE_R_TLV("PGA Capture Volume" , LADC_VOL, RADC_VOL, |
414 | 0, 119, 0, adc_tlv), |
415 | SOC_DOUBLE_R("PGA Capture Switch" , LADC_VOL, RADC_VOL, 7, 0x01, 1), |
416 | |
417 | SOC_ENUM("ADC HPF Cut-off" , aic3x_adc_hpf_enum), |
418 | |
419 | /* Pop reduction */ |
420 | SOC_ENUM("Output Driver Power-On time" , aic3x_poweron_time_enum), |
421 | SOC_ENUM("Output Driver Ramp-up step" , aic3x_rampup_step_enum), |
422 | }; |
423 | |
424 | /* For other than tlv320aic3104 */ |
425 | static const struct snd_kcontrol_new [] = { |
426 | /* |
427 | * Output controls that map to output mixer switches. Note these are |
428 | * only for swapped L-to-R and R-to-L routes. See below stereo controls |
429 | * for direct L-to-L and R-to-R routes. |
430 | */ |
431 | SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume" , |
432 | LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
433 | |
434 | SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume" , |
435 | LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
436 | |
437 | SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume" , |
438 | LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
439 | |
440 | SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume" , |
441 | LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
442 | |
443 | SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume" , |
444 | LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
445 | |
446 | SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume" , |
447 | LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
448 | |
449 | /* Stereo output controls for direct L-to-L and R-to-R routes */ |
450 | SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume" , |
451 | LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL, |
452 | 0, 118, 1, output_stage_tlv), |
453 | |
454 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume" , |
455 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, |
456 | 0, 118, 1, output_stage_tlv), |
457 | |
458 | SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume" , |
459 | LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, |
460 | 0, 118, 1, output_stage_tlv), |
461 | }; |
462 | |
463 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { |
464 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume" , |
465 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, |
466 | 0, 118, 1, output_stage_tlv), |
467 | SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume" , |
468 | PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, |
469 | 0, 118, 1, output_stage_tlv), |
470 | SOC_DOUBLE_R_TLV("Mono DAC Playback Volume" , |
471 | DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, |
472 | 0, 118, 1, output_stage_tlv), |
473 | |
474 | SOC_SINGLE("Mono Playback Switch" , MONOLOPM_CTRL, 3, 0x01, 0), |
475 | SOC_SINGLE_TLV("Mono Playback Volume" , MONOLOPM_CTRL, 4, 9, 0, |
476 | out_tlv), |
477 | |
478 | }; |
479 | |
480 | /* |
481 | * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps |
482 | */ |
483 | static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); |
484 | |
485 | static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = |
486 | SOC_DOUBLE_TLV("Class-D Playback Volume" , CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); |
487 | |
488 | /* Left DAC Mux */ |
489 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
490 | SOC_DAPM_ENUM("Route" , aic3x_left_dac_enum); |
491 | |
492 | /* Right DAC Mux */ |
493 | static const struct snd_kcontrol_new aic3x_right_dac_mux_controls = |
494 | SOC_DAPM_ENUM("Route" , aic3x_right_dac_enum); |
495 | |
496 | /* Left HPCOM Mux */ |
497 | static const struct snd_kcontrol_new aic3x_left_hpcom_mux_controls = |
498 | SOC_DAPM_ENUM("Route" , aic3x_left_hpcom_enum); |
499 | |
500 | /* Right HPCOM Mux */ |
501 | static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = |
502 | SOC_DAPM_ENUM("Route" , aic3x_right_hpcom_enum); |
503 | |
504 | /* Left Line Mixer */ |
505 | static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { |
506 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_LLOPM_VOL, 7, 1, 0), |
507 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_LLOPM_VOL, 7, 1, 0), |
508 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_LLOPM_VOL, 7, 1, 0), |
509 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_LLOPM_VOL, 7, 1, 0), |
510 | /* Not on tlv320aic3104 */ |
511 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_LLOPM_VOL, 7, 1, 0), |
512 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_LLOPM_VOL, 7, 1, 0), |
513 | }; |
514 | |
515 | /* Right Line Mixer */ |
516 | static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = { |
517 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_RLOPM_VOL, 7, 1, 0), |
518 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_RLOPM_VOL, 7, 1, 0), |
519 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_RLOPM_VOL, 7, 1, 0), |
520 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_RLOPM_VOL, 7, 1, 0), |
521 | /* Not on tlv320aic3104 */ |
522 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_RLOPM_VOL, 7, 1, 0), |
523 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_RLOPM_VOL, 7, 1, 0), |
524 | }; |
525 | |
526 | /* Mono Mixer */ |
527 | static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = { |
528 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_MONOLOPM_VOL, 7, 1, 0), |
529 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_MONOLOPM_VOL, 7, 1, 0), |
530 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_MONOLOPM_VOL, 7, 1, 0), |
531 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_MONOLOPM_VOL, 7, 1, 0), |
532 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_MONOLOPM_VOL, 7, 1, 0), |
533 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_MONOLOPM_VOL, 7, 1, 0), |
534 | }; |
535 | |
536 | /* Left HP Mixer */ |
537 | static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = { |
538 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_HPLOUT_VOL, 7, 1, 0), |
539 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_HPLOUT_VOL, 7, 1, 0), |
540 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_HPLOUT_VOL, 7, 1, 0), |
541 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_HPLOUT_VOL, 7, 1, 0), |
542 | /* Not on tlv320aic3104 */ |
543 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_HPLOUT_VOL, 7, 1, 0), |
544 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_HPLOUT_VOL, 7, 1, 0), |
545 | }; |
546 | |
547 | /* Right HP Mixer */ |
548 | static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = { |
549 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_HPROUT_VOL, 7, 1, 0), |
550 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_HPROUT_VOL, 7, 1, 0), |
551 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_HPROUT_VOL, 7, 1, 0), |
552 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_HPROUT_VOL, 7, 1, 0), |
553 | /* Not on tlv320aic3104 */ |
554 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_HPROUT_VOL, 7, 1, 0), |
555 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_HPROUT_VOL, 7, 1, 0), |
556 | }; |
557 | |
558 | /* Left HPCOM Mixer */ |
559 | static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = { |
560 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_HPLCOM_VOL, 7, 1, 0), |
561 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_HPLCOM_VOL, 7, 1, 0), |
562 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_HPLCOM_VOL, 7, 1, 0), |
563 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_HPLCOM_VOL, 7, 1, 0), |
564 | /* Not on tlv320aic3104 */ |
565 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_HPLCOM_VOL, 7, 1, 0), |
566 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_HPLCOM_VOL, 7, 1, 0), |
567 | }; |
568 | |
569 | /* Right HPCOM Mixer */ |
570 | static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = { |
571 | SOC_DAPM_SINGLE("PGAL Bypass Switch" , PGAL_2_HPRCOM_VOL, 7, 1, 0), |
572 | SOC_DAPM_SINGLE("DACL1 Switch" , DACL1_2_HPRCOM_VOL, 7, 1, 0), |
573 | SOC_DAPM_SINGLE("PGAR Bypass Switch" , PGAR_2_HPRCOM_VOL, 7, 1, 0), |
574 | SOC_DAPM_SINGLE("DACR1 Switch" , DACR1_2_HPRCOM_VOL, 7, 1, 0), |
575 | /* Not on tlv320aic3104 */ |
576 | SOC_DAPM_SINGLE("Line2L Bypass Switch" , LINE2L_2_HPRCOM_VOL, 7, 1, 0), |
577 | SOC_DAPM_SINGLE("Line2R Bypass Switch" , LINE2R_2_HPRCOM_VOL, 7, 1, 0), |
578 | }; |
579 | |
580 | /* Left PGA Mixer */ |
581 | static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = { |
582 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch" , LINE1L_2_LADC_CTRL, 3, 1, 1), |
583 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch" , LINE1R_2_LADC_CTRL, 3, 1, 1), |
584 | SOC_DAPM_SINGLE_AIC3X("Line2L Switch" , LINE2L_2_LADC_CTRL, 3, 1, 1), |
585 | SOC_DAPM_SINGLE_AIC3X("Mic3L Switch" , MIC3LR_2_LADC_CTRL, 4, 1, 1), |
586 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch" , MIC3LR_2_LADC_CTRL, 0, 1, 1), |
587 | }; |
588 | |
589 | /* Right PGA Mixer */ |
590 | static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { |
591 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch" , LINE1R_2_RADC_CTRL, 3, 1, 1), |
592 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch" , LINE1L_2_RADC_CTRL, 3, 1, 1), |
593 | SOC_DAPM_SINGLE_AIC3X("Line2R Switch" , LINE2R_2_RADC_CTRL, 3, 1, 1), |
594 | SOC_DAPM_SINGLE_AIC3X("Mic3L Switch" , MIC3LR_2_RADC_CTRL, 4, 1, 1), |
595 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch" , MIC3LR_2_RADC_CTRL, 0, 1, 1), |
596 | }; |
597 | |
598 | /* Left PGA Mixer for tlv320aic3104 */ |
599 | static const struct snd_kcontrol_new aic3104_left_pga_mixer_controls[] = { |
600 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch" , LINE1L_2_LADC_CTRL, 3, 1, 1), |
601 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch" , LINE1R_2_LADC_CTRL, 3, 1, 1), |
602 | SOC_DAPM_SINGLE_AIC3X("Mic2L Switch" , MIC3LR_2_LADC_CTRL, 4, 1, 1), |
603 | SOC_DAPM_SINGLE_AIC3X("Mic2R Switch" , MIC3LR_2_LADC_CTRL, 0, 1, 1), |
604 | }; |
605 | |
606 | /* Right PGA Mixer for tlv320aic3104 */ |
607 | static const struct snd_kcontrol_new aic3104_right_pga_mixer_controls[] = { |
608 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch" , LINE1R_2_RADC_CTRL, 3, 1, 1), |
609 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch" , LINE1L_2_RADC_CTRL, 3, 1, 1), |
610 | SOC_DAPM_SINGLE_AIC3X("Mic2L Switch" , MIC3LR_2_RADC_CTRL, 4, 1, 1), |
611 | SOC_DAPM_SINGLE_AIC3X("Mic2R Switch" , MIC3LR_2_RADC_CTRL, 0, 1, 1), |
612 | }; |
613 | |
614 | /* Left Line1 Mux */ |
615 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = |
616 | SOC_DAPM_ENUM("Route" , aic3x_line1l_2_l_enum); |
617 | static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = |
618 | SOC_DAPM_ENUM("Route" , aic3x_line1l_2_r_enum); |
619 | |
620 | /* Right Line1 Mux */ |
621 | static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = |
622 | SOC_DAPM_ENUM("Route" , aic3x_line1r_2_r_enum); |
623 | static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = |
624 | SOC_DAPM_ENUM("Route" , aic3x_line1r_2_l_enum); |
625 | |
626 | /* Left Line2 Mux */ |
627 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = |
628 | SOC_DAPM_ENUM("Route" , aic3x_line2l_2_ldac_enum); |
629 | |
630 | /* Right Line2 Mux */ |
631 | static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = |
632 | SOC_DAPM_ENUM("Route" , aic3x_line2r_2_rdac_enum); |
633 | |
634 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { |
635 | /* Left DAC to Left Outputs */ |
636 | SND_SOC_DAPM_DAC("Left DAC" , "Left Playback" , DAC_PWR, 7, 0), |
637 | SND_SOC_DAPM_MUX("Left DAC Mux" , SND_SOC_NOPM, 0, 0, |
638 | &aic3x_left_dac_mux_controls), |
639 | SND_SOC_DAPM_MUX("Left HPCOM Mux" , SND_SOC_NOPM, 0, 0, |
640 | &aic3x_left_hpcom_mux_controls), |
641 | SND_SOC_DAPM_PGA("Left Line Out" , LLOPM_CTRL, 0, 0, NULL, 0), |
642 | SND_SOC_DAPM_PGA("Left HP Out" , HPLOUT_CTRL, 0, 0, NULL, 0), |
643 | SND_SOC_DAPM_PGA("Left HP Com" , HPLCOM_CTRL, 0, 0, NULL, 0), |
644 | |
645 | /* Right DAC to Right Outputs */ |
646 | SND_SOC_DAPM_DAC("Right DAC" , "Right Playback" , DAC_PWR, 6, 0), |
647 | SND_SOC_DAPM_MUX("Right DAC Mux" , SND_SOC_NOPM, 0, 0, |
648 | &aic3x_right_dac_mux_controls), |
649 | SND_SOC_DAPM_MUX("Right HPCOM Mux" , SND_SOC_NOPM, 0, 0, |
650 | &aic3x_right_hpcom_mux_controls), |
651 | SND_SOC_DAPM_PGA("Right Line Out" , RLOPM_CTRL, 0, 0, NULL, 0), |
652 | SND_SOC_DAPM_PGA("Right HP Out" , HPROUT_CTRL, 0, 0, NULL, 0), |
653 | SND_SOC_DAPM_PGA("Right HP Com" , HPRCOM_CTRL, 0, 0, NULL, 0), |
654 | |
655 | /* Inputs to Left ADC */ |
656 | SND_SOC_DAPM_ADC("Left ADC" , "Left Capture" , LINE1L_2_LADC_CTRL, 2, 0), |
657 | SND_SOC_DAPM_MUX("Left Line1L Mux" , SND_SOC_NOPM, 0, 0, |
658 | &aic3x_left_line1l_mux_controls), |
659 | SND_SOC_DAPM_MUX("Left Line1R Mux" , SND_SOC_NOPM, 0, 0, |
660 | &aic3x_left_line1r_mux_controls), |
661 | |
662 | /* Inputs to Right ADC */ |
663 | SND_SOC_DAPM_ADC("Right ADC" , "Right Capture" , |
664 | LINE1R_2_RADC_CTRL, 2, 0), |
665 | SND_SOC_DAPM_MUX("Right Line1L Mux" , SND_SOC_NOPM, 0, 0, |
666 | &aic3x_right_line1l_mux_controls), |
667 | SND_SOC_DAPM_MUX("Right Line1R Mux" , SND_SOC_NOPM, 0, 0, |
668 | &aic3x_right_line1r_mux_controls), |
669 | |
670 | /* Mic Bias */ |
671 | SND_SOC_DAPM_SUPPLY("Mic Bias" , MICBIAS_CTRL, 6, 0, |
672 | mic_bias_event, |
673 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
674 | |
675 | SND_SOC_DAPM_OUTPUT("LLOUT" ), |
676 | SND_SOC_DAPM_OUTPUT("RLOUT" ), |
677 | SND_SOC_DAPM_OUTPUT("HPLOUT" ), |
678 | SND_SOC_DAPM_OUTPUT("HPROUT" ), |
679 | SND_SOC_DAPM_OUTPUT("HPLCOM" ), |
680 | SND_SOC_DAPM_OUTPUT("HPRCOM" ), |
681 | |
682 | SND_SOC_DAPM_INPUT("LINE1L" ), |
683 | SND_SOC_DAPM_INPUT("LINE1R" ), |
684 | |
685 | /* |
686 | * Virtual output pin to detection block inside codec. This can be |
687 | * used to keep codec bias on if gpio or detection features are needed. |
688 | * Force pin on or construct a path with an input jack and mic bias |
689 | * widgets. |
690 | */ |
691 | SND_SOC_DAPM_OUTPUT("Detection" ), |
692 | }; |
693 | |
694 | /* For other than tlv320aic3104 */ |
695 | static const struct snd_soc_dapm_widget [] = { |
696 | /* Inputs to Left ADC */ |
697 | SND_SOC_DAPM_MIXER("Left PGA Mixer" , SND_SOC_NOPM, 0, 0, |
698 | &aic3x_left_pga_mixer_controls[0], |
699 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), |
700 | SND_SOC_DAPM_MUX("Left Line2L Mux" , SND_SOC_NOPM, 0, 0, |
701 | &aic3x_left_line2_mux_controls), |
702 | |
703 | /* Inputs to Right ADC */ |
704 | SND_SOC_DAPM_MIXER("Right PGA Mixer" , SND_SOC_NOPM, 0, 0, |
705 | &aic3x_right_pga_mixer_controls[0], |
706 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), |
707 | SND_SOC_DAPM_MUX("Right Line2R Mux" , SND_SOC_NOPM, 0, 0, |
708 | &aic3x_right_line2_mux_controls), |
709 | |
710 | /* |
711 | * Not a real mic bias widget but similar function. This is for dynamic |
712 | * control of GPIO1 digital mic modulator clock output function when |
713 | * using digital mic. |
714 | */ |
715 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "GPIO1 dmic modclk" , |
716 | AIC3X_GPIO1_REG, 4, 0xf, |
717 | AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK, |
718 | AIC3X_GPIO1_FUNC_DISABLED), |
719 | |
720 | /* |
721 | * Also similar function like mic bias. Selects digital mic with |
722 | * configurable oversampling rate instead of ADC converter. |
723 | */ |
724 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 128" , |
725 | AIC3X_ASD_INTF_CTRLA, 0, 3, 1, 0), |
726 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 64" , |
727 | AIC3X_ASD_INTF_CTRLA, 0, 3, 2, 0), |
728 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32" , |
729 | AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), |
730 | |
731 | /* Output mixers */ |
732 | SND_SOC_DAPM_MIXER("Left Line Mixer" , SND_SOC_NOPM, 0, 0, |
733 | &aic3x_left_line_mixer_controls[0], |
734 | ARRAY_SIZE(aic3x_left_line_mixer_controls)), |
735 | SND_SOC_DAPM_MIXER("Right Line Mixer" , SND_SOC_NOPM, 0, 0, |
736 | &aic3x_right_line_mixer_controls[0], |
737 | ARRAY_SIZE(aic3x_right_line_mixer_controls)), |
738 | SND_SOC_DAPM_MIXER("Left HP Mixer" , SND_SOC_NOPM, 0, 0, |
739 | &aic3x_left_hp_mixer_controls[0], |
740 | ARRAY_SIZE(aic3x_left_hp_mixer_controls)), |
741 | SND_SOC_DAPM_MIXER("Right HP Mixer" , SND_SOC_NOPM, 0, 0, |
742 | &aic3x_right_hp_mixer_controls[0], |
743 | ARRAY_SIZE(aic3x_right_hp_mixer_controls)), |
744 | SND_SOC_DAPM_MIXER("Left HPCOM Mixer" , SND_SOC_NOPM, 0, 0, |
745 | &aic3x_left_hpcom_mixer_controls[0], |
746 | ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)), |
747 | SND_SOC_DAPM_MIXER("Right HPCOM Mixer" , SND_SOC_NOPM, 0, 0, |
748 | &aic3x_right_hpcom_mixer_controls[0], |
749 | ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)), |
750 | |
751 | SND_SOC_DAPM_INPUT("MIC3L" ), |
752 | SND_SOC_DAPM_INPUT("MIC3R" ), |
753 | SND_SOC_DAPM_INPUT("LINE2L" ), |
754 | SND_SOC_DAPM_INPUT("LINE2R" ), |
755 | }; |
756 | |
757 | /* For tlv320aic3104 */ |
758 | static const struct snd_soc_dapm_widget [] = { |
759 | /* Inputs to Left ADC */ |
760 | SND_SOC_DAPM_MIXER("Left PGA Mixer" , SND_SOC_NOPM, 0, 0, |
761 | &aic3104_left_pga_mixer_controls[0], |
762 | ARRAY_SIZE(aic3104_left_pga_mixer_controls)), |
763 | |
764 | /* Inputs to Right ADC */ |
765 | SND_SOC_DAPM_MIXER("Right PGA Mixer" , SND_SOC_NOPM, 0, 0, |
766 | &aic3104_right_pga_mixer_controls[0], |
767 | ARRAY_SIZE(aic3104_right_pga_mixer_controls)), |
768 | |
769 | /* Output mixers */ |
770 | SND_SOC_DAPM_MIXER("Left Line Mixer" , SND_SOC_NOPM, 0, 0, |
771 | &aic3x_left_line_mixer_controls[0], |
772 | ARRAY_SIZE(aic3x_left_line_mixer_controls) - 2), |
773 | SND_SOC_DAPM_MIXER("Right Line Mixer" , SND_SOC_NOPM, 0, 0, |
774 | &aic3x_right_line_mixer_controls[0], |
775 | ARRAY_SIZE(aic3x_right_line_mixer_controls) - 2), |
776 | SND_SOC_DAPM_MIXER("Left HP Mixer" , SND_SOC_NOPM, 0, 0, |
777 | &aic3x_left_hp_mixer_controls[0], |
778 | ARRAY_SIZE(aic3x_left_hp_mixer_controls) - 2), |
779 | SND_SOC_DAPM_MIXER("Right HP Mixer" , SND_SOC_NOPM, 0, 0, |
780 | &aic3x_right_hp_mixer_controls[0], |
781 | ARRAY_SIZE(aic3x_right_hp_mixer_controls) - 2), |
782 | SND_SOC_DAPM_MIXER("Left HPCOM Mixer" , SND_SOC_NOPM, 0, 0, |
783 | &aic3x_left_hpcom_mixer_controls[0], |
784 | ARRAY_SIZE(aic3x_left_hpcom_mixer_controls) - 2), |
785 | SND_SOC_DAPM_MIXER("Right HPCOM Mixer" , SND_SOC_NOPM, 0, 0, |
786 | &aic3x_right_hpcom_mixer_controls[0], |
787 | ARRAY_SIZE(aic3x_right_hpcom_mixer_controls) - 2), |
788 | |
789 | SND_SOC_DAPM_INPUT("MIC2L" ), |
790 | SND_SOC_DAPM_INPUT("MIC2R" ), |
791 | }; |
792 | |
793 | static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = { |
794 | /* Mono Output */ |
795 | SND_SOC_DAPM_PGA("Mono Out" , MONOLOPM_CTRL, 0, 0, NULL, 0), |
796 | |
797 | SND_SOC_DAPM_MIXER("Mono Mixer" , SND_SOC_NOPM, 0, 0, |
798 | &aic3x_mono_mixer_controls[0], |
799 | ARRAY_SIZE(aic3x_mono_mixer_controls)), |
800 | |
801 | SND_SOC_DAPM_OUTPUT("MONO_LOUT" ), |
802 | }; |
803 | |
804 | static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { |
805 | /* Class-D outputs */ |
806 | SND_SOC_DAPM_PGA("Left Class-D Out" , CLASSD_CTRL, 3, 0, NULL, 0), |
807 | SND_SOC_DAPM_PGA("Right Class-D Out" , CLASSD_CTRL, 2, 0, NULL, 0), |
808 | |
809 | SND_SOC_DAPM_OUTPUT("SPOP" ), |
810 | SND_SOC_DAPM_OUTPUT("SPOM" ), |
811 | }; |
812 | |
813 | static const struct snd_soc_dapm_route intercon[] = { |
814 | /* Left Input */ |
815 | {"Left Line1L Mux" , "single-ended" , "LINE1L" }, |
816 | {"Left Line1L Mux" , "differential" , "LINE1L" }, |
817 | {"Left Line1R Mux" , "single-ended" , "LINE1R" }, |
818 | {"Left Line1R Mux" , "differential" , "LINE1R" }, |
819 | |
820 | {"Left PGA Mixer" , "Line1L Switch" , "Left Line1L Mux" }, |
821 | {"Left PGA Mixer" , "Line1R Switch" , "Left Line1R Mux" }, |
822 | |
823 | {"Left ADC" , NULL, "Left PGA Mixer" }, |
824 | |
825 | /* Right Input */ |
826 | {"Right Line1R Mux" , "single-ended" , "LINE1R" }, |
827 | {"Right Line1R Mux" , "differential" , "LINE1R" }, |
828 | {"Right Line1L Mux" , "single-ended" , "LINE1L" }, |
829 | {"Right Line1L Mux" , "differential" , "LINE1L" }, |
830 | |
831 | {"Right PGA Mixer" , "Line1L Switch" , "Right Line1L Mux" }, |
832 | {"Right PGA Mixer" , "Line1R Switch" , "Right Line1R Mux" }, |
833 | |
834 | {"Right ADC" , NULL, "Right PGA Mixer" }, |
835 | |
836 | /* Left DAC Output */ |
837 | {"Left DAC Mux" , "DAC_L1" , "Left DAC" }, |
838 | {"Left DAC Mux" , "DAC_L2" , "Left DAC" }, |
839 | {"Left DAC Mux" , "DAC_L3" , "Left DAC" }, |
840 | |
841 | /* Right DAC Output */ |
842 | {"Right DAC Mux" , "DAC_R1" , "Right DAC" }, |
843 | {"Right DAC Mux" , "DAC_R2" , "Right DAC" }, |
844 | {"Right DAC Mux" , "DAC_R3" , "Right DAC" }, |
845 | |
846 | /* Left Line Output */ |
847 | {"Left Line Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
848 | {"Left Line Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
849 | {"Left Line Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
850 | {"Left Line Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
851 | |
852 | {"Left Line Out" , NULL, "Left Line Mixer" }, |
853 | {"Left Line Out" , NULL, "Left DAC Mux" }, |
854 | {"LLOUT" , NULL, "Left Line Out" }, |
855 | |
856 | /* Right Line Output */ |
857 | {"Right Line Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
858 | {"Right Line Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
859 | {"Right Line Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
860 | {"Right Line Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
861 | |
862 | {"Right Line Out" , NULL, "Right Line Mixer" }, |
863 | {"Right Line Out" , NULL, "Right DAC Mux" }, |
864 | {"RLOUT" , NULL, "Right Line Out" }, |
865 | |
866 | /* Left HP Output */ |
867 | {"Left HP Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
868 | {"Left HP Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
869 | {"Left HP Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
870 | {"Left HP Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
871 | |
872 | {"Left HP Out" , NULL, "Left HP Mixer" }, |
873 | {"Left HP Out" , NULL, "Left DAC Mux" }, |
874 | {"HPLOUT" , NULL, "Left HP Out" }, |
875 | |
876 | /* Right HP Output */ |
877 | {"Right HP Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
878 | {"Right HP Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
879 | {"Right HP Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
880 | {"Right HP Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
881 | |
882 | {"Right HP Out" , NULL, "Right HP Mixer" }, |
883 | {"Right HP Out" , NULL, "Right DAC Mux" }, |
884 | {"HPROUT" , NULL, "Right HP Out" }, |
885 | |
886 | /* Left HPCOM Output */ |
887 | {"Left HPCOM Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
888 | {"Left HPCOM Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
889 | {"Left HPCOM Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
890 | {"Left HPCOM Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
891 | |
892 | {"Left HPCOM Mux" , "differential of HPLOUT" , "Left HP Mixer" }, |
893 | {"Left HPCOM Mux" , "constant VCM" , "Left HPCOM Mixer" }, |
894 | {"Left HPCOM Mux" , "single-ended" , "Left HPCOM Mixer" }, |
895 | {"Left HP Com" , NULL, "Left HPCOM Mux" }, |
896 | {"HPLCOM" , NULL, "Left HP Com" }, |
897 | |
898 | /* Right HPCOM Output */ |
899 | {"Right HPCOM Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
900 | {"Right HPCOM Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
901 | {"Right HPCOM Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
902 | {"Right HPCOM Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
903 | |
904 | {"Right HPCOM Mux" , "differential of HPROUT" , "Right HP Mixer" }, |
905 | {"Right HPCOM Mux" , "constant VCM" , "Right HPCOM Mixer" }, |
906 | {"Right HPCOM Mux" , "single-ended" , "Right HPCOM Mixer" }, |
907 | {"Right HPCOM Mux" , "differential of HPLCOM" , "Left HPCOM Mixer" }, |
908 | {"Right HPCOM Mux" , "external feedback" , "Right HPCOM Mixer" }, |
909 | {"Right HP Com" , NULL, "Right HPCOM Mux" }, |
910 | {"HPRCOM" , NULL, "Right HP Com" }, |
911 | }; |
912 | |
913 | /* For other than tlv320aic3104 */ |
914 | static const struct snd_soc_dapm_route [] = { |
915 | /* Left Input */ |
916 | {"Left Line2L Mux" , "single-ended" , "LINE2L" }, |
917 | {"Left Line2L Mux" , "differential" , "LINE2L" }, |
918 | |
919 | {"Left PGA Mixer" , "Line2L Switch" , "Left Line2L Mux" }, |
920 | {"Left PGA Mixer" , "Mic3L Switch" , "MIC3L" }, |
921 | {"Left PGA Mixer" , "Mic3R Switch" , "MIC3R" }, |
922 | |
923 | {"Left ADC" , NULL, "GPIO1 dmic modclk" }, |
924 | |
925 | /* Right Input */ |
926 | {"Right Line2R Mux" , "single-ended" , "LINE2R" }, |
927 | {"Right Line2R Mux" , "differential" , "LINE2R" }, |
928 | |
929 | {"Right PGA Mixer" , "Line2R Switch" , "Right Line2R Mux" }, |
930 | {"Right PGA Mixer" , "Mic3L Switch" , "MIC3L" }, |
931 | {"Right PGA Mixer" , "Mic3R Switch" , "MIC3R" }, |
932 | |
933 | {"Right ADC" , NULL, "GPIO1 dmic modclk" }, |
934 | |
935 | /* |
936 | * Logical path between digital mic enable and GPIO1 modulator clock |
937 | * output function |
938 | */ |
939 | {"GPIO1 dmic modclk" , NULL, "DMic Rate 128" }, |
940 | {"GPIO1 dmic modclk" , NULL, "DMic Rate 64" }, |
941 | {"GPIO1 dmic modclk" , NULL, "DMic Rate 32" }, |
942 | |
943 | /* Left Line Output */ |
944 | {"Left Line Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
945 | {"Left Line Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
946 | |
947 | /* Right Line Output */ |
948 | {"Right Line Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
949 | {"Right Line Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
950 | |
951 | /* Left HP Output */ |
952 | {"Left HP Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
953 | {"Left HP Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
954 | |
955 | /* Right HP Output */ |
956 | {"Right HP Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
957 | {"Right HP Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
958 | |
959 | /* Left HPCOM Output */ |
960 | {"Left HPCOM Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
961 | {"Left HPCOM Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
962 | |
963 | /* Right HPCOM Output */ |
964 | {"Right HPCOM Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
965 | {"Right HPCOM Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
966 | }; |
967 | |
968 | /* For tlv320aic3104 */ |
969 | static const struct snd_soc_dapm_route [] = { |
970 | /* Left Input */ |
971 | {"Left PGA Mixer" , "Mic2L Switch" , "MIC2L" }, |
972 | {"Left PGA Mixer" , "Mic2R Switch" , "MIC2R" }, |
973 | |
974 | /* Right Input */ |
975 | {"Right PGA Mixer" , "Mic2L Switch" , "MIC2L" }, |
976 | {"Right PGA Mixer" , "Mic2R Switch" , "MIC2R" }, |
977 | }; |
978 | |
979 | static const struct snd_soc_dapm_route intercon_mono[] = { |
980 | /* Mono Output */ |
981 | {"Mono Mixer" , "Line2L Bypass Switch" , "Left Line2L Mux" }, |
982 | {"Mono Mixer" , "PGAL Bypass Switch" , "Left PGA Mixer" }, |
983 | {"Mono Mixer" , "DACL1 Switch" , "Left DAC Mux" }, |
984 | {"Mono Mixer" , "Line2R Bypass Switch" , "Right Line2R Mux" }, |
985 | {"Mono Mixer" , "PGAR Bypass Switch" , "Right PGA Mixer" }, |
986 | {"Mono Mixer" , "DACR1 Switch" , "Right DAC Mux" }, |
987 | {"Mono Out" , NULL, "Mono Mixer" }, |
988 | {"MONO_LOUT" , NULL, "Mono Out" }, |
989 | }; |
990 | |
991 | static const struct snd_soc_dapm_route intercon_3007[] = { |
992 | /* Class-D outputs */ |
993 | {"Left Class-D Out" , NULL, "Left Line Out" }, |
994 | {"Right Class-D Out" , NULL, "Left Line Out" }, |
995 | {"SPOP" , NULL, "Left Class-D Out" }, |
996 | {"SPOM" , NULL, "Right Class-D Out" }, |
997 | }; |
998 | |
999 | static int aic3x_add_widgets(struct snd_soc_component *component) |
1000 | { |
1001 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1002 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
1003 | |
1004 | switch (aic3x->model) { |
1005 | case AIC3X_MODEL_3X: |
1006 | case AIC3X_MODEL_33: |
1007 | case AIC3X_MODEL_3106: |
1008 | snd_soc_dapm_new_controls(dapm, widget: aic3x_extra_dapm_widgets, |
1009 | ARRAY_SIZE(aic3x_extra_dapm_widgets)); |
1010 | snd_soc_dapm_add_routes(dapm, route: intercon_extra, |
1011 | ARRAY_SIZE(intercon_extra)); |
1012 | snd_soc_dapm_new_controls(dapm, widget: aic3x_dapm_mono_widgets, |
1013 | ARRAY_SIZE(aic3x_dapm_mono_widgets)); |
1014 | snd_soc_dapm_add_routes(dapm, route: intercon_mono, |
1015 | ARRAY_SIZE(intercon_mono)); |
1016 | break; |
1017 | case AIC3X_MODEL_3007: |
1018 | snd_soc_dapm_new_controls(dapm, widget: aic3x_extra_dapm_widgets, |
1019 | ARRAY_SIZE(aic3x_extra_dapm_widgets)); |
1020 | snd_soc_dapm_add_routes(dapm, route: intercon_extra, |
1021 | ARRAY_SIZE(intercon_extra)); |
1022 | snd_soc_dapm_new_controls(dapm, widget: aic3007_dapm_widgets, |
1023 | ARRAY_SIZE(aic3007_dapm_widgets)); |
1024 | snd_soc_dapm_add_routes(dapm, route: intercon_3007, |
1025 | ARRAY_SIZE(intercon_3007)); |
1026 | break; |
1027 | case AIC3X_MODEL_3104: |
1028 | snd_soc_dapm_new_controls(dapm, widget: aic3104_extra_dapm_widgets, |
1029 | ARRAY_SIZE(aic3104_extra_dapm_widgets)); |
1030 | snd_soc_dapm_add_routes(dapm, route: intercon_extra_3104, |
1031 | ARRAY_SIZE(intercon_extra_3104)); |
1032 | break; |
1033 | } |
1034 | |
1035 | return 0; |
1036 | } |
1037 | |
1038 | static int aic3x_hw_params(struct snd_pcm_substream *substream, |
1039 | struct snd_pcm_hw_params *params, |
1040 | struct snd_soc_dai *dai) |
1041 | { |
1042 | struct snd_soc_component *component = dai->component; |
1043 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1044 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; |
1045 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; |
1046 | u16 d, pll_d = 1; |
1047 | int clk; |
1048 | int width = aic3x->slot_width; |
1049 | |
1050 | if (!width) |
1051 | width = params_width(p: params); |
1052 | |
1053 | /* select data word length */ |
1054 | data = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); |
1055 | switch (width) { |
1056 | case 16: |
1057 | break; |
1058 | case 20: |
1059 | data |= (0x01 << 4); |
1060 | break; |
1061 | case 24: |
1062 | data |= (0x02 << 4); |
1063 | break; |
1064 | case 32: |
1065 | data |= (0x03 << 4); |
1066 | break; |
1067 | } |
1068 | snd_soc_component_write(component, AIC3X_ASD_INTF_CTRLB, val: data); |
1069 | |
1070 | /* Fsref can be 44100 or 48000 */ |
1071 | fsref = (params_rate(p: params) % 11025 == 0) ? 44100 : 48000; |
1072 | |
1073 | /* Try to find a value for Q which allows us to bypass the PLL and |
1074 | * generate CODEC_CLK directly. */ |
1075 | for (pll_q = 2; pll_q < 18; pll_q++) |
1076 | if (aic3x->sysclk / (128 * pll_q) == fsref) { |
1077 | bypass_pll = 1; |
1078 | break; |
1079 | } |
1080 | |
1081 | if (bypass_pll) { |
1082 | pll_q &= 0xf; |
1083 | snd_soc_component_write(component, AIC3X_PLL_PROGA_REG, val: pll_q << PLLQ_SHIFT); |
1084 | snd_soc_component_write(component, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); |
1085 | /* disable PLL if it is bypassed */ |
1086 | snd_soc_component_update_bits(component, AIC3X_PLL_PROGA_REG, PLL_ENABLE, val: 0); |
1087 | |
1088 | } else { |
1089 | snd_soc_component_write(component, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); |
1090 | /* enable PLL when it is used */ |
1091 | snd_soc_component_update_bits(component, AIC3X_PLL_PROGA_REG, |
1092 | PLL_ENABLE, PLL_ENABLE); |
1093 | } |
1094 | |
1095 | /* Route Left DAC to left channel input and |
1096 | * right DAC to right channel input */ |
1097 | data = (LDAC2LCH | RDAC2RCH); |
1098 | data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000; |
1099 | if (params_rate(p: params) >= 64000) |
1100 | data |= DUAL_RATE_MODE; |
1101 | snd_soc_component_write(component, AIC3X_CODEC_DATAPATH_REG, val: data); |
1102 | |
1103 | /* codec sample rate select */ |
1104 | data = (fsref * 20) / params_rate(p: params); |
1105 | if (params_rate(p: params) < 64000) |
1106 | data /= 2; |
1107 | data /= 5; |
1108 | data -= 2; |
1109 | data |= (data << 4); |
1110 | snd_soc_component_write(component, AIC3X_SAMPLE_RATE_SEL_REG, val: data); |
1111 | |
1112 | if (bypass_pll) |
1113 | return 0; |
1114 | |
1115 | /* Use PLL, compute appropriate setup for j, d, r and p, the closest |
1116 | * one wins the game. Try with d==0 first, next with d!=0. |
1117 | * Constraints for j are according to the datasheet. |
1118 | * The sysclk is divided by 1000 to prevent integer overflows. |
1119 | */ |
1120 | |
1121 | codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000); |
1122 | |
1123 | for (r = 1; r <= 16; r++) |
1124 | for (p = 1; p <= 8; p++) { |
1125 | for (j = 4; j <= 55; j++) { |
1126 | /* This is actually 1000*((j+(d/10000))*r)/p |
1127 | * The term had to be converted to get |
1128 | * rid of the division by 10000; d = 0 here |
1129 | */ |
1130 | int tmp_clk = (1000 * j * r) / p; |
1131 | |
1132 | /* Check whether this values get closer than |
1133 | * the best ones we had before |
1134 | */ |
1135 | if (abs(codec_clk - tmp_clk) < |
1136 | abs(codec_clk - last_clk)) { |
1137 | pll_j = j; pll_d = 0; |
1138 | pll_r = r; pll_p = p; |
1139 | last_clk = tmp_clk; |
1140 | } |
1141 | |
1142 | /* Early exit for exact matches */ |
1143 | if (tmp_clk == codec_clk) |
1144 | goto found; |
1145 | } |
1146 | } |
1147 | |
1148 | /* try with d != 0 */ |
1149 | for (p = 1; p <= 8; p++) { |
1150 | j = codec_clk * p / 1000; |
1151 | |
1152 | if (j < 4 || j > 11) |
1153 | continue; |
1154 | |
1155 | /* do not use codec_clk here since we'd loose precision */ |
1156 | d = ((2048 * p * fsref) - j * aic3x->sysclk) |
1157 | * 100 / (aic3x->sysclk/100); |
1158 | |
1159 | clk = (10000 * j + d) / (10 * p); |
1160 | |
1161 | /* check whether this values get closer than the best |
1162 | * ones we had before */ |
1163 | if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) { |
1164 | pll_j = j; pll_d = d; pll_r = 1; pll_p = p; |
1165 | last_clk = clk; |
1166 | } |
1167 | |
1168 | /* Early exit for exact matches */ |
1169 | if (clk == codec_clk) |
1170 | goto found; |
1171 | } |
1172 | |
1173 | if (last_clk == 0) { |
1174 | printk(KERN_ERR "%s(): unable to setup PLL\n" , __func__); |
1175 | return -EINVAL; |
1176 | } |
1177 | |
1178 | found: |
1179 | snd_soc_component_update_bits(component, AIC3X_PLL_PROGA_REG, PLLP_MASK, val: pll_p); |
1180 | snd_soc_component_write(component, AIC3X_OVRF_STATUS_AND_PLLR_REG, |
1181 | val: pll_r << PLLR_SHIFT); |
1182 | snd_soc_component_write(component, AIC3X_PLL_PROGB_REG, val: pll_j << PLLJ_SHIFT); |
1183 | snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, |
1184 | val: (pll_d >> 6) << PLLD_MSB_SHIFT); |
1185 | snd_soc_component_write(component, AIC3X_PLL_PROGD_REG, |
1186 | val: (pll_d & 0x3F) << PLLD_LSB_SHIFT); |
1187 | |
1188 | return 0; |
1189 | } |
1190 | |
1191 | static int aic3x_prepare(struct snd_pcm_substream *substream, |
1192 | struct snd_soc_dai *dai) |
1193 | { |
1194 | struct snd_soc_component *component = dai->component; |
1195 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1196 | int delay = 0; |
1197 | int width = aic3x->slot_width; |
1198 | |
1199 | if (!width) |
1200 | width = substream->runtime->sample_bits; |
1201 | |
1202 | /* TDM slot selection only valid in DSP_A/_B mode */ |
1203 | if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_A) |
1204 | delay += (aic3x->tdm_delay*width + 1); |
1205 | else if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_B) |
1206 | delay += aic3x->tdm_delay*width; |
1207 | |
1208 | /* Configure data delay */ |
1209 | snd_soc_component_write(component, AIC3X_ASD_INTF_CTRLC, val: delay); |
1210 | |
1211 | return 0; |
1212 | } |
1213 | |
1214 | static int aic3x_mute(struct snd_soc_dai *dai, int mute, int direction) |
1215 | { |
1216 | struct snd_soc_component *component = dai->component; |
1217 | u8 ldac_reg = snd_soc_component_read(component, LDAC_VOL) & ~MUTE_ON; |
1218 | u8 rdac_reg = snd_soc_component_read(component, RDAC_VOL) & ~MUTE_ON; |
1219 | |
1220 | if (mute) { |
1221 | snd_soc_component_write(component, LDAC_VOL, val: ldac_reg | MUTE_ON); |
1222 | snd_soc_component_write(component, RDAC_VOL, val: rdac_reg | MUTE_ON); |
1223 | } else { |
1224 | snd_soc_component_write(component, LDAC_VOL, val: ldac_reg); |
1225 | snd_soc_component_write(component, RDAC_VOL, val: rdac_reg); |
1226 | } |
1227 | |
1228 | return 0; |
1229 | } |
1230 | |
1231 | static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
1232 | int clk_id, unsigned int freq, int dir) |
1233 | { |
1234 | struct snd_soc_component *component = codec_dai->component; |
1235 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1236 | |
1237 | /* set clock on MCLK or GPIO2 or BCLK */ |
1238 | snd_soc_component_update_bits(component, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK, |
1239 | val: clk_id << PLLCLK_IN_SHIFT); |
1240 | snd_soc_component_update_bits(component, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK, |
1241 | val: clk_id << CLKDIV_IN_SHIFT); |
1242 | |
1243 | aic3x->sysclk = freq; |
1244 | return 0; |
1245 | } |
1246 | |
1247 | static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, |
1248 | unsigned int fmt) |
1249 | { |
1250 | struct snd_soc_component *component = codec_dai->component; |
1251 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1252 | u8 iface_areg, iface_breg; |
1253 | |
1254 | iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; |
1255 | iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; |
1256 | |
1257 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
1258 | case SND_SOC_DAIFMT_CBP_CFP: |
1259 | aic3x->master = 1; |
1260 | iface_areg |= BIT_CLK_MASTER | WORD_CLK_MASTER; |
1261 | break; |
1262 | case SND_SOC_DAIFMT_CBC_CFC: |
1263 | aic3x->master = 0; |
1264 | iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); |
1265 | break; |
1266 | case SND_SOC_DAIFMT_CBP_CFC: |
1267 | aic3x->master = 1; |
1268 | iface_areg |= BIT_CLK_MASTER; |
1269 | iface_areg &= ~WORD_CLK_MASTER; |
1270 | break; |
1271 | case SND_SOC_DAIFMT_CBC_CFP: |
1272 | aic3x->master = 1; |
1273 | iface_areg |= WORD_CLK_MASTER; |
1274 | iface_areg &= ~BIT_CLK_MASTER; |
1275 | break; |
1276 | default: |
1277 | return -EINVAL; |
1278 | } |
1279 | |
1280 | /* |
1281 | * match both interface format and signal polarities since they |
1282 | * are fixed |
1283 | */ |
1284 | switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | |
1285 | SND_SOC_DAIFMT_INV_MASK)) { |
1286 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): |
1287 | break; |
1288 | case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): |
1289 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): |
1290 | iface_breg |= (0x01 << 6); |
1291 | break; |
1292 | case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF): |
1293 | iface_breg |= (0x02 << 6); |
1294 | break; |
1295 | case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): |
1296 | iface_breg |= (0x03 << 6); |
1297 | break; |
1298 | default: |
1299 | return -EINVAL; |
1300 | } |
1301 | |
1302 | aic3x->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
1303 | |
1304 | /* set iface */ |
1305 | snd_soc_component_write(component, AIC3X_ASD_INTF_CTRLA, val: iface_areg); |
1306 | snd_soc_component_write(component, AIC3X_ASD_INTF_CTRLB, val: iface_breg); |
1307 | |
1308 | return 0; |
1309 | } |
1310 | |
1311 | static int aic3x_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, |
1312 | unsigned int tx_mask, unsigned int rx_mask, |
1313 | int slots, int slot_width) |
1314 | { |
1315 | struct snd_soc_component *component = codec_dai->component; |
1316 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1317 | unsigned int lsb; |
1318 | |
1319 | if (tx_mask != rx_mask) { |
1320 | dev_err(component->dev, "tx and rx masks must be symmetric\n" ); |
1321 | return -EINVAL; |
1322 | } |
1323 | |
1324 | if (unlikely(!tx_mask)) { |
1325 | dev_err(component->dev, "tx and rx masks need to be non 0\n" ); |
1326 | return -EINVAL; |
1327 | } |
1328 | |
1329 | /* TDM based on DSP mode requires slots to be adjacent */ |
1330 | lsb = __ffs(tx_mask); |
1331 | if ((lsb + 1) != __fls(word: tx_mask)) { |
1332 | dev_err(component->dev, "Invalid mask, slots must be adjacent\n" ); |
1333 | return -EINVAL; |
1334 | } |
1335 | |
1336 | switch (slot_width) { |
1337 | case 16: |
1338 | case 20: |
1339 | case 24: |
1340 | case 32: |
1341 | break; |
1342 | default: |
1343 | dev_err(component->dev, "Unsupported slot width %d\n" , slot_width); |
1344 | return -EINVAL; |
1345 | } |
1346 | |
1347 | |
1348 | aic3x->tdm_delay = lsb; |
1349 | aic3x->slot_width = slot_width; |
1350 | |
1351 | /* DOUT in high-impedance on inactive bit clocks */ |
1352 | snd_soc_component_update_bits(component, AIC3X_ASD_INTF_CTRLA, |
1353 | DOUT_TRISTATE, DOUT_TRISTATE); |
1354 | |
1355 | return 0; |
1356 | } |
1357 | |
1358 | static int aic3x_regulator_event(struct notifier_block *nb, |
1359 | unsigned long event, void *data) |
1360 | { |
1361 | struct aic3x_disable_nb *disable_nb = |
1362 | container_of(nb, struct aic3x_disable_nb, nb); |
1363 | struct aic3x_priv *aic3x = disable_nb->aic3x; |
1364 | |
1365 | if (event & REGULATOR_EVENT_DISABLE) { |
1366 | /* |
1367 | * Put codec to reset and require cache sync as at least one |
1368 | * of the supplies was disabled |
1369 | */ |
1370 | if (aic3x->gpio_reset) |
1371 | gpiod_set_value(desc: aic3x->gpio_reset, value: 1); |
1372 | regcache_mark_dirty(map: aic3x->regmap); |
1373 | } |
1374 | |
1375 | return 0; |
1376 | } |
1377 | |
1378 | static int aic3x_set_power(struct snd_soc_component *component, int power) |
1379 | { |
1380 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1381 | unsigned int pll_c, pll_d; |
1382 | int ret; |
1383 | |
1384 | if (power) { |
1385 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), |
1386 | consumers: aic3x->supplies); |
1387 | if (ret) |
1388 | goto out; |
1389 | aic3x->power = 1; |
1390 | |
1391 | if (aic3x->gpio_reset) { |
1392 | udelay(1); |
1393 | gpiod_set_value(desc: aic3x->gpio_reset, value: 0); |
1394 | } |
1395 | |
1396 | /* Sync reg_cache with the hardware */ |
1397 | regcache_cache_only(map: aic3x->regmap, enable: false); |
1398 | regcache_sync(map: aic3x->regmap); |
1399 | |
1400 | /* Rewrite paired PLL D registers in case cached sync skipped |
1401 | * writing one of them and thus caused other one also not |
1402 | * being written |
1403 | */ |
1404 | pll_c = snd_soc_component_read(component, AIC3X_PLL_PROGC_REG); |
1405 | pll_d = snd_soc_component_read(component, AIC3X_PLL_PROGD_REG); |
1406 | if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || |
1407 | pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { |
1408 | snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, val: pll_c); |
1409 | snd_soc_component_write(component, AIC3X_PLL_PROGD_REG, val: pll_d); |
1410 | } |
1411 | |
1412 | /* |
1413 | * Delay is needed to reduce pop-noise after syncing back the |
1414 | * registers |
1415 | */ |
1416 | mdelay(50); |
1417 | } else { |
1418 | /* |
1419 | * Do soft reset to this codec instance in order to clear |
1420 | * possible VDD leakage currents in case the supply regulators |
1421 | * remain on |
1422 | */ |
1423 | snd_soc_component_write(component, AIC3X_RESET, SOFT_RESET); |
1424 | regcache_mark_dirty(map: aic3x->regmap); |
1425 | aic3x->power = 0; |
1426 | /* HW writes are needless when bias is off */ |
1427 | regcache_cache_only(map: aic3x->regmap, enable: true); |
1428 | ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), |
1429 | consumers: aic3x->supplies); |
1430 | } |
1431 | out: |
1432 | return ret; |
1433 | } |
1434 | |
1435 | static int aic3x_set_bias_level(struct snd_soc_component *component, |
1436 | enum snd_soc_bias_level level) |
1437 | { |
1438 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1439 | |
1440 | switch (level) { |
1441 | case SND_SOC_BIAS_ON: |
1442 | break; |
1443 | case SND_SOC_BIAS_PREPARE: |
1444 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY && |
1445 | aic3x->master) { |
1446 | /* enable pll */ |
1447 | snd_soc_component_update_bits(component, AIC3X_PLL_PROGA_REG, |
1448 | PLL_ENABLE, PLL_ENABLE); |
1449 | } |
1450 | break; |
1451 | case SND_SOC_BIAS_STANDBY: |
1452 | if (!aic3x->power) |
1453 | aic3x_set_power(component, power: 1); |
1454 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE && |
1455 | aic3x->master) { |
1456 | /* disable pll */ |
1457 | snd_soc_component_update_bits(component, AIC3X_PLL_PROGA_REG, |
1458 | PLL_ENABLE, val: 0); |
1459 | } |
1460 | break; |
1461 | case SND_SOC_BIAS_OFF: |
1462 | if (aic3x->power) |
1463 | aic3x_set_power(component, power: 0); |
1464 | break; |
1465 | } |
1466 | |
1467 | return 0; |
1468 | } |
1469 | |
1470 | #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 |
1471 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1472 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
1473 | SNDRV_PCM_FMTBIT_S32_LE) |
1474 | |
1475 | static const struct snd_soc_dai_ops aic3x_dai_ops = { |
1476 | .hw_params = aic3x_hw_params, |
1477 | .prepare = aic3x_prepare, |
1478 | .mute_stream = aic3x_mute, |
1479 | .set_sysclk = aic3x_set_dai_sysclk, |
1480 | .set_fmt = aic3x_set_dai_fmt, |
1481 | .set_tdm_slot = aic3x_set_dai_tdm_slot, |
1482 | .no_capture_mute = 1, |
1483 | }; |
1484 | |
1485 | static struct snd_soc_dai_driver aic3x_dai = { |
1486 | .name = "tlv320aic3x-hifi" , |
1487 | .playback = { |
1488 | .stream_name = "Playback" , |
1489 | .channels_min = 2, |
1490 | .channels_max = 2, |
1491 | .rates = AIC3X_RATES, |
1492 | .formats = AIC3X_FORMATS,}, |
1493 | .capture = { |
1494 | .stream_name = "Capture" , |
1495 | .channels_min = 2, |
1496 | .channels_max = 2, |
1497 | .rates = AIC3X_RATES, |
1498 | .formats = AIC3X_FORMATS,}, |
1499 | .ops = &aic3x_dai_ops, |
1500 | .symmetric_rate = 1, |
1501 | }; |
1502 | |
1503 | static void aic3x_mono_init(struct snd_soc_component *component) |
1504 | { |
1505 | /* DAC to Mono Line Out default volume and route to Output mixer */ |
1506 | snd_soc_component_write(component, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1507 | snd_soc_component_write(component, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1508 | |
1509 | /* unmute all outputs */ |
1510 | snd_soc_component_update_bits(component, MONOLOPM_CTRL, UNMUTE, UNMUTE); |
1511 | |
1512 | /* PGA to Mono Line Out default volume, disconnect from Output Mixer */ |
1513 | snd_soc_component_write(component, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL); |
1514 | snd_soc_component_write(component, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL); |
1515 | |
1516 | /* Line2 to Mono Out default volume, disconnect from Output Mixer */ |
1517 | snd_soc_component_write(component, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); |
1518 | snd_soc_component_write(component, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); |
1519 | } |
1520 | |
1521 | /* |
1522 | * initialise the AIC3X driver |
1523 | * register the mixer and dsp interfaces with the kernel |
1524 | */ |
1525 | static int aic3x_init(struct snd_soc_component *component) |
1526 | { |
1527 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1528 | |
1529 | snd_soc_component_write(component, AIC3X_PAGE_SELECT, PAGE0_SELECT); |
1530 | snd_soc_component_write(component, AIC3X_RESET, SOFT_RESET); |
1531 | |
1532 | /* DAC default volume and mute */ |
1533 | snd_soc_component_write(component, LDAC_VOL, DEFAULT_VOL | MUTE_ON); |
1534 | snd_soc_component_write(component, RDAC_VOL, DEFAULT_VOL | MUTE_ON); |
1535 | |
1536 | /* DAC to HP default volume and route to Output mixer */ |
1537 | snd_soc_component_write(component, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON); |
1538 | snd_soc_component_write(component, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON); |
1539 | snd_soc_component_write(component, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON); |
1540 | snd_soc_component_write(component, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON); |
1541 | /* DAC to Line Out default volume and route to Output mixer */ |
1542 | snd_soc_component_write(component, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1543 | snd_soc_component_write(component, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1544 | |
1545 | /* unmute all outputs */ |
1546 | snd_soc_component_update_bits(component, LLOPM_CTRL, UNMUTE, UNMUTE); |
1547 | snd_soc_component_update_bits(component, RLOPM_CTRL, UNMUTE, UNMUTE); |
1548 | snd_soc_component_update_bits(component, HPLOUT_CTRL, UNMUTE, UNMUTE); |
1549 | snd_soc_component_update_bits(component, HPROUT_CTRL, UNMUTE, UNMUTE); |
1550 | snd_soc_component_update_bits(component, HPLCOM_CTRL, UNMUTE, UNMUTE); |
1551 | snd_soc_component_update_bits(component, HPRCOM_CTRL, UNMUTE, UNMUTE); |
1552 | |
1553 | /* ADC default volume and unmute */ |
1554 | snd_soc_component_write(component, LADC_VOL, DEFAULT_GAIN); |
1555 | snd_soc_component_write(component, RADC_VOL, DEFAULT_GAIN); |
1556 | /* By default route Line1 to ADC PGA mixer */ |
1557 | snd_soc_component_write(component, LINE1L_2_LADC_CTRL, val: 0x0); |
1558 | snd_soc_component_write(component, LINE1R_2_RADC_CTRL, val: 0x0); |
1559 | |
1560 | /* PGA to HP Bypass default volume, disconnect from Output Mixer */ |
1561 | snd_soc_component_write(component, PGAL_2_HPLOUT_VOL, DEFAULT_VOL); |
1562 | snd_soc_component_write(component, PGAR_2_HPROUT_VOL, DEFAULT_VOL); |
1563 | snd_soc_component_write(component, PGAL_2_HPLCOM_VOL, DEFAULT_VOL); |
1564 | snd_soc_component_write(component, PGAR_2_HPRCOM_VOL, DEFAULT_VOL); |
1565 | /* PGA to Line Out default volume, disconnect from Output Mixer */ |
1566 | snd_soc_component_write(component, PGAL_2_LLOPM_VOL, DEFAULT_VOL); |
1567 | snd_soc_component_write(component, PGAR_2_RLOPM_VOL, DEFAULT_VOL); |
1568 | |
1569 | /* On tlv320aic3104, these registers are reserved and must not be written */ |
1570 | if (aic3x->model != AIC3X_MODEL_3104) { |
1571 | /* Line2 to HP Bypass default volume, disconnect from Output Mixer */ |
1572 | snd_soc_component_write(component, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL); |
1573 | snd_soc_component_write(component, LINE2R_2_HPROUT_VOL, DEFAULT_VOL); |
1574 | snd_soc_component_write(component, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL); |
1575 | snd_soc_component_write(component, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL); |
1576 | /* Line2 Line Out default volume, disconnect from Output Mixer */ |
1577 | snd_soc_component_write(component, LINE2L_2_LLOPM_VOL, DEFAULT_VOL); |
1578 | snd_soc_component_write(component, LINE2R_2_RLOPM_VOL, DEFAULT_VOL); |
1579 | } |
1580 | |
1581 | switch (aic3x->model) { |
1582 | case AIC3X_MODEL_3X: |
1583 | case AIC3X_MODEL_33: |
1584 | case AIC3X_MODEL_3106: |
1585 | aic3x_mono_init(component); |
1586 | break; |
1587 | case AIC3X_MODEL_3007: |
1588 | snd_soc_component_write(component, CLASSD_CTRL, val: 0); |
1589 | break; |
1590 | } |
1591 | |
1592 | /* Output common-mode voltage = 1.5 V */ |
1593 | snd_soc_component_update_bits(component, HPOUT_SC, HPOUT_SC_OCMV_MASK, |
1594 | val: aic3x->ocmv << HPOUT_SC_OCMV_SHIFT); |
1595 | |
1596 | return 0; |
1597 | } |
1598 | |
1599 | static int aic3x_component_probe(struct snd_soc_component *component) |
1600 | { |
1601 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(c: component); |
1602 | int ret, i; |
1603 | |
1604 | aic3x->component = component; |
1605 | |
1606 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { |
1607 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; |
1608 | aic3x->disable_nb[i].aic3x = aic3x; |
1609 | ret = devm_regulator_register_notifier( |
1610 | regulator: aic3x->supplies[i].consumer, |
1611 | nb: &aic3x->disable_nb[i].nb); |
1612 | if (ret) { |
1613 | dev_err(component->dev, |
1614 | "Failed to request regulator notifier: %d\n" , |
1615 | ret); |
1616 | return ret; |
1617 | } |
1618 | } |
1619 | |
1620 | regcache_mark_dirty(map: aic3x->regmap); |
1621 | aic3x_init(component); |
1622 | |
1623 | if (aic3x->setup) { |
1624 | if (aic3x->model != AIC3X_MODEL_3104) { |
1625 | /* setup GPIO functions */ |
1626 | snd_soc_component_write(component, AIC3X_GPIO1_REG, |
1627 | val: (aic3x->setup->gpio_func[0] & 0xf) << 4); |
1628 | snd_soc_component_write(component, AIC3X_GPIO2_REG, |
1629 | val: (aic3x->setup->gpio_func[1] & 0xf) << 4); |
1630 | } else { |
1631 | dev_warn(component->dev, "GPIO functionality is not supported on tlv320aic3104\n" ); |
1632 | } |
1633 | } |
1634 | |
1635 | switch (aic3x->model) { |
1636 | case AIC3X_MODEL_3X: |
1637 | case AIC3X_MODEL_33: |
1638 | case AIC3X_MODEL_3106: |
1639 | snd_soc_add_component_controls(component, controls: aic3x_extra_snd_controls, |
1640 | ARRAY_SIZE(aic3x_extra_snd_controls)); |
1641 | snd_soc_add_component_controls(component, controls: aic3x_mono_controls, |
1642 | ARRAY_SIZE(aic3x_mono_controls)); |
1643 | break; |
1644 | case AIC3X_MODEL_3007: |
1645 | snd_soc_add_component_controls(component, controls: aic3x_extra_snd_controls, |
1646 | ARRAY_SIZE(aic3x_extra_snd_controls)); |
1647 | snd_soc_add_component_controls(component, |
1648 | controls: &aic3x_classd_amp_gain_ctrl, num_controls: 1); |
1649 | break; |
1650 | case AIC3X_MODEL_3104: |
1651 | break; |
1652 | } |
1653 | |
1654 | /* set mic bias voltage */ |
1655 | switch (aic3x->micbias_vg) { |
1656 | case AIC3X_MICBIAS_2_0V: |
1657 | case AIC3X_MICBIAS_2_5V: |
1658 | case AIC3X_MICBIAS_AVDDV: |
1659 | snd_soc_component_update_bits(component, MICBIAS_CTRL, |
1660 | MICBIAS_LEVEL_MASK, |
1661 | val: (aic3x->micbias_vg) << MICBIAS_LEVEL_SHIFT); |
1662 | break; |
1663 | case AIC3X_MICBIAS_OFF: |
1664 | /* |
1665 | * noting to do. target won't enter here. This is just to avoid |
1666 | * compile time warning "warning: enumeration value |
1667 | * 'AIC3X_MICBIAS_OFF' not handled in switch" |
1668 | */ |
1669 | break; |
1670 | } |
1671 | |
1672 | aic3x_add_widgets(component); |
1673 | |
1674 | return 0; |
1675 | } |
1676 | |
1677 | static const struct snd_soc_component_driver soc_component_dev_aic3x = { |
1678 | .set_bias_level = aic3x_set_bias_level, |
1679 | .probe = aic3x_component_probe, |
1680 | .controls = aic3x_snd_controls, |
1681 | .num_controls = ARRAY_SIZE(aic3x_snd_controls), |
1682 | .dapm_widgets = aic3x_dapm_widgets, |
1683 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), |
1684 | .dapm_routes = intercon, |
1685 | .num_dapm_routes = ARRAY_SIZE(intercon), |
1686 | .use_pmdown_time = 1, |
1687 | .endianness = 1, |
1688 | }; |
1689 | |
1690 | static void aic3x_configure_ocmv(struct device *dev, struct aic3x_priv *aic3x) |
1691 | { |
1692 | struct device_node *np = dev->of_node; |
1693 | u32 value; |
1694 | int dvdd, avdd; |
1695 | |
1696 | if (np && !of_property_read_u32(np, propname: "ai3x-ocmv" , out_value: &value)) { |
1697 | /* OCMV setting is forced by DT */ |
1698 | if (value <= 3) { |
1699 | aic3x->ocmv = value; |
1700 | return; |
1701 | } |
1702 | } |
1703 | |
1704 | dvdd = regulator_get_voltage(regulator: aic3x->supplies[1].consumer); |
1705 | avdd = regulator_get_voltage(regulator: aic3x->supplies[2].consumer); |
1706 | |
1707 | if (avdd > 3600000 || dvdd > 1950000) { |
1708 | dev_warn(dev, |
1709 | "Too high supply voltage(s) AVDD: %d, DVDD: %d\n" , |
1710 | avdd, dvdd); |
1711 | } else if (avdd == 3600000 && dvdd == 1950000) { |
1712 | aic3x->ocmv = HPOUT_SC_OCMV_1_8V; |
1713 | } else if (avdd > 3300000 && dvdd > 1800000) { |
1714 | aic3x->ocmv = HPOUT_SC_OCMV_1_65V; |
1715 | } else if (avdd > 3000000 && dvdd > 1650000) { |
1716 | aic3x->ocmv = HPOUT_SC_OCMV_1_5V; |
1717 | } else if (avdd >= 2700000 && dvdd >= 1525000) { |
1718 | aic3x->ocmv = HPOUT_SC_OCMV_1_35V; |
1719 | } else { |
1720 | dev_warn(dev, |
1721 | "Invalid supply voltage(s) AVDD: %d, DVDD: %d\n" , |
1722 | avdd, dvdd); |
1723 | } |
1724 | } |
1725 | |
1726 | |
1727 | static const struct reg_sequence aic3007_class_d[] = { |
1728 | /* Class-D speaker driver init; datasheet p. 46 */ |
1729 | { AIC3X_PAGE_SELECT, 0x0D }, |
1730 | { 0xD, 0x0D }, |
1731 | { 0x8, 0x5C }, |
1732 | { 0x8, 0x5D }, |
1733 | { 0x8, 0x5C }, |
1734 | { AIC3X_PAGE_SELECT, 0x00 }, |
1735 | }; |
1736 | |
1737 | int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data) |
1738 | { |
1739 | struct aic3x_priv *aic3x; |
1740 | struct aic3x_setup_data *ai3x_setup; |
1741 | struct device_node *np = dev->of_node; |
1742 | int ret, i; |
1743 | u32 value; |
1744 | |
1745 | aic3x = devm_kzalloc(dev, size: sizeof(struct aic3x_priv), GFP_KERNEL); |
1746 | if (!aic3x) |
1747 | return -ENOMEM; |
1748 | |
1749 | aic3x->regmap = regmap; |
1750 | if (IS_ERR(ptr: aic3x->regmap)) { |
1751 | ret = PTR_ERR(ptr: aic3x->regmap); |
1752 | return ret; |
1753 | } |
1754 | |
1755 | regcache_cache_only(map: aic3x->regmap, enable: true); |
1756 | |
1757 | dev_set_drvdata(dev, data: aic3x); |
1758 | if (np) { |
1759 | ai3x_setup = devm_kzalloc(dev, size: sizeof(*ai3x_setup), GFP_KERNEL); |
1760 | if (!ai3x_setup) |
1761 | return -ENOMEM; |
1762 | |
1763 | if (of_property_read_u32_array(np, propname: "ai3x-gpio-func" , |
1764 | out_values: ai3x_setup->gpio_func, sz: 2) >= 0) { |
1765 | aic3x->setup = ai3x_setup; |
1766 | } |
1767 | |
1768 | if (!of_property_read_u32(np, propname: "ai3x-micbias-vg" , out_value: &value)) { |
1769 | switch (value) { |
1770 | case 1 : |
1771 | aic3x->micbias_vg = AIC3X_MICBIAS_2_0V; |
1772 | break; |
1773 | case 2 : |
1774 | aic3x->micbias_vg = AIC3X_MICBIAS_2_5V; |
1775 | break; |
1776 | case 3 : |
1777 | aic3x->micbias_vg = AIC3X_MICBIAS_AVDDV; |
1778 | break; |
1779 | default : |
1780 | aic3x->micbias_vg = AIC3X_MICBIAS_OFF; |
1781 | dev_err(dev, "Unsuitable MicBias voltage " |
1782 | "found in DT\n" ); |
1783 | } |
1784 | } else { |
1785 | aic3x->micbias_vg = AIC3X_MICBIAS_OFF; |
1786 | } |
1787 | } |
1788 | |
1789 | aic3x->model = driver_data; |
1790 | |
1791 | aic3x->gpio_reset = devm_gpiod_get_optional(dev, con_id: "reset" , |
1792 | flags: GPIOD_OUT_HIGH); |
1793 | ret = PTR_ERR_OR_ZERO(ptr: aic3x->gpio_reset); |
1794 | if (ret) { |
1795 | if (ret != -EBUSY) |
1796 | return ret; |
1797 | |
1798 | /* |
1799 | * Apparently there are setups where the codec is sharing |
1800 | * its reset line. Try to get it non-exclusively, although |
1801 | * the utility of this is unclear: how do we make sure that |
1802 | * resetting one chip will not disturb the others that share |
1803 | * the same line? |
1804 | */ |
1805 | aic3x->gpio_reset = devm_gpiod_get(dev, con_id: "reset" , |
1806 | flags: GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE); |
1807 | ret = PTR_ERR_OR_ZERO(ptr: aic3x->gpio_reset); |
1808 | if (ret) |
1809 | return ret; |
1810 | |
1811 | aic3x->shared_reset = true; |
1812 | } |
1813 | |
1814 | gpiod_set_consumer_name(desc: aic3x->gpio_reset, name: "tlv320aic3x reset" ); |
1815 | |
1816 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1817 | aic3x->supplies[i].supply = aic3x_supply_names[i]; |
1818 | |
1819 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(aic3x->supplies), |
1820 | consumers: aic3x->supplies); |
1821 | if (ret) { |
1822 | dev_err(dev, "Failed to request supplies: %d\n" , ret); |
1823 | return ret; |
1824 | } |
1825 | |
1826 | aic3x_configure_ocmv(dev, aic3x); |
1827 | |
1828 | if (aic3x->model == AIC3X_MODEL_3007) { |
1829 | ret = regmap_register_patch(map: aic3x->regmap, regs: aic3007_class_d, |
1830 | ARRAY_SIZE(aic3007_class_d)); |
1831 | if (ret != 0) |
1832 | dev_err(dev, "Failed to init class D: %d\n" , ret); |
1833 | } |
1834 | |
1835 | ret = devm_snd_soc_register_component(dev, component_driver: &soc_component_dev_aic3x, dai_drv: &aic3x_dai, num_dai: 1); |
1836 | if (ret) |
1837 | return ret; |
1838 | |
1839 | return 0; |
1840 | } |
1841 | EXPORT_SYMBOL(aic3x_probe); |
1842 | |
1843 | void aic3x_remove(struct device *dev) |
1844 | { |
1845 | struct aic3x_priv *aic3x = dev_get_drvdata(dev); |
1846 | |
1847 | /* Leave the codec in reset state */ |
1848 | if (aic3x->gpio_reset && !aic3x->shared_reset) |
1849 | gpiod_set_value(desc: aic3x->gpio_reset, value: 1); |
1850 | } |
1851 | EXPORT_SYMBOL(aic3x_remove); |
1852 | |
1853 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver" ); |
1854 | MODULE_AUTHOR("Vladimir Barinov" ); |
1855 | MODULE_LICENSE("GPL" ); |
1856 | |