1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * wm8994.c -- WM8994 ALSA SoC Audio driver |
4 | * |
5 | * Copyright 2009-12 Wolfson Microelectronics plc |
6 | * |
7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
8 | */ |
9 | |
10 | #include <linux/module.h> |
11 | #include <linux/moduleparam.h> |
12 | #include <linux/init.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/pm.h> |
15 | #include <linux/gcd.h> |
16 | #include <linux/i2c.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regulator/consumer.h> |
20 | #include <linux/slab.h> |
21 | #include <sound/core.h> |
22 | #include <sound/jack.h> |
23 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> |
25 | #include <sound/soc.h> |
26 | #include <sound/initval.h> |
27 | #include <sound/tlv.h> |
28 | #include <trace/events/asoc.h> |
29 | |
30 | #include <linux/mfd/wm8994/core.h> |
31 | #include <linux/mfd/wm8994/registers.h> |
32 | #include <linux/mfd/wm8994/pdata.h> |
33 | #include <linux/mfd/wm8994/gpio.h> |
34 | |
35 | #include "wm8994.h" |
36 | #include "wm_hubs.h" |
37 | |
38 | #define WM1811_JACKDET_MODE_NONE 0x0000 |
39 | #define WM1811_JACKDET_MODE_JACK 0x0100 |
40 | #define WM1811_JACKDET_MODE_MIC 0x0080 |
41 | #define WM1811_JACKDET_MODE_AUDIO 0x0180 |
42 | |
43 | #define WM8994_NUM_DRC 3 |
44 | #define WM8994_NUM_EQ 3 |
45 | |
46 | struct wm8994_reg_mask { |
47 | unsigned int reg; |
48 | unsigned int mask; |
49 | }; |
50 | |
51 | static struct wm8994_reg_mask wm8994_vu_bits[] = { |
52 | { WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, |
53 | { WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, |
54 | { WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, |
55 | { WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, |
56 | { WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, |
57 | { WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, |
58 | { WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, |
59 | { WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, |
60 | { WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, |
61 | { WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, |
62 | |
63 | { WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, |
64 | { WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, |
65 | { WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, |
66 | { WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, |
67 | { WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, |
68 | { WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, |
69 | { WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, |
70 | { WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, |
71 | { WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, |
72 | { WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, |
73 | { WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, |
74 | { WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, |
75 | }; |
76 | |
77 | /* VU bitfields for ADC2, DAC2 not available on WM1811 */ |
78 | static struct wm8994_reg_mask wm8994_adc2_dac2_vu_bits[] = { |
79 | { WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, |
80 | { WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, |
81 | { WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, |
82 | { WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, |
83 | }; |
84 | |
85 | static int wm8994_drc_base[] = { |
86 | WM8994_AIF1_DRC1_1, |
87 | WM8994_AIF1_DRC2_1, |
88 | WM8994_AIF2_DRC_1, |
89 | }; |
90 | |
91 | static int wm8994_retune_mobile_base[] = { |
92 | WM8994_AIF1_DAC1_EQ_GAINS_1, |
93 | WM8994_AIF1_DAC2_EQ_GAINS_1, |
94 | WM8994_AIF2_EQ_GAINS_1, |
95 | }; |
96 | |
97 | static const struct wm8958_micd_rate micdet_rates[] = { |
98 | { 32768, true, 1, 4 }, |
99 | { 32768, false, 1, 1 }, |
100 | { 44100 * 256, true, 7, 10 }, |
101 | { 44100 * 256, false, 7, 10 }, |
102 | }; |
103 | |
104 | static const struct wm8958_micd_rate jackdet_rates[] = { |
105 | { 32768, true, 0, 1 }, |
106 | { 32768, false, 0, 1 }, |
107 | { 44100 * 256, true, 10, 10 }, |
108 | { 44100 * 256, false, 7, 8 }, |
109 | }; |
110 | |
111 | static void wm8958_micd_set_rate(struct snd_soc_component *component) |
112 | { |
113 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
114 | struct wm8994 *control = wm8994->wm8994; |
115 | int best, i, sysclk, val; |
116 | bool idle; |
117 | const struct wm8958_micd_rate *rates; |
118 | int num_rates; |
119 | |
120 | idle = !wm8994->jack_mic; |
121 | |
122 | sysclk = snd_soc_component_read(component, WM8994_CLOCKING_1); |
123 | if (sysclk & WM8994_SYSCLK_SRC) |
124 | sysclk = wm8994->aifclk[1]; |
125 | else |
126 | sysclk = wm8994->aifclk[0]; |
127 | |
128 | if (control->pdata.micd_rates) { |
129 | rates = control->pdata.micd_rates; |
130 | num_rates = control->pdata.num_micd_rates; |
131 | } else if (wm8994->jackdet) { |
132 | rates = jackdet_rates; |
133 | num_rates = ARRAY_SIZE(jackdet_rates); |
134 | } else { |
135 | rates = micdet_rates; |
136 | num_rates = ARRAY_SIZE(micdet_rates); |
137 | } |
138 | |
139 | best = 0; |
140 | for (i = 0; i < num_rates; i++) { |
141 | if (rates[i].idle != idle) |
142 | continue; |
143 | if (abs(rates[i].sysclk - sysclk) < |
144 | abs(rates[best].sysclk - sysclk)) |
145 | best = i; |
146 | else if (rates[best].idle != idle) |
147 | best = i; |
148 | } |
149 | |
150 | val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT |
151 | | rates[best].rate << WM8958_MICD_RATE_SHIFT; |
152 | |
153 | dev_dbg(component->dev, "MICD rate %d,%d for %dHz %s\n" , |
154 | rates[best].start, rates[best].rate, sysclk, |
155 | idle ? "idle" : "active" ); |
156 | |
157 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, |
158 | WM8958_MICD_BIAS_STARTTIME_MASK | |
159 | WM8958_MICD_RATE_MASK, val); |
160 | } |
161 | |
162 | static int configure_aif_clock(struct snd_soc_component *component, int aif) |
163 | { |
164 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
165 | int rate; |
166 | int reg1 = 0; |
167 | int offset; |
168 | |
169 | if (aif) |
170 | offset = 4; |
171 | else |
172 | offset = 0; |
173 | |
174 | switch (wm8994->sysclk[aif]) { |
175 | case WM8994_SYSCLK_MCLK1: |
176 | rate = wm8994->mclk_rate[0]; |
177 | break; |
178 | |
179 | case WM8994_SYSCLK_MCLK2: |
180 | reg1 |= 0x8; |
181 | rate = wm8994->mclk_rate[1]; |
182 | break; |
183 | |
184 | case WM8994_SYSCLK_FLL1: |
185 | reg1 |= 0x10; |
186 | rate = wm8994->fll[0].out; |
187 | break; |
188 | |
189 | case WM8994_SYSCLK_FLL2: |
190 | reg1 |= 0x18; |
191 | rate = wm8994->fll[1].out; |
192 | break; |
193 | |
194 | default: |
195 | return -EINVAL; |
196 | } |
197 | |
198 | if (rate >= 13500000) { |
199 | rate /= 2; |
200 | reg1 |= WM8994_AIF1CLK_DIV; |
201 | |
202 | dev_dbg(component->dev, "Dividing AIF%d clock to %dHz\n" , |
203 | aif + 1, rate); |
204 | } |
205 | |
206 | wm8994->aifclk[aif] = rate; |
207 | |
208 | snd_soc_component_update_bits(component, WM8994_AIF1_CLOCKING_1 + offset, |
209 | WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV, |
210 | val: reg1); |
211 | |
212 | return 0; |
213 | } |
214 | |
215 | static int configure_clock(struct snd_soc_component *component) |
216 | { |
217 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
218 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
219 | int change, new; |
220 | |
221 | /* Bring up the AIF clocks first */ |
222 | configure_aif_clock(component, aif: 0); |
223 | configure_aif_clock(component, aif: 1); |
224 | |
225 | /* Then switch CLK_SYS over to the higher of them; a change |
226 | * can only happen as a result of a clocking change which can |
227 | * only be made outside of DAPM so we can safely redo the |
228 | * clocking. |
229 | */ |
230 | |
231 | /* If they're equal it doesn't matter which is used */ |
232 | if (wm8994->aifclk[0] == wm8994->aifclk[1]) { |
233 | wm8958_micd_set_rate(component); |
234 | return 0; |
235 | } |
236 | |
237 | if (wm8994->aifclk[0] < wm8994->aifclk[1]) |
238 | new = WM8994_SYSCLK_SRC; |
239 | else |
240 | new = 0; |
241 | |
242 | change = snd_soc_component_update_bits(component, WM8994_CLOCKING_1, |
243 | WM8994_SYSCLK_SRC, val: new); |
244 | if (change) |
245 | snd_soc_dapm_sync(dapm); |
246 | |
247 | wm8958_micd_set_rate(component); |
248 | |
249 | return 0; |
250 | } |
251 | |
252 | static int check_clk_sys(struct snd_soc_dapm_widget *source, |
253 | struct snd_soc_dapm_widget *sink) |
254 | { |
255 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: source->dapm); |
256 | int reg = snd_soc_component_read(component, WM8994_CLOCKING_1); |
257 | const char *clk; |
258 | |
259 | /* Check what we're currently using for CLK_SYS */ |
260 | if (reg & WM8994_SYSCLK_SRC) |
261 | clk = "AIF2CLK" ; |
262 | else |
263 | clk = "AIF1CLK" ; |
264 | |
265 | return snd_soc_dapm_widget_name_cmp(widget: source, s: clk) == 0; |
266 | } |
267 | |
268 | static const char *sidetone_hpf_text[] = { |
269 | "2.7kHz" , "1.35kHz" , "675Hz" , "370Hz" , "180Hz" , "90Hz" , "45Hz" |
270 | }; |
271 | |
272 | static SOC_ENUM_SINGLE_DECL(sidetone_hpf, |
273 | WM8994_SIDETONE, 7, sidetone_hpf_text); |
274 | |
275 | static const char *adc_hpf_text[] = { |
276 | "HiFi" , "Voice 1" , "Voice 2" , "Voice 3" |
277 | }; |
278 | |
279 | static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf, |
280 | WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text); |
281 | |
282 | static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf, |
283 | WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text); |
284 | |
285 | static SOC_ENUM_SINGLE_DECL(aif2adc_hpf, |
286 | WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text); |
287 | |
288 | static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); |
289 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); |
290 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); |
291 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); |
292 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
293 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); |
294 | |
295 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
296 | SOC_SINGLE_EXT(xname, reg, shift, 1, 0, \ |
297 | snd_soc_get_volsw, wm8994_put_drc_sw) |
298 | |
299 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, |
300 | struct snd_ctl_elem_value *ucontrol) |
301 | { |
302 | struct soc_mixer_control *mc = |
303 | (struct soc_mixer_control *)kcontrol->private_value; |
304 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
305 | int mask, ret; |
306 | |
307 | /* Can't enable both ADC and DAC paths simultaneously */ |
308 | if (mc->shift == WM8994_AIF1DAC1_DRC_ENA_SHIFT) |
309 | mask = WM8994_AIF1ADC1L_DRC_ENA_MASK | |
310 | WM8994_AIF1ADC1R_DRC_ENA_MASK; |
311 | else |
312 | mask = WM8994_AIF1DAC1_DRC_ENA_MASK; |
313 | |
314 | ret = snd_soc_component_read(component, reg: mc->reg); |
315 | if (ret < 0) |
316 | return ret; |
317 | if (ret & mask) |
318 | return -EINVAL; |
319 | |
320 | return snd_soc_put_volsw(kcontrol, ucontrol); |
321 | } |
322 | |
323 | static void wm8994_set_drc(struct snd_soc_component *component, int drc) |
324 | { |
325 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
326 | struct wm8994 *control = wm8994->wm8994; |
327 | struct wm8994_pdata *pdata = &control->pdata; |
328 | int base = wm8994_drc_base[drc]; |
329 | int cfg = wm8994->drc_cfg[drc]; |
330 | int save, i; |
331 | |
332 | /* Save any enables; the configuration should clear them. */ |
333 | save = snd_soc_component_read(component, reg: base); |
334 | save &= WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | |
335 | WM8994_AIF1ADC1R_DRC_ENA; |
336 | |
337 | for (i = 0; i < WM8994_DRC_REGS; i++) |
338 | snd_soc_component_update_bits(component, reg: base + i, mask: 0xffff, |
339 | val: pdata->drc_cfgs[cfg].regs[i]); |
340 | |
341 | snd_soc_component_update_bits(component, reg: base, WM8994_AIF1DAC1_DRC_ENA | |
342 | WM8994_AIF1ADC1L_DRC_ENA | |
343 | WM8994_AIF1ADC1R_DRC_ENA, val: save); |
344 | } |
345 | |
346 | /* Icky as hell but saves code duplication */ |
347 | static int wm8994_get_drc(const char *name) |
348 | { |
349 | if (strcmp(name, "AIF1DRC1 Mode" ) == 0) |
350 | return 0; |
351 | if (strcmp(name, "AIF1DRC2 Mode" ) == 0) |
352 | return 1; |
353 | if (strcmp(name, "AIF2DRC Mode" ) == 0) |
354 | return 2; |
355 | return -EINVAL; |
356 | } |
357 | |
358 | static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, |
359 | struct snd_ctl_elem_value *ucontrol) |
360 | { |
361 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
362 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
363 | struct wm8994 *control = wm8994->wm8994; |
364 | struct wm8994_pdata *pdata = &control->pdata; |
365 | int drc = wm8994_get_drc(name: kcontrol->id.name); |
366 | int value = ucontrol->value.enumerated.item[0]; |
367 | |
368 | if (drc < 0) |
369 | return drc; |
370 | |
371 | if (value >= pdata->num_drc_cfgs) |
372 | return -EINVAL; |
373 | |
374 | wm8994->drc_cfg[drc] = value; |
375 | |
376 | wm8994_set_drc(component, drc); |
377 | |
378 | return 0; |
379 | } |
380 | |
381 | static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol, |
382 | struct snd_ctl_elem_value *ucontrol) |
383 | { |
384 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
385 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
386 | int drc = wm8994_get_drc(name: kcontrol->id.name); |
387 | |
388 | if (drc < 0) |
389 | return drc; |
390 | ucontrol->value.enumerated.item[0] = wm8994->drc_cfg[drc]; |
391 | |
392 | return 0; |
393 | } |
394 | |
395 | static void wm8994_set_retune_mobile(struct snd_soc_component *component, int block) |
396 | { |
397 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
398 | struct wm8994 *control = wm8994->wm8994; |
399 | struct wm8994_pdata *pdata = &control->pdata; |
400 | int base = wm8994_retune_mobile_base[block]; |
401 | int iface, best, best_val, save, i, cfg; |
402 | |
403 | if (!pdata || !wm8994->num_retune_mobile_texts) |
404 | return; |
405 | |
406 | switch (block) { |
407 | case 0: |
408 | case 1: |
409 | iface = 0; |
410 | break; |
411 | case 2: |
412 | iface = 1; |
413 | break; |
414 | default: |
415 | return; |
416 | } |
417 | |
418 | /* Find the version of the currently selected configuration |
419 | * with the nearest sample rate. */ |
420 | cfg = wm8994->retune_mobile_cfg[block]; |
421 | best = 0; |
422 | best_val = INT_MAX; |
423 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { |
424 | if (strcmp(pdata->retune_mobile_cfgs[i].name, |
425 | wm8994->retune_mobile_texts[cfg]) == 0 && |
426 | abs(pdata->retune_mobile_cfgs[i].rate |
427 | - wm8994->dac_rates[iface]) < best_val) { |
428 | best = i; |
429 | best_val = abs(pdata->retune_mobile_cfgs[i].rate |
430 | - wm8994->dac_rates[iface]); |
431 | } |
432 | } |
433 | |
434 | dev_dbg(component->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n" , |
435 | block, |
436 | pdata->retune_mobile_cfgs[best].name, |
437 | pdata->retune_mobile_cfgs[best].rate, |
438 | wm8994->dac_rates[iface]); |
439 | |
440 | /* The EQ will be disabled while reconfiguring it, remember the |
441 | * current configuration. |
442 | */ |
443 | save = snd_soc_component_read(component, reg: base); |
444 | save &= WM8994_AIF1DAC1_EQ_ENA; |
445 | |
446 | for (i = 0; i < WM8994_EQ_REGS; i++) |
447 | snd_soc_component_update_bits(component, reg: base + i, mask: 0xffff, |
448 | val: pdata->retune_mobile_cfgs[best].regs[i]); |
449 | |
450 | snd_soc_component_update_bits(component, reg: base, WM8994_AIF1DAC1_EQ_ENA, val: save); |
451 | } |
452 | |
453 | /* Icky as hell but saves code duplication */ |
454 | static int wm8994_get_retune_mobile_block(const char *name) |
455 | { |
456 | if (strcmp(name, "AIF1.1 EQ Mode" ) == 0) |
457 | return 0; |
458 | if (strcmp(name, "AIF1.2 EQ Mode" ) == 0) |
459 | return 1; |
460 | if (strcmp(name, "AIF2 EQ Mode" ) == 0) |
461 | return 2; |
462 | return -EINVAL; |
463 | } |
464 | |
465 | static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, |
466 | struct snd_ctl_elem_value *ucontrol) |
467 | { |
468 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
469 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
470 | struct wm8994 *control = wm8994->wm8994; |
471 | struct wm8994_pdata *pdata = &control->pdata; |
472 | int block = wm8994_get_retune_mobile_block(name: kcontrol->id.name); |
473 | int value = ucontrol->value.enumerated.item[0]; |
474 | |
475 | if (block < 0) |
476 | return block; |
477 | |
478 | if (value >= pdata->num_retune_mobile_cfgs) |
479 | return -EINVAL; |
480 | |
481 | wm8994->retune_mobile_cfg[block] = value; |
482 | |
483 | wm8994_set_retune_mobile(component, block); |
484 | |
485 | return 0; |
486 | } |
487 | |
488 | static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, |
489 | struct snd_ctl_elem_value *ucontrol) |
490 | { |
491 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
492 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
493 | int block = wm8994_get_retune_mobile_block(name: kcontrol->id.name); |
494 | |
495 | if (block < 0) |
496 | return block; |
497 | |
498 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
499 | |
500 | return 0; |
501 | } |
502 | |
503 | static const char *aif_chan_src_text[] = { |
504 | "Left" , "Right" |
505 | }; |
506 | |
507 | static SOC_ENUM_SINGLE_DECL(aif1adcl_src, |
508 | WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text); |
509 | |
510 | static SOC_ENUM_SINGLE_DECL(aif1adcr_src, |
511 | WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text); |
512 | |
513 | static SOC_ENUM_SINGLE_DECL(aif2adcl_src, |
514 | WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text); |
515 | |
516 | static SOC_ENUM_SINGLE_DECL(aif2adcr_src, |
517 | WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text); |
518 | |
519 | static SOC_ENUM_SINGLE_DECL(aif1dacl_src, |
520 | WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text); |
521 | |
522 | static SOC_ENUM_SINGLE_DECL(aif1dacr_src, |
523 | WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text); |
524 | |
525 | static SOC_ENUM_SINGLE_DECL(aif2dacl_src, |
526 | WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text); |
527 | |
528 | static SOC_ENUM_SINGLE_DECL(aif2dacr_src, |
529 | WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text); |
530 | |
531 | static const char *osr_text[] = { |
532 | "Low Power" , "High Performance" , |
533 | }; |
534 | |
535 | static SOC_ENUM_SINGLE_DECL(dac_osr, |
536 | WM8994_OVERSAMPLING, 0, osr_text); |
537 | |
538 | static SOC_ENUM_SINGLE_DECL(adc_osr, |
539 | WM8994_OVERSAMPLING, 1, osr_text); |
540 | |
541 | static const struct snd_kcontrol_new wm8994_common_snd_controls[] = { |
542 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume" , WM8994_AIF1_ADC1_LEFT_VOLUME, |
543 | WM8994_AIF1_ADC1_RIGHT_VOLUME, |
544 | 1, 119, 0, digital_tlv), |
545 | SOC_DOUBLE_R_TLV("AIF2ADC Volume" , WM8994_AIF2_ADC_LEFT_VOLUME, |
546 | WM8994_AIF2_ADC_RIGHT_VOLUME, |
547 | 1, 119, 0, digital_tlv), |
548 | |
549 | SOC_ENUM("AIF1ADCL Source" , aif1adcl_src), |
550 | SOC_ENUM("AIF1ADCR Source" , aif1adcr_src), |
551 | SOC_ENUM("AIF2ADCL Source" , aif2adcl_src), |
552 | SOC_ENUM("AIF2ADCR Source" , aif2adcr_src), |
553 | |
554 | SOC_ENUM("AIF1DACL Source" , aif1dacl_src), |
555 | SOC_ENUM("AIF1DACR Source" , aif1dacr_src), |
556 | SOC_ENUM("AIF2DACL Source" , aif2dacl_src), |
557 | SOC_ENUM("AIF2DACR Source" , aif2dacr_src), |
558 | |
559 | SOC_DOUBLE_R_TLV("AIF1DAC1 Volume" , WM8994_AIF1_DAC1_LEFT_VOLUME, |
560 | WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), |
561 | SOC_DOUBLE_R_TLV("AIF2DAC Volume" , WM8994_AIF2_DAC_LEFT_VOLUME, |
562 | WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv), |
563 | |
564 | SOC_SINGLE_TLV("AIF1 Boost Volume" , WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv), |
565 | SOC_SINGLE_TLV("AIF2 Boost Volume" , WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv), |
566 | |
567 | SOC_SINGLE("AIF1DAC1 EQ Switch" , WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0), |
568 | SOC_SINGLE("AIF2 EQ Switch" , WM8994_AIF2_EQ_GAINS_1, 0, 1, 0), |
569 | |
570 | WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch" , WM8994_AIF1_DRC1_1, 2), |
571 | WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch" , WM8994_AIF1_DRC1_1, 1), |
572 | WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch" , WM8994_AIF1_DRC1_1, 0), |
573 | |
574 | WM8994_DRC_SWITCH("AIF2DAC DRC Switch" , WM8994_AIF2_DRC_1, 2), |
575 | WM8994_DRC_SWITCH("AIF2ADCL DRC Switch" , WM8994_AIF2_DRC_1, 1), |
576 | WM8994_DRC_SWITCH("AIF2ADCR DRC Switch" , WM8994_AIF2_DRC_1, 0), |
577 | |
578 | SOC_SINGLE_TLV("DAC1 Right Sidetone Volume" , WM8994_DAC1_MIXER_VOLUMES, |
579 | 5, 12, 0, st_tlv), |
580 | SOC_SINGLE_TLV("DAC1 Left Sidetone Volume" , WM8994_DAC1_MIXER_VOLUMES, |
581 | 0, 12, 0, st_tlv), |
582 | SOC_SINGLE_TLV("DAC2 Right Sidetone Volume" , WM8994_DAC2_MIXER_VOLUMES, |
583 | 5, 12, 0, st_tlv), |
584 | SOC_SINGLE_TLV("DAC2 Left Sidetone Volume" , WM8994_DAC2_MIXER_VOLUMES, |
585 | 0, 12, 0, st_tlv), |
586 | SOC_ENUM("Sidetone HPF Mux" , sidetone_hpf), |
587 | SOC_SINGLE("Sidetone HPF Switch" , WM8994_SIDETONE, 6, 1, 0), |
588 | |
589 | SOC_ENUM("AIF1ADC1 HPF Mode" , aif1adc1_hpf), |
590 | SOC_DOUBLE("AIF1ADC1 HPF Switch" , WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0), |
591 | |
592 | SOC_ENUM("AIF2ADC HPF Mode" , aif2adc_hpf), |
593 | SOC_DOUBLE("AIF2ADC HPF Switch" , WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0), |
594 | |
595 | SOC_ENUM("ADC OSR" , adc_osr), |
596 | SOC_ENUM("DAC OSR" , dac_osr), |
597 | |
598 | SOC_DOUBLE_R_TLV("DAC1 Volume" , WM8994_DAC1_LEFT_VOLUME, |
599 | WM8994_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), |
600 | SOC_DOUBLE_R("DAC1 Switch" , WM8994_DAC1_LEFT_VOLUME, |
601 | WM8994_DAC1_RIGHT_VOLUME, 9, 1, 1), |
602 | |
603 | SOC_DOUBLE_R_TLV("DAC2 Volume" , WM8994_DAC2_LEFT_VOLUME, |
604 | WM8994_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), |
605 | SOC_DOUBLE_R("DAC2 Switch" , WM8994_DAC2_LEFT_VOLUME, |
606 | WM8994_DAC2_RIGHT_VOLUME, 9, 1, 1), |
607 | |
608 | SOC_SINGLE_TLV("SPKL DAC2 Volume" , WM8994_SPKMIXL_ATTENUATION, |
609 | 6, 1, 1, wm_hubs_spkmix_tlv), |
610 | SOC_SINGLE_TLV("SPKL DAC1 Volume" , WM8994_SPKMIXL_ATTENUATION, |
611 | 2, 1, 1, wm_hubs_spkmix_tlv), |
612 | |
613 | SOC_SINGLE_TLV("SPKR DAC2 Volume" , WM8994_SPKMIXR_ATTENUATION, |
614 | 6, 1, 1, wm_hubs_spkmix_tlv), |
615 | SOC_SINGLE_TLV("SPKR DAC1 Volume" , WM8994_SPKMIXR_ATTENUATION, |
616 | 2, 1, 1, wm_hubs_spkmix_tlv), |
617 | |
618 | SOC_SINGLE_TLV("AIF1DAC1 3D Stereo Volume" , WM8994_AIF1_DAC1_FILTERS_2, |
619 | 10, 15, 0, wm8994_3d_tlv), |
620 | SOC_SINGLE("AIF1DAC1 3D Stereo Switch" , WM8994_AIF1_DAC1_FILTERS_2, |
621 | 8, 1, 0), |
622 | SOC_SINGLE_TLV("AIF1DAC2 3D Stereo Volume" , WM8994_AIF1_DAC2_FILTERS_2, |
623 | 10, 15, 0, wm8994_3d_tlv), |
624 | SOC_SINGLE("AIF1DAC2 3D Stereo Switch" , WM8994_AIF1_DAC2_FILTERS_2, |
625 | 8, 1, 0), |
626 | SOC_SINGLE_TLV("AIF2DAC 3D Stereo Volume" , WM8994_AIF2_DAC_FILTERS_2, |
627 | 10, 15, 0, wm8994_3d_tlv), |
628 | SOC_SINGLE("AIF2DAC 3D Stereo Switch" , WM8994_AIF2_DAC_FILTERS_2, |
629 | 8, 1, 0), |
630 | }; |
631 | |
632 | /* Controls not available on WM1811 */ |
633 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { |
634 | SOC_DOUBLE_R_TLV("AIF1ADC2 Volume" , WM8994_AIF1_ADC2_LEFT_VOLUME, |
635 | WM8994_AIF1_ADC2_RIGHT_VOLUME, |
636 | 1, 119, 0, digital_tlv), |
637 | SOC_DOUBLE_R_TLV("AIF1DAC2 Volume" , WM8994_AIF1_DAC2_LEFT_VOLUME, |
638 | WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), |
639 | |
640 | SOC_SINGLE("AIF1DAC2 EQ Switch" , WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0), |
641 | |
642 | WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch" , WM8994_AIF1_DRC2_1, 2), |
643 | WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch" , WM8994_AIF1_DRC2_1, 1), |
644 | WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch" , WM8994_AIF1_DRC2_1, 0), |
645 | |
646 | SOC_ENUM("AIF1ADC2 HPF Mode" , aif1adc2_hpf), |
647 | SOC_DOUBLE("AIF1ADC2 HPF Switch" , WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0), |
648 | }; |
649 | |
650 | static const struct snd_kcontrol_new wm8994_eq_controls[] = { |
651 | SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume" , WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0, |
652 | eq_tlv), |
653 | SOC_SINGLE_TLV("AIF1DAC1 EQ2 Volume" , WM8994_AIF1_DAC1_EQ_GAINS_1, 6, 31, 0, |
654 | eq_tlv), |
655 | SOC_SINGLE_TLV("AIF1DAC1 EQ3 Volume" , WM8994_AIF1_DAC1_EQ_GAINS_1, 1, 31, 0, |
656 | eq_tlv), |
657 | SOC_SINGLE_TLV("AIF1DAC1 EQ4 Volume" , WM8994_AIF1_DAC1_EQ_GAINS_2, 11, 31, 0, |
658 | eq_tlv), |
659 | SOC_SINGLE_TLV("AIF1DAC1 EQ5 Volume" , WM8994_AIF1_DAC1_EQ_GAINS_2, 6, 31, 0, |
660 | eq_tlv), |
661 | |
662 | SOC_SINGLE_TLV("AIF1DAC2 EQ1 Volume" , WM8994_AIF1_DAC2_EQ_GAINS_1, 11, 31, 0, |
663 | eq_tlv), |
664 | SOC_SINGLE_TLV("AIF1DAC2 EQ2 Volume" , WM8994_AIF1_DAC2_EQ_GAINS_1, 6, 31, 0, |
665 | eq_tlv), |
666 | SOC_SINGLE_TLV("AIF1DAC2 EQ3 Volume" , WM8994_AIF1_DAC2_EQ_GAINS_1, 1, 31, 0, |
667 | eq_tlv), |
668 | SOC_SINGLE_TLV("AIF1DAC2 EQ4 Volume" , WM8994_AIF1_DAC2_EQ_GAINS_2, 11, 31, 0, |
669 | eq_tlv), |
670 | SOC_SINGLE_TLV("AIF1DAC2 EQ5 Volume" , WM8994_AIF1_DAC2_EQ_GAINS_2, 6, 31, 0, |
671 | eq_tlv), |
672 | |
673 | SOC_SINGLE_TLV("AIF2 EQ1 Volume" , WM8994_AIF2_EQ_GAINS_1, 11, 31, 0, |
674 | eq_tlv), |
675 | SOC_SINGLE_TLV("AIF2 EQ2 Volume" , WM8994_AIF2_EQ_GAINS_1, 6, 31, 0, |
676 | eq_tlv), |
677 | SOC_SINGLE_TLV("AIF2 EQ3 Volume" , WM8994_AIF2_EQ_GAINS_1, 1, 31, 0, |
678 | eq_tlv), |
679 | SOC_SINGLE_TLV("AIF2 EQ4 Volume" , WM8994_AIF2_EQ_GAINS_2, 11, 31, 0, |
680 | eq_tlv), |
681 | SOC_SINGLE_TLV("AIF2 EQ5 Volume" , WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, |
682 | eq_tlv), |
683 | }; |
684 | |
685 | static const struct snd_kcontrol_new wm8994_drc_controls[] = { |
686 | SND_SOC_BYTES_MASK("AIF1.1 DRC" , WM8994_AIF1_DRC1_1, 5, |
687 | WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | |
688 | WM8994_AIF1ADC1R_DRC_ENA), |
689 | SND_SOC_BYTES_MASK("AIF1.2 DRC" , WM8994_AIF1_DRC2_1, 5, |
690 | WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | |
691 | WM8994_AIF1ADC2R_DRC_ENA), |
692 | SND_SOC_BYTES_MASK("AIF2 DRC" , WM8994_AIF2_DRC_1, 5, |
693 | WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | |
694 | WM8994_AIF2ADCR_DRC_ENA), |
695 | }; |
696 | |
697 | static const char *wm8958_ng_text[] = { |
698 | "30ms" , "125ms" , "250ms" , "500ms" , |
699 | }; |
700 | |
701 | static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold, |
702 | WM8958_AIF1_DAC1_NOISE_GATE, |
703 | WM8958_AIF1DAC1_NG_THR_SHIFT, |
704 | wm8958_ng_text); |
705 | |
706 | static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold, |
707 | WM8958_AIF1_DAC2_NOISE_GATE, |
708 | WM8958_AIF1DAC2_NG_THR_SHIFT, |
709 | wm8958_ng_text); |
710 | |
711 | static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold, |
712 | WM8958_AIF2_DAC_NOISE_GATE, |
713 | WM8958_AIF2DAC_NG_THR_SHIFT, |
714 | wm8958_ng_text); |
715 | |
716 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { |
717 | SOC_SINGLE_TLV("AIF3 Boost Volume" , WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), |
718 | |
719 | SOC_SINGLE("AIF1DAC1 Noise Gate Switch" , WM8958_AIF1_DAC1_NOISE_GATE, |
720 | WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0), |
721 | SOC_ENUM("AIF1DAC1 Noise Gate Hold Time" , wm8958_aif1dac1_ng_hold), |
722 | SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume" , |
723 | WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT, |
724 | 7, 1, ng_tlv), |
725 | |
726 | SOC_SINGLE("AIF1DAC2 Noise Gate Switch" , WM8958_AIF1_DAC2_NOISE_GATE, |
727 | WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0), |
728 | SOC_ENUM("AIF1DAC2 Noise Gate Hold Time" , wm8958_aif1dac2_ng_hold), |
729 | SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume" , |
730 | WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT, |
731 | 7, 1, ng_tlv), |
732 | |
733 | SOC_SINGLE("AIF2DAC Noise Gate Switch" , WM8958_AIF2_DAC_NOISE_GATE, |
734 | WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0), |
735 | SOC_ENUM("AIF2DAC Noise Gate Hold Time" , wm8958_aif2dac_ng_hold), |
736 | SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume" , |
737 | WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT, |
738 | 7, 1, ng_tlv), |
739 | }; |
740 | |
741 | /* We run all mode setting through a function to enforce audio mode */ |
742 | static void wm1811_jackdet_set_mode(struct snd_soc_component *component, u16 mode) |
743 | { |
744 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
745 | |
746 | if (!wm8994->jackdet || !wm8994->micdet[0].jack) |
747 | return; |
748 | |
749 | if (wm8994->active_refcount) |
750 | mode = WM1811_JACKDET_MODE_AUDIO; |
751 | |
752 | if (mode == wm8994->jackdet_mode) |
753 | return; |
754 | |
755 | wm8994->jackdet_mode = mode; |
756 | |
757 | /* Always use audio mode to detect while the system is active */ |
758 | if (mode != WM1811_JACKDET_MODE_NONE) |
759 | mode = WM1811_JACKDET_MODE_AUDIO; |
760 | |
761 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
762 | WM1811_JACKDET_MODE_MASK, val: mode); |
763 | } |
764 | |
765 | static void active_reference(struct snd_soc_component *component) |
766 | { |
767 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
768 | |
769 | mutex_lock(&wm8994->accdet_lock); |
770 | |
771 | wm8994->active_refcount++; |
772 | |
773 | dev_dbg(component->dev, "Active refcount incremented, now %d\n" , |
774 | wm8994->active_refcount); |
775 | |
776 | /* If we're using jack detection go into audio mode */ |
777 | wm1811_jackdet_set_mode(component, WM1811_JACKDET_MODE_AUDIO); |
778 | |
779 | mutex_unlock(lock: &wm8994->accdet_lock); |
780 | } |
781 | |
782 | static void active_dereference(struct snd_soc_component *component) |
783 | { |
784 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
785 | u16 mode; |
786 | |
787 | mutex_lock(&wm8994->accdet_lock); |
788 | |
789 | wm8994->active_refcount--; |
790 | |
791 | dev_dbg(component->dev, "Active refcount decremented, now %d\n" , |
792 | wm8994->active_refcount); |
793 | |
794 | if (wm8994->active_refcount == 0) { |
795 | /* Go into appropriate detection only mode */ |
796 | if (wm8994->jack_mic || wm8994->mic_detecting) |
797 | mode = WM1811_JACKDET_MODE_MIC; |
798 | else |
799 | mode = WM1811_JACKDET_MODE_JACK; |
800 | |
801 | wm1811_jackdet_set_mode(component, mode); |
802 | } |
803 | |
804 | mutex_unlock(lock: &wm8994->accdet_lock); |
805 | } |
806 | |
807 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
808 | struct snd_kcontrol *kcontrol, int event) |
809 | { |
810 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
811 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
812 | |
813 | switch (event) { |
814 | case SND_SOC_DAPM_PRE_PMU: |
815 | return configure_clock(component); |
816 | |
817 | case SND_SOC_DAPM_POST_PMU: |
818 | /* |
819 | * JACKDET won't run until we start the clock and it |
820 | * only reports deltas, make sure we notify the state |
821 | * up the stack on startup. Use a *very* generous |
822 | * timeout for paranoia, there's no urgency and we |
823 | * don't want false reports. |
824 | */ |
825 | if (wm8994->jackdet && !wm8994->clk_has_run) { |
826 | queue_delayed_work(wq: system_power_efficient_wq, |
827 | dwork: &wm8994->jackdet_bootstrap, |
828 | delay: msecs_to_jiffies(m: 1000)); |
829 | wm8994->clk_has_run = true; |
830 | } |
831 | break; |
832 | |
833 | case SND_SOC_DAPM_POST_PMD: |
834 | configure_clock(component); |
835 | break; |
836 | } |
837 | |
838 | return 0; |
839 | } |
840 | |
841 | static void vmid_reference(struct snd_soc_component *component) |
842 | { |
843 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
844 | |
845 | pm_runtime_get_sync(dev: component->dev); |
846 | |
847 | wm8994->vmid_refcount++; |
848 | |
849 | dev_dbg(component->dev, "Referencing VMID, refcount is now %d\n" , |
850 | wm8994->vmid_refcount); |
851 | |
852 | if (wm8994->vmid_refcount == 1) { |
853 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_1, |
854 | WM8994_LINEOUT1_DISCH | |
855 | WM8994_LINEOUT2_DISCH, val: 0); |
856 | |
857 | wm_hubs_vmid_ena(component); |
858 | |
859 | switch (wm8994->vmid_mode) { |
860 | default: |
861 | WARN_ON(NULL == "Invalid VMID mode" ); |
862 | fallthrough; |
863 | case WM8994_VMID_NORMAL: |
864 | /* Startup bias, VMID ramp & buffer */ |
865 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
866 | WM8994_BIAS_SRC | |
867 | WM8994_VMID_DISCH | |
868 | WM8994_STARTUP_BIAS_ENA | |
869 | WM8994_VMID_BUF_ENA | |
870 | WM8994_VMID_RAMP_MASK, |
871 | WM8994_BIAS_SRC | |
872 | WM8994_STARTUP_BIAS_ENA | |
873 | WM8994_VMID_BUF_ENA | |
874 | (0x2 << WM8994_VMID_RAMP_SHIFT)); |
875 | |
876 | /* Main bias enable, VMID=2x40k */ |
877 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_1, |
878 | WM8994_BIAS_ENA | |
879 | WM8994_VMID_SEL_MASK, |
880 | WM8994_BIAS_ENA | 0x2); |
881 | |
882 | msleep(msecs: 300); |
883 | |
884 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
885 | WM8994_VMID_RAMP_MASK | |
886 | WM8994_BIAS_SRC, |
887 | val: 0); |
888 | break; |
889 | |
890 | case WM8994_VMID_FORCE: |
891 | /* Startup bias, slow VMID ramp & buffer */ |
892 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
893 | WM8994_BIAS_SRC | |
894 | WM8994_VMID_DISCH | |
895 | WM8994_STARTUP_BIAS_ENA | |
896 | WM8994_VMID_BUF_ENA | |
897 | WM8994_VMID_RAMP_MASK, |
898 | WM8994_BIAS_SRC | |
899 | WM8994_STARTUP_BIAS_ENA | |
900 | WM8994_VMID_BUF_ENA | |
901 | (0x2 << WM8994_VMID_RAMP_SHIFT)); |
902 | |
903 | /* Main bias enable, VMID=2x40k */ |
904 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_1, |
905 | WM8994_BIAS_ENA | |
906 | WM8994_VMID_SEL_MASK, |
907 | WM8994_BIAS_ENA | 0x2); |
908 | |
909 | msleep(msecs: 400); |
910 | |
911 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
912 | WM8994_VMID_RAMP_MASK | |
913 | WM8994_BIAS_SRC, |
914 | val: 0); |
915 | break; |
916 | } |
917 | } |
918 | } |
919 | |
920 | static void vmid_dereference(struct snd_soc_component *component) |
921 | { |
922 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
923 | |
924 | wm8994->vmid_refcount--; |
925 | |
926 | dev_dbg(component->dev, "Dereferencing VMID, refcount is now %d\n" , |
927 | wm8994->vmid_refcount); |
928 | |
929 | if (wm8994->vmid_refcount == 0) { |
930 | if (wm8994->hubs.lineout1_se) |
931 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_3, |
932 | WM8994_LINEOUT1N_ENA | |
933 | WM8994_LINEOUT1P_ENA, |
934 | WM8994_LINEOUT1N_ENA | |
935 | WM8994_LINEOUT1P_ENA); |
936 | |
937 | if (wm8994->hubs.lineout2_se) |
938 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_3, |
939 | WM8994_LINEOUT2N_ENA | |
940 | WM8994_LINEOUT2P_ENA, |
941 | WM8994_LINEOUT2N_ENA | |
942 | WM8994_LINEOUT2P_ENA); |
943 | |
944 | /* Start discharging VMID */ |
945 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
946 | WM8994_BIAS_SRC | |
947 | WM8994_VMID_DISCH, |
948 | WM8994_BIAS_SRC | |
949 | WM8994_VMID_DISCH); |
950 | |
951 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_1, |
952 | WM8994_VMID_SEL_MASK, val: 0); |
953 | |
954 | msleep(msecs: 400); |
955 | |
956 | /* Active discharge */ |
957 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_1, |
958 | WM8994_LINEOUT1_DISCH | |
959 | WM8994_LINEOUT2_DISCH, |
960 | WM8994_LINEOUT1_DISCH | |
961 | WM8994_LINEOUT2_DISCH); |
962 | |
963 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_3, |
964 | WM8994_LINEOUT1N_ENA | |
965 | WM8994_LINEOUT1P_ENA | |
966 | WM8994_LINEOUT2N_ENA | |
967 | WM8994_LINEOUT2P_ENA, val: 0); |
968 | |
969 | /* Switch off startup biases */ |
970 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, |
971 | WM8994_BIAS_SRC | |
972 | WM8994_STARTUP_BIAS_ENA | |
973 | WM8994_VMID_BUF_ENA | |
974 | WM8994_VMID_RAMP_MASK, val: 0); |
975 | |
976 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_1, |
977 | WM8994_VMID_SEL_MASK, val: 0); |
978 | } |
979 | |
980 | pm_runtime_put(dev: component->dev); |
981 | } |
982 | |
983 | static int vmid_event(struct snd_soc_dapm_widget *w, |
984 | struct snd_kcontrol *kcontrol, int event) |
985 | { |
986 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
987 | |
988 | switch (event) { |
989 | case SND_SOC_DAPM_PRE_PMU: |
990 | vmid_reference(component); |
991 | break; |
992 | |
993 | case SND_SOC_DAPM_POST_PMD: |
994 | vmid_dereference(component); |
995 | break; |
996 | } |
997 | |
998 | return 0; |
999 | } |
1000 | |
1001 | static bool wm8994_check_class_w_digital(struct snd_soc_component *component) |
1002 | { |
1003 | int source = 0; /* GCC flow analysis can't track enable */ |
1004 | int reg, reg_r; |
1005 | |
1006 | /* We also need the same AIF source for L/R and only one path */ |
1007 | reg = snd_soc_component_read(component, WM8994_DAC1_LEFT_MIXER_ROUTING); |
1008 | switch (reg) { |
1009 | case WM8994_AIF2DACL_TO_DAC1L: |
1010 | dev_vdbg(component->dev, "Class W source AIF2DAC\n" ); |
1011 | source = 2 << WM8994_CP_DYN_SRC_SEL_SHIFT; |
1012 | break; |
1013 | case WM8994_AIF1DAC2L_TO_DAC1L: |
1014 | dev_vdbg(component->dev, "Class W source AIF1DAC2\n" ); |
1015 | source = 1 << WM8994_CP_DYN_SRC_SEL_SHIFT; |
1016 | break; |
1017 | case WM8994_AIF1DAC1L_TO_DAC1L: |
1018 | dev_vdbg(component->dev, "Class W source AIF1DAC1\n" ); |
1019 | source = 0 << WM8994_CP_DYN_SRC_SEL_SHIFT; |
1020 | break; |
1021 | default: |
1022 | dev_vdbg(component->dev, "DAC mixer setting: %x\n" , reg); |
1023 | return false; |
1024 | } |
1025 | |
1026 | reg_r = snd_soc_component_read(component, WM8994_DAC1_RIGHT_MIXER_ROUTING); |
1027 | if (reg_r != reg) { |
1028 | dev_vdbg(component->dev, "Left and right DAC mixers different\n" ); |
1029 | return false; |
1030 | } |
1031 | |
1032 | /* Set the source up */ |
1033 | snd_soc_component_update_bits(component, WM8994_CLASS_W_1, |
1034 | WM8994_CP_DYN_SRC_SEL_MASK, val: source); |
1035 | |
1036 | return true; |
1037 | } |
1038 | |
1039 | static void wm8994_update_vu_bits(struct snd_soc_component *component) |
1040 | { |
1041 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1042 | struct wm8994 *control = wm8994->wm8994; |
1043 | int i; |
1044 | |
1045 | for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) |
1046 | snd_soc_component_write(component, reg: wm8994_vu_bits[i].reg, |
1047 | val: snd_soc_component_read(component, |
1048 | reg: wm8994_vu_bits[i].reg)); |
1049 | if (control->type == WM1811) |
1050 | return; |
1051 | |
1052 | for (i = 0; i < ARRAY_SIZE(wm8994_adc2_dac2_vu_bits); i++) |
1053 | snd_soc_component_write(component, |
1054 | reg: wm8994_adc2_dac2_vu_bits[i].reg, |
1055 | val: snd_soc_component_read(component, |
1056 | reg: wm8994_adc2_dac2_vu_bits[i].reg)); |
1057 | } |
1058 | |
1059 | static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enable) |
1060 | { |
1061 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1062 | unsigned int offset, val, clk_idx; |
1063 | int ret; |
1064 | |
1065 | if (aif) |
1066 | offset = 4; |
1067 | else |
1068 | offset = 0; |
1069 | |
1070 | val = snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1 + offset); |
1071 | val &= WM8994_AIF1CLK_SRC_MASK; |
1072 | |
1073 | switch (val) { |
1074 | case 0: |
1075 | clk_idx = WM8994_MCLK1; |
1076 | break; |
1077 | case 1: |
1078 | clk_idx = WM8994_MCLK2; |
1079 | break; |
1080 | default: |
1081 | return 0; |
1082 | } |
1083 | |
1084 | if (enable) { |
1085 | ret = clk_prepare_enable(clk: wm8994->mclk[clk_idx].clk); |
1086 | if (ret < 0) { |
1087 | dev_err(component->dev, "Failed to enable MCLK%d\n" , |
1088 | clk_idx); |
1089 | return ret; |
1090 | } |
1091 | } else { |
1092 | clk_disable_unprepare(clk: wm8994->mclk[clk_idx].clk); |
1093 | } |
1094 | |
1095 | return 0; |
1096 | } |
1097 | |
1098 | static int aif1clk_ev(struct snd_soc_dapm_widget *w, |
1099 | struct snd_kcontrol *kcontrol, int event) |
1100 | { |
1101 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1102 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1103 | struct wm8994 *control = wm8994->wm8994; |
1104 | int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; |
1105 | int ret; |
1106 | int dac; |
1107 | int adc; |
1108 | int val; |
1109 | |
1110 | switch (control->type) { |
1111 | case WM8994: |
1112 | case WM8958: |
1113 | mask |= WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA; |
1114 | break; |
1115 | default: |
1116 | break; |
1117 | } |
1118 | |
1119 | switch (event) { |
1120 | case SND_SOC_DAPM_PRE_PMU: |
1121 | ret = aif_mclk_set(component, aif: 0, enable: true); |
1122 | if (ret < 0) |
1123 | return ret; |
1124 | |
1125 | /* Don't enable timeslot 2 if not in use */ |
1126 | if (wm8994->channels[0] <= 2) |
1127 | mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); |
1128 | |
1129 | val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_1); |
1130 | if ((val & WM8994_AIF1ADCL_SRC) && |
1131 | (val & WM8994_AIF1ADCR_SRC)) |
1132 | adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; |
1133 | else if (!(val & WM8994_AIF1ADCL_SRC) && |
1134 | !(val & WM8994_AIF1ADCR_SRC)) |
1135 | adc = WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; |
1136 | else |
1137 | adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | |
1138 | WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; |
1139 | |
1140 | val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_2); |
1141 | if ((val & WM8994_AIF1DACL_SRC) && |
1142 | (val & WM8994_AIF1DACR_SRC)) |
1143 | dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; |
1144 | else if (!(val & WM8994_AIF1DACL_SRC) && |
1145 | !(val & WM8994_AIF1DACR_SRC)) |
1146 | dac = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; |
1147 | else |
1148 | dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA | |
1149 | WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; |
1150 | |
1151 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, |
1152 | mask, val: adc); |
1153 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1154 | mask, val: dac); |
1155 | snd_soc_component_update_bits(component, WM8994_CLOCKING_1, |
1156 | WM8994_AIF1DSPCLK_ENA | |
1157 | WM8994_SYSDSPCLK_ENA, |
1158 | WM8994_AIF1DSPCLK_ENA | |
1159 | WM8994_SYSDSPCLK_ENA); |
1160 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, mask, |
1161 | WM8994_AIF1ADC1R_ENA | |
1162 | WM8994_AIF1ADC1L_ENA | |
1163 | WM8994_AIF1ADC2R_ENA | |
1164 | WM8994_AIF1ADC2L_ENA); |
1165 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, mask, |
1166 | WM8994_AIF1DAC1R_ENA | |
1167 | WM8994_AIF1DAC1L_ENA | |
1168 | WM8994_AIF1DAC2R_ENA | |
1169 | WM8994_AIF1DAC2L_ENA); |
1170 | break; |
1171 | |
1172 | case SND_SOC_DAPM_POST_PMU: |
1173 | wm8994_update_vu_bits(component); |
1174 | break; |
1175 | |
1176 | case SND_SOC_DAPM_PRE_PMD: |
1177 | case SND_SOC_DAPM_POST_PMD: |
1178 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1179 | mask, val: 0); |
1180 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, |
1181 | mask, val: 0); |
1182 | |
1183 | val = snd_soc_component_read(component, WM8994_CLOCKING_1); |
1184 | if (val & WM8994_AIF2DSPCLK_ENA) |
1185 | val = WM8994_SYSDSPCLK_ENA; |
1186 | else |
1187 | val = 0; |
1188 | snd_soc_component_update_bits(component, WM8994_CLOCKING_1, |
1189 | WM8994_SYSDSPCLK_ENA | |
1190 | WM8994_AIF1DSPCLK_ENA, val); |
1191 | break; |
1192 | } |
1193 | |
1194 | switch (event) { |
1195 | case SND_SOC_DAPM_POST_PMD: |
1196 | aif_mclk_set(component, aif: 0, enable: false); |
1197 | break; |
1198 | } |
1199 | |
1200 | return 0; |
1201 | } |
1202 | |
1203 | static int aif2clk_ev(struct snd_soc_dapm_widget *w, |
1204 | struct snd_kcontrol *kcontrol, int event) |
1205 | { |
1206 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1207 | int ret; |
1208 | int dac; |
1209 | int adc; |
1210 | int val; |
1211 | |
1212 | switch (event) { |
1213 | case SND_SOC_DAPM_PRE_PMU: |
1214 | ret = aif_mclk_set(component, aif: 1, enable: true); |
1215 | if (ret < 0) |
1216 | return ret; |
1217 | |
1218 | val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_1); |
1219 | if ((val & WM8994_AIF2ADCL_SRC) && |
1220 | (val & WM8994_AIF2ADCR_SRC)) |
1221 | adc = WM8994_AIF2ADCR_ENA; |
1222 | else if (!(val & WM8994_AIF2ADCL_SRC) && |
1223 | !(val & WM8994_AIF2ADCR_SRC)) |
1224 | adc = WM8994_AIF2ADCL_ENA; |
1225 | else |
1226 | adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; |
1227 | |
1228 | |
1229 | val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_2); |
1230 | if ((val & WM8994_AIF2DACL_SRC) && |
1231 | (val & WM8994_AIF2DACR_SRC)) |
1232 | dac = WM8994_AIF2DACR_ENA; |
1233 | else if (!(val & WM8994_AIF2DACL_SRC) && |
1234 | !(val & WM8994_AIF2DACR_SRC)) |
1235 | dac = WM8994_AIF2DACL_ENA; |
1236 | else |
1237 | dac = WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA; |
1238 | |
1239 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, |
1240 | WM8994_AIF2ADCL_ENA | |
1241 | WM8994_AIF2ADCR_ENA, val: adc); |
1242 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1243 | WM8994_AIF2DACL_ENA | |
1244 | WM8994_AIF2DACR_ENA, val: dac); |
1245 | snd_soc_component_update_bits(component, WM8994_CLOCKING_1, |
1246 | WM8994_AIF2DSPCLK_ENA | |
1247 | WM8994_SYSDSPCLK_ENA, |
1248 | WM8994_AIF2DSPCLK_ENA | |
1249 | WM8994_SYSDSPCLK_ENA); |
1250 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, |
1251 | WM8994_AIF2ADCL_ENA | |
1252 | WM8994_AIF2ADCR_ENA, |
1253 | WM8994_AIF2ADCL_ENA | |
1254 | WM8994_AIF2ADCR_ENA); |
1255 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1256 | WM8994_AIF2DACL_ENA | |
1257 | WM8994_AIF2DACR_ENA, |
1258 | WM8994_AIF2DACL_ENA | |
1259 | WM8994_AIF2DACR_ENA); |
1260 | break; |
1261 | |
1262 | case SND_SOC_DAPM_POST_PMU: |
1263 | wm8994_update_vu_bits(component); |
1264 | break; |
1265 | |
1266 | case SND_SOC_DAPM_PRE_PMD: |
1267 | case SND_SOC_DAPM_POST_PMD: |
1268 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1269 | WM8994_AIF2DACL_ENA | |
1270 | WM8994_AIF2DACR_ENA, val: 0); |
1271 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, |
1272 | WM8994_AIF2ADCL_ENA | |
1273 | WM8994_AIF2ADCR_ENA, val: 0); |
1274 | |
1275 | val = snd_soc_component_read(component, WM8994_CLOCKING_1); |
1276 | if (val & WM8994_AIF1DSPCLK_ENA) |
1277 | val = WM8994_SYSDSPCLK_ENA; |
1278 | else |
1279 | val = 0; |
1280 | snd_soc_component_update_bits(component, WM8994_CLOCKING_1, |
1281 | WM8994_SYSDSPCLK_ENA | |
1282 | WM8994_AIF2DSPCLK_ENA, val); |
1283 | break; |
1284 | } |
1285 | |
1286 | switch (event) { |
1287 | case SND_SOC_DAPM_POST_PMD: |
1288 | aif_mclk_set(component, aif: 1, enable: false); |
1289 | break; |
1290 | } |
1291 | |
1292 | return 0; |
1293 | } |
1294 | |
1295 | static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, |
1296 | struct snd_kcontrol *kcontrol, int event) |
1297 | { |
1298 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1299 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1300 | |
1301 | switch (event) { |
1302 | case SND_SOC_DAPM_PRE_PMU: |
1303 | wm8994->aif1clk_enable = 1; |
1304 | break; |
1305 | case SND_SOC_DAPM_POST_PMD: |
1306 | wm8994->aif1clk_disable = 1; |
1307 | break; |
1308 | } |
1309 | |
1310 | return 0; |
1311 | } |
1312 | |
1313 | static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, |
1314 | struct snd_kcontrol *kcontrol, int event) |
1315 | { |
1316 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1317 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1318 | |
1319 | switch (event) { |
1320 | case SND_SOC_DAPM_PRE_PMU: |
1321 | wm8994->aif2clk_enable = 1; |
1322 | break; |
1323 | case SND_SOC_DAPM_POST_PMD: |
1324 | wm8994->aif2clk_disable = 1; |
1325 | break; |
1326 | } |
1327 | |
1328 | return 0; |
1329 | } |
1330 | |
1331 | static int late_enable_ev(struct snd_soc_dapm_widget *w, |
1332 | struct snd_kcontrol *kcontrol, int event) |
1333 | { |
1334 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1335 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1336 | |
1337 | switch (event) { |
1338 | case SND_SOC_DAPM_PRE_PMU: |
1339 | if (wm8994->aif1clk_enable) { |
1340 | aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); |
1341 | snd_soc_component_update_bits(component, WM8994_AIF1_CLOCKING_1, |
1342 | WM8994_AIF1CLK_ENA_MASK, |
1343 | WM8994_AIF1CLK_ENA); |
1344 | aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); |
1345 | wm8994->aif1clk_enable = 0; |
1346 | } |
1347 | if (wm8994->aif2clk_enable) { |
1348 | aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); |
1349 | snd_soc_component_update_bits(component, WM8994_AIF2_CLOCKING_1, |
1350 | WM8994_AIF2CLK_ENA_MASK, |
1351 | WM8994_AIF2CLK_ENA); |
1352 | aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); |
1353 | wm8994->aif2clk_enable = 0; |
1354 | } |
1355 | break; |
1356 | } |
1357 | |
1358 | /* We may also have postponed startup of DSP, handle that. */ |
1359 | wm8958_aif_ev(w, kcontrol, event); |
1360 | |
1361 | return 0; |
1362 | } |
1363 | |
1364 | static int late_disable_ev(struct snd_soc_dapm_widget *w, |
1365 | struct snd_kcontrol *kcontrol, int event) |
1366 | { |
1367 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1368 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
1369 | |
1370 | switch (event) { |
1371 | case SND_SOC_DAPM_POST_PMD: |
1372 | if (wm8994->aif1clk_disable) { |
1373 | aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); |
1374 | snd_soc_component_update_bits(component, WM8994_AIF1_CLOCKING_1, |
1375 | WM8994_AIF1CLK_ENA_MASK, val: 0); |
1376 | aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); |
1377 | wm8994->aif1clk_disable = 0; |
1378 | } |
1379 | if (wm8994->aif2clk_disable) { |
1380 | aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); |
1381 | snd_soc_component_update_bits(component, WM8994_AIF2_CLOCKING_1, |
1382 | WM8994_AIF2CLK_ENA_MASK, val: 0); |
1383 | aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); |
1384 | wm8994->aif2clk_disable = 0; |
1385 | } |
1386 | break; |
1387 | } |
1388 | |
1389 | return 0; |
1390 | } |
1391 | |
1392 | static int adc_mux_ev(struct snd_soc_dapm_widget *w, |
1393 | struct snd_kcontrol *kcontrol, int event) |
1394 | { |
1395 | late_enable_ev(w, kcontrol, event); |
1396 | return 0; |
1397 | } |
1398 | |
1399 | static int micbias_ev(struct snd_soc_dapm_widget *w, |
1400 | struct snd_kcontrol *kcontrol, int event) |
1401 | { |
1402 | late_enable_ev(w, kcontrol, event); |
1403 | return 0; |
1404 | } |
1405 | |
1406 | static int dac_ev(struct snd_soc_dapm_widget *w, |
1407 | struct snd_kcontrol *kcontrol, int event) |
1408 | { |
1409 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1410 | unsigned int mask = 1 << w->shift; |
1411 | |
1412 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_5, |
1413 | mask, val: mask); |
1414 | return 0; |
1415 | } |
1416 | |
1417 | static const char *adc_mux_text[] = { |
1418 | "ADC" , |
1419 | "DMIC" , |
1420 | }; |
1421 | |
1422 | static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); |
1423 | |
1424 | static const struct snd_kcontrol_new adcl_mux = |
1425 | SOC_DAPM_ENUM("ADCL Mux" , adc_enum); |
1426 | |
1427 | static const struct snd_kcontrol_new adcr_mux = |
1428 | SOC_DAPM_ENUM("ADCR Mux" , adc_enum); |
1429 | |
1430 | static const struct snd_kcontrol_new left_speaker_mixer[] = { |
1431 | SOC_DAPM_SINGLE("DAC2 Switch" , WM8994_SPEAKER_MIXER, 9, 1, 0), |
1432 | SOC_DAPM_SINGLE("Input Switch" , WM8994_SPEAKER_MIXER, 7, 1, 0), |
1433 | SOC_DAPM_SINGLE("IN1LP Switch" , WM8994_SPEAKER_MIXER, 5, 1, 0), |
1434 | SOC_DAPM_SINGLE("Output Switch" , WM8994_SPEAKER_MIXER, 3, 1, 0), |
1435 | SOC_DAPM_SINGLE("DAC1 Switch" , WM8994_SPEAKER_MIXER, 1, 1, 0), |
1436 | }; |
1437 | |
1438 | static const struct snd_kcontrol_new right_speaker_mixer[] = { |
1439 | SOC_DAPM_SINGLE("DAC2 Switch" , WM8994_SPEAKER_MIXER, 8, 1, 0), |
1440 | SOC_DAPM_SINGLE("Input Switch" , WM8994_SPEAKER_MIXER, 6, 1, 0), |
1441 | SOC_DAPM_SINGLE("IN1RP Switch" , WM8994_SPEAKER_MIXER, 4, 1, 0), |
1442 | SOC_DAPM_SINGLE("Output Switch" , WM8994_SPEAKER_MIXER, 2, 1, 0), |
1443 | SOC_DAPM_SINGLE("DAC1 Switch" , WM8994_SPEAKER_MIXER, 0, 1, 0), |
1444 | }; |
1445 | |
1446 | /* Debugging; dump chip status after DAPM transitions */ |
1447 | static int post_ev(struct snd_soc_dapm_widget *w, |
1448 | struct snd_kcontrol *kcontrol, int event) |
1449 | { |
1450 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1451 | dev_dbg(component->dev, "SRC status: %x\n" , |
1452 | snd_soc_component_read(component, |
1453 | WM8994_RATE_STATUS)); |
1454 | return 0; |
1455 | } |
1456 | |
1457 | static const struct snd_kcontrol_new aif1adc1l_mix[] = { |
1458 | SOC_DAPM_SINGLE("ADC/DMIC Switch" , WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, |
1459 | 1, 1, 0), |
1460 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, |
1461 | 0, 1, 0), |
1462 | }; |
1463 | |
1464 | static const struct snd_kcontrol_new aif1adc1r_mix[] = { |
1465 | SOC_DAPM_SINGLE("ADC/DMIC Switch" , WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, |
1466 | 1, 1, 0), |
1467 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, |
1468 | 0, 1, 0), |
1469 | }; |
1470 | |
1471 | static const struct snd_kcontrol_new aif1adc2l_mix[] = { |
1472 | SOC_DAPM_SINGLE("DMIC Switch" , WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, |
1473 | 1, 1, 0), |
1474 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, |
1475 | 0, 1, 0), |
1476 | }; |
1477 | |
1478 | static const struct snd_kcontrol_new aif1adc2r_mix[] = { |
1479 | SOC_DAPM_SINGLE("DMIC Switch" , WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, |
1480 | 1, 1, 0), |
1481 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, |
1482 | 0, 1, 0), |
1483 | }; |
1484 | |
1485 | static const struct snd_kcontrol_new aif2dac2l_mix[] = { |
1486 | SOC_DAPM_SINGLE("Right Sidetone Switch" , WM8994_DAC2_LEFT_MIXER_ROUTING, |
1487 | 5, 1, 0), |
1488 | SOC_DAPM_SINGLE("Left Sidetone Switch" , WM8994_DAC2_LEFT_MIXER_ROUTING, |
1489 | 4, 1, 0), |
1490 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_DAC2_LEFT_MIXER_ROUTING, |
1491 | 2, 1, 0), |
1492 | SOC_DAPM_SINGLE("AIF1.2 Switch" , WM8994_DAC2_LEFT_MIXER_ROUTING, |
1493 | 1, 1, 0), |
1494 | SOC_DAPM_SINGLE("AIF1.1 Switch" , WM8994_DAC2_LEFT_MIXER_ROUTING, |
1495 | 0, 1, 0), |
1496 | }; |
1497 | |
1498 | static const struct snd_kcontrol_new aif2dac2r_mix[] = { |
1499 | SOC_DAPM_SINGLE("Right Sidetone Switch" , WM8994_DAC2_RIGHT_MIXER_ROUTING, |
1500 | 5, 1, 0), |
1501 | SOC_DAPM_SINGLE("Left Sidetone Switch" , WM8994_DAC2_RIGHT_MIXER_ROUTING, |
1502 | 4, 1, 0), |
1503 | SOC_DAPM_SINGLE("AIF2 Switch" , WM8994_DAC2_RIGHT_MIXER_ROUTING, |
1504 | 2, 1, 0), |
1505 | SOC_DAPM_SINGLE("AIF1.2 Switch" , WM8994_DAC2_RIGHT_MIXER_ROUTING, |
1506 | 1, 1, 0), |
1507 | SOC_DAPM_SINGLE("AIF1.1 Switch" , WM8994_DAC2_RIGHT_MIXER_ROUTING, |
1508 | 0, 1, 0), |
1509 | }; |
1510 | |
1511 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ |
1512 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
1513 | snd_soc_dapm_get_volsw, wm8994_put_class_w) |
1514 | |
1515 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, |
1516 | struct snd_ctl_elem_value *ucontrol) |
1517 | { |
1518 | struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); |
1519 | int ret; |
1520 | |
1521 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); |
1522 | |
1523 | wm_hubs_update_class_w(component); |
1524 | |
1525 | return ret; |
1526 | } |
1527 | |
1528 | static const struct snd_kcontrol_new dac1l_mix[] = { |
1529 | WM8994_CLASS_W_SWITCH("Right Sidetone Switch" , WM8994_DAC1_LEFT_MIXER_ROUTING, |
1530 | 5, 1, 0), |
1531 | WM8994_CLASS_W_SWITCH("Left Sidetone Switch" , WM8994_DAC1_LEFT_MIXER_ROUTING, |
1532 | 4, 1, 0), |
1533 | WM8994_CLASS_W_SWITCH("AIF2 Switch" , WM8994_DAC1_LEFT_MIXER_ROUTING, |
1534 | 2, 1, 0), |
1535 | WM8994_CLASS_W_SWITCH("AIF1.2 Switch" , WM8994_DAC1_LEFT_MIXER_ROUTING, |
1536 | 1, 1, 0), |
1537 | WM8994_CLASS_W_SWITCH("AIF1.1 Switch" , WM8994_DAC1_LEFT_MIXER_ROUTING, |
1538 | 0, 1, 0), |
1539 | }; |
1540 | |
1541 | static const struct snd_kcontrol_new dac1r_mix[] = { |
1542 | WM8994_CLASS_W_SWITCH("Right Sidetone Switch" , WM8994_DAC1_RIGHT_MIXER_ROUTING, |
1543 | 5, 1, 0), |
1544 | WM8994_CLASS_W_SWITCH("Left Sidetone Switch" , WM8994_DAC1_RIGHT_MIXER_ROUTING, |
1545 | 4, 1, 0), |
1546 | WM8994_CLASS_W_SWITCH("AIF2 Switch" , WM8994_DAC1_RIGHT_MIXER_ROUTING, |
1547 | 2, 1, 0), |
1548 | WM8994_CLASS_W_SWITCH("AIF1.2 Switch" , WM8994_DAC1_RIGHT_MIXER_ROUTING, |
1549 | 1, 1, 0), |
1550 | WM8994_CLASS_W_SWITCH("AIF1.1 Switch" , WM8994_DAC1_RIGHT_MIXER_ROUTING, |
1551 | 0, 1, 0), |
1552 | }; |
1553 | |
1554 | static const char *sidetone_text[] = { |
1555 | "ADC/DMIC1" , "DMIC2" , |
1556 | }; |
1557 | |
1558 | static SOC_ENUM_SINGLE_DECL(sidetone1_enum, |
1559 | WM8994_SIDETONE, 0, sidetone_text); |
1560 | |
1561 | static const struct snd_kcontrol_new sidetone1_mux = |
1562 | SOC_DAPM_ENUM("Left Sidetone Mux" , sidetone1_enum); |
1563 | |
1564 | static SOC_ENUM_SINGLE_DECL(sidetone2_enum, |
1565 | WM8994_SIDETONE, 1, sidetone_text); |
1566 | |
1567 | static const struct snd_kcontrol_new sidetone2_mux = |
1568 | SOC_DAPM_ENUM("Right Sidetone Mux" , sidetone2_enum); |
1569 | |
1570 | static const char *aif1dac_text[] = { |
1571 | "AIF1DACDAT" , "AIF3DACDAT" , |
1572 | }; |
1573 | |
1574 | static const char *loopback_text[] = { |
1575 | "None" , "ADCDAT" , |
1576 | }; |
1577 | |
1578 | static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum, |
1579 | WM8994_AIF1_CONTROL_2, |
1580 | WM8994_AIF1_LOOPBACK_SHIFT, |
1581 | loopback_text); |
1582 | |
1583 | static const struct snd_kcontrol_new aif1_loopback = |
1584 | SOC_DAPM_ENUM("AIF1 Loopback" , aif1_loopback_enum); |
1585 | |
1586 | static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum, |
1587 | WM8994_AIF2_CONTROL_2, |
1588 | WM8994_AIF2_LOOPBACK_SHIFT, |
1589 | loopback_text); |
1590 | |
1591 | static const struct snd_kcontrol_new aif2_loopback = |
1592 | SOC_DAPM_ENUM("AIF2 Loopback" , aif2_loopback_enum); |
1593 | |
1594 | static SOC_ENUM_SINGLE_DECL(aif1dac_enum, |
1595 | WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text); |
1596 | |
1597 | static const struct snd_kcontrol_new aif1dac_mux = |
1598 | SOC_DAPM_ENUM("AIF1DAC Mux" , aif1dac_enum); |
1599 | |
1600 | static const char *aif2dac_text[] = { |
1601 | "AIF2DACDAT" , "AIF3DACDAT" , |
1602 | }; |
1603 | |
1604 | static SOC_ENUM_SINGLE_DECL(aif2dac_enum, |
1605 | WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text); |
1606 | |
1607 | static const struct snd_kcontrol_new aif2dac_mux = |
1608 | SOC_DAPM_ENUM("AIF2DAC Mux" , aif2dac_enum); |
1609 | |
1610 | static const char *aif2adc_text[] = { |
1611 | "AIF2ADCDAT" , "AIF3DACDAT" , |
1612 | }; |
1613 | |
1614 | static SOC_ENUM_SINGLE_DECL(aif2adc_enum, |
1615 | WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text); |
1616 | |
1617 | static const struct snd_kcontrol_new aif2adc_mux = |
1618 | SOC_DAPM_ENUM("AIF2ADC Mux" , aif2adc_enum); |
1619 | |
1620 | static const char *aif3adc_text[] = { |
1621 | "AIF1ADCDAT" , "AIF2ADCDAT" , "AIF2DACDAT" , "Mono PCM" , |
1622 | }; |
1623 | |
1624 | static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum, |
1625 | WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); |
1626 | |
1627 | static const struct snd_kcontrol_new wm8994_aif3adc_mux = |
1628 | SOC_DAPM_ENUM("AIF3ADC Mux" , wm8994_aif3adc_enum); |
1629 | |
1630 | static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum, |
1631 | WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); |
1632 | |
1633 | static const struct snd_kcontrol_new wm8958_aif3adc_mux = |
1634 | SOC_DAPM_ENUM("AIF3ADC Mux" , wm8958_aif3adc_enum); |
1635 | |
1636 | static const char *mono_pcm_out_text[] = { |
1637 | "None" , "AIF2ADCL" , "AIF2ADCR" , |
1638 | }; |
1639 | |
1640 | static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum, |
1641 | WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text); |
1642 | |
1643 | static const struct snd_kcontrol_new mono_pcm_out_mux = |
1644 | SOC_DAPM_ENUM("Mono PCM Out Mux" , mono_pcm_out_enum); |
1645 | |
1646 | static const char *aif2dac_src_text[] = { |
1647 | "AIF2" , "AIF3" , |
1648 | }; |
1649 | |
1650 | /* Note that these two control shouldn't be simultaneously switched to AIF3 */ |
1651 | static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum, |
1652 | WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text); |
1653 | |
1654 | static const struct snd_kcontrol_new aif2dacl_src_mux = |
1655 | SOC_DAPM_ENUM("AIF2DACL Mux" , aif2dacl_src_enum); |
1656 | |
1657 | static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum, |
1658 | WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text); |
1659 | |
1660 | static const struct snd_kcontrol_new aif2dacr_src_mux = |
1661 | SOC_DAPM_ENUM("AIF2DACR Mux" , aif2dacr_src_enum); |
1662 | |
1663 | static const struct snd_soc_dapm_widget wm8994_lateclk_revd_widgets[] = { |
1664 | SND_SOC_DAPM_SUPPLY("AIF1CLK" , SND_SOC_NOPM, 0, 0, aif1clk_late_ev, |
1665 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1666 | SND_SOC_DAPM_SUPPLY("AIF2CLK" , SND_SOC_NOPM, 0, 0, aif2clk_late_ev, |
1667 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1668 | |
1669 | SND_SOC_DAPM_PGA_E("Late DAC1L Enable PGA" , SND_SOC_NOPM, 0, 0, NULL, 0, |
1670 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1671 | SND_SOC_DAPM_PGA_E("Late DAC1R Enable PGA" , SND_SOC_NOPM, 0, 0, NULL, 0, |
1672 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1673 | SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA" , SND_SOC_NOPM, 0, 0, NULL, 0, |
1674 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1675 | SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA" , SND_SOC_NOPM, 0, 0, NULL, 0, |
1676 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1677 | SND_SOC_DAPM_PGA_E("Direct Voice" , SND_SOC_NOPM, 0, 0, NULL, 0, |
1678 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1679 | |
1680 | SND_SOC_DAPM_MIXER_E("SPKL" , WM8994_POWER_MANAGEMENT_3, 8, 0, |
1681 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer), |
1682 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1683 | SND_SOC_DAPM_MIXER_E("SPKR" , WM8994_POWER_MANAGEMENT_3, 9, 0, |
1684 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer), |
1685 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1686 | SND_SOC_DAPM_MUX_E("Left Headphone Mux" , SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux, |
1687 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1688 | SND_SOC_DAPM_MUX_E("Right Headphone Mux" , SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux, |
1689 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1690 | |
1691 | SND_SOC_DAPM_POST("Late Disable PGA" , late_disable_ev) |
1692 | }; |
1693 | |
1694 | static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { |
1695 | SND_SOC_DAPM_SUPPLY("AIF1CLK" , WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, |
1696 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1697 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1698 | SND_SOC_DAPM_SUPPLY("AIF2CLK" , WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, |
1699 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1700 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1701 | SND_SOC_DAPM_PGA("Direct Voice" , SND_SOC_NOPM, 0, 0, NULL, 0), |
1702 | SND_SOC_DAPM_MIXER("SPKL" , WM8994_POWER_MANAGEMENT_3, 8, 0, |
1703 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), |
1704 | SND_SOC_DAPM_MIXER("SPKR" , WM8994_POWER_MANAGEMENT_3, 9, 0, |
1705 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), |
1706 | SND_SOC_DAPM_MUX("Left Headphone Mux" , SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux), |
1707 | SND_SOC_DAPM_MUX("Right Headphone Mux" , SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux), |
1708 | }; |
1709 | |
1710 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { |
1711 | SND_SOC_DAPM_DAC_E("DAC2L" , NULL, SND_SOC_NOPM, 3, 0, |
1712 | dac_ev, SND_SOC_DAPM_PRE_PMU), |
1713 | SND_SOC_DAPM_DAC_E("DAC2R" , NULL, SND_SOC_NOPM, 2, 0, |
1714 | dac_ev, SND_SOC_DAPM_PRE_PMU), |
1715 | SND_SOC_DAPM_DAC_E("DAC1L" , NULL, SND_SOC_NOPM, 1, 0, |
1716 | dac_ev, SND_SOC_DAPM_PRE_PMU), |
1717 | SND_SOC_DAPM_DAC_E("DAC1R" , NULL, SND_SOC_NOPM, 0, 0, |
1718 | dac_ev, SND_SOC_DAPM_PRE_PMU), |
1719 | }; |
1720 | |
1721 | static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { |
1722 | SND_SOC_DAPM_DAC("DAC2L" , NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), |
1723 | SND_SOC_DAPM_DAC("DAC2R" , NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), |
1724 | SND_SOC_DAPM_DAC("DAC1L" , NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), |
1725 | SND_SOC_DAPM_DAC("DAC1R" , NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), |
1726 | }; |
1727 | |
1728 | static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { |
1729 | SND_SOC_DAPM_MUX_E("ADCL Mux" , WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, |
1730 | adc_mux_ev, SND_SOC_DAPM_PRE_PMU), |
1731 | SND_SOC_DAPM_MUX_E("ADCR Mux" , WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, |
1732 | adc_mux_ev, SND_SOC_DAPM_PRE_PMU), |
1733 | }; |
1734 | |
1735 | static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { |
1736 | SND_SOC_DAPM_MUX("ADCL Mux" , WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), |
1737 | SND_SOC_DAPM_MUX("ADCR Mux" , WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), |
1738 | }; |
1739 | |
1740 | static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { |
1741 | SND_SOC_DAPM_INPUT("DMIC1DAT" ), |
1742 | SND_SOC_DAPM_INPUT("DMIC2DAT" ), |
1743 | SND_SOC_DAPM_INPUT("Clock" ), |
1744 | |
1745 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply" , 1, SND_SOC_NOPM, 0, 0, micbias_ev, |
1746 | SND_SOC_DAPM_PRE_PMU), |
1747 | SND_SOC_DAPM_SUPPLY("VMID" , SND_SOC_NOPM, 0, 0, vmid_event, |
1748 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1749 | |
1750 | SND_SOC_DAPM_SUPPLY("CLK_SYS" , SND_SOC_NOPM, 0, 0, clk_sys_event, |
1751 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1752 | SND_SOC_DAPM_PRE_PMD), |
1753 | |
1754 | SND_SOC_DAPM_SUPPLY("DSP1CLK" , SND_SOC_NOPM, 3, 0, NULL, 0), |
1755 | SND_SOC_DAPM_SUPPLY("DSP2CLK" , SND_SOC_NOPM, 2, 0, NULL, 0), |
1756 | SND_SOC_DAPM_SUPPLY("DSPINTCLK" , SND_SOC_NOPM, 1, 0, NULL, 0), |
1757 | |
1758 | SND_SOC_DAPM_AIF_OUT("AIF1ADC1L" , NULL, |
1759 | 0, SND_SOC_NOPM, 9, 0), |
1760 | SND_SOC_DAPM_AIF_OUT("AIF1ADC1R" , NULL, |
1761 | 0, SND_SOC_NOPM, 8, 0), |
1762 | SND_SOC_DAPM_AIF_IN_E("AIF1DAC1L" , NULL, 0, |
1763 | SND_SOC_NOPM, 9, 0, wm8958_aif_ev, |
1764 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1765 | SND_SOC_DAPM_AIF_IN_E("AIF1DAC1R" , NULL, 0, |
1766 | SND_SOC_NOPM, 8, 0, wm8958_aif_ev, |
1767 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1768 | |
1769 | SND_SOC_DAPM_AIF_OUT("AIF1ADC2L" , NULL, |
1770 | 0, SND_SOC_NOPM, 11, 0), |
1771 | SND_SOC_DAPM_AIF_OUT("AIF1ADC2R" , NULL, |
1772 | 0, SND_SOC_NOPM, 10, 0), |
1773 | SND_SOC_DAPM_AIF_IN_E("AIF1DAC2L" , NULL, 0, |
1774 | SND_SOC_NOPM, 11, 0, wm8958_aif_ev, |
1775 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1776 | SND_SOC_DAPM_AIF_IN_E("AIF1DAC2R" , NULL, 0, |
1777 | SND_SOC_NOPM, 10, 0, wm8958_aif_ev, |
1778 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1779 | |
1780 | SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer" , SND_SOC_NOPM, 0, 0, |
1781 | aif1adc1l_mix, ARRAY_SIZE(aif1adc1l_mix)), |
1782 | SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer" , SND_SOC_NOPM, 0, 0, |
1783 | aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), |
1784 | |
1785 | SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer" , SND_SOC_NOPM, 0, 0, |
1786 | aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)), |
1787 | SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer" , SND_SOC_NOPM, 0, 0, |
1788 | aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)), |
1789 | |
1790 | SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer" , SND_SOC_NOPM, 0, 0, |
1791 | aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), |
1792 | SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer" , SND_SOC_NOPM, 0, 0, |
1793 | aif2dac2r_mix, ARRAY_SIZE(aif2dac2r_mix)), |
1794 | |
1795 | SND_SOC_DAPM_MUX("Left Sidetone" , SND_SOC_NOPM, 0, 0, &sidetone1_mux), |
1796 | SND_SOC_DAPM_MUX("Right Sidetone" , SND_SOC_NOPM, 0, 0, &sidetone2_mux), |
1797 | |
1798 | SND_SOC_DAPM_MIXER("DAC1L Mixer" , SND_SOC_NOPM, 0, 0, |
1799 | dac1l_mix, ARRAY_SIZE(dac1l_mix)), |
1800 | SND_SOC_DAPM_MIXER("DAC1R Mixer" , SND_SOC_NOPM, 0, 0, |
1801 | dac1r_mix, ARRAY_SIZE(dac1r_mix)), |
1802 | |
1803 | SND_SOC_DAPM_AIF_OUT("AIF2ADCL" , NULL, 0, |
1804 | SND_SOC_NOPM, 13, 0), |
1805 | SND_SOC_DAPM_AIF_OUT("AIF2ADCR" , NULL, 0, |
1806 | SND_SOC_NOPM, 12, 0), |
1807 | SND_SOC_DAPM_AIF_IN_E("AIF2DACL" , NULL, 0, |
1808 | SND_SOC_NOPM, 13, 0, wm8958_aif_ev, |
1809 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1810 | SND_SOC_DAPM_AIF_IN_E("AIF2DACR" , NULL, 0, |
1811 | SND_SOC_NOPM, 12, 0, wm8958_aif_ev, |
1812 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1813 | |
1814 | SND_SOC_DAPM_AIF_IN("AIF1DACDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1815 | SND_SOC_DAPM_AIF_IN("AIF2DACDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1816 | SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1817 | SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1818 | |
1819 | SND_SOC_DAPM_MUX("AIF1DAC Mux" , SND_SOC_NOPM, 0, 0, &aif1dac_mux), |
1820 | SND_SOC_DAPM_MUX("AIF2DAC Mux" , SND_SOC_NOPM, 0, 0, &aif2dac_mux), |
1821 | SND_SOC_DAPM_MUX("AIF2ADC Mux" , SND_SOC_NOPM, 0, 0, &aif2adc_mux), |
1822 | |
1823 | SND_SOC_DAPM_AIF_IN("AIF3DACDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1824 | SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1825 | |
1826 | SND_SOC_DAPM_SUPPLY("TOCLK" , WM8994_CLOCKING_1, 4, 0, NULL, 0), |
1827 | |
1828 | SND_SOC_DAPM_ADC("DMIC2L" , NULL, WM8994_POWER_MANAGEMENT_4, 5, 0), |
1829 | SND_SOC_DAPM_ADC("DMIC2R" , NULL, WM8994_POWER_MANAGEMENT_4, 4, 0), |
1830 | SND_SOC_DAPM_ADC("DMIC1L" , NULL, WM8994_POWER_MANAGEMENT_4, 3, 0), |
1831 | SND_SOC_DAPM_ADC("DMIC1R" , NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), |
1832 | |
1833 | /* Power is done with the muxes since the ADC power also controls the |
1834 | * downsampling chain, the chip will automatically manage the analogue |
1835 | * specific portions. |
1836 | */ |
1837 | SND_SOC_DAPM_ADC("ADCL" , NULL, SND_SOC_NOPM, 1, 0), |
1838 | SND_SOC_DAPM_ADC("ADCR" , NULL, SND_SOC_NOPM, 0, 0), |
1839 | |
1840 | SND_SOC_DAPM_MUX("AIF1 Loopback" , SND_SOC_NOPM, 0, 0, &aif1_loopback), |
1841 | SND_SOC_DAPM_MUX("AIF2 Loopback" , SND_SOC_NOPM, 0, 0, &aif2_loopback), |
1842 | |
1843 | SND_SOC_DAPM_POST("Debug log" , post_ev), |
1844 | }; |
1845 | |
1846 | static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = { |
1847 | SND_SOC_DAPM_MUX("AIF3ADC Mux" , SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux), |
1848 | }; |
1849 | |
1850 | static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = { |
1851 | SND_SOC_DAPM_SUPPLY("AIF3" , WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0), |
1852 | SND_SOC_DAPM_MUX("Mono PCM Out Mux" , SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux), |
1853 | SND_SOC_DAPM_MUX("AIF2DACL Mux" , SND_SOC_NOPM, 0, 0, &aif2dacl_src_mux), |
1854 | SND_SOC_DAPM_MUX("AIF2DACR Mux" , SND_SOC_NOPM, 0, 0, &aif2dacr_src_mux), |
1855 | SND_SOC_DAPM_MUX("AIF3ADC Mux" , SND_SOC_NOPM, 0, 0, &wm8958_aif3adc_mux), |
1856 | }; |
1857 | |
1858 | static const struct snd_soc_dapm_route intercon[] = { |
1859 | { "CLK_SYS" , NULL, "AIF1CLK" , check_clk_sys }, |
1860 | { "CLK_SYS" , NULL, "AIF2CLK" , check_clk_sys }, |
1861 | |
1862 | { "DSP1CLK" , NULL, "CLK_SYS" }, |
1863 | { "DSP2CLK" , NULL, "CLK_SYS" }, |
1864 | { "DSPINTCLK" , NULL, "CLK_SYS" }, |
1865 | |
1866 | { "AIF1ADC1L" , NULL, "AIF1CLK" }, |
1867 | { "AIF1ADC1L" , NULL, "DSP1CLK" }, |
1868 | { "AIF1ADC1R" , NULL, "AIF1CLK" }, |
1869 | { "AIF1ADC1R" , NULL, "DSP1CLK" }, |
1870 | { "AIF1ADC1R" , NULL, "DSPINTCLK" }, |
1871 | |
1872 | { "AIF1DAC1L" , NULL, "AIF1CLK" }, |
1873 | { "AIF1DAC1L" , NULL, "DSP1CLK" }, |
1874 | { "AIF1DAC1R" , NULL, "AIF1CLK" }, |
1875 | { "AIF1DAC1R" , NULL, "DSP1CLK" }, |
1876 | { "AIF1DAC1R" , NULL, "DSPINTCLK" }, |
1877 | |
1878 | { "AIF1ADC2L" , NULL, "AIF1CLK" }, |
1879 | { "AIF1ADC2L" , NULL, "DSP1CLK" }, |
1880 | { "AIF1ADC2R" , NULL, "AIF1CLK" }, |
1881 | { "AIF1ADC2R" , NULL, "DSP1CLK" }, |
1882 | { "AIF1ADC2R" , NULL, "DSPINTCLK" }, |
1883 | |
1884 | { "AIF1DAC2L" , NULL, "AIF1CLK" }, |
1885 | { "AIF1DAC2L" , NULL, "DSP1CLK" }, |
1886 | { "AIF1DAC2R" , NULL, "AIF1CLK" }, |
1887 | { "AIF1DAC2R" , NULL, "DSP1CLK" }, |
1888 | { "AIF1DAC2R" , NULL, "DSPINTCLK" }, |
1889 | |
1890 | { "AIF2ADCL" , NULL, "AIF2CLK" }, |
1891 | { "AIF2ADCL" , NULL, "DSP2CLK" }, |
1892 | { "AIF2ADCR" , NULL, "AIF2CLK" }, |
1893 | { "AIF2ADCR" , NULL, "DSP2CLK" }, |
1894 | { "AIF2ADCR" , NULL, "DSPINTCLK" }, |
1895 | |
1896 | { "AIF2DACL" , NULL, "AIF2CLK" }, |
1897 | { "AIF2DACL" , NULL, "DSP2CLK" }, |
1898 | { "AIF2DACR" , NULL, "AIF2CLK" }, |
1899 | { "AIF2DACR" , NULL, "DSP2CLK" }, |
1900 | { "AIF2DACR" , NULL, "DSPINTCLK" }, |
1901 | |
1902 | { "DMIC1L" , NULL, "DMIC1DAT" }, |
1903 | { "DMIC1L" , NULL, "CLK_SYS" }, |
1904 | { "DMIC1R" , NULL, "DMIC1DAT" }, |
1905 | { "DMIC1R" , NULL, "CLK_SYS" }, |
1906 | { "DMIC2L" , NULL, "DMIC2DAT" }, |
1907 | { "DMIC2L" , NULL, "CLK_SYS" }, |
1908 | { "DMIC2R" , NULL, "DMIC2DAT" }, |
1909 | { "DMIC2R" , NULL, "CLK_SYS" }, |
1910 | |
1911 | { "ADCL" , NULL, "AIF1CLK" }, |
1912 | { "ADCL" , NULL, "DSP1CLK" }, |
1913 | { "ADCL" , NULL, "DSPINTCLK" }, |
1914 | |
1915 | { "ADCR" , NULL, "AIF1CLK" }, |
1916 | { "ADCR" , NULL, "DSP1CLK" }, |
1917 | { "ADCR" , NULL, "DSPINTCLK" }, |
1918 | |
1919 | { "ADCL Mux" , "ADC" , "ADCL" }, |
1920 | { "ADCL Mux" , "DMIC" , "DMIC1L" }, |
1921 | { "ADCR Mux" , "ADC" , "ADCR" }, |
1922 | { "ADCR Mux" , "DMIC" , "DMIC1R" }, |
1923 | |
1924 | { "DAC1L" , NULL, "AIF1CLK" }, |
1925 | { "DAC1L" , NULL, "DSP1CLK" }, |
1926 | { "DAC1L" , NULL, "DSPINTCLK" }, |
1927 | |
1928 | { "DAC1R" , NULL, "AIF1CLK" }, |
1929 | { "DAC1R" , NULL, "DSP1CLK" }, |
1930 | { "DAC1R" , NULL, "DSPINTCLK" }, |
1931 | |
1932 | { "DAC2L" , NULL, "AIF2CLK" }, |
1933 | { "DAC2L" , NULL, "DSP2CLK" }, |
1934 | { "DAC2L" , NULL, "DSPINTCLK" }, |
1935 | |
1936 | { "DAC2R" , NULL, "AIF2DACR" }, |
1937 | { "DAC2R" , NULL, "AIF2CLK" }, |
1938 | { "DAC2R" , NULL, "DSP2CLK" }, |
1939 | { "DAC2R" , NULL, "DSPINTCLK" }, |
1940 | |
1941 | { "TOCLK" , NULL, "CLK_SYS" }, |
1942 | |
1943 | { "AIF1DACDAT" , NULL, "AIF1 Playback" }, |
1944 | { "AIF2DACDAT" , NULL, "AIF2 Playback" }, |
1945 | { "AIF3DACDAT" , NULL, "AIF3 Playback" }, |
1946 | |
1947 | { "AIF1 Capture" , NULL, "AIF1ADCDAT" }, |
1948 | { "AIF2 Capture" , NULL, "AIF2ADCDAT" }, |
1949 | { "AIF3 Capture" , NULL, "AIF3ADCDAT" }, |
1950 | |
1951 | /* AIF1 outputs */ |
1952 | { "AIF1ADC1L" , NULL, "AIF1ADC1L Mixer" }, |
1953 | { "AIF1ADC1L Mixer" , "ADC/DMIC Switch" , "ADCL Mux" }, |
1954 | { "AIF1ADC1L Mixer" , "AIF2 Switch" , "AIF2DACL" }, |
1955 | |
1956 | { "AIF1ADC1R" , NULL, "AIF1ADC1R Mixer" }, |
1957 | { "AIF1ADC1R Mixer" , "ADC/DMIC Switch" , "ADCR Mux" }, |
1958 | { "AIF1ADC1R Mixer" , "AIF2 Switch" , "AIF2DACR" }, |
1959 | |
1960 | { "AIF1ADC2L" , NULL, "AIF1ADC2L Mixer" }, |
1961 | { "AIF1ADC2L Mixer" , "DMIC Switch" , "DMIC2L" }, |
1962 | { "AIF1ADC2L Mixer" , "AIF2 Switch" , "AIF2DACL" }, |
1963 | |
1964 | { "AIF1ADC2R" , NULL, "AIF1ADC2R Mixer" }, |
1965 | { "AIF1ADC2R Mixer" , "DMIC Switch" , "DMIC2R" }, |
1966 | { "AIF1ADC2R Mixer" , "AIF2 Switch" , "AIF2DACR" }, |
1967 | |
1968 | /* Pin level routing for AIF3 */ |
1969 | { "AIF1DAC1L" , NULL, "AIF1DAC Mux" }, |
1970 | { "AIF1DAC1R" , NULL, "AIF1DAC Mux" }, |
1971 | { "AIF1DAC2L" , NULL, "AIF1DAC Mux" }, |
1972 | { "AIF1DAC2R" , NULL, "AIF1DAC Mux" }, |
1973 | |
1974 | { "AIF1DAC Mux" , "AIF1DACDAT" , "AIF1 Loopback" }, |
1975 | { "AIF1DAC Mux" , "AIF3DACDAT" , "AIF3DACDAT" }, |
1976 | { "AIF2DAC Mux" , "AIF2DACDAT" , "AIF2 Loopback" }, |
1977 | { "AIF2DAC Mux" , "AIF3DACDAT" , "AIF3DACDAT" }, |
1978 | { "AIF2ADC Mux" , "AIF2ADCDAT" , "AIF2ADCL" }, |
1979 | { "AIF2ADC Mux" , "AIF2ADCDAT" , "AIF2ADCR" }, |
1980 | { "AIF2ADC Mux" , "AIF3DACDAT" , "AIF3ADCDAT" }, |
1981 | |
1982 | /* DAC1 inputs */ |
1983 | { "DAC1L Mixer" , "AIF2 Switch" , "AIF2DACL" }, |
1984 | { "DAC1L Mixer" , "AIF1.2 Switch" , "AIF1DAC2L" }, |
1985 | { "DAC1L Mixer" , "AIF1.1 Switch" , "AIF1DAC1L" }, |
1986 | { "DAC1L Mixer" , "Left Sidetone Switch" , "Left Sidetone" }, |
1987 | { "DAC1L Mixer" , "Right Sidetone Switch" , "Right Sidetone" }, |
1988 | |
1989 | { "DAC1R Mixer" , "AIF2 Switch" , "AIF2DACR" }, |
1990 | { "DAC1R Mixer" , "AIF1.2 Switch" , "AIF1DAC2R" }, |
1991 | { "DAC1R Mixer" , "AIF1.1 Switch" , "AIF1DAC1R" }, |
1992 | { "DAC1R Mixer" , "Left Sidetone Switch" , "Left Sidetone" }, |
1993 | { "DAC1R Mixer" , "Right Sidetone Switch" , "Right Sidetone" }, |
1994 | |
1995 | /* DAC2/AIF2 outputs */ |
1996 | { "AIF2ADCL" , NULL, "AIF2DAC2L Mixer" }, |
1997 | { "AIF2DAC2L Mixer" , "AIF2 Switch" , "AIF2DACL" }, |
1998 | { "AIF2DAC2L Mixer" , "AIF1.2 Switch" , "AIF1DAC2L" }, |
1999 | { "AIF2DAC2L Mixer" , "AIF1.1 Switch" , "AIF1DAC1L" }, |
2000 | { "AIF2DAC2L Mixer" , "Left Sidetone Switch" , "Left Sidetone" }, |
2001 | { "AIF2DAC2L Mixer" , "Right Sidetone Switch" , "Right Sidetone" }, |
2002 | |
2003 | { "AIF2ADCR" , NULL, "AIF2DAC2R Mixer" }, |
2004 | { "AIF2DAC2R Mixer" , "AIF2 Switch" , "AIF2DACR" }, |
2005 | { "AIF2DAC2R Mixer" , "AIF1.2 Switch" , "AIF1DAC2R" }, |
2006 | { "AIF2DAC2R Mixer" , "AIF1.1 Switch" , "AIF1DAC1R" }, |
2007 | { "AIF2DAC2R Mixer" , "Left Sidetone Switch" , "Left Sidetone" }, |
2008 | { "AIF2DAC2R Mixer" , "Right Sidetone Switch" , "Right Sidetone" }, |
2009 | |
2010 | { "AIF1ADCDAT" , NULL, "AIF1ADC1L" }, |
2011 | { "AIF1ADCDAT" , NULL, "AIF1ADC1R" }, |
2012 | { "AIF1ADCDAT" , NULL, "AIF1ADC2L" }, |
2013 | { "AIF1ADCDAT" , NULL, "AIF1ADC2R" }, |
2014 | |
2015 | { "AIF2ADCDAT" , NULL, "AIF2ADC Mux" }, |
2016 | |
2017 | /* AIF3 output */ |
2018 | { "AIF3ADC Mux" , "AIF1ADCDAT" , "AIF1ADC1L" }, |
2019 | { "AIF3ADC Mux" , "AIF1ADCDAT" , "AIF1ADC1R" }, |
2020 | { "AIF3ADC Mux" , "AIF1ADCDAT" , "AIF1ADC2L" }, |
2021 | { "AIF3ADC Mux" , "AIF1ADCDAT" , "AIF1ADC2R" }, |
2022 | { "AIF3ADC Mux" , "AIF2ADCDAT" , "AIF2ADCL" }, |
2023 | { "AIF3ADC Mux" , "AIF2ADCDAT" , "AIF2ADCR" }, |
2024 | { "AIF3ADC Mux" , "AIF2DACDAT" , "AIF2DACL" }, |
2025 | { "AIF3ADC Mux" , "AIF2DACDAT" , "AIF2DACR" }, |
2026 | |
2027 | { "AIF3ADCDAT" , NULL, "AIF3ADC Mux" }, |
2028 | |
2029 | /* Loopback */ |
2030 | { "AIF1 Loopback" , "ADCDAT" , "AIF1ADCDAT" }, |
2031 | { "AIF1 Loopback" , "None" , "AIF1DACDAT" }, |
2032 | { "AIF2 Loopback" , "ADCDAT" , "AIF2ADCDAT" }, |
2033 | { "AIF2 Loopback" , "None" , "AIF2DACDAT" }, |
2034 | |
2035 | /* Sidetone */ |
2036 | { "Left Sidetone" , "ADC/DMIC1" , "ADCL Mux" }, |
2037 | { "Left Sidetone" , "DMIC2" , "DMIC2L" }, |
2038 | { "Right Sidetone" , "ADC/DMIC1" , "ADCR Mux" }, |
2039 | { "Right Sidetone" , "DMIC2" , "DMIC2R" }, |
2040 | |
2041 | /* Output stages */ |
2042 | { "Left Output Mixer" , "DAC Switch" , "DAC1L" }, |
2043 | { "Right Output Mixer" , "DAC Switch" , "DAC1R" }, |
2044 | |
2045 | { "SPKL" , "DAC1 Switch" , "DAC1L" }, |
2046 | { "SPKL" , "DAC2 Switch" , "DAC2L" }, |
2047 | |
2048 | { "SPKR" , "DAC1 Switch" , "DAC1R" }, |
2049 | { "SPKR" , "DAC2 Switch" , "DAC2R" }, |
2050 | |
2051 | { "Left Headphone Mux" , "DAC" , "DAC1L" }, |
2052 | { "Right Headphone Mux" , "DAC" , "DAC1R" }, |
2053 | }; |
2054 | |
2055 | static const struct snd_soc_dapm_route wm8994_lateclk_revd_intercon[] = { |
2056 | { "DAC1L" , NULL, "Late DAC1L Enable PGA" }, |
2057 | { "Late DAC1L Enable PGA" , NULL, "DAC1L Mixer" }, |
2058 | { "DAC1R" , NULL, "Late DAC1R Enable PGA" }, |
2059 | { "Late DAC1R Enable PGA" , NULL, "DAC1R Mixer" }, |
2060 | { "DAC2L" , NULL, "Late DAC2L Enable PGA" }, |
2061 | { "Late DAC2L Enable PGA" , NULL, "AIF2DAC2L Mixer" }, |
2062 | { "DAC2R" , NULL, "Late DAC2R Enable PGA" }, |
2063 | { "Late DAC2R Enable PGA" , NULL, "AIF2DAC2R Mixer" } |
2064 | }; |
2065 | |
2066 | static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = { |
2067 | { "DAC1L" , NULL, "DAC1L Mixer" }, |
2068 | { "DAC1R" , NULL, "DAC1R Mixer" }, |
2069 | { "DAC2L" , NULL, "AIF2DAC2L Mixer" }, |
2070 | { "DAC2R" , NULL, "AIF2DAC2R Mixer" }, |
2071 | }; |
2072 | |
2073 | static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { |
2074 | { "AIF1DACDAT" , NULL, "AIF2DACDAT" }, |
2075 | { "AIF2DACDAT" , NULL, "AIF1DACDAT" }, |
2076 | { "AIF1ADCDAT" , NULL, "AIF2ADCDAT" }, |
2077 | { "AIF2ADCDAT" , NULL, "AIF1ADCDAT" }, |
2078 | { "MICBIAS1" , NULL, "CLK_SYS" }, |
2079 | { "MICBIAS1" , NULL, "MICBIAS Supply" }, |
2080 | { "MICBIAS2" , NULL, "CLK_SYS" }, |
2081 | { "MICBIAS2" , NULL, "MICBIAS Supply" }, |
2082 | }; |
2083 | |
2084 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
2085 | { "AIF2DACL" , NULL, "AIF2DAC Mux" }, |
2086 | { "AIF2DACR" , NULL, "AIF2DAC Mux" }, |
2087 | { "MICBIAS1" , NULL, "VMID" }, |
2088 | { "MICBIAS2" , NULL, "VMID" }, |
2089 | }; |
2090 | |
2091 | static const struct snd_soc_dapm_route wm8958_intercon[] = { |
2092 | { "AIF2DACL" , NULL, "AIF2DACL Mux" }, |
2093 | { "AIF2DACR" , NULL, "AIF2DACR Mux" }, |
2094 | |
2095 | { "AIF2DACL Mux" , "AIF2" , "AIF2DAC Mux" }, |
2096 | { "AIF2DACL Mux" , "AIF3" , "AIF3DACDAT" }, |
2097 | { "AIF2DACR Mux" , "AIF2" , "AIF2DAC Mux" }, |
2098 | { "AIF2DACR Mux" , "AIF3" , "AIF3DACDAT" }, |
2099 | |
2100 | { "AIF3DACDAT" , NULL, "AIF3" }, |
2101 | { "AIF3ADCDAT" , NULL, "AIF3" }, |
2102 | |
2103 | { "Mono PCM Out Mux" , "AIF2ADCL" , "AIF2ADCL" }, |
2104 | { "Mono PCM Out Mux" , "AIF2ADCR" , "AIF2ADCR" }, |
2105 | |
2106 | { "AIF3ADC Mux" , "Mono PCM" , "Mono PCM Out Mux" }, |
2107 | }; |
2108 | |
2109 | /* The size in bits of the FLL divide multiplied by 10 |
2110 | * to allow rounding later */ |
2111 | #define FIXED_FLL_SIZE ((1 << 16) * 10) |
2112 | |
2113 | struct fll_div { |
2114 | u16 outdiv; |
2115 | u16 n; |
2116 | u16 k; |
2117 | u16 lambda; |
2118 | u16 clk_ref_div; |
2119 | u16 fll_fratio; |
2120 | }; |
2121 | |
2122 | static int wm8994_get_fll_config(struct wm8994 *control, struct fll_div *fll, |
2123 | int freq_in, int freq_out) |
2124 | { |
2125 | u64 Kpart; |
2126 | unsigned int K, Ndiv, Nmod, gcd_fll; |
2127 | |
2128 | pr_debug("FLL input=%dHz, output=%dHz\n" , freq_in, freq_out); |
2129 | |
2130 | /* Scale the input frequency down to <= 13.5MHz */ |
2131 | fll->clk_ref_div = 0; |
2132 | while (freq_in > 13500000) { |
2133 | fll->clk_ref_div++; |
2134 | freq_in /= 2; |
2135 | |
2136 | if (fll->clk_ref_div > 3) |
2137 | return -EINVAL; |
2138 | } |
2139 | pr_debug("CLK_REF_DIV=%d, Fref=%dHz\n" , fll->clk_ref_div, freq_in); |
2140 | |
2141 | /* Scale the output to give 90MHz<=Fvco<=100MHz */ |
2142 | fll->outdiv = 3; |
2143 | while (freq_out * (fll->outdiv + 1) < 90000000) { |
2144 | fll->outdiv++; |
2145 | if (fll->outdiv > 63) |
2146 | return -EINVAL; |
2147 | } |
2148 | freq_out *= fll->outdiv + 1; |
2149 | pr_debug("OUTDIV=%d, Fvco=%dHz\n" , fll->outdiv, freq_out); |
2150 | |
2151 | if (freq_in > 1000000) { |
2152 | fll->fll_fratio = 0; |
2153 | } else if (freq_in > 256000) { |
2154 | fll->fll_fratio = 1; |
2155 | freq_in *= 2; |
2156 | } else if (freq_in > 128000) { |
2157 | fll->fll_fratio = 2; |
2158 | freq_in *= 4; |
2159 | } else if (freq_in > 64000) { |
2160 | fll->fll_fratio = 3; |
2161 | freq_in *= 8; |
2162 | } else { |
2163 | fll->fll_fratio = 4; |
2164 | freq_in *= 16; |
2165 | } |
2166 | pr_debug("FLL_FRATIO=%d, Fref=%dHz\n" , fll->fll_fratio, freq_in); |
2167 | |
2168 | /* Now, calculate N.K */ |
2169 | Ndiv = freq_out / freq_in; |
2170 | |
2171 | fll->n = Ndiv; |
2172 | Nmod = freq_out % freq_in; |
2173 | pr_debug("Nmod=%d\n" , Nmod); |
2174 | |
2175 | switch (control->type) { |
2176 | case WM8994: |
2177 | /* Calculate fractional part - scale up so we can round. */ |
2178 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; |
2179 | |
2180 | do_div(Kpart, freq_in); |
2181 | |
2182 | K = Kpart & 0xFFFFFFFF; |
2183 | |
2184 | if ((K % 10) >= 5) |
2185 | K += 5; |
2186 | |
2187 | /* Move down to proper range now rounding is done */ |
2188 | fll->k = K / 10; |
2189 | fll->lambda = 0; |
2190 | |
2191 | pr_debug("N=%x K=%x\n" , fll->n, fll->k); |
2192 | break; |
2193 | |
2194 | default: |
2195 | gcd_fll = gcd(a: freq_out, b: freq_in); |
2196 | |
2197 | fll->k = (freq_out - (freq_in * fll->n)) / gcd_fll; |
2198 | fll->lambda = freq_in / gcd_fll; |
2199 | |
2200 | } |
2201 | |
2202 | return 0; |
2203 | } |
2204 | |
2205 | static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, |
2206 | unsigned int freq_in, unsigned int freq_out) |
2207 | { |
2208 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2209 | struct wm8994 *control = wm8994->wm8994; |
2210 | int reg_offset, ret; |
2211 | struct fll_div fll; |
2212 | u16 reg, clk1, aif_reg, aif_src; |
2213 | unsigned long timeout; |
2214 | bool was_enabled; |
2215 | struct clk *mclk; |
2216 | |
2217 | switch (id) { |
2218 | case WM8994_FLL1: |
2219 | reg_offset = 0; |
2220 | id = 0; |
2221 | aif_src = 0x10; |
2222 | break; |
2223 | case WM8994_FLL2: |
2224 | reg_offset = 0x20; |
2225 | id = 1; |
2226 | aif_src = 0x18; |
2227 | break; |
2228 | default: |
2229 | return -EINVAL; |
2230 | } |
2231 | |
2232 | reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_1 + reg_offset); |
2233 | was_enabled = reg & WM8994_FLL1_ENA; |
2234 | |
2235 | switch (src) { |
2236 | case 0: |
2237 | /* Allow no source specification when stopping */ |
2238 | if (freq_out) |
2239 | return -EINVAL; |
2240 | src = wm8994->fll[id].src; |
2241 | break; |
2242 | case WM8994_FLL_SRC_MCLK1: |
2243 | case WM8994_FLL_SRC_MCLK2: |
2244 | case WM8994_FLL_SRC_LRCLK: |
2245 | case WM8994_FLL_SRC_BCLK: |
2246 | break; |
2247 | case WM8994_FLL_SRC_INTERNAL: |
2248 | freq_in = 12000000; |
2249 | freq_out = 12000000; |
2250 | break; |
2251 | default: |
2252 | return -EINVAL; |
2253 | } |
2254 | |
2255 | /* Are we changing anything? */ |
2256 | if (wm8994->fll[id].src == src && |
2257 | wm8994->fll[id].in == freq_in && wm8994->fll[id].out == freq_out) |
2258 | return 0; |
2259 | |
2260 | /* If we're stopping the FLL redo the old config - no |
2261 | * registers will actually be written but we avoid GCC flow |
2262 | * analysis bugs spewing warnings. |
2263 | */ |
2264 | if (freq_out) |
2265 | ret = wm8994_get_fll_config(control, fll: &fll, freq_in, freq_out); |
2266 | else |
2267 | ret = wm8994_get_fll_config(control, fll: &fll, freq_in: wm8994->fll[id].in, |
2268 | freq_out: wm8994->fll[id].out); |
2269 | if (ret < 0) |
2270 | return ret; |
2271 | |
2272 | /* Make sure that we're not providing SYSCLK right now */ |
2273 | clk1 = snd_soc_component_read(component, WM8994_CLOCKING_1); |
2274 | if (clk1 & WM8994_SYSCLK_SRC) |
2275 | aif_reg = WM8994_AIF2_CLOCKING_1; |
2276 | else |
2277 | aif_reg = WM8994_AIF1_CLOCKING_1; |
2278 | reg = snd_soc_component_read(component, reg: aif_reg); |
2279 | |
2280 | if ((reg & WM8994_AIF1CLK_ENA) && |
2281 | (reg & WM8994_AIF1CLK_SRC_MASK) == aif_src) { |
2282 | dev_err(component->dev, "FLL%d is currently providing SYSCLK\n" , |
2283 | id + 1); |
2284 | return -EBUSY; |
2285 | } |
2286 | |
2287 | /* We always need to disable the FLL while reconfiguring */ |
2288 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_1 + reg_offset, |
2289 | WM8994_FLL1_ENA, val: 0); |
2290 | |
2291 | /* Disable MCLK if needed before we possibly change to new clock parent */ |
2292 | if (was_enabled) { |
2293 | reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_5 |
2294 | + reg_offset); |
2295 | reg = ((reg & WM8994_FLL1_REFCLK_SRC_MASK) |
2296 | >> WM8994_FLL1_REFCLK_SRC_SHIFT) + 1; |
2297 | |
2298 | switch (reg) { |
2299 | case WM8994_FLL_SRC_MCLK1: |
2300 | mclk = wm8994->mclk[WM8994_MCLK1].clk; |
2301 | break; |
2302 | case WM8994_FLL_SRC_MCLK2: |
2303 | mclk = wm8994->mclk[WM8994_MCLK2].clk; |
2304 | break; |
2305 | default: |
2306 | mclk = NULL; |
2307 | } |
2308 | |
2309 | clk_disable_unprepare(clk: mclk); |
2310 | } |
2311 | |
2312 | if (wm8994->fll_byp && src == WM8994_FLL_SRC_BCLK && |
2313 | freq_in == freq_out && freq_out) { |
2314 | dev_dbg(component->dev, "Bypassing FLL%d\n" , id + 1); |
2315 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_5 + reg_offset, |
2316 | WM8958_FLL1_BYP, WM8958_FLL1_BYP); |
2317 | goto out; |
2318 | } |
2319 | |
2320 | reg = (fll.outdiv << WM8994_FLL1_OUTDIV_SHIFT) | |
2321 | (fll.fll_fratio << WM8994_FLL1_FRATIO_SHIFT); |
2322 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_2 + reg_offset, |
2323 | WM8994_FLL1_OUTDIV_MASK | |
2324 | WM8994_FLL1_FRATIO_MASK, val: reg); |
2325 | |
2326 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_3 + reg_offset, |
2327 | WM8994_FLL1_K_MASK, val: fll.k); |
2328 | |
2329 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_4 + reg_offset, |
2330 | WM8994_FLL1_N_MASK, |
2331 | val: fll.n << WM8994_FLL1_N_SHIFT); |
2332 | |
2333 | if (fll.lambda) { |
2334 | snd_soc_component_update_bits(component, WM8958_FLL1_EFS_1 + reg_offset, |
2335 | WM8958_FLL1_LAMBDA_MASK, |
2336 | val: fll.lambda); |
2337 | snd_soc_component_update_bits(component, WM8958_FLL1_EFS_2 + reg_offset, |
2338 | WM8958_FLL1_EFS_ENA, WM8958_FLL1_EFS_ENA); |
2339 | } else { |
2340 | snd_soc_component_update_bits(component, WM8958_FLL1_EFS_2 + reg_offset, |
2341 | WM8958_FLL1_EFS_ENA, val: 0); |
2342 | } |
2343 | |
2344 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_5 + reg_offset, |
2345 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
2346 | WM8994_FLL1_REFCLK_DIV_MASK | |
2347 | WM8994_FLL1_REFCLK_SRC_MASK, |
2348 | val: ((src == WM8994_FLL_SRC_INTERNAL) |
2349 | << WM8994_FLL1_FRC_NCO_SHIFT) | |
2350 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
2351 | (src - 1)); |
2352 | |
2353 | /* Clear any pending completion from a previous failure */ |
2354 | try_wait_for_completion(x: &wm8994->fll_locked[id]); |
2355 | |
2356 | switch (src) { |
2357 | case WM8994_FLL_SRC_MCLK1: |
2358 | mclk = wm8994->mclk[WM8994_MCLK1].clk; |
2359 | break; |
2360 | case WM8994_FLL_SRC_MCLK2: |
2361 | mclk = wm8994->mclk[WM8994_MCLK2].clk; |
2362 | break; |
2363 | default: |
2364 | mclk = NULL; |
2365 | } |
2366 | |
2367 | /* Enable (with fractional mode if required) */ |
2368 | if (freq_out) { |
2369 | ret = clk_prepare_enable(clk: mclk); |
2370 | if (ret < 0) { |
2371 | dev_err(component->dev, "Failed to enable MCLK for FLL%d\n" , |
2372 | id + 1); |
2373 | return ret; |
2374 | } |
2375 | |
2376 | /* Enable VMID if we need it */ |
2377 | if (!was_enabled) { |
2378 | |
2379 | active_reference(component); |
2380 | |
2381 | switch (control->type) { |
2382 | case WM8994: |
2383 | vmid_reference(component); |
2384 | break; |
2385 | case WM8958: |
2386 | if (control->revision < 1) |
2387 | vmid_reference(component); |
2388 | break; |
2389 | default: |
2390 | break; |
2391 | } |
2392 | } |
2393 | |
2394 | reg = WM8994_FLL1_ENA; |
2395 | |
2396 | if (fll.k) |
2397 | reg |= WM8994_FLL1_FRAC; |
2398 | if (src == WM8994_FLL_SRC_INTERNAL) |
2399 | reg |= WM8994_FLL1_OSC_ENA; |
2400 | |
2401 | snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_1 + reg_offset, |
2402 | WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | |
2403 | WM8994_FLL1_FRAC, val: reg); |
2404 | |
2405 | if (wm8994->fll_locked_irq) { |
2406 | timeout = wait_for_completion_timeout(x: &wm8994->fll_locked[id], |
2407 | timeout: msecs_to_jiffies(m: 10)); |
2408 | if (timeout == 0) |
2409 | dev_warn(component->dev, |
2410 | "Timed out waiting for FLL lock\n" ); |
2411 | } else { |
2412 | msleep(msecs: 5); |
2413 | } |
2414 | } else { |
2415 | if (was_enabled) { |
2416 | switch (control->type) { |
2417 | case WM8994: |
2418 | vmid_dereference(component); |
2419 | break; |
2420 | case WM8958: |
2421 | if (control->revision < 1) |
2422 | vmid_dereference(component); |
2423 | break; |
2424 | default: |
2425 | break; |
2426 | } |
2427 | |
2428 | active_dereference(component); |
2429 | } |
2430 | } |
2431 | |
2432 | out: |
2433 | wm8994->fll[id].in = freq_in; |
2434 | wm8994->fll[id].out = freq_out; |
2435 | wm8994->fll[id].src = src; |
2436 | |
2437 | configure_clock(component); |
2438 | |
2439 | /* |
2440 | * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers |
2441 | * for detection. |
2442 | */ |
2443 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { |
2444 | dev_dbg(component->dev, "Configuring AIFs for 128fs\n" ); |
2445 | |
2446 | wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) |
2447 | & WM8994_AIF1CLK_RATE_MASK; |
2448 | wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) |
2449 | & WM8994_AIF1CLK_RATE_MASK; |
2450 | |
2451 | snd_soc_component_update_bits(component, WM8994_AIF1_RATE, |
2452 | WM8994_AIF1CLK_RATE_MASK, val: 0x1); |
2453 | snd_soc_component_update_bits(component, WM8994_AIF2_RATE, |
2454 | WM8994_AIF2CLK_RATE_MASK, val: 0x1); |
2455 | } else if (wm8994->aifdiv[0]) { |
2456 | snd_soc_component_update_bits(component, WM8994_AIF1_RATE, |
2457 | WM8994_AIF1CLK_RATE_MASK, |
2458 | val: wm8994->aifdiv[0]); |
2459 | snd_soc_component_update_bits(component, WM8994_AIF2_RATE, |
2460 | WM8994_AIF2CLK_RATE_MASK, |
2461 | val: wm8994->aifdiv[1]); |
2462 | |
2463 | wm8994->aifdiv[0] = 0; |
2464 | wm8994->aifdiv[1] = 0; |
2465 | } |
2466 | |
2467 | return 0; |
2468 | } |
2469 | |
2470 | static irqreturn_t wm8994_fll_locked_irq(int irq, void *data) |
2471 | { |
2472 | struct completion *completion = data; |
2473 | |
2474 | complete(completion); |
2475 | |
2476 | return IRQ_HANDLED; |
2477 | } |
2478 | |
2479 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
2480 | |
2481 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, |
2482 | unsigned int freq_in, unsigned int freq_out) |
2483 | { |
2484 | return _wm8994_set_fll(component: dai->component, id, src, freq_in, freq_out); |
2485 | } |
2486 | |
2487 | static int wm8994_set_mclk_rate(struct wm8994_priv *wm8994, unsigned int id, |
2488 | unsigned int *freq) |
2489 | { |
2490 | int ret; |
2491 | |
2492 | if (!wm8994->mclk[id].clk || *freq == wm8994->mclk_rate[id]) |
2493 | return 0; |
2494 | |
2495 | ret = clk_set_rate(clk: wm8994->mclk[id].clk, rate: *freq); |
2496 | if (ret < 0) |
2497 | return ret; |
2498 | |
2499 | *freq = clk_get_rate(clk: wm8994->mclk[id].clk); |
2500 | |
2501 | return 0; |
2502 | } |
2503 | |
2504 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, |
2505 | int clk_id, unsigned int freq, int dir) |
2506 | { |
2507 | struct snd_soc_component *component = dai->component; |
2508 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2509 | int ret, i; |
2510 | |
2511 | switch (dai->id) { |
2512 | case 1: |
2513 | case 2: |
2514 | break; |
2515 | |
2516 | default: |
2517 | /* AIF3 shares clocking with AIF1/2 */ |
2518 | return -EINVAL; |
2519 | } |
2520 | |
2521 | switch (clk_id) { |
2522 | case WM8994_SYSCLK_MCLK1: |
2523 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1; |
2524 | |
2525 | ret = wm8994_set_mclk_rate(wm8994, id: dai->id - 1, freq: &freq); |
2526 | if (ret < 0) |
2527 | return ret; |
2528 | |
2529 | wm8994->mclk_rate[0] = freq; |
2530 | dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n" , |
2531 | dai->id, freq); |
2532 | break; |
2533 | |
2534 | case WM8994_SYSCLK_MCLK2: |
2535 | /* TODO: Set GPIO AF */ |
2536 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2; |
2537 | |
2538 | ret = wm8994_set_mclk_rate(wm8994, id: dai->id - 1, freq: &freq); |
2539 | if (ret < 0) |
2540 | return ret; |
2541 | |
2542 | wm8994->mclk_rate[1] = freq; |
2543 | dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n" , |
2544 | dai->id, freq); |
2545 | break; |
2546 | |
2547 | case WM8994_SYSCLK_FLL1: |
2548 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL1; |
2549 | dev_dbg(dai->dev, "AIF%d using FLL1\n" , dai->id); |
2550 | break; |
2551 | |
2552 | case WM8994_SYSCLK_FLL2: |
2553 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL2; |
2554 | dev_dbg(dai->dev, "AIF%d using FLL2\n" , dai->id); |
2555 | break; |
2556 | |
2557 | case WM8994_SYSCLK_OPCLK: |
2558 | /* Special case - a division (times 10) is given and |
2559 | * no effect on main clocking. |
2560 | */ |
2561 | if (freq) { |
2562 | for (i = 0; i < ARRAY_SIZE(opclk_divs); i++) |
2563 | if (opclk_divs[i] == freq) |
2564 | break; |
2565 | if (i == ARRAY_SIZE(opclk_divs)) |
2566 | return -EINVAL; |
2567 | snd_soc_component_update_bits(component, WM8994_CLOCKING_2, |
2568 | WM8994_OPCLK_DIV_MASK, val: i); |
2569 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_2, |
2570 | WM8994_OPCLK_ENA, WM8994_OPCLK_ENA); |
2571 | } else { |
2572 | snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_2, |
2573 | WM8994_OPCLK_ENA, val: 0); |
2574 | } |
2575 | break; |
2576 | |
2577 | default: |
2578 | return -EINVAL; |
2579 | } |
2580 | |
2581 | configure_clock(component); |
2582 | |
2583 | /* |
2584 | * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers |
2585 | * for detection. |
2586 | */ |
2587 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { |
2588 | dev_dbg(component->dev, "Configuring AIFs for 128fs\n" ); |
2589 | |
2590 | wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) |
2591 | & WM8994_AIF1CLK_RATE_MASK; |
2592 | wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) |
2593 | & WM8994_AIF1CLK_RATE_MASK; |
2594 | |
2595 | snd_soc_component_update_bits(component, WM8994_AIF1_RATE, |
2596 | WM8994_AIF1CLK_RATE_MASK, val: 0x1); |
2597 | snd_soc_component_update_bits(component, WM8994_AIF2_RATE, |
2598 | WM8994_AIF2CLK_RATE_MASK, val: 0x1); |
2599 | } else if (wm8994->aifdiv[0]) { |
2600 | snd_soc_component_update_bits(component, WM8994_AIF1_RATE, |
2601 | WM8994_AIF1CLK_RATE_MASK, |
2602 | val: wm8994->aifdiv[0]); |
2603 | snd_soc_component_update_bits(component, WM8994_AIF2_RATE, |
2604 | WM8994_AIF2CLK_RATE_MASK, |
2605 | val: wm8994->aifdiv[1]); |
2606 | |
2607 | wm8994->aifdiv[0] = 0; |
2608 | wm8994->aifdiv[1] = 0; |
2609 | } |
2610 | |
2611 | return 0; |
2612 | } |
2613 | |
2614 | static int wm8994_set_bias_level(struct snd_soc_component *component, |
2615 | enum snd_soc_bias_level level) |
2616 | { |
2617 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2618 | struct wm8994 *control = wm8994->wm8994; |
2619 | |
2620 | wm_hubs_set_bias_level(component, level); |
2621 | |
2622 | switch (level) { |
2623 | case SND_SOC_BIAS_ON: |
2624 | break; |
2625 | |
2626 | case SND_SOC_BIAS_PREPARE: |
2627 | /* MICBIAS into regulating mode */ |
2628 | switch (control->type) { |
2629 | case WM8958: |
2630 | case WM1811: |
2631 | snd_soc_component_update_bits(component, WM8958_MICBIAS1, |
2632 | WM8958_MICB1_MODE, val: 0); |
2633 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
2634 | WM8958_MICB2_MODE, val: 0); |
2635 | break; |
2636 | default: |
2637 | break; |
2638 | } |
2639 | |
2640 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) |
2641 | active_reference(component); |
2642 | break; |
2643 | |
2644 | case SND_SOC_BIAS_STANDBY: |
2645 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { |
2646 | switch (control->type) { |
2647 | case WM8958: |
2648 | if (control->revision == 0) { |
2649 | /* Optimise performance for rev A */ |
2650 | snd_soc_component_update_bits(component, |
2651 | WM8958_CHARGE_PUMP_2, |
2652 | WM8958_CP_DISCH, |
2653 | WM8958_CP_DISCH); |
2654 | } |
2655 | break; |
2656 | |
2657 | default: |
2658 | break; |
2659 | } |
2660 | |
2661 | /* Discharge LINEOUT1 & 2 */ |
2662 | snd_soc_component_update_bits(component, WM8994_ANTIPOP_1, |
2663 | WM8994_LINEOUT1_DISCH | |
2664 | WM8994_LINEOUT2_DISCH, |
2665 | WM8994_LINEOUT1_DISCH | |
2666 | WM8994_LINEOUT2_DISCH); |
2667 | } |
2668 | |
2669 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) |
2670 | active_dereference(component); |
2671 | |
2672 | /* MICBIAS into bypass mode on newer devices */ |
2673 | switch (control->type) { |
2674 | case WM8958: |
2675 | case WM1811: |
2676 | snd_soc_component_update_bits(component, WM8958_MICBIAS1, |
2677 | WM8958_MICB1_MODE, |
2678 | WM8958_MICB1_MODE); |
2679 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
2680 | WM8958_MICB2_MODE, |
2681 | WM8958_MICB2_MODE); |
2682 | break; |
2683 | default: |
2684 | break; |
2685 | } |
2686 | break; |
2687 | |
2688 | case SND_SOC_BIAS_OFF: |
2689 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) |
2690 | wm8994->cur_fw = NULL; |
2691 | break; |
2692 | } |
2693 | |
2694 | return 0; |
2695 | } |
2696 | |
2697 | int wm8994_vmid_mode(struct snd_soc_component *component, enum wm8994_vmid_mode mode) |
2698 | { |
2699 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2700 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
2701 | |
2702 | switch (mode) { |
2703 | case WM8994_VMID_NORMAL: |
2704 | snd_soc_dapm_mutex_lock(dapm); |
2705 | |
2706 | if (wm8994->hubs.lineout1_se) { |
2707 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2708 | pin: "LINEOUT1N Driver" ); |
2709 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2710 | pin: "LINEOUT1P Driver" ); |
2711 | } |
2712 | if (wm8994->hubs.lineout2_se) { |
2713 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2714 | pin: "LINEOUT2N Driver" ); |
2715 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2716 | pin: "LINEOUT2P Driver" ); |
2717 | } |
2718 | |
2719 | /* Do the sync with the old mode to allow it to clean up */ |
2720 | snd_soc_dapm_sync_unlocked(dapm); |
2721 | wm8994->vmid_mode = mode; |
2722 | |
2723 | snd_soc_dapm_mutex_unlock(dapm); |
2724 | break; |
2725 | |
2726 | case WM8994_VMID_FORCE: |
2727 | snd_soc_dapm_mutex_lock(dapm); |
2728 | |
2729 | if (wm8994->hubs.lineout1_se) { |
2730 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2731 | pin: "LINEOUT1N Driver" ); |
2732 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2733 | pin: "LINEOUT1P Driver" ); |
2734 | } |
2735 | if (wm8994->hubs.lineout2_se) { |
2736 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2737 | pin: "LINEOUT2N Driver" ); |
2738 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2739 | pin: "LINEOUT2P Driver" ); |
2740 | } |
2741 | |
2742 | wm8994->vmid_mode = mode; |
2743 | snd_soc_dapm_sync_unlocked(dapm); |
2744 | |
2745 | snd_soc_dapm_mutex_unlock(dapm); |
2746 | break; |
2747 | |
2748 | default: |
2749 | return -EINVAL; |
2750 | } |
2751 | |
2752 | return 0; |
2753 | } |
2754 | |
2755 | static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
2756 | { |
2757 | struct snd_soc_component *component = dai->component; |
2758 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2759 | struct wm8994 *control = wm8994->wm8994; |
2760 | int ms_reg; |
2761 | int aif1_reg; |
2762 | int dac_reg; |
2763 | int adc_reg; |
2764 | int ms = 0; |
2765 | int aif1 = 0; |
2766 | int lrclk = 0; |
2767 | |
2768 | switch (dai->id) { |
2769 | case 1: |
2770 | ms_reg = WM8994_AIF1_MASTER_SLAVE; |
2771 | aif1_reg = WM8994_AIF1_CONTROL_1; |
2772 | dac_reg = WM8994_AIF1DAC_LRCLK; |
2773 | adc_reg = WM8994_AIF1ADC_LRCLK; |
2774 | break; |
2775 | case 2: |
2776 | ms_reg = WM8994_AIF2_MASTER_SLAVE; |
2777 | aif1_reg = WM8994_AIF2_CONTROL_1; |
2778 | dac_reg = WM8994_AIF1DAC_LRCLK; |
2779 | adc_reg = WM8994_AIF1ADC_LRCLK; |
2780 | break; |
2781 | default: |
2782 | return -EINVAL; |
2783 | } |
2784 | |
2785 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
2786 | case SND_SOC_DAIFMT_CBS_CFS: |
2787 | break; |
2788 | case SND_SOC_DAIFMT_CBM_CFM: |
2789 | ms = WM8994_AIF1_MSTR; |
2790 | break; |
2791 | default: |
2792 | return -EINVAL; |
2793 | } |
2794 | |
2795 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
2796 | case SND_SOC_DAIFMT_DSP_B: |
2797 | aif1 |= WM8994_AIF1_LRCLK_INV; |
2798 | lrclk |= WM8958_AIF1_LRCLK_INV; |
2799 | fallthrough; |
2800 | case SND_SOC_DAIFMT_DSP_A: |
2801 | aif1 |= 0x18; |
2802 | break; |
2803 | case SND_SOC_DAIFMT_I2S: |
2804 | aif1 |= 0x10; |
2805 | break; |
2806 | case SND_SOC_DAIFMT_RIGHT_J: |
2807 | break; |
2808 | case SND_SOC_DAIFMT_LEFT_J: |
2809 | aif1 |= 0x8; |
2810 | break; |
2811 | default: |
2812 | return -EINVAL; |
2813 | } |
2814 | |
2815 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
2816 | case SND_SOC_DAIFMT_DSP_A: |
2817 | case SND_SOC_DAIFMT_DSP_B: |
2818 | /* frame inversion not valid for DSP modes */ |
2819 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
2820 | case SND_SOC_DAIFMT_NB_NF: |
2821 | break; |
2822 | case SND_SOC_DAIFMT_IB_NF: |
2823 | aif1 |= WM8994_AIF1_BCLK_INV; |
2824 | break; |
2825 | default: |
2826 | return -EINVAL; |
2827 | } |
2828 | break; |
2829 | |
2830 | case SND_SOC_DAIFMT_I2S: |
2831 | case SND_SOC_DAIFMT_RIGHT_J: |
2832 | case SND_SOC_DAIFMT_LEFT_J: |
2833 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
2834 | case SND_SOC_DAIFMT_NB_NF: |
2835 | break; |
2836 | case SND_SOC_DAIFMT_IB_IF: |
2837 | aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; |
2838 | lrclk |= WM8958_AIF1_LRCLK_INV; |
2839 | break; |
2840 | case SND_SOC_DAIFMT_IB_NF: |
2841 | aif1 |= WM8994_AIF1_BCLK_INV; |
2842 | break; |
2843 | case SND_SOC_DAIFMT_NB_IF: |
2844 | aif1 |= WM8994_AIF1_LRCLK_INV; |
2845 | lrclk |= WM8958_AIF1_LRCLK_INV; |
2846 | break; |
2847 | default: |
2848 | return -EINVAL; |
2849 | } |
2850 | break; |
2851 | default: |
2852 | return -EINVAL; |
2853 | } |
2854 | |
2855 | /* The AIF2 format configuration needs to be mirrored to AIF3 |
2856 | * on WM8958 if it's in use so just do it all the time. */ |
2857 | switch (control->type) { |
2858 | case WM1811: |
2859 | case WM8958: |
2860 | if (dai->id == 2) |
2861 | snd_soc_component_update_bits(component, WM8958_AIF3_CONTROL_1, |
2862 | WM8994_AIF1_LRCLK_INV | |
2863 | WM8958_AIF3_FMT_MASK, val: aif1); |
2864 | break; |
2865 | |
2866 | default: |
2867 | break; |
2868 | } |
2869 | |
2870 | snd_soc_component_update_bits(component, reg: aif1_reg, |
2871 | WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | |
2872 | WM8994_AIF1_FMT_MASK, |
2873 | val: aif1); |
2874 | snd_soc_component_update_bits(component, reg: ms_reg, WM8994_AIF1_MSTR, |
2875 | val: ms); |
2876 | snd_soc_component_update_bits(component, reg: dac_reg, |
2877 | WM8958_AIF1_LRCLK_INV, val: lrclk); |
2878 | snd_soc_component_update_bits(component, reg: adc_reg, |
2879 | WM8958_AIF1_LRCLK_INV, val: lrclk); |
2880 | |
2881 | return 0; |
2882 | } |
2883 | |
2884 | static struct { |
2885 | int val, rate; |
2886 | } srs[] = { |
2887 | { 0, 8000 }, |
2888 | { 1, 11025 }, |
2889 | { 2, 12000 }, |
2890 | { 3, 16000 }, |
2891 | { 4, 22050 }, |
2892 | { 5, 24000 }, |
2893 | { 6, 32000 }, |
2894 | { 7, 44100 }, |
2895 | { 8, 48000 }, |
2896 | { 9, 88200 }, |
2897 | { 10, 96000 }, |
2898 | }; |
2899 | |
2900 | static int fs_ratios[] = { |
2901 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536 |
2902 | }; |
2903 | |
2904 | static int bclk_divs[] = { |
2905 | 10, 15, 20, 30, 40, 50, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480, |
2906 | 640, 880, 960, 1280, 1760, 1920 |
2907 | }; |
2908 | |
2909 | static int wm8994_hw_params(struct snd_pcm_substream *substream, |
2910 | struct snd_pcm_hw_params *params, |
2911 | struct snd_soc_dai *dai) |
2912 | { |
2913 | struct snd_soc_component *component = dai->component; |
2914 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
2915 | struct wm8994 *control = wm8994->wm8994; |
2916 | struct wm8994_pdata *pdata = &control->pdata; |
2917 | int aif1_reg; |
2918 | int aif2_reg; |
2919 | int bclk_reg; |
2920 | int lrclk_reg; |
2921 | int rate_reg; |
2922 | int aif1 = 0; |
2923 | int aif2 = 0; |
2924 | int bclk = 0; |
2925 | int lrclk = 0; |
2926 | int rate_val = 0; |
2927 | int id = dai->id - 1; |
2928 | |
2929 | int i, cur_val, best_val, bclk_rate, best; |
2930 | |
2931 | switch (dai->id) { |
2932 | case 1: |
2933 | aif1_reg = WM8994_AIF1_CONTROL_1; |
2934 | aif2_reg = WM8994_AIF1_CONTROL_2; |
2935 | bclk_reg = WM8994_AIF1_BCLK; |
2936 | rate_reg = WM8994_AIF1_RATE; |
2937 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || |
2938 | wm8994->lrclk_shared[0]) { |
2939 | lrclk_reg = WM8994_AIF1DAC_LRCLK; |
2940 | } else { |
2941 | lrclk_reg = WM8994_AIF1ADC_LRCLK; |
2942 | dev_dbg(component->dev, "AIF1 using split LRCLK\n" ); |
2943 | } |
2944 | break; |
2945 | case 2: |
2946 | aif1_reg = WM8994_AIF2_CONTROL_1; |
2947 | aif2_reg = WM8994_AIF2_CONTROL_2; |
2948 | bclk_reg = WM8994_AIF2_BCLK; |
2949 | rate_reg = WM8994_AIF2_RATE; |
2950 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || |
2951 | wm8994->lrclk_shared[1]) { |
2952 | lrclk_reg = WM8994_AIF2DAC_LRCLK; |
2953 | } else { |
2954 | lrclk_reg = WM8994_AIF2ADC_LRCLK; |
2955 | dev_dbg(component->dev, "AIF2 using split LRCLK\n" ); |
2956 | } |
2957 | break; |
2958 | default: |
2959 | return -EINVAL; |
2960 | } |
2961 | |
2962 | bclk_rate = params_rate(p: params); |
2963 | switch (params_width(p: params)) { |
2964 | case 16: |
2965 | bclk_rate *= 16; |
2966 | break; |
2967 | case 20: |
2968 | bclk_rate *= 20; |
2969 | aif1 |= 0x20; |
2970 | break; |
2971 | case 24: |
2972 | bclk_rate *= 24; |
2973 | aif1 |= 0x40; |
2974 | break; |
2975 | case 32: |
2976 | bclk_rate *= 32; |
2977 | aif1 |= 0x60; |
2978 | break; |
2979 | default: |
2980 | return -EINVAL; |
2981 | } |
2982 | |
2983 | wm8994->channels[id] = params_channels(p: params); |
2984 | if (pdata->max_channels_clocked[id] && |
2985 | wm8994->channels[id] > pdata->max_channels_clocked[id]) { |
2986 | dev_dbg(dai->dev, "Constraining channels to %d from %d\n" , |
2987 | pdata->max_channels_clocked[id], wm8994->channels[id]); |
2988 | wm8994->channels[id] = pdata->max_channels_clocked[id]; |
2989 | } |
2990 | |
2991 | switch (wm8994->channels[id]) { |
2992 | case 1: |
2993 | case 2: |
2994 | bclk_rate *= 2; |
2995 | break; |
2996 | default: |
2997 | bclk_rate *= 4; |
2998 | break; |
2999 | } |
3000 | |
3001 | /* Try to find an appropriate sample rate; look for an exact match. */ |
3002 | for (i = 0; i < ARRAY_SIZE(srs); i++) |
3003 | if (srs[i].rate == params_rate(p: params)) |
3004 | break; |
3005 | if (i == ARRAY_SIZE(srs)) |
3006 | return -EINVAL; |
3007 | rate_val |= srs[i].val << WM8994_AIF1_SR_SHIFT; |
3008 | |
3009 | dev_dbg(dai->dev, "Sample rate is %dHz\n" , srs[i].rate); |
3010 | dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n" , |
3011 | dai->id, wm8994->aifclk[id], bclk_rate); |
3012 | |
3013 | if (wm8994->channels[id] == 1 && |
3014 | (snd_soc_component_read(component, reg: aif1_reg) & 0x18) == 0x18) |
3015 | aif2 |= WM8994_AIF1_MONO; |
3016 | |
3017 | if (wm8994->aifclk[id] == 0) { |
3018 | dev_err(dai->dev, "AIF%dCLK not configured\n" , dai->id); |
3019 | return -EINVAL; |
3020 | } |
3021 | |
3022 | /* AIFCLK/fs ratio; look for a close match in either direction */ |
3023 | best = 0; |
3024 | best_val = abs((fs_ratios[0] * params_rate(params)) |
3025 | - wm8994->aifclk[id]); |
3026 | for (i = 1; i < ARRAY_SIZE(fs_ratios); i++) { |
3027 | cur_val = abs((fs_ratios[i] * params_rate(params)) |
3028 | - wm8994->aifclk[id]); |
3029 | if (cur_val >= best_val) |
3030 | continue; |
3031 | best = i; |
3032 | best_val = cur_val; |
3033 | } |
3034 | dev_dbg(dai->dev, "Selected AIF%dCLK/fs = %d\n" , |
3035 | dai->id, fs_ratios[best]); |
3036 | rate_val |= best; |
3037 | |
3038 | /* We may not get quite the right frequency if using |
3039 | * approximate clocks so look for the closest match that is |
3040 | * higher than the target (we need to ensure that there enough |
3041 | * BCLKs to clock out the samples). |
3042 | */ |
3043 | best = 0; |
3044 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { |
3045 | cur_val = (wm8994->aifclk[id] * 10 / bclk_divs[i]) - bclk_rate; |
3046 | if (cur_val < 0) /* BCLK table is sorted */ |
3047 | break; |
3048 | best = i; |
3049 | } |
3050 | bclk_rate = wm8994->aifclk[id] * 10 / bclk_divs[best]; |
3051 | dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n" , |
3052 | bclk_divs[best], bclk_rate); |
3053 | bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; |
3054 | |
3055 | lrclk = bclk_rate / params_rate(p: params); |
3056 | if (!lrclk) { |
3057 | dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n" , |
3058 | bclk_rate); |
3059 | return -EINVAL; |
3060 | } |
3061 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n" , |
3062 | lrclk, bclk_rate / lrclk); |
3063 | |
3064 | snd_soc_component_update_bits(component, reg: aif1_reg, WM8994_AIF1_WL_MASK, val: aif1); |
3065 | snd_soc_component_update_bits(component, reg: aif2_reg, WM8994_AIF1_MONO, val: aif2); |
3066 | snd_soc_component_update_bits(component, reg: bclk_reg, WM8994_AIF1_BCLK_DIV_MASK, val: bclk); |
3067 | snd_soc_component_update_bits(component, reg: lrclk_reg, WM8994_AIF1DAC_RATE_MASK, |
3068 | val: lrclk); |
3069 | snd_soc_component_update_bits(component, reg: rate_reg, WM8994_AIF1_SR_MASK | |
3070 | WM8994_AIF1CLK_RATE_MASK, val: rate_val); |
3071 | |
3072 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3073 | switch (dai->id) { |
3074 | case 1: |
3075 | wm8994->dac_rates[0] = params_rate(p: params); |
3076 | wm8994_set_retune_mobile(component, block: 0); |
3077 | wm8994_set_retune_mobile(component, block: 1); |
3078 | break; |
3079 | case 2: |
3080 | wm8994->dac_rates[1] = params_rate(p: params); |
3081 | wm8994_set_retune_mobile(component, block: 2); |
3082 | break; |
3083 | } |
3084 | } |
3085 | |
3086 | return 0; |
3087 | } |
3088 | |
3089 | static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, |
3090 | struct snd_pcm_hw_params *params, |
3091 | struct snd_soc_dai *dai) |
3092 | { |
3093 | struct snd_soc_component *component = dai->component; |
3094 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3095 | struct wm8994 *control = wm8994->wm8994; |
3096 | int aif1_reg; |
3097 | int aif1 = 0; |
3098 | |
3099 | switch (dai->id) { |
3100 | case 3: |
3101 | switch (control->type) { |
3102 | case WM1811: |
3103 | case WM8958: |
3104 | aif1_reg = WM8958_AIF3_CONTROL_1; |
3105 | break; |
3106 | default: |
3107 | return 0; |
3108 | } |
3109 | break; |
3110 | default: |
3111 | return 0; |
3112 | } |
3113 | |
3114 | switch (params_width(p: params)) { |
3115 | case 16: |
3116 | break; |
3117 | case 20: |
3118 | aif1 |= 0x20; |
3119 | break; |
3120 | case 24: |
3121 | aif1 |= 0x40; |
3122 | break; |
3123 | case 32: |
3124 | aif1 |= 0x60; |
3125 | break; |
3126 | default: |
3127 | return -EINVAL; |
3128 | } |
3129 | |
3130 | return snd_soc_component_update_bits(component, reg: aif1_reg, WM8994_AIF1_WL_MASK, val: aif1); |
3131 | } |
3132 | |
3133 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute, |
3134 | int direction) |
3135 | { |
3136 | struct snd_soc_component *component = codec_dai->component; |
3137 | int mute_reg; |
3138 | int reg; |
3139 | |
3140 | switch (codec_dai->id) { |
3141 | case 1: |
3142 | mute_reg = WM8994_AIF1_DAC1_FILTERS_1; |
3143 | break; |
3144 | case 2: |
3145 | mute_reg = WM8994_AIF2_DAC_FILTERS_1; |
3146 | break; |
3147 | default: |
3148 | return -EINVAL; |
3149 | } |
3150 | |
3151 | if (mute) |
3152 | reg = WM8994_AIF1DAC1_MUTE; |
3153 | else |
3154 | reg = 0; |
3155 | |
3156 | snd_soc_component_update_bits(component, reg: mute_reg, WM8994_AIF1DAC1_MUTE, val: reg); |
3157 | |
3158 | return 0; |
3159 | } |
3160 | |
3161 | static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) |
3162 | { |
3163 | struct snd_soc_component *component = codec_dai->component; |
3164 | int reg, val, mask; |
3165 | |
3166 | switch (codec_dai->id) { |
3167 | case 1: |
3168 | reg = WM8994_AIF1_MASTER_SLAVE; |
3169 | mask = WM8994_AIF1_TRI; |
3170 | break; |
3171 | case 2: |
3172 | reg = WM8994_AIF2_MASTER_SLAVE; |
3173 | mask = WM8994_AIF2_TRI; |
3174 | break; |
3175 | default: |
3176 | return -EINVAL; |
3177 | } |
3178 | |
3179 | if (tristate) |
3180 | val = mask; |
3181 | else |
3182 | val = 0; |
3183 | |
3184 | return snd_soc_component_update_bits(component, reg, mask, val); |
3185 | } |
3186 | |
3187 | static int wm8994_aif2_probe(struct snd_soc_dai *dai) |
3188 | { |
3189 | struct snd_soc_component *component = dai->component; |
3190 | |
3191 | /* Disable the pulls on the AIF if we're using it to save power. */ |
3192 | snd_soc_component_update_bits(component, WM8994_GPIO_3, |
3193 | WM8994_GPN_PU | WM8994_GPN_PD, val: 0); |
3194 | snd_soc_component_update_bits(component, WM8994_GPIO_4, |
3195 | WM8994_GPN_PU | WM8994_GPN_PD, val: 0); |
3196 | snd_soc_component_update_bits(component, WM8994_GPIO_5, |
3197 | WM8994_GPN_PU | WM8994_GPN_PD, val: 0); |
3198 | |
3199 | return 0; |
3200 | } |
3201 | |
3202 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 |
3203 | |
3204 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
3205 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
3206 | |
3207 | static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = { |
3208 | .set_sysclk = wm8994_set_dai_sysclk, |
3209 | .set_fmt = wm8994_set_dai_fmt, |
3210 | .hw_params = wm8994_hw_params, |
3211 | .mute_stream = wm8994_aif_mute, |
3212 | .set_pll = wm8994_set_fll, |
3213 | .set_tristate = wm8994_set_tristate, |
3214 | .no_capture_mute = 1, |
3215 | }; |
3216 | |
3217 | static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = { |
3218 | .probe = wm8994_aif2_probe, |
3219 | .set_sysclk = wm8994_set_dai_sysclk, |
3220 | .set_fmt = wm8994_set_dai_fmt, |
3221 | .hw_params = wm8994_hw_params, |
3222 | .mute_stream = wm8994_aif_mute, |
3223 | .set_pll = wm8994_set_fll, |
3224 | .set_tristate = wm8994_set_tristate, |
3225 | .no_capture_mute = 1, |
3226 | }; |
3227 | |
3228 | static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = { |
3229 | .hw_params = wm8994_aif3_hw_params, |
3230 | }; |
3231 | |
3232 | static struct snd_soc_dai_driver wm8994_dai[] = { |
3233 | { |
3234 | .name = "wm8994-aif1" , |
3235 | .id = 1, |
3236 | .playback = { |
3237 | .stream_name = "AIF1 Playback" , |
3238 | .channels_min = 1, |
3239 | .channels_max = 2, |
3240 | .rates = WM8994_RATES, |
3241 | .formats = WM8994_FORMATS, |
3242 | .sig_bits = 24, |
3243 | }, |
3244 | .capture = { |
3245 | .stream_name = "AIF1 Capture" , |
3246 | .channels_min = 1, |
3247 | .channels_max = 2, |
3248 | .rates = WM8994_RATES, |
3249 | .formats = WM8994_FORMATS, |
3250 | .sig_bits = 24, |
3251 | }, |
3252 | .ops = &wm8994_aif1_dai_ops, |
3253 | }, |
3254 | { |
3255 | .name = "wm8994-aif2" , |
3256 | .id = 2, |
3257 | .playback = { |
3258 | .stream_name = "AIF2 Playback" , |
3259 | .channels_min = 1, |
3260 | .channels_max = 2, |
3261 | .rates = WM8994_RATES, |
3262 | .formats = WM8994_FORMATS, |
3263 | .sig_bits = 24, |
3264 | }, |
3265 | .capture = { |
3266 | .stream_name = "AIF2 Capture" , |
3267 | .channels_min = 1, |
3268 | .channels_max = 2, |
3269 | .rates = WM8994_RATES, |
3270 | .formats = WM8994_FORMATS, |
3271 | .sig_bits = 24, |
3272 | }, |
3273 | .ops = &wm8994_aif2_dai_ops, |
3274 | }, |
3275 | { |
3276 | .name = "wm8994-aif3" , |
3277 | .id = 3, |
3278 | .playback = { |
3279 | .stream_name = "AIF3 Playback" , |
3280 | .channels_min = 1, |
3281 | .channels_max = 2, |
3282 | .rates = WM8994_RATES, |
3283 | .formats = WM8994_FORMATS, |
3284 | .sig_bits = 24, |
3285 | }, |
3286 | .capture = { |
3287 | .stream_name = "AIF3 Capture" , |
3288 | .channels_min = 1, |
3289 | .channels_max = 2, |
3290 | .rates = WM8994_RATES, |
3291 | .formats = WM8994_FORMATS, |
3292 | .sig_bits = 24, |
3293 | }, |
3294 | .ops = &wm8994_aif3_dai_ops, |
3295 | } |
3296 | }; |
3297 | |
3298 | #ifdef CONFIG_PM |
3299 | static int wm8994_component_suspend(struct snd_soc_component *component) |
3300 | { |
3301 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3302 | int i, ret; |
3303 | |
3304 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3305 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
3306 | sizeof(struct wm8994_fll_config)); |
3307 | ret = _wm8994_set_fll(component, id: i + 1, src: 0, freq_in: 0, freq_out: 0); |
3308 | if (ret < 0) |
3309 | dev_warn(component->dev, "Failed to stop FLL%d: %d\n" , |
3310 | i + 1, ret); |
3311 | } |
3312 | |
3313 | snd_soc_component_force_bias_level(component, level: SND_SOC_BIAS_OFF); |
3314 | |
3315 | return 0; |
3316 | } |
3317 | |
3318 | static int wm8994_component_resume(struct snd_soc_component *component) |
3319 | { |
3320 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3321 | int i, ret; |
3322 | |
3323 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3324 | if (!wm8994->fll_suspend[i].out) |
3325 | continue; |
3326 | |
3327 | ret = _wm8994_set_fll(component, id: i + 1, |
3328 | src: wm8994->fll_suspend[i].src, |
3329 | freq_in: wm8994->fll_suspend[i].in, |
3330 | freq_out: wm8994->fll_suspend[i].out); |
3331 | if (ret < 0) |
3332 | dev_warn(component->dev, "Failed to restore FLL%d: %d\n" , |
3333 | i + 1, ret); |
3334 | } |
3335 | |
3336 | return 0; |
3337 | } |
3338 | #else |
3339 | #define wm8994_component_suspend NULL |
3340 | #define wm8994_component_resume NULL |
3341 | #endif |
3342 | |
3343 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3344 | { |
3345 | struct snd_soc_component *component = wm8994->hubs.component; |
3346 | struct wm8994 *control = wm8994->wm8994; |
3347 | struct wm8994_pdata *pdata = &control->pdata; |
3348 | struct snd_kcontrol_new controls[] = { |
3349 | SOC_ENUM_EXT("AIF1.1 EQ Mode" , |
3350 | wm8994->retune_mobile_enum, |
3351 | wm8994_get_retune_mobile_enum, |
3352 | wm8994_put_retune_mobile_enum), |
3353 | SOC_ENUM_EXT("AIF1.2 EQ Mode" , |
3354 | wm8994->retune_mobile_enum, |
3355 | wm8994_get_retune_mobile_enum, |
3356 | wm8994_put_retune_mobile_enum), |
3357 | SOC_ENUM_EXT("AIF2 EQ Mode" , |
3358 | wm8994->retune_mobile_enum, |
3359 | wm8994_get_retune_mobile_enum, |
3360 | wm8994_put_retune_mobile_enum), |
3361 | }; |
3362 | int ret, i, j; |
3363 | const char **t; |
3364 | |
3365 | /* We need an array of texts for the enum API but the number |
3366 | * of texts is likely to be less than the number of |
3367 | * configurations due to the sample rate dependency of the |
3368 | * configurations. */ |
3369 | wm8994->num_retune_mobile_texts = 0; |
3370 | wm8994->retune_mobile_texts = NULL; |
3371 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { |
3372 | for (j = 0; j < wm8994->num_retune_mobile_texts; j++) { |
3373 | if (strcmp(pdata->retune_mobile_cfgs[i].name, |
3374 | wm8994->retune_mobile_texts[j]) == 0) |
3375 | break; |
3376 | } |
3377 | |
3378 | if (j != wm8994->num_retune_mobile_texts) |
3379 | continue; |
3380 | |
3381 | /* Expand the array... */ |
3382 | t = krealloc(objp: wm8994->retune_mobile_texts, |
3383 | new_size: sizeof(char *) * |
3384 | (wm8994->num_retune_mobile_texts + 1), |
3385 | GFP_KERNEL); |
3386 | if (t == NULL) |
3387 | continue; |
3388 | |
3389 | /* ...store the new entry... */ |
3390 | t[wm8994->num_retune_mobile_texts] = |
3391 | pdata->retune_mobile_cfgs[i].name; |
3392 | |
3393 | /* ...and remember the new version. */ |
3394 | wm8994->num_retune_mobile_texts++; |
3395 | wm8994->retune_mobile_texts = t; |
3396 | } |
3397 | |
3398 | dev_dbg(component->dev, "Allocated %d unique ReTune Mobile names\n" , |
3399 | wm8994->num_retune_mobile_texts); |
3400 | |
3401 | wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts; |
3402 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3403 | |
3404 | ret = snd_soc_add_component_controls(component: wm8994->hubs.component, controls, |
3405 | ARRAY_SIZE(controls)); |
3406 | if (ret != 0) |
3407 | dev_err(wm8994->hubs.component->dev, |
3408 | "Failed to add ReTune Mobile controls: %d\n" , ret); |
3409 | } |
3410 | |
3411 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3412 | { |
3413 | struct snd_soc_component *component = wm8994->hubs.component; |
3414 | struct wm8994 *control = wm8994->wm8994; |
3415 | struct wm8994_pdata *pdata = &control->pdata; |
3416 | int ret, i; |
3417 | |
3418 | if (!pdata) |
3419 | return; |
3420 | |
3421 | wm_hubs_handle_analogue_pdata(component, lineout1_diff: pdata->lineout1_diff, |
3422 | lineout2_diff: pdata->lineout2_diff, |
3423 | lineout1fb: pdata->lineout1fb, |
3424 | lineout2fb: pdata->lineout2fb, |
3425 | jd_scthr: pdata->jd_scthr, |
3426 | jd_thr: pdata->jd_thr, |
3427 | micbias1_delay: pdata->micb1_delay, |
3428 | micbias2_delay: pdata->micb2_delay, |
3429 | micbias1_lvl: pdata->micbias1_lvl, |
3430 | micbias2_lvl: pdata->micbias2_lvl); |
3431 | |
3432 | dev_dbg(component->dev, "%d DRC configurations\n" , pdata->num_drc_cfgs); |
3433 | |
3434 | if (pdata->num_drc_cfgs) { |
3435 | struct snd_kcontrol_new controls[] = { |
3436 | SOC_ENUM_EXT("AIF1DRC1 Mode" , wm8994->drc_enum, |
3437 | wm8994_get_drc_enum, wm8994_put_drc_enum), |
3438 | SOC_ENUM_EXT("AIF1DRC2 Mode" , wm8994->drc_enum, |
3439 | wm8994_get_drc_enum, wm8994_put_drc_enum), |
3440 | SOC_ENUM_EXT("AIF2DRC Mode" , wm8994->drc_enum, |
3441 | wm8994_get_drc_enum, wm8994_put_drc_enum), |
3442 | }; |
3443 | |
3444 | /* We need an array of texts for the enum API */ |
3445 | wm8994->drc_texts = devm_kcalloc(dev: wm8994->hubs.component->dev, |
3446 | n: pdata->num_drc_cfgs, size: sizeof(char *), GFP_KERNEL); |
3447 | if (!wm8994->drc_texts) |
3448 | return; |
3449 | |
3450 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
3451 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; |
3452 | |
3453 | wm8994->drc_enum.items = pdata->num_drc_cfgs; |
3454 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3455 | |
3456 | ret = snd_soc_add_component_controls(component: wm8994->hubs.component, controls, |
3457 | ARRAY_SIZE(controls)); |
3458 | for (i = 0; i < WM8994_NUM_DRC; i++) |
3459 | wm8994_set_drc(component, drc: i); |
3460 | } else { |
3461 | ret = snd_soc_add_component_controls(component: wm8994->hubs.component, |
3462 | controls: wm8994_drc_controls, |
3463 | ARRAY_SIZE(wm8994_drc_controls)); |
3464 | } |
3465 | |
3466 | if (ret != 0) |
3467 | dev_err(wm8994->hubs.component->dev, |
3468 | "Failed to add DRC mode controls: %d\n" , ret); |
3469 | |
3470 | |
3471 | dev_dbg(component->dev, "%d ReTune Mobile configurations\n" , |
3472 | pdata->num_retune_mobile_cfgs); |
3473 | |
3474 | if (pdata->num_retune_mobile_cfgs) |
3475 | wm8994_handle_retune_mobile_pdata(wm8994); |
3476 | else |
3477 | snd_soc_add_component_controls(component: wm8994->hubs.component, controls: wm8994_eq_controls, |
3478 | ARRAY_SIZE(wm8994_eq_controls)); |
3479 | |
3480 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { |
3481 | if (pdata->micbias[i]) { |
3482 | snd_soc_component_write(component, WM8958_MICBIAS1 + i, |
3483 | val: pdata->micbias[i] & 0xffff); |
3484 | } |
3485 | } |
3486 | } |
3487 | |
3488 | /** |
3489 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ |
3490 | * |
3491 | * @component: WM8994 component |
3492 | * @jack: jack to report detection events on |
3493 | * @micbias: microphone bias to detect on |
3494 | * |
3495 | * Enable microphone detection via IRQ on the WM8994. If GPIOs are |
3496 | * being used to bring out signals to the processor then only platform |
3497 | * data configuration is needed for WM8994 and processor GPIOs should |
3498 | * be configured using snd_soc_jack_add_gpios() instead. |
3499 | * |
3500 | * Configuration of detection levels is available via the micbias1_lvl |
3501 | * and micbias2_lvl platform data members. |
3502 | */ |
3503 | int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack, |
3504 | int micbias) |
3505 | { |
3506 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
3507 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3508 | struct wm8994_micdet *micdet; |
3509 | struct wm8994 *control = wm8994->wm8994; |
3510 | int reg, ret; |
3511 | |
3512 | if (control->type != WM8994) { |
3513 | dev_warn(component->dev, "Not a WM8994\n" ); |
3514 | return -EINVAL; |
3515 | } |
3516 | |
3517 | pm_runtime_get_sync(dev: component->dev); |
3518 | |
3519 | switch (micbias) { |
3520 | case 1: |
3521 | micdet = &wm8994->micdet[0]; |
3522 | if (jack) |
3523 | ret = snd_soc_dapm_force_enable_pin(dapm, pin: "MICBIAS1" ); |
3524 | else |
3525 | ret = snd_soc_dapm_disable_pin(dapm, pin: "MICBIAS1" ); |
3526 | break; |
3527 | case 2: |
3528 | micdet = &wm8994->micdet[1]; |
3529 | if (jack) |
3530 | ret = snd_soc_dapm_force_enable_pin(dapm, pin: "MICBIAS1" ); |
3531 | else |
3532 | ret = snd_soc_dapm_disable_pin(dapm, pin: "MICBIAS1" ); |
3533 | break; |
3534 | default: |
3535 | dev_warn(component->dev, "Invalid MICBIAS %d\n" , micbias); |
3536 | return -EINVAL; |
3537 | } |
3538 | |
3539 | if (ret != 0) |
3540 | dev_warn(component->dev, "Failed to configure MICBIAS%d: %d\n" , |
3541 | micbias, ret); |
3542 | |
3543 | dev_dbg(component->dev, "Configuring microphone detection on %d %p\n" , |
3544 | micbias, jack); |
3545 | |
3546 | /* Store the configuration */ |
3547 | micdet->jack = jack; |
3548 | micdet->detecting = true; |
3549 | |
3550 | /* If either of the jacks is set up then enable detection */ |
3551 | if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) |
3552 | reg = WM8994_MICD_ENA; |
3553 | else |
3554 | reg = 0; |
3555 | |
3556 | snd_soc_component_update_bits(component, WM8994_MICBIAS, WM8994_MICD_ENA, val: reg); |
3557 | |
3558 | /* enable MICDET and MICSHRT deboune */ |
3559 | snd_soc_component_update_bits(component, WM8994_IRQ_DEBOUNCE, |
3560 | WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | |
3561 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, |
3562 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); |
3563 | |
3564 | snd_soc_dapm_sync(dapm); |
3565 | |
3566 | pm_runtime_put(dev: component->dev); |
3567 | |
3568 | return 0; |
3569 | } |
3570 | EXPORT_SYMBOL_GPL(wm8994_mic_detect); |
3571 | |
3572 | static void wm8994_mic_work(struct work_struct *work) |
3573 | { |
3574 | struct wm8994_priv *priv = container_of(work, |
3575 | struct wm8994_priv, |
3576 | mic_work.work); |
3577 | struct regmap *regmap = priv->wm8994->regmap; |
3578 | struct device *dev = priv->wm8994->dev; |
3579 | unsigned int reg; |
3580 | int ret; |
3581 | int report; |
3582 | |
3583 | pm_runtime_get_sync(dev); |
3584 | |
3585 | ret = regmap_read(map: regmap, WM8994_INTERRUPT_RAW_STATUS_2, val: ®); |
3586 | if (ret < 0) { |
3587 | dev_err(dev, "Failed to read microphone status: %d\n" , |
3588 | ret); |
3589 | pm_runtime_put(dev); |
3590 | return; |
3591 | } |
3592 | |
3593 | dev_dbg(dev, "Microphone status: %x\n" , reg); |
3594 | |
3595 | report = 0; |
3596 | if (reg & WM8994_MIC1_DET_STS) { |
3597 | if (priv->micdet[0].detecting) |
3598 | report = SND_JACK_HEADSET; |
3599 | } |
3600 | if (reg & WM8994_MIC1_SHRT_STS) { |
3601 | if (priv->micdet[0].detecting) |
3602 | report = SND_JACK_HEADPHONE; |
3603 | else |
3604 | report |= SND_JACK_BTN_0; |
3605 | } |
3606 | if (report) |
3607 | priv->micdet[0].detecting = false; |
3608 | else |
3609 | priv->micdet[0].detecting = true; |
3610 | |
3611 | snd_soc_jack_report(jack: priv->micdet[0].jack, status: report, |
3612 | mask: SND_JACK_HEADSET | SND_JACK_BTN_0); |
3613 | |
3614 | report = 0; |
3615 | if (reg & WM8994_MIC2_DET_STS) { |
3616 | if (priv->micdet[1].detecting) |
3617 | report = SND_JACK_HEADSET; |
3618 | } |
3619 | if (reg & WM8994_MIC2_SHRT_STS) { |
3620 | if (priv->micdet[1].detecting) |
3621 | report = SND_JACK_HEADPHONE; |
3622 | else |
3623 | report |= SND_JACK_BTN_0; |
3624 | } |
3625 | if (report) |
3626 | priv->micdet[1].detecting = false; |
3627 | else |
3628 | priv->micdet[1].detecting = true; |
3629 | |
3630 | snd_soc_jack_report(jack: priv->micdet[1].jack, status: report, |
3631 | mask: SND_JACK_HEADSET | SND_JACK_BTN_0); |
3632 | |
3633 | pm_runtime_put(dev); |
3634 | } |
3635 | |
3636 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3637 | { |
3638 | struct wm8994_priv *priv = data; |
3639 | struct snd_soc_component *component = priv->hubs.component; |
3640 | |
3641 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
3642 | trace_snd_soc_jack_irq(name: dev_name(dev: component->dev)); |
3643 | #endif |
3644 | |
3645 | pm_wakeup_event(dev: component->dev, msec: 300); |
3646 | |
3647 | queue_delayed_work(wq: system_power_efficient_wq, |
3648 | dwork: &priv->mic_work, delay: msecs_to_jiffies(m: 250)); |
3649 | |
3650 | return IRQ_HANDLED; |
3651 | } |
3652 | |
3653 | /* Should be called with accdet_lock held */ |
3654 | static void wm1811_micd_stop(struct snd_soc_component *component) |
3655 | { |
3656 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
3657 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3658 | |
3659 | if (!wm8994->jackdet) |
3660 | return; |
3661 | |
3662 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, val: 0); |
3663 | |
3664 | wm1811_jackdet_set_mode(component, WM1811_JACKDET_MODE_JACK); |
3665 | |
3666 | if (wm8994->wm8994->pdata.jd_ext_cap) |
3667 | snd_soc_dapm_disable_pin(dapm, pin: "MICBIAS2" ); |
3668 | } |
3669 | |
3670 | static void wm8958_button_det(struct snd_soc_component *component, u16 status) |
3671 | { |
3672 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3673 | int report; |
3674 | |
3675 | report = 0; |
3676 | if (status & 0x4) |
3677 | report |= SND_JACK_BTN_0; |
3678 | |
3679 | if (status & 0x8) |
3680 | report |= SND_JACK_BTN_1; |
3681 | |
3682 | if (status & 0x10) |
3683 | report |= SND_JACK_BTN_2; |
3684 | |
3685 | if (status & 0x20) |
3686 | report |= SND_JACK_BTN_3; |
3687 | |
3688 | if (status & 0x40) |
3689 | report |= SND_JACK_BTN_4; |
3690 | |
3691 | if (status & 0x80) |
3692 | report |= SND_JACK_BTN_5; |
3693 | |
3694 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: report, |
3695 | mask: wm8994->btn_mask); |
3696 | } |
3697 | |
3698 | static void wm8958_open_circuit_work(struct work_struct *work) |
3699 | { |
3700 | struct wm8994_priv *wm8994 = container_of(work, |
3701 | struct wm8994_priv, |
3702 | open_circuit_work.work); |
3703 | struct device *dev = wm8994->wm8994->dev; |
3704 | |
3705 | mutex_lock(&wm8994->accdet_lock); |
3706 | |
3707 | wm1811_micd_stop(component: wm8994->hubs.component); |
3708 | |
3709 | dev_dbg(dev, "Reporting open circuit\n" ); |
3710 | |
3711 | wm8994->jack_mic = false; |
3712 | wm8994->mic_detecting = true; |
3713 | |
3714 | wm8958_micd_set_rate(component: wm8994->hubs.component); |
3715 | |
3716 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: 0, |
3717 | mask: wm8994->btn_mask | |
3718 | SND_JACK_HEADSET); |
3719 | |
3720 | mutex_unlock(lock: &wm8994->accdet_lock); |
3721 | } |
3722 | |
3723 | static void wm8958_mic_id(void *data, u16 status) |
3724 | { |
3725 | struct snd_soc_component *component = data; |
3726 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3727 | |
3728 | /* Either nothing present or just starting detection */ |
3729 | if (!(status & WM8958_MICD_STS)) { |
3730 | /* If nothing present then clear our statuses */ |
3731 | dev_dbg(component->dev, "Detected open circuit\n" ); |
3732 | |
3733 | queue_delayed_work(wq: system_power_efficient_wq, |
3734 | dwork: &wm8994->open_circuit_work, |
3735 | delay: msecs_to_jiffies(m: 2500)); |
3736 | return; |
3737 | } |
3738 | |
3739 | /* If the measurement is showing a high impedence we've got a |
3740 | * microphone. |
3741 | */ |
3742 | if (status & 0x600) { |
3743 | dev_dbg(component->dev, "Detected microphone\n" ); |
3744 | |
3745 | wm8994->mic_detecting = false; |
3746 | wm8994->jack_mic = true; |
3747 | |
3748 | wm8958_micd_set_rate(component); |
3749 | |
3750 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: SND_JACK_HEADSET, |
3751 | mask: SND_JACK_HEADSET); |
3752 | } |
3753 | |
3754 | |
3755 | if (status & 0xfc) { |
3756 | dev_dbg(component->dev, "Detected headphone\n" ); |
3757 | wm8994->mic_detecting = false; |
3758 | |
3759 | wm8958_micd_set_rate(component); |
3760 | |
3761 | /* If we have jackdet that will detect removal */ |
3762 | wm1811_micd_stop(component); |
3763 | |
3764 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: SND_JACK_HEADPHONE, |
3765 | mask: SND_JACK_HEADSET); |
3766 | } |
3767 | } |
3768 | |
3769 | /* Deferred mic detection to allow for extra settling time */ |
3770 | static void wm1811_mic_work(struct work_struct *work) |
3771 | { |
3772 | struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv, |
3773 | mic_work.work); |
3774 | struct wm8994 *control = wm8994->wm8994; |
3775 | struct snd_soc_component *component = wm8994->hubs.component; |
3776 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
3777 | |
3778 | pm_runtime_get_sync(dev: component->dev); |
3779 | |
3780 | /* If required for an external cap force MICBIAS on */ |
3781 | if (control->pdata.jd_ext_cap) { |
3782 | snd_soc_dapm_force_enable_pin(dapm, pin: "MICBIAS2" ); |
3783 | snd_soc_dapm_sync(dapm); |
3784 | } |
3785 | |
3786 | mutex_lock(&wm8994->accdet_lock); |
3787 | |
3788 | dev_dbg(component->dev, "Starting mic detection\n" ); |
3789 | |
3790 | /* Use a user-supplied callback if we have one */ |
3791 | if (wm8994->micd_cb) { |
3792 | wm8994->micd_cb(wm8994->micd_cb_data); |
3793 | } else { |
3794 | /* |
3795 | * Start off measument of microphone impedence to find out |
3796 | * what's actually there. |
3797 | */ |
3798 | wm8994->mic_detecting = true; |
3799 | wm1811_jackdet_set_mode(component, WM1811_JACKDET_MODE_MIC); |
3800 | |
3801 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, |
3802 | WM8958_MICD_ENA, WM8958_MICD_ENA); |
3803 | } |
3804 | |
3805 | mutex_unlock(lock: &wm8994->accdet_lock); |
3806 | |
3807 | pm_runtime_put(dev: component->dev); |
3808 | } |
3809 | |
3810 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) |
3811 | { |
3812 | struct wm8994_priv *wm8994 = data; |
3813 | struct wm8994 *control = wm8994->wm8994; |
3814 | struct snd_soc_component *component = wm8994->hubs.component; |
3815 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
3816 | int reg, delay; |
3817 | bool present; |
3818 | |
3819 | pm_runtime_get_sync(dev: component->dev); |
3820 | |
3821 | cancel_delayed_work_sync(dwork: &wm8994->mic_complete_work); |
3822 | |
3823 | mutex_lock(&wm8994->accdet_lock); |
3824 | |
3825 | reg = snd_soc_component_read(component, WM1811_JACKDET_CTRL); |
3826 | if (reg < 0) { |
3827 | dev_err(component->dev, "Failed to read jack status: %d\n" , reg); |
3828 | mutex_unlock(lock: &wm8994->accdet_lock); |
3829 | pm_runtime_put(dev: component->dev); |
3830 | return IRQ_NONE; |
3831 | } |
3832 | |
3833 | dev_dbg(component->dev, "JACKDET %x\n" , reg); |
3834 | |
3835 | present = reg & WM1811_JACKDET_LVL; |
3836 | |
3837 | if (present) { |
3838 | dev_dbg(component->dev, "Jack detected\n" ); |
3839 | |
3840 | wm8958_micd_set_rate(component); |
3841 | |
3842 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
3843 | WM8958_MICB2_DISCH, val: 0); |
3844 | |
3845 | /* Disable debounce while inserted */ |
3846 | snd_soc_component_update_bits(component, WM1811_JACKDET_CTRL, |
3847 | WM1811_JACKDET_DB, val: 0); |
3848 | |
3849 | delay = control->pdata.micdet_delay; |
3850 | queue_delayed_work(wq: system_power_efficient_wq, |
3851 | dwork: &wm8994->mic_work, |
3852 | delay: msecs_to_jiffies(m: delay)); |
3853 | } else { |
3854 | dev_dbg(component->dev, "Jack not detected\n" ); |
3855 | |
3856 | /* Release wm8994->accdet_lock to avoid deadlock: |
3857 | * cancel_delayed_work_sync() takes wm8994->mic_work internal |
3858 | * lock and wm1811_mic_work takes wm8994->accdet_lock */ |
3859 | mutex_unlock(lock: &wm8994->accdet_lock); |
3860 | cancel_delayed_work_sync(dwork: &wm8994->mic_work); |
3861 | mutex_lock(&wm8994->accdet_lock); |
3862 | |
3863 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
3864 | WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); |
3865 | |
3866 | /* Enable debounce while removed */ |
3867 | snd_soc_component_update_bits(component, WM1811_JACKDET_CTRL, |
3868 | WM1811_JACKDET_DB, WM1811_JACKDET_DB); |
3869 | |
3870 | wm8994->mic_detecting = false; |
3871 | wm8994->jack_mic = false; |
3872 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, |
3873 | WM8958_MICD_ENA, val: 0); |
3874 | wm1811_jackdet_set_mode(component, WM1811_JACKDET_MODE_JACK); |
3875 | } |
3876 | |
3877 | mutex_unlock(lock: &wm8994->accdet_lock); |
3878 | |
3879 | /* Turn off MICBIAS if it was on for an external cap */ |
3880 | if (control->pdata.jd_ext_cap && !present) |
3881 | snd_soc_dapm_disable_pin(dapm, pin: "MICBIAS2" ); |
3882 | |
3883 | if (present) |
3884 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, |
3885 | status: SND_JACK_MECHANICAL, mask: SND_JACK_MECHANICAL); |
3886 | else |
3887 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: 0, |
3888 | mask: SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
3889 | wm8994->btn_mask); |
3890 | |
3891 | /* Since we only report deltas force an update, ensures we |
3892 | * avoid bootstrapping issues with the core. */ |
3893 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: 0, mask: 0); |
3894 | |
3895 | pm_runtime_put(dev: component->dev); |
3896 | return IRQ_HANDLED; |
3897 | } |
3898 | |
3899 | static void wm1811_jackdet_bootstrap(struct work_struct *work) |
3900 | { |
3901 | struct wm8994_priv *wm8994 = container_of(work, |
3902 | struct wm8994_priv, |
3903 | jackdet_bootstrap.work); |
3904 | wm1811_jackdet_irq(irq: 0, data: wm8994); |
3905 | } |
3906 | |
3907 | /** |
3908 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
3909 | * |
3910 | * @component: WM8958 component |
3911 | * @jack: jack to report detection events on |
3912 | * @det_cb: detection callback |
3913 | * @det_cb_data: data for detection callback |
3914 | * @id_cb: mic id callback |
3915 | * @id_cb_data: data for mic id callback |
3916 | * |
3917 | * Enable microphone detection functionality for the WM8958. By |
3918 | * default simple detection which supports the detection of up to 6 |
3919 | * buttons plus video and microphone functionality is supported. |
3920 | * |
3921 | * The WM8958 has an advanced jack detection facility which is able to |
3922 | * support complex accessory detection, especially when used in |
3923 | * conjunction with external circuitry. In order to provide maximum |
3924 | * flexiblity a callback is provided which allows a completely custom |
3925 | * detection algorithm. |
3926 | */ |
3927 | int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack, |
3928 | wm1811_micdet_cb det_cb, void *det_cb_data, |
3929 | wm1811_mic_id_cb id_cb, void *id_cb_data) |
3930 | { |
3931 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
3932 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
3933 | struct wm8994 *control = wm8994->wm8994; |
3934 | u16 micd_lvl_sel; |
3935 | |
3936 | switch (control->type) { |
3937 | case WM1811: |
3938 | case WM8958: |
3939 | break; |
3940 | default: |
3941 | return -EINVAL; |
3942 | } |
3943 | |
3944 | pm_runtime_get_sync(dev: component->dev); |
3945 | |
3946 | if (jack) { |
3947 | snd_soc_dapm_force_enable_pin(dapm, pin: "CLK_SYS" ); |
3948 | snd_soc_dapm_sync(dapm); |
3949 | |
3950 | wm8994->micdet[0].jack = jack; |
3951 | |
3952 | if (det_cb) { |
3953 | wm8994->micd_cb = det_cb; |
3954 | wm8994->micd_cb_data = det_cb_data; |
3955 | } else { |
3956 | wm8994->mic_detecting = true; |
3957 | wm8994->jack_mic = false; |
3958 | } |
3959 | |
3960 | if (id_cb) { |
3961 | wm8994->mic_id_cb = id_cb; |
3962 | wm8994->mic_id_cb_data = id_cb_data; |
3963 | } else { |
3964 | wm8994->mic_id_cb = wm8958_mic_id; |
3965 | wm8994->mic_id_cb_data = component; |
3966 | } |
3967 | |
3968 | wm8958_micd_set_rate(component); |
3969 | |
3970 | /* Detect microphones and short circuits by default */ |
3971 | if (control->pdata.micd_lvl_sel) |
3972 | micd_lvl_sel = control->pdata.micd_lvl_sel; |
3973 | else |
3974 | micd_lvl_sel = 0x41; |
3975 | |
3976 | wm8994->btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
3977 | SND_JACK_BTN_2 | SND_JACK_BTN_3 | |
3978 | SND_JACK_BTN_4 | SND_JACK_BTN_5; |
3979 | |
3980 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_2, |
3981 | WM8958_MICD_LVL_SEL_MASK, val: micd_lvl_sel); |
3982 | |
3983 | WARN_ON(snd_soc_component_get_bias_level(component) > SND_SOC_BIAS_STANDBY); |
3984 | |
3985 | /* |
3986 | * If we can use jack detection start off with that, |
3987 | * otherwise jump straight to microphone detection. |
3988 | */ |
3989 | if (wm8994->jackdet) { |
3990 | /* Disable debounce for the initial detect */ |
3991 | snd_soc_component_update_bits(component, WM1811_JACKDET_CTRL, |
3992 | WM1811_JACKDET_DB, val: 0); |
3993 | |
3994 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
3995 | WM8958_MICB2_DISCH, |
3996 | WM8958_MICB2_DISCH); |
3997 | snd_soc_component_update_bits(component, WM8994_LDO_1, |
3998 | WM8994_LDO1_DISCH, val: 0); |
3999 | wm1811_jackdet_set_mode(component, |
4000 | WM1811_JACKDET_MODE_JACK); |
4001 | } else { |
4002 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, |
4003 | WM8958_MICD_ENA, WM8958_MICD_ENA); |
4004 | } |
4005 | |
4006 | } else { |
4007 | snd_soc_component_update_bits(component, WM8958_MIC_DETECT_1, |
4008 | WM8958_MICD_ENA, val: 0); |
4009 | wm1811_jackdet_set_mode(component, WM1811_JACKDET_MODE_NONE); |
4010 | snd_soc_dapm_disable_pin(dapm, pin: "CLK_SYS" ); |
4011 | snd_soc_dapm_sync(dapm); |
4012 | } |
4013 | |
4014 | pm_runtime_put(dev: component->dev); |
4015 | |
4016 | return 0; |
4017 | } |
4018 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); |
4019 | |
4020 | static void wm8958_mic_work(struct work_struct *work) |
4021 | { |
4022 | struct wm8994_priv *wm8994 = container_of(work, |
4023 | struct wm8994_priv, |
4024 | mic_complete_work.work); |
4025 | struct snd_soc_component *component = wm8994->hubs.component; |
4026 | |
4027 | pm_runtime_get_sync(dev: component->dev); |
4028 | |
4029 | mutex_lock(&wm8994->accdet_lock); |
4030 | |
4031 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, wm8994->mic_status); |
4032 | |
4033 | mutex_unlock(lock: &wm8994->accdet_lock); |
4034 | |
4035 | pm_runtime_put(dev: component->dev); |
4036 | } |
4037 | |
4038 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
4039 | { |
4040 | struct wm8994_priv *wm8994 = data; |
4041 | struct snd_soc_component *component = wm8994->hubs.component; |
4042 | int reg, count, ret, id_delay; |
4043 | |
4044 | /* |
4045 | * Jack detection may have detected a removal simulataneously |
4046 | * with an update of the MICDET status; if so it will have |
4047 | * stopped detection and we can ignore this interrupt. |
4048 | */ |
4049 | if (!(snd_soc_component_read(component, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) |
4050 | return IRQ_HANDLED; |
4051 | |
4052 | cancel_delayed_work_sync(dwork: &wm8994->mic_complete_work); |
4053 | cancel_delayed_work_sync(dwork: &wm8994->open_circuit_work); |
4054 | |
4055 | pm_runtime_get_sync(dev: component->dev); |
4056 | |
4057 | /* We may occasionally read a detection without an impedence |
4058 | * range being provided - if that happens loop again. |
4059 | */ |
4060 | count = 10; |
4061 | do { |
4062 | reg = snd_soc_component_read(component, WM8958_MIC_DETECT_3); |
4063 | if (reg < 0) { |
4064 | dev_err(component->dev, |
4065 | "Failed to read mic detect status: %d\n" , |
4066 | reg); |
4067 | pm_runtime_put(dev: component->dev); |
4068 | return IRQ_NONE; |
4069 | } |
4070 | |
4071 | if (!(reg & WM8958_MICD_VALID)) { |
4072 | dev_dbg(component->dev, "Mic detect data not valid\n" ); |
4073 | goto out; |
4074 | } |
4075 | |
4076 | if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK)) |
4077 | break; |
4078 | |
4079 | msleep(msecs: 1); |
4080 | } while (count--); |
4081 | |
4082 | if (count == 0) |
4083 | dev_warn(component->dev, "No impedance range reported for jack\n" ); |
4084 | |
4085 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
4086 | trace_snd_soc_jack_irq(name: dev_name(dev: component->dev)); |
4087 | #endif |
4088 | |
4089 | /* Avoid a transient report when the accessory is being removed */ |
4090 | if (wm8994->jackdet) { |
4091 | ret = snd_soc_component_read(component, WM1811_JACKDET_CTRL); |
4092 | if (ret < 0) { |
4093 | dev_err(component->dev, "Failed to read jack status: %d\n" , |
4094 | ret); |
4095 | } else if (!(ret & WM1811_JACKDET_LVL)) { |
4096 | dev_dbg(component->dev, "Ignoring removed jack\n" ); |
4097 | goto out; |
4098 | } |
4099 | } else if (!(reg & WM8958_MICD_STS)) { |
4100 | snd_soc_jack_report(jack: wm8994->micdet[0].jack, status: 0, |
4101 | mask: SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
4102 | wm8994->btn_mask); |
4103 | wm8994->mic_detecting = true; |
4104 | goto out; |
4105 | } |
4106 | |
4107 | wm8994->mic_status = reg; |
4108 | id_delay = wm8994->wm8994->pdata.mic_id_delay; |
4109 | |
4110 | if (wm8994->mic_detecting) |
4111 | queue_delayed_work(wq: system_power_efficient_wq, |
4112 | dwork: &wm8994->mic_complete_work, |
4113 | delay: msecs_to_jiffies(m: id_delay)); |
4114 | else |
4115 | wm8958_button_det(component, status: reg); |
4116 | |
4117 | out: |
4118 | pm_runtime_put(dev: component->dev); |
4119 | return IRQ_HANDLED; |
4120 | } |
4121 | |
4122 | static irqreturn_t wm8994_fifo_error(int irq, void *data) |
4123 | { |
4124 | struct snd_soc_component *component = data; |
4125 | |
4126 | dev_err(component->dev, "FIFO error\n" ); |
4127 | |
4128 | return IRQ_HANDLED; |
4129 | } |
4130 | |
4131 | static irqreturn_t wm8994_temp_warn(int irq, void *data) |
4132 | { |
4133 | struct snd_soc_component *component = data; |
4134 | |
4135 | dev_err(component->dev, "Thermal warning\n" ); |
4136 | |
4137 | return IRQ_HANDLED; |
4138 | } |
4139 | |
4140 | static irqreturn_t wm8994_temp_shut(int irq, void *data) |
4141 | { |
4142 | struct snd_soc_component *component = data; |
4143 | |
4144 | dev_crit(component->dev, "Thermal shutdown\n" ); |
4145 | |
4146 | return IRQ_HANDLED; |
4147 | } |
4148 | |
4149 | static int wm8994_component_probe(struct snd_soc_component *component) |
4150 | { |
4151 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
4152 | struct wm8994 *control = dev_get_drvdata(dev: component->dev->parent); |
4153 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
4154 | unsigned int reg; |
4155 | int ret, i; |
4156 | |
4157 | snd_soc_component_init_regmap(component, regmap: control->regmap); |
4158 | |
4159 | wm8994->hubs.component = component; |
4160 | |
4161 | mutex_init(&wm8994->accdet_lock); |
4162 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, |
4163 | wm1811_jackdet_bootstrap); |
4164 | INIT_DELAYED_WORK(&wm8994->open_circuit_work, |
4165 | wm8958_open_circuit_work); |
4166 | |
4167 | switch (control->type) { |
4168 | case WM8994: |
4169 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); |
4170 | break; |
4171 | case WM1811: |
4172 | INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work); |
4173 | break; |
4174 | default: |
4175 | break; |
4176 | } |
4177 | |
4178 | INIT_DELAYED_WORK(&wm8994->mic_complete_work, wm8958_mic_work); |
4179 | |
4180 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
4181 | init_completion(x: &wm8994->fll_locked[i]); |
4182 | |
4183 | wm8994->micdet_irq = control->pdata.micdet_irq; |
4184 | |
4185 | /* By default use idle_bias_off, will override for WM8994 */ |
4186 | dapm->idle_bias_off = 1; |
4187 | |
4188 | /* Set revision-specific configuration */ |
4189 | switch (control->type) { |
4190 | case WM8994: |
4191 | /* Single ended line outputs should have VMID on. */ |
4192 | if (!control->pdata.lineout1_diff || |
4193 | !control->pdata.lineout2_diff) |
4194 | dapm->idle_bias_off = 0; |
4195 | |
4196 | switch (control->revision) { |
4197 | case 2: |
4198 | case 3: |
4199 | wm8994->hubs.dcs_codes_l = -5; |
4200 | wm8994->hubs.dcs_codes_r = -5; |
4201 | wm8994->hubs.hp_startup_mode = 1; |
4202 | wm8994->hubs.dcs_readback_mode = 1; |
4203 | wm8994->hubs.series_startup = 1; |
4204 | break; |
4205 | default: |
4206 | wm8994->hubs.dcs_readback_mode = 2; |
4207 | break; |
4208 | } |
4209 | wm8994->hubs.micd_scthr = true; |
4210 | break; |
4211 | |
4212 | case WM8958: |
4213 | wm8994->hubs.dcs_readback_mode = 1; |
4214 | wm8994->hubs.hp_startup_mode = 1; |
4215 | wm8994->hubs.micd_scthr = true; |
4216 | |
4217 | switch (control->revision) { |
4218 | case 0: |
4219 | break; |
4220 | default: |
4221 | wm8994->fll_byp = true; |
4222 | break; |
4223 | } |
4224 | break; |
4225 | |
4226 | case WM1811: |
4227 | wm8994->hubs.dcs_readback_mode = 2; |
4228 | wm8994->hubs.no_series_update = 1; |
4229 | wm8994->hubs.hp_startup_mode = 1; |
4230 | wm8994->hubs.no_cache_dac_hp_direct = true; |
4231 | wm8994->fll_byp = true; |
4232 | |
4233 | wm8994->hubs.dcs_codes_l = -9; |
4234 | wm8994->hubs.dcs_codes_r = -7; |
4235 | |
4236 | snd_soc_component_update_bits(component, WM8994_ANALOGUE_HP_1, |
4237 | WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); |
4238 | break; |
4239 | |
4240 | default: |
4241 | break; |
4242 | } |
4243 | |
4244 | wm8994_request_irq(wm8994: wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, |
4245 | handler: wm8994_fifo_error, name: "FIFO error" , data: component); |
4246 | wm8994_request_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_WARN, |
4247 | handler: wm8994_temp_warn, name: "Thermal warning" , data: component); |
4248 | wm8994_request_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, |
4249 | handler: wm8994_temp_shut, name: "Thermal shutdown" , data: component); |
4250 | |
4251 | switch (control->type) { |
4252 | case WM8994: |
4253 | if (wm8994->micdet_irq) |
4254 | ret = request_threaded_irq(irq: wm8994->micdet_irq, NULL, |
4255 | thread_fn: wm8994_mic_irq, |
4256 | IRQF_TRIGGER_RISING | |
4257 | IRQF_ONESHOT, |
4258 | name: "Mic1 detect" , |
4259 | dev: wm8994); |
4260 | else |
4261 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4262 | WM8994_IRQ_MIC1_DET, |
4263 | handler: wm8994_mic_irq, name: "Mic 1 detect" , |
4264 | data: wm8994); |
4265 | |
4266 | if (ret != 0) |
4267 | dev_warn(component->dev, |
4268 | "Failed to request Mic1 detect IRQ: %d\n" , |
4269 | ret); |
4270 | |
4271 | |
4272 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4273 | WM8994_IRQ_MIC1_SHRT, |
4274 | handler: wm8994_mic_irq, name: "Mic 1 short" , |
4275 | data: wm8994); |
4276 | if (ret != 0) |
4277 | dev_warn(component->dev, |
4278 | "Failed to request Mic1 short IRQ: %d\n" , |
4279 | ret); |
4280 | |
4281 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4282 | WM8994_IRQ_MIC2_DET, |
4283 | handler: wm8994_mic_irq, name: "Mic 2 detect" , |
4284 | data: wm8994); |
4285 | if (ret != 0) |
4286 | dev_warn(component->dev, |
4287 | "Failed to request Mic2 detect IRQ: %d\n" , |
4288 | ret); |
4289 | |
4290 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4291 | WM8994_IRQ_MIC2_SHRT, |
4292 | handler: wm8994_mic_irq, name: "Mic 2 short" , |
4293 | data: wm8994); |
4294 | if (ret != 0) |
4295 | dev_warn(component->dev, |
4296 | "Failed to request Mic2 short IRQ: %d\n" , |
4297 | ret); |
4298 | break; |
4299 | |
4300 | case WM8958: |
4301 | case WM1811: |
4302 | if (wm8994->micdet_irq) { |
4303 | ret = request_threaded_irq(irq: wm8994->micdet_irq, NULL, |
4304 | thread_fn: wm8958_mic_irq, |
4305 | IRQF_TRIGGER_RISING | |
4306 | IRQF_ONESHOT, |
4307 | name: "Mic detect" , |
4308 | dev: wm8994); |
4309 | if (ret != 0) |
4310 | dev_warn(component->dev, |
4311 | "Failed to request Mic detect IRQ: %d\n" , |
4312 | ret); |
4313 | } else { |
4314 | wm8994_request_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC1_DET, |
4315 | handler: wm8958_mic_irq, name: "Mic detect" , |
4316 | data: wm8994); |
4317 | } |
4318 | } |
4319 | |
4320 | switch (control->type) { |
4321 | case WM1811: |
4322 | if (control->cust_id > 1 || control->revision > 1) { |
4323 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4324 | WM8994_IRQ_GPIO(6), |
4325 | handler: wm1811_jackdet_irq, name: "JACKDET" , |
4326 | data: wm8994); |
4327 | if (ret == 0) |
4328 | wm8994->jackdet = true; |
4329 | } |
4330 | break; |
4331 | default: |
4332 | break; |
4333 | } |
4334 | |
4335 | wm8994->fll_locked_irq = true; |
4336 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { |
4337 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, |
4338 | WM8994_IRQ_FLL1_LOCK + i, |
4339 | handler: wm8994_fll_locked_irq, name: "FLL lock" , |
4340 | data: &wm8994->fll_locked[i]); |
4341 | if (ret != 0) |
4342 | wm8994->fll_locked_irq = false; |
4343 | } |
4344 | |
4345 | /* Make sure we can read from the GPIOs if they're inputs */ |
4346 | pm_runtime_get_sync(dev: component->dev); |
4347 | |
4348 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
4349 | * configured on init - if a system wants to do this dynamically |
4350 | * at runtime we can deal with that then. |
4351 | */ |
4352 | ret = regmap_read(map: control->regmap, WM8994_GPIO_1, val: ®); |
4353 | if (ret < 0) { |
4354 | dev_err(component->dev, "Failed to read GPIO1 state: %d\n" , ret); |
4355 | goto err_irq; |
4356 | } |
4357 | if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { |
4358 | wm8994->lrclk_shared[0] = 1; |
4359 | wm8994_dai[0].symmetric_rate = 1; |
4360 | } else { |
4361 | wm8994->lrclk_shared[0] = 0; |
4362 | } |
4363 | |
4364 | ret = regmap_read(map: control->regmap, WM8994_GPIO_6, val: ®); |
4365 | if (ret < 0) { |
4366 | dev_err(component->dev, "Failed to read GPIO6 state: %d\n" , ret); |
4367 | goto err_irq; |
4368 | } |
4369 | if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { |
4370 | wm8994->lrclk_shared[1] = 1; |
4371 | wm8994_dai[1].symmetric_rate = 1; |
4372 | } else { |
4373 | wm8994->lrclk_shared[1] = 0; |
4374 | } |
4375 | |
4376 | pm_runtime_put(dev: component->dev); |
4377 | |
4378 | /* Latch volume update bits */ |
4379 | for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) |
4380 | snd_soc_component_update_bits(component, reg: wm8994_vu_bits[i].reg, |
4381 | mask: wm8994_vu_bits[i].mask, |
4382 | val: wm8994_vu_bits[i].mask); |
4383 | |
4384 | if (control->type != WM1811) { |
4385 | for (i = 0; i < ARRAY_SIZE(wm8994_adc2_dac2_vu_bits); i++) |
4386 | snd_soc_component_update_bits(component, |
4387 | reg: wm8994_adc2_dac2_vu_bits[i].reg, |
4388 | mask: wm8994_adc2_dac2_vu_bits[i].mask, |
4389 | val: wm8994_adc2_dac2_vu_bits[i].mask); |
4390 | } |
4391 | |
4392 | /* Set the low bit of the 3D stereo depth so TLV matches */ |
4393 | snd_soc_component_update_bits(component, WM8994_AIF1_DAC1_FILTERS_2, |
4394 | mask: 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT, |
4395 | val: 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT); |
4396 | snd_soc_component_update_bits(component, WM8994_AIF1_DAC2_FILTERS_2, |
4397 | mask: 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT, |
4398 | val: 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT); |
4399 | snd_soc_component_update_bits(component, WM8994_AIF2_DAC_FILTERS_2, |
4400 | mask: 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, |
4401 | val: 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); |
4402 | |
4403 | /* Unconditionally enable AIF1 ADC TDM mode on chips which can |
4404 | * use this; it only affects behaviour on idle TDM clock |
4405 | * cycles. */ |
4406 | switch (control->type) { |
4407 | case WM8994: |
4408 | case WM8958: |
4409 | snd_soc_component_update_bits(component, WM8994_AIF1_CONTROL_1, |
4410 | WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); |
4411 | break; |
4412 | default: |
4413 | break; |
4414 | } |
4415 | |
4416 | /* Put MICBIAS into bypass mode by default on newer devices */ |
4417 | switch (control->type) { |
4418 | case WM8958: |
4419 | case WM1811: |
4420 | snd_soc_component_update_bits(component, WM8958_MICBIAS1, |
4421 | WM8958_MICB1_MODE, WM8958_MICB1_MODE); |
4422 | snd_soc_component_update_bits(component, WM8958_MICBIAS2, |
4423 | WM8958_MICB2_MODE, WM8958_MICB2_MODE); |
4424 | break; |
4425 | default: |
4426 | break; |
4427 | } |
4428 | |
4429 | wm8994->hubs.check_class_w_digital = wm8994_check_class_w_digital; |
4430 | wm_hubs_update_class_w(component); |
4431 | |
4432 | wm8994_handle_pdata(wm8994); |
4433 | |
4434 | wm_hubs_add_analogue_controls(component); |
4435 | snd_soc_add_component_controls(component, controls: wm8994_common_snd_controls, |
4436 | ARRAY_SIZE(wm8994_common_snd_controls)); |
4437 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dapm_widgets, |
4438 | ARRAY_SIZE(wm8994_dapm_widgets)); |
4439 | |
4440 | switch (control->type) { |
4441 | case WM8994: |
4442 | snd_soc_add_component_controls(component, controls: wm8994_snd_controls, |
4443 | ARRAY_SIZE(wm8994_snd_controls)); |
4444 | snd_soc_dapm_new_controls(dapm, widget: wm8994_specific_dapm_widgets, |
4445 | ARRAY_SIZE(wm8994_specific_dapm_widgets)); |
4446 | if (control->revision < 4) { |
4447 | snd_soc_dapm_new_controls(dapm, widget: wm8994_lateclk_revd_widgets, |
4448 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); |
4449 | snd_soc_dapm_new_controls(dapm, widget: wm8994_adc_revd_widgets, |
4450 | ARRAY_SIZE(wm8994_adc_revd_widgets)); |
4451 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dac_revd_widgets, |
4452 | ARRAY_SIZE(wm8994_dac_revd_widgets)); |
4453 | } else { |
4454 | snd_soc_dapm_new_controls(dapm, widget: wm8994_lateclk_widgets, |
4455 | ARRAY_SIZE(wm8994_lateclk_widgets)); |
4456 | snd_soc_dapm_new_controls(dapm, widget: wm8994_adc_widgets, |
4457 | ARRAY_SIZE(wm8994_adc_widgets)); |
4458 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dac_widgets, |
4459 | ARRAY_SIZE(wm8994_dac_widgets)); |
4460 | } |
4461 | break; |
4462 | case WM8958: |
4463 | snd_soc_add_component_controls(component, controls: wm8994_snd_controls, |
4464 | ARRAY_SIZE(wm8994_snd_controls)); |
4465 | snd_soc_add_component_controls(component, controls: wm8958_snd_controls, |
4466 | ARRAY_SIZE(wm8958_snd_controls)); |
4467 | snd_soc_dapm_new_controls(dapm, widget: wm8958_dapm_widgets, |
4468 | ARRAY_SIZE(wm8958_dapm_widgets)); |
4469 | if (control->revision < 1) { |
4470 | snd_soc_dapm_new_controls(dapm, widget: wm8994_lateclk_revd_widgets, |
4471 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); |
4472 | snd_soc_dapm_new_controls(dapm, widget: wm8994_adc_revd_widgets, |
4473 | ARRAY_SIZE(wm8994_adc_revd_widgets)); |
4474 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dac_revd_widgets, |
4475 | ARRAY_SIZE(wm8994_dac_revd_widgets)); |
4476 | } else { |
4477 | snd_soc_dapm_new_controls(dapm, widget: wm8994_lateclk_widgets, |
4478 | ARRAY_SIZE(wm8994_lateclk_widgets)); |
4479 | snd_soc_dapm_new_controls(dapm, widget: wm8994_adc_widgets, |
4480 | ARRAY_SIZE(wm8994_adc_widgets)); |
4481 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dac_widgets, |
4482 | ARRAY_SIZE(wm8994_dac_widgets)); |
4483 | } |
4484 | break; |
4485 | |
4486 | case WM1811: |
4487 | snd_soc_add_component_controls(component, controls: wm8958_snd_controls, |
4488 | ARRAY_SIZE(wm8958_snd_controls)); |
4489 | snd_soc_dapm_new_controls(dapm, widget: wm8958_dapm_widgets, |
4490 | ARRAY_SIZE(wm8958_dapm_widgets)); |
4491 | snd_soc_dapm_new_controls(dapm, widget: wm8994_lateclk_widgets, |
4492 | ARRAY_SIZE(wm8994_lateclk_widgets)); |
4493 | snd_soc_dapm_new_controls(dapm, widget: wm8994_adc_widgets, |
4494 | ARRAY_SIZE(wm8994_adc_widgets)); |
4495 | snd_soc_dapm_new_controls(dapm, widget: wm8994_dac_widgets, |
4496 | ARRAY_SIZE(wm8994_dac_widgets)); |
4497 | break; |
4498 | } |
4499 | |
4500 | wm_hubs_add_analogue_routes(component, 0, 0); |
4501 | ret = wm8994_request_irq(wm8994: wm8994->wm8994, WM8994_IRQ_DCS_DONE, |
4502 | handler: wm_hubs_dcs_done, name: "DC servo done" , |
4503 | data: &wm8994->hubs); |
4504 | if (ret == 0) |
4505 | wm8994->hubs.dcs_done_irq = true; |
4506 | snd_soc_dapm_add_routes(dapm, route: intercon, ARRAY_SIZE(intercon)); |
4507 | |
4508 | switch (control->type) { |
4509 | case WM8994: |
4510 | snd_soc_dapm_add_routes(dapm, route: wm8994_intercon, |
4511 | ARRAY_SIZE(wm8994_intercon)); |
4512 | |
4513 | if (control->revision < 4) { |
4514 | snd_soc_dapm_add_routes(dapm, route: wm8994_revd_intercon, |
4515 | ARRAY_SIZE(wm8994_revd_intercon)); |
4516 | snd_soc_dapm_add_routes(dapm, route: wm8994_lateclk_revd_intercon, |
4517 | ARRAY_SIZE(wm8994_lateclk_revd_intercon)); |
4518 | } else { |
4519 | snd_soc_dapm_add_routes(dapm, route: wm8994_lateclk_intercon, |
4520 | ARRAY_SIZE(wm8994_lateclk_intercon)); |
4521 | } |
4522 | break; |
4523 | case WM8958: |
4524 | if (control->revision < 1) { |
4525 | snd_soc_dapm_add_routes(dapm, route: wm8994_intercon, |
4526 | ARRAY_SIZE(wm8994_intercon)); |
4527 | snd_soc_dapm_add_routes(dapm, route: wm8994_revd_intercon, |
4528 | ARRAY_SIZE(wm8994_revd_intercon)); |
4529 | snd_soc_dapm_add_routes(dapm, route: wm8994_lateclk_revd_intercon, |
4530 | ARRAY_SIZE(wm8994_lateclk_revd_intercon)); |
4531 | } else { |
4532 | snd_soc_dapm_add_routes(dapm, route: wm8994_lateclk_intercon, |
4533 | ARRAY_SIZE(wm8994_lateclk_intercon)); |
4534 | snd_soc_dapm_add_routes(dapm, route: wm8958_intercon, |
4535 | ARRAY_SIZE(wm8958_intercon)); |
4536 | } |
4537 | |
4538 | wm8958_dsp2_init(component); |
4539 | break; |
4540 | case WM1811: |
4541 | snd_soc_dapm_add_routes(dapm, route: wm8994_lateclk_intercon, |
4542 | ARRAY_SIZE(wm8994_lateclk_intercon)); |
4543 | snd_soc_dapm_add_routes(dapm, route: wm8958_intercon, |
4544 | ARRAY_SIZE(wm8958_intercon)); |
4545 | break; |
4546 | } |
4547 | |
4548 | return 0; |
4549 | |
4550 | err_irq: |
4551 | if (wm8994->jackdet) |
4552 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_GPIO(6), data: wm8994); |
4553 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, data: wm8994); |
4554 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC2_DET, data: wm8994); |
4555 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, data: wm8994); |
4556 | if (wm8994->micdet_irq) |
4557 | free_irq(wm8994->micdet_irq, wm8994); |
4558 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
4559 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, |
4560 | data: &wm8994->fll_locked[i]); |
4561 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_DCS_DONE, |
4562 | data: &wm8994->hubs); |
4563 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, data: component); |
4564 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, data: component); |
4565 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_WARN, data: component); |
4566 | |
4567 | return ret; |
4568 | } |
4569 | |
4570 | static void wm8994_component_remove(struct snd_soc_component *component) |
4571 | { |
4572 | struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(c: component); |
4573 | struct wm8994 *control = wm8994->wm8994; |
4574 | int i; |
4575 | |
4576 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
4577 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, |
4578 | data: &wm8994->fll_locked[i]); |
4579 | |
4580 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_DCS_DONE, |
4581 | data: &wm8994->hubs); |
4582 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, data: component); |
4583 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, data: component); |
4584 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_TEMP_WARN, data: component); |
4585 | |
4586 | if (wm8994->jackdet) |
4587 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_GPIO(6), data: wm8994); |
4588 | |
4589 | switch (control->type) { |
4590 | case WM8994: |
4591 | if (wm8994->micdet_irq) |
4592 | free_irq(wm8994->micdet_irq, wm8994); |
4593 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC2_DET, |
4594 | data: wm8994); |
4595 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, |
4596 | data: wm8994); |
4597 | wm8994_free_irq(wm8994: wm8994->wm8994, WM8994_IRQ_MIC1_DET, |
4598 | data: wm8994); |
4599 | break; |
4600 | |
4601 | case WM1811: |
4602 | case WM8958: |
4603 | if (wm8994->micdet_irq) |
4604 | free_irq(wm8994->micdet_irq, wm8994); |
4605 | break; |
4606 | } |
4607 | release_firmware(fw: wm8994->mbc); |
4608 | release_firmware(fw: wm8994->mbc_vss); |
4609 | release_firmware(fw: wm8994->enh_eq); |
4610 | kfree(objp: wm8994->retune_mobile_texts); |
4611 | } |
4612 | |
4613 | static const struct snd_soc_component_driver soc_component_dev_wm8994 = { |
4614 | .probe = wm8994_component_probe, |
4615 | .remove = wm8994_component_remove, |
4616 | .suspend = wm8994_component_suspend, |
4617 | .resume = wm8994_component_resume, |
4618 | .set_bias_level = wm8994_set_bias_level, |
4619 | .idle_bias_on = 1, |
4620 | .use_pmdown_time = 1, |
4621 | .endianness = 1, |
4622 | }; |
4623 | |
4624 | static int wm8994_probe(struct platform_device *pdev) |
4625 | { |
4626 | struct wm8994_priv *wm8994; |
4627 | int ret; |
4628 | |
4629 | wm8994 = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct wm8994_priv), |
4630 | GFP_KERNEL); |
4631 | if (wm8994 == NULL) |
4632 | return -ENOMEM; |
4633 | platform_set_drvdata(pdev, data: wm8994); |
4634 | |
4635 | mutex_init(&wm8994->fw_lock); |
4636 | |
4637 | wm8994->wm8994 = dev_get_drvdata(dev: pdev->dev.parent); |
4638 | |
4639 | wm8994->mclk[WM8994_MCLK1].id = "MCLK1" ; |
4640 | wm8994->mclk[WM8994_MCLK2].id = "MCLK2" ; |
4641 | |
4642 | ret = devm_clk_bulk_get_optional(dev: pdev->dev.parent, ARRAY_SIZE(wm8994->mclk), |
4643 | clks: wm8994->mclk); |
4644 | if (ret < 0) { |
4645 | dev_err(&pdev->dev, "Failed to get clocks: %d\n" , ret); |
4646 | return ret; |
4647 | } |
4648 | |
4649 | pm_runtime_enable(dev: &pdev->dev); |
4650 | pm_runtime_idle(dev: &pdev->dev); |
4651 | |
4652 | ret = devm_snd_soc_register_component(dev: &pdev->dev, component_driver: &soc_component_dev_wm8994, |
4653 | dai_drv: wm8994_dai, ARRAY_SIZE(wm8994_dai)); |
4654 | if (ret < 0) |
4655 | pm_runtime_disable(dev: &pdev->dev); |
4656 | |
4657 | return ret; |
4658 | } |
4659 | |
4660 | static void wm8994_remove(struct platform_device *pdev) |
4661 | { |
4662 | pm_runtime_disable(dev: &pdev->dev); |
4663 | } |
4664 | |
4665 | #ifdef CONFIG_PM_SLEEP |
4666 | static int wm8994_suspend(struct device *dev) |
4667 | { |
4668 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); |
4669 | |
4670 | /* Drop down to power saving mode when system is suspended */ |
4671 | if (wm8994->jackdet && !wm8994->active_refcount) |
4672 | regmap_update_bits(map: wm8994->wm8994->regmap, WM8994_ANTIPOP_2, |
4673 | WM1811_JACKDET_MODE_MASK, |
4674 | val: wm8994->jackdet_mode); |
4675 | |
4676 | return 0; |
4677 | } |
4678 | |
4679 | static int wm8994_resume(struct device *dev) |
4680 | { |
4681 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); |
4682 | |
4683 | if (wm8994->jackdet && wm8994->jackdet_mode) |
4684 | regmap_update_bits(map: wm8994->wm8994->regmap, WM8994_ANTIPOP_2, |
4685 | WM1811_JACKDET_MODE_MASK, |
4686 | WM1811_JACKDET_MODE_AUDIO); |
4687 | |
4688 | return 0; |
4689 | } |
4690 | #endif |
4691 | |
4692 | static const struct dev_pm_ops wm8994_pm_ops = { |
4693 | SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume) |
4694 | }; |
4695 | |
4696 | static struct platform_driver wm8994_codec_driver = { |
4697 | .driver = { |
4698 | .name = "wm8994-codec" , |
4699 | .pm = &wm8994_pm_ops, |
4700 | }, |
4701 | .probe = wm8994_probe, |
4702 | .remove_new = wm8994_remove, |
4703 | }; |
4704 | |
4705 | module_platform_driver(wm8994_codec_driver); |
4706 | |
4707 | MODULE_DESCRIPTION("ASoC WM8994 driver" ); |
4708 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>" ); |
4709 | MODULE_LICENSE("GPL" ); |
4710 | MODULE_ALIAS("platform:wm8994-codec" ); |
4711 | |