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