1 /*
2 * arizona.c - Wolfson Arizona class device shared support
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13 #include <linux/delay.h>
14 #include <linux/gcd.h>
15 #include <linux/module.h>
16 #include <linux/pm_runtime.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/tlv.h>
20
21 #include <linux/mfd/arizona/core.h>
22 #include <linux/mfd/arizona/registers.h>
23
24 #include "arizona.h"
25
26 #define ARIZONA_AIF_BCLK_CTRL 0x00
27 #define ARIZONA_AIF_TX_PIN_CTRL 0x01
28 #define ARIZONA_AIF_RX_PIN_CTRL 0x02
29 #define ARIZONA_AIF_RATE_CTRL 0x03
30 #define ARIZONA_AIF_FORMAT 0x04
31 #define ARIZONA_AIF_TX_BCLK_RATE 0x05
32 #define ARIZONA_AIF_RX_BCLK_RATE 0x06
33 #define ARIZONA_AIF_FRAME_CTRL_1 0x07
34 #define ARIZONA_AIF_FRAME_CTRL_2 0x08
35 #define ARIZONA_AIF_FRAME_CTRL_3 0x09
36 #define ARIZONA_AIF_FRAME_CTRL_4 0x0A
37 #define ARIZONA_AIF_FRAME_CTRL_5 0x0B
38 #define ARIZONA_AIF_FRAME_CTRL_6 0x0C
39 #define ARIZONA_AIF_FRAME_CTRL_7 0x0D
40 #define ARIZONA_AIF_FRAME_CTRL_8 0x0E
41 #define ARIZONA_AIF_FRAME_CTRL_9 0x0F
42 #define ARIZONA_AIF_FRAME_CTRL_10 0x10
43 #define ARIZONA_AIF_FRAME_CTRL_11 0x11
44 #define ARIZONA_AIF_FRAME_CTRL_12 0x12
45 #define ARIZONA_AIF_FRAME_CTRL_13 0x13
46 #define ARIZONA_AIF_FRAME_CTRL_14 0x14
47 #define ARIZONA_AIF_FRAME_CTRL_15 0x15
48 #define ARIZONA_AIF_FRAME_CTRL_16 0x16
49 #define ARIZONA_AIF_FRAME_CTRL_17 0x17
50 #define ARIZONA_AIF_FRAME_CTRL_18 0x18
51 #define ARIZONA_AIF_TX_ENABLES 0x19
52 #define ARIZONA_AIF_RX_ENABLES 0x1A
53 #define ARIZONA_AIF_FORCE_WRITE 0x1B
54
55 #define ARIZONA_FLL_VCO_CORNER 141900000
56 #define ARIZONA_FLL_MAX_FREF 13500000
57 #define ARIZONA_FLL_MIN_FVCO 90000000
58 #define ARIZONA_FLL_MAX_FRATIO 16
59 #define ARIZONA_FLL_MAX_REFDIV 8
60 #define ARIZONA_FLL_MIN_OUTDIV 2
61 #define ARIZONA_FLL_MAX_OUTDIV 7
62
63 #define ARIZONA_FMT_DSP_MODE_A 0
64 #define ARIZONA_FMT_DSP_MODE_B 1
65 #define ARIZONA_FMT_I2S_MODE 2
66 #define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3
67
68 #define arizona_fll_err(_fll, fmt, ...) \
69 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
70 #define arizona_fll_warn(_fll, fmt, ...) \
71 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
72 #define arizona_fll_dbg(_fll, fmt, ...) \
73 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
74
75 #define arizona_aif_err(_dai, fmt, ...) \
76 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
77 #define arizona_aif_warn(_dai, fmt, ...) \
78 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
79 #define arizona_aif_dbg(_dai, fmt, ...) \
80 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
81
arizona_spk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)82 static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
83 struct snd_kcontrol *kcontrol,
84 int event)
85 {
86 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
87 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
88 int val;
89
90 switch (event) {
91 case SND_SOC_DAPM_POST_PMU:
92 val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
93 if (val & ARIZONA_SPK_OVERHEAT_STS) {
94 dev_crit(arizona->dev,
95 "Speaker not enabled due to temperature\n");
96 return -EBUSY;
97 }
98
99 regmap_update_bits_async(arizona->regmap,
100 ARIZONA_OUTPUT_ENABLES_1,
101 1 << w->shift, 1 << w->shift);
102 break;
103 case SND_SOC_DAPM_PRE_PMD:
104 regmap_update_bits_async(arizona->regmap,
105 ARIZONA_OUTPUT_ENABLES_1,
106 1 << w->shift, 0);
107 break;
108 default:
109 break;
110 }
111
112 return arizona_out_ev(w, kcontrol, event);
113 }
114
arizona_thermal_warn(int irq,void * data)115 static irqreturn_t arizona_thermal_warn(int irq, void *data)
116 {
117 struct arizona *arizona = data;
118 unsigned int val;
119 int ret;
120
121 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
122 &val);
123 if (ret != 0) {
124 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
125 ret);
126 } else if (val & ARIZONA_SPK_OVERHEAT_WARN_STS) {
127 dev_crit(arizona->dev, "Thermal warning\n");
128 }
129
130 return IRQ_HANDLED;
131 }
132
arizona_thermal_shutdown(int irq,void * data)133 static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
134 {
135 struct arizona *arizona = data;
136 unsigned int val;
137 int ret;
138
139 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
140 &val);
141 if (ret != 0) {
142 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
143 ret);
144 } else if (val & ARIZONA_SPK_OVERHEAT_STS) {
145 dev_crit(arizona->dev, "Thermal shutdown\n");
146 ret = regmap_update_bits(arizona->regmap,
147 ARIZONA_OUTPUT_ENABLES_1,
148 ARIZONA_OUT4L_ENA |
149 ARIZONA_OUT4R_ENA, 0);
150 if (ret != 0)
151 dev_crit(arizona->dev,
152 "Failed to disable speaker outputs: %d\n",
153 ret);
154 }
155
156 return IRQ_HANDLED;
157 }
158
159 static const struct snd_soc_dapm_widget arizona_spkl =
160 SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
161 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
162 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
163 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD);
164
165 static const struct snd_soc_dapm_widget arizona_spkr =
166 SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
167 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
168 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
169 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD);
170
arizona_init_spk(struct snd_soc_codec * codec)171 int arizona_init_spk(struct snd_soc_codec *codec)
172 {
173 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
174 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
175 struct arizona *arizona = priv->arizona;
176 int ret;
177
178 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1);
179 if (ret != 0)
180 return ret;
181
182 switch (arizona->type) {
183 case WM8997:
184 case CS47L24:
185 case WM1831:
186 break;
187 default:
188 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
189 if (ret != 0)
190 return ret;
191 break;
192 }
193
194 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
195 "Thermal warning", arizona_thermal_warn,
196 arizona);
197 if (ret != 0)
198 dev_err(arizona->dev,
199 "Failed to get thermal warning IRQ: %d\n",
200 ret);
201
202 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT,
203 "Thermal shutdown", arizona_thermal_shutdown,
204 arizona);
205 if (ret != 0)
206 dev_err(arizona->dev,
207 "Failed to get thermal shutdown IRQ: %d\n",
208 ret);
209
210 return 0;
211 }
212 EXPORT_SYMBOL_GPL(arizona_init_spk);
213
arizona_free_spk(struct snd_soc_codec * codec)214 int arizona_free_spk(struct snd_soc_codec *codec)
215 {
216 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
217 struct arizona *arizona = priv->arizona;
218
219 arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
220 arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
221
222 return 0;
223 }
224 EXPORT_SYMBOL_GPL(arizona_free_spk);
225
226 static const struct snd_soc_dapm_route arizona_mono_routes[] = {
227 { "OUT1R", NULL, "OUT1L" },
228 { "OUT2R", NULL, "OUT2L" },
229 { "OUT3R", NULL, "OUT3L" },
230 { "OUT4R", NULL, "OUT4L" },
231 { "OUT5R", NULL, "OUT5L" },
232 { "OUT6R", NULL, "OUT6L" },
233 };
234
arizona_init_mono(struct snd_soc_codec * codec)235 int arizona_init_mono(struct snd_soc_codec *codec)
236 {
237 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
238 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
239 struct arizona *arizona = priv->arizona;
240 int i;
241
242 for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
243 if (arizona->pdata.out_mono[i])
244 snd_soc_dapm_add_routes(dapm,
245 &arizona_mono_routes[i], 1);
246 }
247
248 return 0;
249 }
250 EXPORT_SYMBOL_GPL(arizona_init_mono);
251
arizona_init_gpio(struct snd_soc_codec * codec)252 int arizona_init_gpio(struct snd_soc_codec *codec)
253 {
254 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
255 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
256 struct arizona *arizona = priv->arizona;
257 int i;
258
259 switch (arizona->type) {
260 case WM5110:
261 case WM8280:
262 snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
263 break;
264 default:
265 break;
266 }
267
268 snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
269
270 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
271 switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
272 case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
273 snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
274 break;
275 case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
276 snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
277 break;
278 default:
279 break;
280 }
281 }
282
283 return 0;
284 }
285 EXPORT_SYMBOL_GPL(arizona_init_gpio);
286
arizona_init_notifiers(struct snd_soc_codec * codec)287 int arizona_init_notifiers(struct snd_soc_codec *codec)
288 {
289 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
290 struct arizona *arizona = priv->arizona;
291
292 BLOCKING_INIT_NOTIFIER_HEAD(&arizona->notifier);
293
294 return 0;
295 }
296 EXPORT_SYMBOL_GPL(arizona_init_notifiers);
297
298 const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
299 "None",
300 "Tone Generator 1",
301 "Tone Generator 2",
302 "Haptics",
303 "AEC",
304 "AEC2",
305 "Mic Mute Mixer",
306 "Noise Generator",
307 "IN1L",
308 "IN1R",
309 "IN2L",
310 "IN2R",
311 "IN3L",
312 "IN3R",
313 "IN4L",
314 "IN4R",
315 "AIF1RX1",
316 "AIF1RX2",
317 "AIF1RX3",
318 "AIF1RX4",
319 "AIF1RX5",
320 "AIF1RX6",
321 "AIF1RX7",
322 "AIF1RX8",
323 "AIF2RX1",
324 "AIF2RX2",
325 "AIF2RX3",
326 "AIF2RX4",
327 "AIF2RX5",
328 "AIF2RX6",
329 "AIF3RX1",
330 "AIF3RX2",
331 "SLIMRX1",
332 "SLIMRX2",
333 "SLIMRX3",
334 "SLIMRX4",
335 "SLIMRX5",
336 "SLIMRX6",
337 "SLIMRX7",
338 "SLIMRX8",
339 "EQ1",
340 "EQ2",
341 "EQ3",
342 "EQ4",
343 "DRC1L",
344 "DRC1R",
345 "DRC2L",
346 "DRC2R",
347 "LHPF1",
348 "LHPF2",
349 "LHPF3",
350 "LHPF4",
351 "DSP1.1",
352 "DSP1.2",
353 "DSP1.3",
354 "DSP1.4",
355 "DSP1.5",
356 "DSP1.6",
357 "DSP2.1",
358 "DSP2.2",
359 "DSP2.3",
360 "DSP2.4",
361 "DSP2.5",
362 "DSP2.6",
363 "DSP3.1",
364 "DSP3.2",
365 "DSP3.3",
366 "DSP3.4",
367 "DSP3.5",
368 "DSP3.6",
369 "DSP4.1",
370 "DSP4.2",
371 "DSP4.3",
372 "DSP4.4",
373 "DSP4.5",
374 "DSP4.6",
375 "ASRC1L",
376 "ASRC1R",
377 "ASRC2L",
378 "ASRC2R",
379 "ISRC1INT1",
380 "ISRC1INT2",
381 "ISRC1INT3",
382 "ISRC1INT4",
383 "ISRC1DEC1",
384 "ISRC1DEC2",
385 "ISRC1DEC3",
386 "ISRC1DEC4",
387 "ISRC2INT1",
388 "ISRC2INT2",
389 "ISRC2INT3",
390 "ISRC2INT4",
391 "ISRC2DEC1",
392 "ISRC2DEC2",
393 "ISRC2DEC3",
394 "ISRC2DEC4",
395 "ISRC3INT1",
396 "ISRC3INT2",
397 "ISRC3INT3",
398 "ISRC3INT4",
399 "ISRC3DEC1",
400 "ISRC3DEC2",
401 "ISRC3DEC3",
402 "ISRC3DEC4",
403 };
404 EXPORT_SYMBOL_GPL(arizona_mixer_texts);
405
406 unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
407 0x00, /* None */
408 0x04, /* Tone */
409 0x05,
410 0x06, /* Haptics */
411 0x08, /* AEC */
412 0x09, /* AEC2 */
413 0x0c, /* Noise mixer */
414 0x0d, /* Comfort noise */
415 0x10, /* IN1L */
416 0x11,
417 0x12,
418 0x13,
419 0x14,
420 0x15,
421 0x16,
422 0x17,
423 0x20, /* AIF1RX1 */
424 0x21,
425 0x22,
426 0x23,
427 0x24,
428 0x25,
429 0x26,
430 0x27,
431 0x28, /* AIF2RX1 */
432 0x29,
433 0x2a,
434 0x2b,
435 0x2c,
436 0x2d,
437 0x30, /* AIF3RX1 */
438 0x31,
439 0x38, /* SLIMRX1 */
440 0x39,
441 0x3a,
442 0x3b,
443 0x3c,
444 0x3d,
445 0x3e,
446 0x3f,
447 0x50, /* EQ1 */
448 0x51,
449 0x52,
450 0x53,
451 0x58, /* DRC1L */
452 0x59,
453 0x5a,
454 0x5b,
455 0x60, /* LHPF1 */
456 0x61,
457 0x62,
458 0x63,
459 0x68, /* DSP1.1 */
460 0x69,
461 0x6a,
462 0x6b,
463 0x6c,
464 0x6d,
465 0x70, /* DSP2.1 */
466 0x71,
467 0x72,
468 0x73,
469 0x74,
470 0x75,
471 0x78, /* DSP3.1 */
472 0x79,
473 0x7a,
474 0x7b,
475 0x7c,
476 0x7d,
477 0x80, /* DSP4.1 */
478 0x81,
479 0x82,
480 0x83,
481 0x84,
482 0x85,
483 0x90, /* ASRC1L */
484 0x91,
485 0x92,
486 0x93,
487 0xa0, /* ISRC1INT1 */
488 0xa1,
489 0xa2,
490 0xa3,
491 0xa4, /* ISRC1DEC1 */
492 0xa5,
493 0xa6,
494 0xa7,
495 0xa8, /* ISRC2DEC1 */
496 0xa9,
497 0xaa,
498 0xab,
499 0xac, /* ISRC2INT1 */
500 0xad,
501 0xae,
502 0xaf,
503 0xb0, /* ISRC3DEC1 */
504 0xb1,
505 0xb2,
506 0xb3,
507 0xb4, /* ISRC3INT1 */
508 0xb5,
509 0xb6,
510 0xb7,
511 };
512 EXPORT_SYMBOL_GPL(arizona_mixer_values);
513
514 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
515 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
516
517 const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
518 "12kHz", "24kHz", "48kHz", "96kHz", "192kHz",
519 "11.025kHz", "22.05kHz", "44.1kHz", "88.2kHz", "176.4kHz",
520 "4kHz", "8kHz", "16kHz", "32kHz",
521 };
522 EXPORT_SYMBOL_GPL(arizona_sample_rate_text);
523
524 const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
525 0x01, 0x02, 0x03, 0x04, 0x05, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
526 0x10, 0x11, 0x12, 0x13,
527 };
528 EXPORT_SYMBOL_GPL(arizona_sample_rate_val);
529
arizona_sample_rate_val_to_name(unsigned int rate_val)530 const char *arizona_sample_rate_val_to_name(unsigned int rate_val)
531 {
532 int i;
533
534 for (i = 0; i < ARRAY_SIZE(arizona_sample_rate_val); ++i) {
535 if (arizona_sample_rate_val[i] == rate_val)
536 return arizona_sample_rate_text[i];
537 }
538
539 return "Illegal";
540 }
541 EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name);
542
543 const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
544 "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
545 };
546 EXPORT_SYMBOL_GPL(arizona_rate_text);
547
548 const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
549 0, 1, 2, 8,
550 };
551 EXPORT_SYMBOL_GPL(arizona_rate_val);
552
553
554 const struct soc_enum arizona_isrc_fsh[] = {
555 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1,
556 ARIZONA_ISRC1_FSH_SHIFT, 0xf,
557 ARIZONA_RATE_ENUM_SIZE,
558 arizona_rate_text, arizona_rate_val),
559 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1,
560 ARIZONA_ISRC2_FSH_SHIFT, 0xf,
561 ARIZONA_RATE_ENUM_SIZE,
562 arizona_rate_text, arizona_rate_val),
563 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1,
564 ARIZONA_ISRC3_FSH_SHIFT, 0xf,
565 ARIZONA_RATE_ENUM_SIZE,
566 arizona_rate_text, arizona_rate_val),
567 };
568 EXPORT_SYMBOL_GPL(arizona_isrc_fsh);
569
570 const struct soc_enum arizona_isrc_fsl[] = {
571 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
572 ARIZONA_ISRC1_FSL_SHIFT, 0xf,
573 ARIZONA_RATE_ENUM_SIZE,
574 arizona_rate_text, arizona_rate_val),
575 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
576 ARIZONA_ISRC2_FSL_SHIFT, 0xf,
577 ARIZONA_RATE_ENUM_SIZE,
578 arizona_rate_text, arizona_rate_val),
579 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
580 ARIZONA_ISRC3_FSL_SHIFT, 0xf,
581 ARIZONA_RATE_ENUM_SIZE,
582 arizona_rate_text, arizona_rate_val),
583 };
584 EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
585
586 const struct soc_enum arizona_asrc_rate1 =
587 SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1,
588 ARIZONA_ASRC_RATE1_SHIFT, 0xf,
589 ARIZONA_RATE_ENUM_SIZE - 1,
590 arizona_rate_text, arizona_rate_val);
591 EXPORT_SYMBOL_GPL(arizona_asrc_rate1);
592
593 static const char * const arizona_vol_ramp_text[] = {
594 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
595 "15ms/6dB", "30ms/6dB",
596 };
597
598 SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp,
599 ARIZONA_INPUT_VOLUME_RAMP,
600 ARIZONA_IN_VD_RAMP_SHIFT,
601 arizona_vol_ramp_text);
602 EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
603
604 SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp,
605 ARIZONA_INPUT_VOLUME_RAMP,
606 ARIZONA_IN_VI_RAMP_SHIFT,
607 arizona_vol_ramp_text);
608 EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
609
610 SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp,
611 ARIZONA_OUTPUT_VOLUME_RAMP,
612 ARIZONA_OUT_VD_RAMP_SHIFT,
613 arizona_vol_ramp_text);
614 EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
615
616 SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp,
617 ARIZONA_OUTPUT_VOLUME_RAMP,
618 ARIZONA_OUT_VI_RAMP_SHIFT,
619 arizona_vol_ramp_text);
620 EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
621
622 static const char * const arizona_lhpf_mode_text[] = {
623 "Low-pass", "High-pass"
624 };
625
626 SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode,
627 ARIZONA_HPLPF1_1,
628 ARIZONA_LHPF1_MODE_SHIFT,
629 arizona_lhpf_mode_text);
630 EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
631
632 SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode,
633 ARIZONA_HPLPF2_1,
634 ARIZONA_LHPF2_MODE_SHIFT,
635 arizona_lhpf_mode_text);
636 EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
637
638 SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode,
639 ARIZONA_HPLPF3_1,
640 ARIZONA_LHPF3_MODE_SHIFT,
641 arizona_lhpf_mode_text);
642 EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
643
644 SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode,
645 ARIZONA_HPLPF4_1,
646 ARIZONA_LHPF4_MODE_SHIFT,
647 arizona_lhpf_mode_text);
648 EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
649
650 static const char * const arizona_ng_hold_text[] = {
651 "30ms", "120ms", "250ms", "500ms",
652 };
653
654 SOC_ENUM_SINGLE_DECL(arizona_ng_hold,
655 ARIZONA_NOISE_GATE_CONTROL,
656 ARIZONA_NGATE_HOLD_SHIFT,
657 arizona_ng_hold_text);
658 EXPORT_SYMBOL_GPL(arizona_ng_hold);
659
660 static const char * const arizona_in_hpf_cut_text[] = {
661 "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
662 };
663
664 SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum,
665 ARIZONA_HPF_CONTROL,
666 ARIZONA_IN_HPF_CUT_SHIFT,
667 arizona_in_hpf_cut_text);
668 EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
669
670 static const char * const arizona_in_dmic_osr_text[] = {
671 "1.536MHz", "3.072MHz", "6.144MHz", "768kHz",
672 };
673
674 const struct soc_enum arizona_in_dmic_osr[] = {
675 SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
676 ARRAY_SIZE(arizona_in_dmic_osr_text),
677 arizona_in_dmic_osr_text),
678 SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
679 ARRAY_SIZE(arizona_in_dmic_osr_text),
680 arizona_in_dmic_osr_text),
681 SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
682 ARRAY_SIZE(arizona_in_dmic_osr_text),
683 arizona_in_dmic_osr_text),
684 SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
685 ARRAY_SIZE(arizona_in_dmic_osr_text),
686 arizona_in_dmic_osr_text),
687 };
688 EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
689
690 static const char * const arizona_anc_input_src_text[] = {
691 "None", "IN1", "IN2", "IN3", "IN4",
692 };
693
694 static const char * const arizona_anc_channel_src_text[] = {
695 "None", "Left", "Right", "Combine",
696 };
697
698 const struct soc_enum arizona_anc_input_src[] = {
699 SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
700 ARIZONA_IN_RXANCL_SEL_SHIFT,
701 ARRAY_SIZE(arizona_anc_input_src_text),
702 arizona_anc_input_src_text),
703 SOC_ENUM_SINGLE(ARIZONA_FCL_ADC_REFORMATTER_CONTROL,
704 ARIZONA_FCL_MIC_MODE_SEL,
705 ARRAY_SIZE(arizona_anc_channel_src_text),
706 arizona_anc_channel_src_text),
707 SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
708 ARIZONA_IN_RXANCR_SEL_SHIFT,
709 ARRAY_SIZE(arizona_anc_input_src_text),
710 arizona_anc_input_src_text),
711 SOC_ENUM_SINGLE(ARIZONA_FCR_ADC_REFORMATTER_CONTROL,
712 ARIZONA_FCR_MIC_MODE_SEL,
713 ARRAY_SIZE(arizona_anc_channel_src_text),
714 arizona_anc_channel_src_text),
715 };
716 EXPORT_SYMBOL_GPL(arizona_anc_input_src);
717
718 static const char * const arizona_anc_ng_texts[] = {
719 "None",
720 "Internal",
721 "External",
722 };
723
724 SOC_ENUM_SINGLE_DECL(arizona_anc_ng_enum, SND_SOC_NOPM, 0,
725 arizona_anc_ng_texts);
726 EXPORT_SYMBOL_GPL(arizona_anc_ng_enum);
727
728 static const char * const arizona_output_anc_src_text[] = {
729 "None", "RXANCL", "RXANCR",
730 };
731
732 const struct soc_enum arizona_output_anc_src[] = {
733 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
734 ARIZONA_OUT1L_ANC_SRC_SHIFT,
735 ARRAY_SIZE(arizona_output_anc_src_text),
736 arizona_output_anc_src_text),
737 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1R,
738 ARIZONA_OUT1R_ANC_SRC_SHIFT,
739 ARRAY_SIZE(arizona_output_anc_src_text),
740 arizona_output_anc_src_text),
741 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
742 ARIZONA_OUT2L_ANC_SRC_SHIFT,
743 ARRAY_SIZE(arizona_output_anc_src_text),
744 arizona_output_anc_src_text),
745 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2R,
746 ARIZONA_OUT2R_ANC_SRC_SHIFT,
747 ARRAY_SIZE(arizona_output_anc_src_text),
748 arizona_output_anc_src_text),
749 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
750 ARIZONA_OUT3L_ANC_SRC_SHIFT,
751 ARRAY_SIZE(arizona_output_anc_src_text),
752 arizona_output_anc_src_text),
753 SOC_ENUM_SINGLE(ARIZONA_DAC_VOLUME_LIMIT_3R,
754 ARIZONA_OUT3R_ANC_SRC_SHIFT,
755 ARRAY_SIZE(arizona_output_anc_src_text),
756 arizona_output_anc_src_text),
757 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4L,
758 ARIZONA_OUT4L_ANC_SRC_SHIFT,
759 ARRAY_SIZE(arizona_output_anc_src_text),
760 arizona_output_anc_src_text),
761 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4R,
762 ARIZONA_OUT4R_ANC_SRC_SHIFT,
763 ARRAY_SIZE(arizona_output_anc_src_text),
764 arizona_output_anc_src_text),
765 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5L,
766 ARIZONA_OUT5L_ANC_SRC_SHIFT,
767 ARRAY_SIZE(arizona_output_anc_src_text),
768 arizona_output_anc_src_text),
769 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5R,
770 ARIZONA_OUT5R_ANC_SRC_SHIFT,
771 ARRAY_SIZE(arizona_output_anc_src_text),
772 arizona_output_anc_src_text),
773 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6L,
774 ARIZONA_OUT6L_ANC_SRC_SHIFT,
775 ARRAY_SIZE(arizona_output_anc_src_text),
776 arizona_output_anc_src_text),
777 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6R,
778 ARIZONA_OUT6R_ANC_SRC_SHIFT,
779 ARRAY_SIZE(arizona_output_anc_src_text),
780 arizona_output_anc_src_text),
781 };
782 EXPORT_SYMBOL_GPL(arizona_output_anc_src);
783
784 const struct snd_kcontrol_new arizona_voice_trigger_switch[] = {
785 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
786 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 1, 1, 0),
787 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 2, 1, 0),
788 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 3, 1, 0),
789 };
790 EXPORT_SYMBOL_GPL(arizona_voice_trigger_switch);
791
arizona_in_set_vu(struct snd_soc_codec * codec,int ena)792 static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
793 {
794 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
795 unsigned int val;
796 int i;
797
798 if (ena)
799 val = ARIZONA_IN_VU;
800 else
801 val = 0;
802
803 for (i = 0; i < priv->num_inputs; i++)
804 snd_soc_update_bits(codec,
805 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
806 ARIZONA_IN_VU, val);
807 }
808
arizona_input_analog(struct snd_soc_codec * codec,int shift)809 bool arizona_input_analog(struct snd_soc_codec *codec, int shift)
810 {
811 unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8);
812 unsigned int val = snd_soc_read(codec, reg);
813
814 return !(val & ARIZONA_IN1_MODE_MASK);
815 }
816 EXPORT_SYMBOL_GPL(arizona_input_analog);
817
arizona_in_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)818 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
819 int event)
820 {
821 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
822 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
823 unsigned int reg;
824
825 if (w->shift % 2)
826 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
827 else
828 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
829
830 switch (event) {
831 case SND_SOC_DAPM_PRE_PMU:
832 priv->in_pending++;
833 break;
834 case SND_SOC_DAPM_POST_PMU:
835 snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);
836
837 /* If this is the last input pending then allow VU */
838 priv->in_pending--;
839 if (priv->in_pending == 0) {
840 msleep(1);
841 arizona_in_set_vu(codec, 1);
842 }
843 break;
844 case SND_SOC_DAPM_PRE_PMD:
845 snd_soc_update_bits(codec, reg,
846 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
847 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
848 break;
849 case SND_SOC_DAPM_POST_PMD:
850 /* Disable volume updates if no inputs are enabled */
851 reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);
852 if (reg == 0)
853 arizona_in_set_vu(codec, 0);
854 break;
855 default:
856 break;
857 }
858
859 return 0;
860 }
861 EXPORT_SYMBOL_GPL(arizona_in_ev);
862
arizona_out_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)863 int arizona_out_ev(struct snd_soc_dapm_widget *w,
864 struct snd_kcontrol *kcontrol,
865 int event)
866 {
867 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
868 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
869 struct arizona *arizona = priv->arizona;
870
871 switch (event) {
872 case SND_SOC_DAPM_PRE_PMU:
873 switch (w->shift) {
874 case ARIZONA_OUT1L_ENA_SHIFT:
875 case ARIZONA_OUT1R_ENA_SHIFT:
876 case ARIZONA_OUT2L_ENA_SHIFT:
877 case ARIZONA_OUT2R_ENA_SHIFT:
878 case ARIZONA_OUT3L_ENA_SHIFT:
879 case ARIZONA_OUT3R_ENA_SHIFT:
880 priv->out_up_pending++;
881 priv->out_up_delay += 17;
882 break;
883 case ARIZONA_OUT4L_ENA_SHIFT:
884 case ARIZONA_OUT4R_ENA_SHIFT:
885 priv->out_up_pending++;
886 switch (arizona->type) {
887 case WM5102:
888 case WM8997:
889 break;
890 default:
891 priv->out_up_delay += 10;
892 break;
893 }
894 break;
895 default:
896 break;
897 }
898 break;
899 case SND_SOC_DAPM_POST_PMU:
900 switch (w->shift) {
901 case ARIZONA_OUT1L_ENA_SHIFT:
902 case ARIZONA_OUT1R_ENA_SHIFT:
903 case ARIZONA_OUT2L_ENA_SHIFT:
904 case ARIZONA_OUT2R_ENA_SHIFT:
905 case ARIZONA_OUT3L_ENA_SHIFT:
906 case ARIZONA_OUT3R_ENA_SHIFT:
907 case ARIZONA_OUT4L_ENA_SHIFT:
908 case ARIZONA_OUT4R_ENA_SHIFT:
909 priv->out_up_pending--;
910 if (!priv->out_up_pending && priv->out_up_delay) {
911 dev_dbg(codec->dev, "Power up delay: %d\n",
912 priv->out_up_delay);
913 msleep(priv->out_up_delay);
914 priv->out_up_delay = 0;
915 }
916 break;
917
918 default:
919 break;
920 }
921 break;
922 case SND_SOC_DAPM_PRE_PMD:
923 switch (w->shift) {
924 case ARIZONA_OUT1L_ENA_SHIFT:
925 case ARIZONA_OUT1R_ENA_SHIFT:
926 case ARIZONA_OUT2L_ENA_SHIFT:
927 case ARIZONA_OUT2R_ENA_SHIFT:
928 case ARIZONA_OUT3L_ENA_SHIFT:
929 case ARIZONA_OUT3R_ENA_SHIFT:
930 priv->out_down_pending++;
931 priv->out_down_delay++;
932 break;
933 case ARIZONA_OUT4L_ENA_SHIFT:
934 case ARIZONA_OUT4R_ENA_SHIFT:
935 priv->out_down_pending++;
936 switch (arizona->type) {
937 case WM5102:
938 case WM8997:
939 break;
940 case WM8998:
941 case WM1814:
942 priv->out_down_delay += 5;
943 break;
944 default:
945 priv->out_down_delay++;
946 break;
947 }
948 default:
949 break;
950 }
951 break;
952 case SND_SOC_DAPM_POST_PMD:
953 switch (w->shift) {
954 case ARIZONA_OUT1L_ENA_SHIFT:
955 case ARIZONA_OUT1R_ENA_SHIFT:
956 case ARIZONA_OUT2L_ENA_SHIFT:
957 case ARIZONA_OUT2R_ENA_SHIFT:
958 case ARIZONA_OUT3L_ENA_SHIFT:
959 case ARIZONA_OUT3R_ENA_SHIFT:
960 case ARIZONA_OUT4L_ENA_SHIFT:
961 case ARIZONA_OUT4R_ENA_SHIFT:
962 priv->out_down_pending--;
963 if (!priv->out_down_pending && priv->out_down_delay) {
964 dev_dbg(codec->dev, "Power down delay: %d\n",
965 priv->out_down_delay);
966 msleep(priv->out_down_delay);
967 priv->out_down_delay = 0;
968 }
969 break;
970 default:
971 break;
972 }
973 break;
974 default:
975 break;
976 }
977
978 return 0;
979 }
980 EXPORT_SYMBOL_GPL(arizona_out_ev);
981
arizona_hp_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)982 int arizona_hp_ev(struct snd_soc_dapm_widget *w,
983 struct snd_kcontrol *kcontrol,
984 int event)
985 {
986 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
987 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
988 struct arizona *arizona = priv->arizona;
989 unsigned int mask = 1 << w->shift;
990 unsigned int val;
991
992 switch (event) {
993 case SND_SOC_DAPM_POST_PMU:
994 val = mask;
995 break;
996 case SND_SOC_DAPM_PRE_PMD:
997 val = 0;
998 break;
999 case SND_SOC_DAPM_PRE_PMU:
1000 case SND_SOC_DAPM_POST_PMD:
1001 return arizona_out_ev(w, kcontrol, event);
1002 default:
1003 return -EINVAL;
1004 }
1005
1006 /* Store the desired state for the HP outputs */
1007 priv->arizona->hp_ena &= ~mask;
1008 priv->arizona->hp_ena |= val;
1009
1010 /* Force off if HPDET clamp is active */
1011 if (priv->arizona->hpdet_clamp)
1012 val = 0;
1013
1014 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
1015 mask, val);
1016
1017 return arizona_out_ev(w, kcontrol, event);
1018 }
1019 EXPORT_SYMBOL_GPL(arizona_hp_ev);
1020
arizona_dvfs_enable(struct snd_soc_codec * codec)1021 static int arizona_dvfs_enable(struct snd_soc_codec *codec)
1022 {
1023 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1024 struct arizona *arizona = priv->arizona;
1025 int ret;
1026
1027 ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
1028 if (ret) {
1029 dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
1030 return ret;
1031 }
1032
1033 ret = regmap_update_bits(arizona->regmap,
1034 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1035 ARIZONA_SUBSYS_MAX_FREQ,
1036 ARIZONA_SUBSYS_MAX_FREQ);
1037 if (ret) {
1038 dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
1039 regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1040 return ret;
1041 }
1042
1043 return 0;
1044 }
1045
arizona_dvfs_disable(struct snd_soc_codec * codec)1046 static int arizona_dvfs_disable(struct snd_soc_codec *codec)
1047 {
1048 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1049 struct arizona *arizona = priv->arizona;
1050 int ret;
1051
1052 ret = regmap_update_bits(arizona->regmap,
1053 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1054 ARIZONA_SUBSYS_MAX_FREQ, 0);
1055 if (ret) {
1056 dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
1057 return ret;
1058 }
1059
1060 ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1061 if (ret) {
1062 dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
1063 return ret;
1064 }
1065
1066 return 0;
1067 }
1068
arizona_dvfs_up(struct snd_soc_codec * codec,unsigned int flags)1069 int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
1070 {
1071 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1072 int ret = 0;
1073
1074 mutex_lock(&priv->dvfs_lock);
1075
1076 if (!priv->dvfs_cached && !priv->dvfs_reqs) {
1077 ret = arizona_dvfs_enable(codec);
1078 if (ret)
1079 goto err;
1080 }
1081
1082 priv->dvfs_reqs |= flags;
1083 err:
1084 mutex_unlock(&priv->dvfs_lock);
1085 return ret;
1086 }
1087 EXPORT_SYMBOL_GPL(arizona_dvfs_up);
1088
arizona_dvfs_down(struct snd_soc_codec * codec,unsigned int flags)1089 int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
1090 {
1091 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1092 unsigned int old_reqs;
1093 int ret = 0;
1094
1095 mutex_lock(&priv->dvfs_lock);
1096
1097 old_reqs = priv->dvfs_reqs;
1098 priv->dvfs_reqs &= ~flags;
1099
1100 if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
1101 ret = arizona_dvfs_disable(codec);
1102
1103 mutex_unlock(&priv->dvfs_lock);
1104 return ret;
1105 }
1106 EXPORT_SYMBOL_GPL(arizona_dvfs_down);
1107
arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)1108 int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
1109 struct snd_kcontrol *kcontrol, int event)
1110 {
1111 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1112 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1113 int ret = 0;
1114
1115 mutex_lock(&priv->dvfs_lock);
1116
1117 switch (event) {
1118 case SND_SOC_DAPM_POST_PMU:
1119 if (priv->dvfs_reqs)
1120 ret = arizona_dvfs_enable(codec);
1121
1122 priv->dvfs_cached = false;
1123 break;
1124 case SND_SOC_DAPM_PRE_PMD:
1125 /* We must ensure DVFS is disabled before the codec goes into
1126 * suspend so that we are never in an illegal state of DVFS
1127 * enabled without enough DCVDD
1128 */
1129 priv->dvfs_cached = true;
1130
1131 if (priv->dvfs_reqs)
1132 ret = arizona_dvfs_disable(codec);
1133 break;
1134 default:
1135 break;
1136 }
1137
1138 mutex_unlock(&priv->dvfs_lock);
1139 return ret;
1140 }
1141 EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
1142
arizona_init_dvfs(struct arizona_priv * priv)1143 void arizona_init_dvfs(struct arizona_priv *priv)
1144 {
1145 mutex_init(&priv->dvfs_lock);
1146 }
1147 EXPORT_SYMBOL_GPL(arizona_init_dvfs);
1148
arizona_anc_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)1149 int arizona_anc_ev(struct snd_soc_dapm_widget *w,
1150 struct snd_kcontrol *kcontrol,
1151 int event)
1152 {
1153 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1154 unsigned int val;
1155
1156 switch (event) {
1157 case SND_SOC_DAPM_POST_PMU:
1158 val = 1 << w->shift;
1159 break;
1160 case SND_SOC_DAPM_PRE_PMD:
1161 val = 1 << (w->shift + 1);
1162 break;
1163 default:
1164 return 0;
1165 }
1166
1167 snd_soc_write(codec, ARIZONA_CLOCK_CONTROL, val);
1168
1169 return 0;
1170 }
1171 EXPORT_SYMBOL_GPL(arizona_anc_ev);
1172
1173 static unsigned int arizona_opclk_ref_48k_rates[] = {
1174 6144000,
1175 12288000,
1176 24576000,
1177 49152000,
1178 };
1179
1180 static unsigned int arizona_opclk_ref_44k1_rates[] = {
1181 5644800,
1182 11289600,
1183 22579200,
1184 45158400,
1185 };
1186
arizona_set_opclk(struct snd_soc_codec * codec,unsigned int clk,unsigned int freq)1187 static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
1188 unsigned int freq)
1189 {
1190 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1191 unsigned int reg;
1192 unsigned int *rates;
1193 int ref, div, refclk;
1194
1195 switch (clk) {
1196 case ARIZONA_CLK_OPCLK:
1197 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
1198 refclk = priv->sysclk;
1199 break;
1200 case ARIZONA_CLK_ASYNC_OPCLK:
1201 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
1202 refclk = priv->asyncclk;
1203 break;
1204 default:
1205 return -EINVAL;
1206 }
1207
1208 if (refclk % 8000)
1209 rates = arizona_opclk_ref_44k1_rates;
1210 else
1211 rates = arizona_opclk_ref_48k_rates;
1212
1213 for (ref = 0; ref < ARRAY_SIZE(arizona_opclk_ref_48k_rates) &&
1214 rates[ref] <= refclk; ref++) {
1215 div = 1;
1216 while (rates[ref] / div >= freq && div < 32) {
1217 if (rates[ref] / div == freq) {
1218 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
1219 freq);
1220 snd_soc_update_bits(codec, reg,
1221 ARIZONA_OPCLK_DIV_MASK |
1222 ARIZONA_OPCLK_SEL_MASK,
1223 (div <<
1224 ARIZONA_OPCLK_DIV_SHIFT) |
1225 ref);
1226 return 0;
1227 }
1228 div++;
1229 }
1230 }
1231
1232 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
1233 return -EINVAL;
1234 }
1235
arizona_set_sysclk(struct snd_soc_codec * codec,int clk_id,int source,unsigned int freq,int dir)1236 int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1237 int source, unsigned int freq, int dir)
1238 {
1239 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1240 struct arizona *arizona = priv->arizona;
1241 char *name;
1242 unsigned int reg;
1243 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
1244 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
1245 int *clk;
1246
1247 switch (clk_id) {
1248 case ARIZONA_CLK_SYSCLK:
1249 name = "SYSCLK";
1250 reg = ARIZONA_SYSTEM_CLOCK_1;
1251 clk = &priv->sysclk;
1252 mask |= ARIZONA_SYSCLK_FRAC;
1253 break;
1254 case ARIZONA_CLK_ASYNCCLK:
1255 name = "ASYNCCLK";
1256 reg = ARIZONA_ASYNC_CLOCK_1;
1257 clk = &priv->asyncclk;
1258 break;
1259 case ARIZONA_CLK_OPCLK:
1260 case ARIZONA_CLK_ASYNC_OPCLK:
1261 return arizona_set_opclk(codec, clk_id, freq);
1262 default:
1263 return -EINVAL;
1264 }
1265
1266 switch (freq) {
1267 case 5644800:
1268 case 6144000:
1269 break;
1270 case 11289600:
1271 case 12288000:
1272 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1273 break;
1274 case 22579200:
1275 case 24576000:
1276 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1277 break;
1278 case 45158400:
1279 case 49152000:
1280 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1281 break;
1282 case 67737600:
1283 case 73728000:
1284 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1285 break;
1286 case 90316800:
1287 case 98304000:
1288 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1289 break;
1290 case 135475200:
1291 case 147456000:
1292 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1293 break;
1294 case 0:
1295 dev_dbg(arizona->dev, "%s cleared\n", name);
1296 *clk = freq;
1297 return 0;
1298 default:
1299 return -EINVAL;
1300 }
1301
1302 *clk = freq;
1303
1304 if (freq % 6144000)
1305 val |= ARIZONA_SYSCLK_FRAC;
1306
1307 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
1308
1309 return regmap_update_bits(arizona->regmap, reg, mask, val);
1310 }
1311 EXPORT_SYMBOL_GPL(arizona_set_sysclk);
1312
arizona_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)1313 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1314 {
1315 struct snd_soc_codec *codec = dai->codec;
1316 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1317 struct arizona *arizona = priv->arizona;
1318 int lrclk, bclk, mode, base;
1319
1320 base = dai->driver->base;
1321
1322 lrclk = 0;
1323 bclk = 0;
1324
1325 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1326 case SND_SOC_DAIFMT_DSP_A:
1327 mode = ARIZONA_FMT_DSP_MODE_A;
1328 break;
1329 case SND_SOC_DAIFMT_DSP_B:
1330 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1331 != SND_SOC_DAIFMT_CBM_CFM) {
1332 arizona_aif_err(dai, "DSP_B not valid in slave mode\n");
1333 return -EINVAL;
1334 }
1335 mode = ARIZONA_FMT_DSP_MODE_B;
1336 break;
1337 case SND_SOC_DAIFMT_I2S:
1338 mode = ARIZONA_FMT_I2S_MODE;
1339 break;
1340 case SND_SOC_DAIFMT_LEFT_J:
1341 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1342 != SND_SOC_DAIFMT_CBM_CFM) {
1343 arizona_aif_err(dai, "LEFT_J not valid in slave mode\n");
1344 return -EINVAL;
1345 }
1346 mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE;
1347 break;
1348 default:
1349 arizona_aif_err(dai, "Unsupported DAI format %d\n",
1350 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1351 return -EINVAL;
1352 }
1353
1354 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1355 case SND_SOC_DAIFMT_CBS_CFS:
1356 break;
1357 case SND_SOC_DAIFMT_CBS_CFM:
1358 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1359 break;
1360 case SND_SOC_DAIFMT_CBM_CFS:
1361 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1362 break;
1363 case SND_SOC_DAIFMT_CBM_CFM:
1364 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1365 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1366 break;
1367 default:
1368 arizona_aif_err(dai, "Unsupported master mode %d\n",
1369 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1370 return -EINVAL;
1371 }
1372
1373 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1374 case SND_SOC_DAIFMT_NB_NF:
1375 break;
1376 case SND_SOC_DAIFMT_IB_IF:
1377 bclk |= ARIZONA_AIF1_BCLK_INV;
1378 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1379 break;
1380 case SND_SOC_DAIFMT_IB_NF:
1381 bclk |= ARIZONA_AIF1_BCLK_INV;
1382 break;
1383 case SND_SOC_DAIFMT_NB_IF:
1384 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1385 break;
1386 default:
1387 return -EINVAL;
1388 }
1389
1390 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
1391 ARIZONA_AIF1_BCLK_INV |
1392 ARIZONA_AIF1_BCLK_MSTR,
1393 bclk);
1394 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
1395 ARIZONA_AIF1TX_LRCLK_INV |
1396 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
1397 regmap_update_bits_async(arizona->regmap,
1398 base + ARIZONA_AIF_RX_PIN_CTRL,
1399 ARIZONA_AIF1RX_LRCLK_INV |
1400 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
1401 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
1402 ARIZONA_AIF1_FMT_MASK, mode);
1403
1404 return 0;
1405 }
1406
1407 static const int arizona_48k_bclk_rates[] = {
1408 -1,
1409 48000,
1410 64000,
1411 96000,
1412 128000,
1413 192000,
1414 256000,
1415 384000,
1416 512000,
1417 768000,
1418 1024000,
1419 1536000,
1420 2048000,
1421 3072000,
1422 4096000,
1423 6144000,
1424 8192000,
1425 12288000,
1426 24576000,
1427 };
1428
1429 static const int arizona_44k1_bclk_rates[] = {
1430 -1,
1431 44100,
1432 58800,
1433 88200,
1434 117600,
1435 177640,
1436 235200,
1437 352800,
1438 470400,
1439 705600,
1440 940800,
1441 1411200,
1442 1881600,
1443 2822400,
1444 3763200,
1445 5644800,
1446 7526400,
1447 11289600,
1448 22579200,
1449 };
1450
1451 static const unsigned int arizona_sr_vals[] = {
1452 0,
1453 12000,
1454 24000,
1455 48000,
1456 96000,
1457 192000,
1458 384000,
1459 768000,
1460 0,
1461 11025,
1462 22050,
1463 44100,
1464 88200,
1465 176400,
1466 352800,
1467 705600,
1468 4000,
1469 8000,
1470 16000,
1471 32000,
1472 64000,
1473 128000,
1474 256000,
1475 512000,
1476 };
1477
1478 #define ARIZONA_48K_RATE_MASK 0x0F003E
1479 #define ARIZONA_44K1_RATE_MASK 0x003E00
1480 #define ARIZONA_RATE_MASK (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK)
1481
1482 static const struct snd_pcm_hw_constraint_list arizona_constraint = {
1483 .count = ARRAY_SIZE(arizona_sr_vals),
1484 .list = arizona_sr_vals,
1485 };
1486
arizona_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1487 static int arizona_startup(struct snd_pcm_substream *substream,
1488 struct snd_soc_dai *dai)
1489 {
1490 struct snd_soc_codec *codec = dai->codec;
1491 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1492 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1493 unsigned int base_rate;
1494
1495 if (!substream->runtime)
1496 return 0;
1497
1498 switch (dai_priv->clk) {
1499 case ARIZONA_CLK_SYSCLK:
1500 base_rate = priv->sysclk;
1501 break;
1502 case ARIZONA_CLK_ASYNCCLK:
1503 base_rate = priv->asyncclk;
1504 break;
1505 default:
1506 return 0;
1507 }
1508
1509 if (base_rate == 0)
1510 dai_priv->constraint.mask = ARIZONA_RATE_MASK;
1511 else if (base_rate % 8000)
1512 dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK;
1513 else
1514 dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK;
1515
1516 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1517 SNDRV_PCM_HW_PARAM_RATE,
1518 &dai_priv->constraint);
1519 }
1520
arizona_wm5102_set_dac_comp(struct snd_soc_codec * codec,unsigned int rate)1521 static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1522 unsigned int rate)
1523 {
1524 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1525 struct arizona *arizona = priv->arizona;
1526 struct reg_sequence dac_comp[] = {
1527 { 0x80, 0x3 },
1528 { ARIZONA_DAC_COMP_1, 0 },
1529 { ARIZONA_DAC_COMP_2, 0 },
1530 { 0x80, 0x0 },
1531 };
1532
1533 mutex_lock(&arizona->dac_comp_lock);
1534
1535 dac_comp[1].def = arizona->dac_comp_coeff;
1536 if (rate >= 176400)
1537 dac_comp[2].def = arizona->dac_comp_enabled;
1538
1539 mutex_unlock(&arizona->dac_comp_lock);
1540
1541 regmap_multi_reg_write(arizona->regmap,
1542 dac_comp,
1543 ARRAY_SIZE(dac_comp));
1544 }
1545
arizona_hw_params_rate(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)1546 static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1547 struct snd_pcm_hw_params *params,
1548 struct snd_soc_dai *dai)
1549 {
1550 struct snd_soc_codec *codec = dai->codec;
1551 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1552 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1553 int base = dai->driver->base;
1554 int i, sr_val, ret;
1555
1556 /*
1557 * We will need to be more flexible than this in future,
1558 * currently we use a single sample rate for SYSCLK.
1559 */
1560 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1561 if (arizona_sr_vals[i] == params_rate(params))
1562 break;
1563 if (i == ARRAY_SIZE(arizona_sr_vals)) {
1564 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1565 params_rate(params));
1566 return -EINVAL;
1567 }
1568 sr_val = i;
1569
1570 switch (priv->arizona->type) {
1571 case WM5102:
1572 case WM8997:
1573 if (arizona_sr_vals[sr_val] >= 88200)
1574 ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
1575 else
1576 ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
1577
1578 if (ret) {
1579 arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
1580 return ret;
1581 }
1582 break;
1583 default:
1584 break;
1585 }
1586
1587 switch (dai_priv->clk) {
1588 case ARIZONA_CLK_SYSCLK:
1589 switch (priv->arizona->type) {
1590 case WM5102:
1591 arizona_wm5102_set_dac_comp(codec,
1592 params_rate(params));
1593 break;
1594 default:
1595 break;
1596 }
1597
1598 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1599 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1600 if (base)
1601 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1602 ARIZONA_AIF1_RATE_MASK, 0);
1603 break;
1604 case ARIZONA_CLK_ASYNCCLK:
1605 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
1606 ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val);
1607 if (base)
1608 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1609 ARIZONA_AIF1_RATE_MASK,
1610 8 << ARIZONA_AIF1_RATE_SHIFT);
1611 break;
1612 default:
1613 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1614 return -EINVAL;
1615 }
1616
1617 return 0;
1618 }
1619
arizona_aif_cfg_changed(struct snd_soc_codec * codec,int base,int bclk,int lrclk,int frame)1620 static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1621 int base, int bclk, int lrclk, int frame)
1622 {
1623 int val;
1624
1625 val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1626 if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1627 return true;
1628
1629 val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1630 if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1631 return true;
1632
1633 val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1634 if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1635 ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1636 return true;
1637
1638 return false;
1639 }
1640
arizona_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)1641 static int arizona_hw_params(struct snd_pcm_substream *substream,
1642 struct snd_pcm_hw_params *params,
1643 struct snd_soc_dai *dai)
1644 {
1645 struct snd_soc_codec *codec = dai->codec;
1646 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1647 struct arizona *arizona = priv->arizona;
1648 int base = dai->driver->base;
1649 const int *rates;
1650 int i, ret, val;
1651 int channels = params_channels(params);
1652 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
1653 int tdm_width = arizona->tdm_width[dai->id - 1];
1654 int tdm_slots = arizona->tdm_slots[dai->id - 1];
1655 int bclk, lrclk, wl, frame, bclk_target;
1656 bool reconfig;
1657 unsigned int aif_tx_state, aif_rx_state;
1658
1659 if (params_rate(params) % 4000)
1660 rates = &arizona_44k1_bclk_rates[0];
1661 else
1662 rates = &arizona_48k_bclk_rates[0];
1663
1664 wl = params_width(params);
1665
1666 if (tdm_slots) {
1667 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
1668 tdm_slots, tdm_width);
1669 bclk_target = tdm_slots * tdm_width * params_rate(params);
1670 channels = tdm_slots;
1671 } else {
1672 bclk_target = snd_soc_params_to_bclk(params);
1673 tdm_width = wl;
1674 }
1675
1676 if (chan_limit && chan_limit < channels) {
1677 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
1678 bclk_target /= channels;
1679 bclk_target *= chan_limit;
1680 }
1681
1682 /* Force multiple of 2 channels for I2S mode */
1683 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
1684 val &= ARIZONA_AIF1_FMT_MASK;
1685 if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) {
1686 arizona_aif_dbg(dai, "Forcing stereo mode\n");
1687 bclk_target /= channels;
1688 bclk_target *= channels + 1;
1689 }
1690
1691 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
1692 if (rates[i] >= bclk_target &&
1693 rates[i] % params_rate(params) == 0) {
1694 bclk = i;
1695 break;
1696 }
1697 }
1698 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
1699 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1700 params_rate(params));
1701 return -EINVAL;
1702 }
1703
1704 lrclk = rates[bclk] / params_rate(params);
1705
1706 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1707 rates[bclk], rates[bclk] / lrclk);
1708
1709 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width;
1710
1711 reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1712
1713 if (reconfig) {
1714 /* Save AIF TX/RX state */
1715 aif_tx_state = snd_soc_read(codec,
1716 base + ARIZONA_AIF_TX_ENABLES);
1717 aif_rx_state = snd_soc_read(codec,
1718 base + ARIZONA_AIF_RX_ENABLES);
1719 /* Disable AIF TX/RX before reconfiguring it */
1720 regmap_update_bits_async(arizona->regmap,
1721 base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1722 regmap_update_bits(arizona->regmap,
1723 base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1724 }
1725
1726 ret = arizona_hw_params_rate(substream, params, dai);
1727 if (ret != 0)
1728 goto restore_aif;
1729
1730 if (reconfig) {
1731 regmap_update_bits_async(arizona->regmap,
1732 base + ARIZONA_AIF_BCLK_CTRL,
1733 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1734 regmap_update_bits_async(arizona->regmap,
1735 base + ARIZONA_AIF_TX_BCLK_RATE,
1736 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1737 regmap_update_bits_async(arizona->regmap,
1738 base + ARIZONA_AIF_RX_BCLK_RATE,
1739 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1740 regmap_update_bits_async(arizona->regmap,
1741 base + ARIZONA_AIF_FRAME_CTRL_1,
1742 ARIZONA_AIF1TX_WL_MASK |
1743 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1744 regmap_update_bits(arizona->regmap,
1745 base + ARIZONA_AIF_FRAME_CTRL_2,
1746 ARIZONA_AIF1RX_WL_MASK |
1747 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1748 }
1749
1750 restore_aif:
1751 if (reconfig) {
1752 /* Restore AIF TX/RX state */
1753 regmap_update_bits_async(arizona->regmap,
1754 base + ARIZONA_AIF_TX_ENABLES,
1755 0xff, aif_tx_state);
1756 regmap_update_bits(arizona->regmap,
1757 base + ARIZONA_AIF_RX_ENABLES,
1758 0xff, aif_rx_state);
1759 }
1760 return ret;
1761 }
1762
arizona_dai_clk_str(int clk_id)1763 static const char *arizona_dai_clk_str(int clk_id)
1764 {
1765 switch (clk_id) {
1766 case ARIZONA_CLK_SYSCLK:
1767 return "SYSCLK";
1768 case ARIZONA_CLK_ASYNCCLK:
1769 return "ASYNCCLK";
1770 default:
1771 return "Unknown clock";
1772 }
1773 }
1774
arizona_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)1775 static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1776 int clk_id, unsigned int freq, int dir)
1777 {
1778 struct snd_soc_codec *codec = dai->codec;
1779 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
1780 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1781 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1782 struct snd_soc_dapm_route routes[2];
1783
1784 switch (clk_id) {
1785 case ARIZONA_CLK_SYSCLK:
1786 case ARIZONA_CLK_ASYNCCLK:
1787 break;
1788 default:
1789 return -EINVAL;
1790 }
1791
1792 if (clk_id == dai_priv->clk)
1793 return 0;
1794
1795 if (dai->active) {
1796 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1797 dai->id);
1798 return -EBUSY;
1799 }
1800
1801 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1802 arizona_dai_clk_str(clk_id));
1803
1804 memset(&routes, 0, sizeof(routes));
1805 routes[0].sink = dai->driver->capture.stream_name;
1806 routes[1].sink = dai->driver->playback.stream_name;
1807
1808 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1809 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1810 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
1811
1812 routes[0].source = arizona_dai_clk_str(clk_id);
1813 routes[1].source = arizona_dai_clk_str(clk_id);
1814 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
1815
1816 dai_priv->clk = clk_id;
1817
1818 return snd_soc_dapm_sync(dapm);
1819 }
1820
arizona_set_tristate(struct snd_soc_dai * dai,int tristate)1821 static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1822 {
1823 struct snd_soc_codec *codec = dai->codec;
1824 int base = dai->driver->base;
1825 unsigned int reg;
1826
1827 if (tristate)
1828 reg = ARIZONA_AIF1_TRI;
1829 else
1830 reg = 0;
1831
1832 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1833 ARIZONA_AIF1_TRI, reg);
1834 }
1835
arizona_set_channels_to_mask(struct snd_soc_dai * dai,unsigned int base,int channels,unsigned int mask)1836 static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
1837 unsigned int base,
1838 int channels, unsigned int mask)
1839 {
1840 struct snd_soc_codec *codec = dai->codec;
1841 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1842 struct arizona *arizona = priv->arizona;
1843 int slot, i;
1844
1845 for (i = 0; i < channels; ++i) {
1846 slot = ffs(mask) - 1;
1847 if (slot < 0)
1848 return;
1849
1850 regmap_write(arizona->regmap, base + i, slot);
1851
1852 mask &= ~(1 << slot);
1853 }
1854
1855 if (mask)
1856 arizona_aif_warn(dai, "Too many channels in TDM mask\n");
1857 }
1858
arizona_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)1859 static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1860 unsigned int rx_mask, int slots, int slot_width)
1861 {
1862 struct snd_soc_codec *codec = dai->codec;
1863 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1864 struct arizona *arizona = priv->arizona;
1865 int base = dai->driver->base;
1866 int rx_max_chan = dai->driver->playback.channels_max;
1867 int tx_max_chan = dai->driver->capture.channels_max;
1868
1869 /* Only support TDM for the physical AIFs */
1870 if (dai->id > ARIZONA_MAX_AIF)
1871 return -ENOTSUPP;
1872
1873 if (slots == 0) {
1874 tx_mask = (1 << tx_max_chan) - 1;
1875 rx_mask = (1 << rx_max_chan) - 1;
1876 }
1877
1878 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
1879 tx_max_chan, tx_mask);
1880 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
1881 rx_max_chan, rx_mask);
1882
1883 arizona->tdm_width[dai->id - 1] = slot_width;
1884 arizona->tdm_slots[dai->id - 1] = slots;
1885
1886 return 0;
1887 }
1888
1889 const struct snd_soc_dai_ops arizona_dai_ops = {
1890 .startup = arizona_startup,
1891 .set_fmt = arizona_set_fmt,
1892 .set_tdm_slot = arizona_set_tdm_slot,
1893 .hw_params = arizona_hw_params,
1894 .set_sysclk = arizona_dai_set_sysclk,
1895 .set_tristate = arizona_set_tristate,
1896 };
1897 EXPORT_SYMBOL_GPL(arizona_dai_ops);
1898
1899 const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1900 .startup = arizona_startup,
1901 .hw_params = arizona_hw_params_rate,
1902 .set_sysclk = arizona_dai_set_sysclk,
1903 };
1904 EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1905
arizona_init_dai(struct arizona_priv * priv,int id)1906 int arizona_init_dai(struct arizona_priv *priv, int id)
1907 {
1908 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1909
1910 dai_priv->clk = ARIZONA_CLK_SYSCLK;
1911 dai_priv->constraint = arizona_constraint;
1912
1913 return 0;
1914 }
1915 EXPORT_SYMBOL_GPL(arizona_init_dai);
1916
1917 static struct {
1918 unsigned int min;
1919 unsigned int max;
1920 u16 fratio;
1921 int ratio;
1922 } fll_fratios[] = {
1923 { 0, 64000, 4, 16 },
1924 { 64000, 128000, 3, 8 },
1925 { 128000, 256000, 2, 4 },
1926 { 256000, 1000000, 1, 2 },
1927 { 1000000, 13500000, 0, 1 },
1928 };
1929
1930 static const unsigned int pseudo_fref_max[ARIZONA_FLL_MAX_FRATIO] = {
1931 13500000,
1932 6144000,
1933 6144000,
1934 3072000,
1935 3072000,
1936 2822400,
1937 2822400,
1938 1536000,
1939 1536000,
1940 1536000,
1941 1536000,
1942 1536000,
1943 1536000,
1944 1536000,
1945 1536000,
1946 768000,
1947 };
1948
1949 static struct {
1950 unsigned int min;
1951 unsigned int max;
1952 u16 gain;
1953 } fll_gains[] = {
1954 { 0, 256000, 0 },
1955 { 256000, 1000000, 2 },
1956 { 1000000, 13500000, 4 },
1957 };
1958
1959 struct arizona_fll_cfg {
1960 int n;
1961 unsigned int theta;
1962 unsigned int lambda;
1963 int refdiv;
1964 int outdiv;
1965 int fratio;
1966 int gain;
1967 };
1968
arizona_validate_fll(struct arizona_fll * fll,unsigned int Fref,unsigned int Fout)1969 static int arizona_validate_fll(struct arizona_fll *fll,
1970 unsigned int Fref,
1971 unsigned int Fout)
1972 {
1973 unsigned int Fvco_min;
1974
1975 if (fll->fout && Fout != fll->fout) {
1976 arizona_fll_err(fll,
1977 "Can't change output on active FLL\n");
1978 return -EINVAL;
1979 }
1980
1981 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1982 arizona_fll_err(fll,
1983 "Can't scale %dMHz in to <=13.5MHz\n",
1984 Fref);
1985 return -EINVAL;
1986 }
1987
1988 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1989 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1990 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1991 Fout);
1992 return -EINVAL;
1993 }
1994
1995 return 0;
1996 }
1997
arizona_find_fratio(unsigned int Fref,int * fratio)1998 static int arizona_find_fratio(unsigned int Fref, int *fratio)
1999 {
2000 int i;
2001
2002 /* Find an appropriate FLL_FRATIO */
2003 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
2004 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
2005 if (fratio)
2006 *fratio = fll_fratios[i].fratio;
2007 return fll_fratios[i].ratio;
2008 }
2009 }
2010
2011 return -EINVAL;
2012 }
2013
arizona_calc_fratio(struct arizona_fll * fll,struct arizona_fll_cfg * cfg,unsigned int target,unsigned int Fref,bool sync)2014 static int arizona_calc_fratio(struct arizona_fll *fll,
2015 struct arizona_fll_cfg *cfg,
2016 unsigned int target,
2017 unsigned int Fref, bool sync)
2018 {
2019 int init_ratio, ratio;
2020 int refdiv, div;
2021
2022 /* Fref must be <=13.5MHz, find initial refdiv */
2023 div = 1;
2024 cfg->refdiv = 0;
2025 while (Fref > ARIZONA_FLL_MAX_FREF) {
2026 div *= 2;
2027 Fref /= 2;
2028 cfg->refdiv++;
2029
2030 if (div > ARIZONA_FLL_MAX_REFDIV)
2031 return -EINVAL;
2032 }
2033
2034 /* Find an appropriate FLL_FRATIO */
2035 init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
2036 if (init_ratio < 0) {
2037 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
2038 Fref);
2039 return init_ratio;
2040 }
2041
2042 switch (fll->arizona->type) {
2043 case WM5102:
2044 case WM8997:
2045 return init_ratio;
2046 case WM5110:
2047 case WM8280:
2048 if (fll->arizona->rev < 3 || sync)
2049 return init_ratio;
2050 break;
2051 default:
2052 if (sync)
2053 return init_ratio;
2054 break;
2055 }
2056
2057 cfg->fratio = init_ratio - 1;
2058
2059 /* Adjust FRATIO/refdiv to avoid integer mode if possible */
2060 refdiv = cfg->refdiv;
2061
2062 arizona_fll_dbg(fll, "pseudo: initial ratio=%u fref=%u refdiv=%u\n",
2063 init_ratio, Fref, refdiv);
2064
2065 while (div <= ARIZONA_FLL_MAX_REFDIV) {
2066 /* start from init_ratio because this may already give a
2067 * fractional N.K
2068 */
2069 for (ratio = init_ratio; ratio > 0; ratio--) {
2070 if (target % (ratio * Fref)) {
2071 cfg->refdiv = refdiv;
2072 cfg->fratio = ratio - 1;
2073 arizona_fll_dbg(fll,
2074 "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2075 Fref, refdiv, div, ratio);
2076 return ratio;
2077 }
2078 }
2079
2080 for (ratio = init_ratio + 1; ratio <= ARIZONA_FLL_MAX_FRATIO;
2081 ratio++) {
2082 if ((ARIZONA_FLL_VCO_CORNER / 2) /
2083 (fll->vco_mult * ratio) < Fref) {
2084 arizona_fll_dbg(fll, "pseudo: hit VCO corner\n");
2085 break;
2086 }
2087
2088 if (Fref > pseudo_fref_max[ratio - 1]) {
2089 arizona_fll_dbg(fll,
2090 "pseudo: exceeded max fref(%u) for ratio=%u\n",
2091 pseudo_fref_max[ratio - 1],
2092 ratio);
2093 break;
2094 }
2095
2096 if (target % (ratio * Fref)) {
2097 cfg->refdiv = refdiv;
2098 cfg->fratio = ratio - 1;
2099 arizona_fll_dbg(fll,
2100 "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2101 Fref, refdiv, div, ratio);
2102 return ratio;
2103 }
2104 }
2105
2106 div *= 2;
2107 Fref /= 2;
2108 refdiv++;
2109 init_ratio = arizona_find_fratio(Fref, NULL);
2110 arizona_fll_dbg(fll,
2111 "pseudo: change fref=%u refdiv=%d(%d) ratio=%u\n",
2112 Fref, refdiv, div, init_ratio);
2113 }
2114
2115 arizona_fll_warn(fll, "Falling back to integer mode operation\n");
2116 return cfg->fratio + 1;
2117 }
2118
arizona_calc_fll(struct arizona_fll * fll,struct arizona_fll_cfg * cfg,unsigned int Fref,bool sync)2119 static int arizona_calc_fll(struct arizona_fll *fll,
2120 struct arizona_fll_cfg *cfg,
2121 unsigned int Fref, bool sync)
2122 {
2123 unsigned int target, div, gcd_fll;
2124 int i, ratio;
2125
2126 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
2127
2128 /* Fvco should be over the targt; don't check the upper bound */
2129 div = ARIZONA_FLL_MIN_OUTDIV;
2130 while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
2131 div++;
2132 if (div > ARIZONA_FLL_MAX_OUTDIV)
2133 return -EINVAL;
2134 }
2135 target = fll->fout * div / fll->vco_mult;
2136 cfg->outdiv = div;
2137
2138 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
2139
2140 /* Find an appropriate FLL_FRATIO and refdiv */
2141 ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
2142 if (ratio < 0)
2143 return ratio;
2144
2145 /* Apply the division for our remaining calculations */
2146 Fref = Fref / (1 << cfg->refdiv);
2147
2148 cfg->n = target / (ratio * Fref);
2149
2150 if (target % (ratio * Fref)) {
2151 gcd_fll = gcd(target, ratio * Fref);
2152 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
2153
2154 cfg->theta = (target - (cfg->n * ratio * Fref))
2155 / gcd_fll;
2156 cfg->lambda = (ratio * Fref) / gcd_fll;
2157 } else {
2158 cfg->theta = 0;
2159 cfg->lambda = 0;
2160 }
2161
2162 /* Round down to 16bit range with cost of accuracy lost.
2163 * Denominator must be bigger than numerator so we only
2164 * take care of it.
2165 */
2166 while (cfg->lambda >= (1 << 16)) {
2167 cfg->theta >>= 1;
2168 cfg->lambda >>= 1;
2169 }
2170
2171 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
2172 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
2173 cfg->gain = fll_gains[i].gain;
2174 break;
2175 }
2176 }
2177 if (i == ARRAY_SIZE(fll_gains)) {
2178 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
2179 Fref);
2180 return -EINVAL;
2181 }
2182
2183 arizona_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
2184 cfg->n, cfg->theta, cfg->lambda);
2185 arizona_fll_dbg(fll, "FRATIO=0x%x(%d) OUTDIV=%d REFCLK_DIV=0x%x(%d)\n",
2186 cfg->fratio, ratio, cfg->outdiv,
2187 cfg->refdiv, 1 << cfg->refdiv);
2188 arizona_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
2189
2190 return 0;
2191
2192 }
2193
arizona_apply_fll(struct arizona * arizona,unsigned int base,struct arizona_fll_cfg * cfg,int source,bool sync)2194 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
2195 struct arizona_fll_cfg *cfg, int source,
2196 bool sync)
2197 {
2198 regmap_update_bits_async(arizona->regmap, base + 3,
2199 ARIZONA_FLL1_THETA_MASK, cfg->theta);
2200 regmap_update_bits_async(arizona->regmap, base + 4,
2201 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
2202 regmap_update_bits_async(arizona->regmap, base + 5,
2203 ARIZONA_FLL1_FRATIO_MASK,
2204 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
2205 regmap_update_bits_async(arizona->regmap, base + 6,
2206 ARIZONA_FLL1_CLK_REF_DIV_MASK |
2207 ARIZONA_FLL1_CLK_REF_SRC_MASK,
2208 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
2209 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
2210
2211 if (sync) {
2212 regmap_update_bits(arizona->regmap, base + 0x7,
2213 ARIZONA_FLL1_GAIN_MASK,
2214 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2215 } else {
2216 regmap_update_bits(arizona->regmap, base + 0x5,
2217 ARIZONA_FLL1_OUTDIV_MASK,
2218 cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
2219 regmap_update_bits(arizona->regmap, base + 0x9,
2220 ARIZONA_FLL1_GAIN_MASK,
2221 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2222 }
2223
2224 regmap_update_bits_async(arizona->regmap, base + 2,
2225 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
2226 ARIZONA_FLL1_CTRL_UPD | cfg->n);
2227 }
2228
arizona_is_enabled_fll(struct arizona_fll * fll,int base)2229 static int arizona_is_enabled_fll(struct arizona_fll *fll, int base)
2230 {
2231 struct arizona *arizona = fll->arizona;
2232 unsigned int reg;
2233 int ret;
2234
2235 ret = regmap_read(arizona->regmap, base + 1, ®);
2236 if (ret != 0) {
2237 arizona_fll_err(fll, "Failed to read current state: %d\n",
2238 ret);
2239 return ret;
2240 }
2241
2242 return reg & ARIZONA_FLL1_ENA;
2243 }
2244
arizona_enable_fll(struct arizona_fll * fll)2245 static int arizona_enable_fll(struct arizona_fll *fll)
2246 {
2247 struct arizona *arizona = fll->arizona;
2248 bool use_sync = false;
2249 int already_enabled = arizona_is_enabled_fll(fll, fll->base);
2250 int sync_enabled = arizona_is_enabled_fll(fll, fll->base + 0x10);
2251 struct arizona_fll_cfg cfg;
2252 int i;
2253 unsigned int val;
2254
2255 if (already_enabled < 0)
2256 return already_enabled;
2257 if (sync_enabled < 0)
2258 return sync_enabled;
2259
2260 if (already_enabled) {
2261 /* Facilitate smooth refclk across the transition */
2262 regmap_update_bits(fll->arizona->regmap, fll->base + 1,
2263 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
2264 udelay(32);
2265 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
2266 ARIZONA_FLL1_GAIN_MASK, 0);
2267 }
2268
2269 /*
2270 * If we have both REFCLK and SYNCCLK then enable both,
2271 * otherwise apply the SYNCCLK settings to REFCLK.
2272 */
2273 if (fll->ref_src >= 0 && fll->ref_freq &&
2274 fll->ref_src != fll->sync_src) {
2275 arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
2276
2277 /* Ref path hardcodes lambda to 65536 when sync is on */
2278 if (fll->sync_src >= 0 && cfg.lambda)
2279 cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda;
2280
2281 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
2282 false);
2283 if (fll->sync_src >= 0) {
2284 arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
2285
2286 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
2287 fll->sync_src, true);
2288 use_sync = true;
2289 }
2290 } else if (fll->sync_src >= 0) {
2291 arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
2292
2293 arizona_apply_fll(arizona, fll->base, &cfg,
2294 fll->sync_src, false);
2295
2296 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2297 ARIZONA_FLL1_SYNC_ENA, 0);
2298 } else {
2299 arizona_fll_err(fll, "No clocks provided\n");
2300 return -EINVAL;
2301 }
2302
2303 if (already_enabled && !!sync_enabled != use_sync)
2304 arizona_fll_warn(fll, "Synchroniser changed on active FLL\n");
2305
2306 /*
2307 * Increase the bandwidth if we're not using a low frequency
2308 * sync source.
2309 */
2310 if (use_sync && fll->sync_freq > 100000)
2311 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2312 ARIZONA_FLL1_SYNC_BW, 0);
2313 else
2314 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2315 ARIZONA_FLL1_SYNC_BW,
2316 ARIZONA_FLL1_SYNC_BW);
2317
2318 if (!already_enabled)
2319 pm_runtime_get_sync(arizona->dev);
2320
2321 if (use_sync)
2322 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2323 ARIZONA_FLL1_SYNC_ENA,
2324 ARIZONA_FLL1_SYNC_ENA);
2325 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2326 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
2327
2328 if (already_enabled)
2329 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2330 ARIZONA_FLL1_FREERUN, 0);
2331
2332 arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2333 val = 0;
2334 for (i = 0; i < 15; i++) {
2335 if (i < 5)
2336 usleep_range(200, 400);
2337 else
2338 msleep(20);
2339
2340 regmap_read(arizona->regmap,
2341 ARIZONA_INTERRUPT_RAW_STATUS_5,
2342 &val);
2343 if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2344 break;
2345 }
2346 if (i == 15)
2347 arizona_fll_warn(fll, "Timed out waiting for lock\n");
2348 else
2349 arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
2350
2351 return 0;
2352 }
2353
arizona_disable_fll(struct arizona_fll * fll)2354 static void arizona_disable_fll(struct arizona_fll *fll)
2355 {
2356 struct arizona *arizona = fll->arizona;
2357 bool change;
2358
2359 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2360 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
2361 regmap_update_bits_check(arizona->regmap, fll->base + 1,
2362 ARIZONA_FLL1_ENA, 0, &change);
2363 regmap_update_bits(arizona->regmap, fll->base + 0x11,
2364 ARIZONA_FLL1_SYNC_ENA, 0);
2365 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2366 ARIZONA_FLL1_FREERUN, 0);
2367
2368 if (change)
2369 pm_runtime_put_autosuspend(arizona->dev);
2370 }
2371
arizona_set_fll_refclk(struct arizona_fll * fll,int source,unsigned int Fref,unsigned int Fout)2372 int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
2373 unsigned int Fref, unsigned int Fout)
2374 {
2375 int ret = 0;
2376
2377 if (fll->ref_src == source && fll->ref_freq == Fref)
2378 return 0;
2379
2380 if (fll->fout && Fref > 0) {
2381 ret = arizona_validate_fll(fll, Fref, fll->fout);
2382 if (ret != 0)
2383 return ret;
2384 }
2385
2386 fll->ref_src = source;
2387 fll->ref_freq = Fref;
2388
2389 if (fll->fout && Fref > 0) {
2390 ret = arizona_enable_fll(fll);
2391 }
2392
2393 return ret;
2394 }
2395 EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
2396
arizona_set_fll(struct arizona_fll * fll,int source,unsigned int Fref,unsigned int Fout)2397 int arizona_set_fll(struct arizona_fll *fll, int source,
2398 unsigned int Fref, unsigned int Fout)
2399 {
2400 int ret = 0;
2401
2402 if (fll->sync_src == source &&
2403 fll->sync_freq == Fref && fll->fout == Fout)
2404 return 0;
2405
2406 if (Fout) {
2407 if (fll->ref_src >= 0) {
2408 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
2409 if (ret != 0)
2410 return ret;
2411 }
2412
2413 ret = arizona_validate_fll(fll, Fref, Fout);
2414 if (ret != 0)
2415 return ret;
2416 }
2417
2418 fll->sync_src = source;
2419 fll->sync_freq = Fref;
2420 fll->fout = Fout;
2421
2422 if (Fout)
2423 ret = arizona_enable_fll(fll);
2424 else
2425 arizona_disable_fll(fll);
2426
2427 return ret;
2428 }
2429 EXPORT_SYMBOL_GPL(arizona_set_fll);
2430
arizona_init_fll(struct arizona * arizona,int id,int base,int lock_irq,int ok_irq,struct arizona_fll * fll)2431 int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2432 int ok_irq, struct arizona_fll *fll)
2433 {
2434 unsigned int val;
2435
2436 fll->id = id;
2437 fll->base = base;
2438 fll->arizona = arizona;
2439 fll->sync_src = ARIZONA_FLL_SRC_NONE;
2440
2441 /* Configure default refclk to 32kHz if we have one */
2442 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
2443 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
2444 case ARIZONA_CLK_SRC_MCLK1:
2445 case ARIZONA_CLK_SRC_MCLK2:
2446 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
2447 break;
2448 default:
2449 fll->ref_src = ARIZONA_FLL_SRC_NONE;
2450 }
2451 fll->ref_freq = 32768;
2452
2453 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
2454 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2455 "FLL%d clock OK", id);
2456
2457 regmap_update_bits(arizona->regmap, fll->base + 1,
2458 ARIZONA_FLL1_FREERUN, 0);
2459
2460 return 0;
2461 }
2462 EXPORT_SYMBOL_GPL(arizona_init_fll);
2463
2464 /**
2465 * arizona_set_output_mode - Set the mode of the specified output
2466 *
2467 * @codec: Device to configure
2468 * @output: Output number
2469 * @diff: True to set the output to differential mode
2470 *
2471 * Some systems use external analogue switches to connect more
2472 * analogue devices to the CODEC than are supported by the device. In
2473 * some systems this requires changing the switched output from single
2474 * ended to differential mode dynamically at runtime, an operation
2475 * supported using this function.
2476 *
2477 * Most systems have a single static configuration and should use
2478 * platform data instead.
2479 */
arizona_set_output_mode(struct snd_soc_codec * codec,int output,bool diff)2480 int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
2481 {
2482 unsigned int reg, val;
2483
2484 if (output < 1 || output > 6)
2485 return -EINVAL;
2486
2487 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
2488
2489 if (diff)
2490 val = ARIZONA_OUT1_MONO;
2491 else
2492 val = 0;
2493
2494 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
2495 }
2496 EXPORT_SYMBOL_GPL(arizona_set_output_mode);
2497
2498 static const struct soc_enum arizona_adsp2_rate_enum[] = {
2499 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
2500 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2501 ARIZONA_RATE_ENUM_SIZE,
2502 arizona_rate_text, arizona_rate_val),
2503 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
2504 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2505 ARIZONA_RATE_ENUM_SIZE,
2506 arizona_rate_text, arizona_rate_val),
2507 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
2508 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2509 ARIZONA_RATE_ENUM_SIZE,
2510 arizona_rate_text, arizona_rate_val),
2511 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
2512 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2513 ARIZONA_RATE_ENUM_SIZE,
2514 arizona_rate_text, arizona_rate_val),
2515 };
2516
2517 const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2518 SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]),
2519 SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]),
2520 SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]),
2521 SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]),
2522 };
2523 EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2524
arizona_eq_filter_unstable(bool mode,__be16 _a,__be16 _b)2525 static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2526 {
2527 s16 a = be16_to_cpu(_a);
2528 s16 b = be16_to_cpu(_b);
2529
2530 if (!mode) {
2531 return abs(a) >= 4096;
2532 } else {
2533 if (abs(b) >= 4096)
2534 return true;
2535
2536 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2537 }
2538 }
2539
arizona_eq_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2540 int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2541 struct snd_ctl_elem_value *ucontrol)
2542 {
2543 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2544 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2545 struct soc_bytes *params = (void *)kcontrol->private_value;
2546 unsigned int val;
2547 __be16 *data;
2548 int len;
2549 int ret;
2550
2551 len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2552
2553 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2554 if (!data)
2555 return -ENOMEM;
2556
2557 data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2558
2559 if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2560 arizona_eq_filter_unstable(true, data[4], data[5]) ||
2561 arizona_eq_filter_unstable(true, data[8], data[9]) ||
2562 arizona_eq_filter_unstable(true, data[12], data[13]) ||
2563 arizona_eq_filter_unstable(false, data[16], data[17])) {
2564 dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2565 ret = -EINVAL;
2566 goto out;
2567 }
2568
2569 ret = regmap_read(arizona->regmap, params->base, &val);
2570 if (ret != 0)
2571 goto out;
2572
2573 val &= ~ARIZONA_EQ1_B1_MODE;
2574 data[0] |= cpu_to_be16(val);
2575
2576 ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2577
2578 out:
2579 kfree(data);
2580 return ret;
2581 }
2582 EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2583
arizona_lhpf_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2584 int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2585 struct snd_ctl_elem_value *ucontrol)
2586 {
2587 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2588 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2589 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2590 s16 val = be16_to_cpu(*data);
2591
2592 if (abs(val) >= 4096) {
2593 dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2594 return -EINVAL;
2595 }
2596
2597 return snd_soc_bytes_put(kcontrol, ucontrol);
2598 }
2599 EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2600
arizona_register_notifier(struct snd_soc_codec * codec,struct notifier_block * nb,int (* notify)(struct notifier_block * nb,unsigned long action,void * data))2601 int arizona_register_notifier(struct snd_soc_codec *codec,
2602 struct notifier_block *nb,
2603 int (*notify)(struct notifier_block *nb,
2604 unsigned long action, void *data))
2605 {
2606 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2607 struct arizona *arizona = priv->arizona;
2608
2609 nb->notifier_call = notify;
2610
2611 return blocking_notifier_chain_register(&arizona->notifier, nb);
2612 }
2613 EXPORT_SYMBOL_GPL(arizona_register_notifier);
2614
arizona_unregister_notifier(struct snd_soc_codec * codec,struct notifier_block * nb)2615 int arizona_unregister_notifier(struct snd_soc_codec *codec,
2616 struct notifier_block *nb)
2617 {
2618 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2619 struct arizona *arizona = priv->arizona;
2620
2621 return blocking_notifier_chain_unregister(&arizona->notifier, nb);
2622 }
2623 EXPORT_SYMBOL_GPL(arizona_unregister_notifier);
2624
2625 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2626 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2627 MODULE_LICENSE("GPL");
2628