ASoC: arizona: Suppress noop FLL updates
[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/gcd.h>
14 #include <linux/module.h>
15 #include <linux/pm_runtime.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/tlv.h>
19
20 #include <linux/mfd/arizona/core.h>
21 #include <linux/mfd/arizona/registers.h>
22
23 #include "arizona.h"
24
25 #define ARIZONA_AIF_BCLK_CTRL 0x00
26 #define ARIZONA_AIF_TX_PIN_CTRL 0x01
27 #define ARIZONA_AIF_RX_PIN_CTRL 0x02
28 #define ARIZONA_AIF_RATE_CTRL 0x03
29 #define ARIZONA_AIF_FORMAT 0x04
30 #define ARIZONA_AIF_TX_BCLK_RATE 0x05
31 #define ARIZONA_AIF_RX_BCLK_RATE 0x06
32 #define ARIZONA_AIF_FRAME_CTRL_1 0x07
33 #define ARIZONA_AIF_FRAME_CTRL_2 0x08
34 #define ARIZONA_AIF_FRAME_CTRL_3 0x09
35 #define ARIZONA_AIF_FRAME_CTRL_4 0x0A
36 #define ARIZONA_AIF_FRAME_CTRL_5 0x0B
37 #define ARIZONA_AIF_FRAME_CTRL_6 0x0C
38 #define ARIZONA_AIF_FRAME_CTRL_7 0x0D
39 #define ARIZONA_AIF_FRAME_CTRL_8 0x0E
40 #define ARIZONA_AIF_FRAME_CTRL_9 0x0F
41 #define ARIZONA_AIF_FRAME_CTRL_10 0x10
42 #define ARIZONA_AIF_FRAME_CTRL_11 0x11
43 #define ARIZONA_AIF_FRAME_CTRL_12 0x12
44 #define ARIZONA_AIF_FRAME_CTRL_13 0x13
45 #define ARIZONA_AIF_FRAME_CTRL_14 0x14
46 #define ARIZONA_AIF_FRAME_CTRL_15 0x15
47 #define ARIZONA_AIF_FRAME_CTRL_16 0x16
48 #define ARIZONA_AIF_FRAME_CTRL_17 0x17
49 #define ARIZONA_AIF_FRAME_CTRL_18 0x18
50 #define ARIZONA_AIF_TX_ENABLES 0x19
51 #define ARIZONA_AIF_RX_ENABLES 0x1A
52 #define ARIZONA_AIF_FORCE_WRITE 0x1B
53
54 #define arizona_fll_err(_fll, fmt, ...) \
55 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
56 #define arizona_fll_warn(_fll, fmt, ...) \
57 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58 #define arizona_fll_dbg(_fll, fmt, ...) \
59 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
60
61 #define arizona_aif_err(_dai, fmt, ...) \
62 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
63 #define arizona_aif_warn(_dai, fmt, ...) \
64 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65 #define arizona_aif_dbg(_dai, fmt, ...) \
66 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67
68 const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69 "None",
70 "Tone Generator 1",
71 "Tone Generator 2",
72 "Haptics",
73 "AEC",
74 "Mic Mute Mixer",
75 "Noise Generator",
76 "IN1L",
77 "IN1R",
78 "IN2L",
79 "IN2R",
80 "IN3L",
81 "IN3R",
82 "IN4L",
83 "IN4R",
84 "AIF1RX1",
85 "AIF1RX2",
86 "AIF1RX3",
87 "AIF1RX4",
88 "AIF1RX5",
89 "AIF1RX6",
90 "AIF1RX7",
91 "AIF1RX8",
92 "AIF2RX1",
93 "AIF2RX2",
94 "AIF3RX1",
95 "AIF3RX2",
96 "SLIMRX1",
97 "SLIMRX2",
98 "SLIMRX3",
99 "SLIMRX4",
100 "SLIMRX5",
101 "SLIMRX6",
102 "SLIMRX7",
103 "SLIMRX8",
104 "EQ1",
105 "EQ2",
106 "EQ3",
107 "EQ4",
108 "DRC1L",
109 "DRC1R",
110 "DRC2L",
111 "DRC2R",
112 "LHPF1",
113 "LHPF2",
114 "LHPF3",
115 "LHPF4",
116 "DSP1.1",
117 "DSP1.2",
118 "DSP1.3",
119 "DSP1.4",
120 "DSP1.5",
121 "DSP1.6",
122 "DSP2.1",
123 "DSP2.2",
124 "DSP2.3",
125 "DSP2.4",
126 "DSP2.5",
127 "DSP2.6",
128 "DSP3.1",
129 "DSP3.2",
130 "DSP3.3",
131 "DSP3.4",
132 "DSP3.5",
133 "DSP3.6",
134 "DSP4.1",
135 "DSP4.2",
136 "DSP4.3",
137 "DSP4.4",
138 "DSP4.5",
139 "DSP4.6",
140 "ASRC1L",
141 "ASRC1R",
142 "ASRC2L",
143 "ASRC2R",
144 };
145 EXPORT_SYMBOL_GPL(arizona_mixer_texts);
146
147 int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
148 0x00, /* None */
149 0x04, /* Tone */
150 0x05,
151 0x06, /* Haptics */
152 0x08, /* AEC */
153 0x0c, /* Noise mixer */
154 0x0d, /* Comfort noise */
155 0x10, /* IN1L */
156 0x11,
157 0x12,
158 0x13,
159 0x14,
160 0x15,
161 0x16,
162 0x17,
163 0x20, /* AIF1RX1 */
164 0x21,
165 0x22,
166 0x23,
167 0x24,
168 0x25,
169 0x26,
170 0x27,
171 0x28, /* AIF2RX1 */
172 0x29,
173 0x30, /* AIF3RX1 */
174 0x31,
175 0x38, /* SLIMRX1 */
176 0x39,
177 0x3a,
178 0x3b,
179 0x3c,
180 0x3d,
181 0x3e,
182 0x3f,
183 0x50, /* EQ1 */
184 0x51,
185 0x52,
186 0x53,
187 0x58, /* DRC1L */
188 0x59,
189 0x5a,
190 0x5b,
191 0x60, /* LHPF1 */
192 0x61,
193 0x62,
194 0x63,
195 0x68, /* DSP1.1 */
196 0x69,
197 0x6a,
198 0x6b,
199 0x6c,
200 0x6d,
201 0x70, /* DSP2.1 */
202 0x71,
203 0x72,
204 0x73,
205 0x74,
206 0x75,
207 0x78, /* DSP3.1 */
208 0x79,
209 0x7a,
210 0x7b,
211 0x7c,
212 0x7d,
213 0x80, /* DSP4.1 */
214 0x81,
215 0x82,
216 0x83,
217 0x84,
218 0x85,
219 0x90, /* ASRC1L */
220 0x91,
221 0x92,
222 0x93,
223 };
224 EXPORT_SYMBOL_GPL(arizona_mixer_values);
225
226 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
227 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
228
229 static const char *arizona_lhpf_mode_text[] = {
230 "Low-pass", "High-pass"
231 };
232
233 const struct soc_enum arizona_lhpf1_mode =
234 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
235 arizona_lhpf_mode_text);
236 EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
237
238 const struct soc_enum arizona_lhpf2_mode =
239 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
240 arizona_lhpf_mode_text);
241 EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
242
243 const struct soc_enum arizona_lhpf3_mode =
244 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
245 arizona_lhpf_mode_text);
246 EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
247
248 const struct soc_enum arizona_lhpf4_mode =
249 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
250 arizona_lhpf_mode_text);
251 EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
252
253 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
254 int event)
255 {
256 return 0;
257 }
258 EXPORT_SYMBOL_GPL(arizona_in_ev);
259
260 int arizona_out_ev(struct snd_soc_dapm_widget *w,
261 struct snd_kcontrol *kcontrol,
262 int event)
263 {
264 return 0;
265 }
266 EXPORT_SYMBOL_GPL(arizona_out_ev);
267
268 static unsigned int arizona_sysclk_48k_rates[] = {
269 6144000,
270 12288000,
271 22579200,
272 49152000,
273 73728000,
274 98304000,
275 147456000,
276 };
277
278 static unsigned int arizona_sysclk_44k1_rates[] = {
279 5644800,
280 11289600,
281 24576000,
282 45158400,
283 67737600,
284 90316800,
285 135475200,
286 };
287
288 static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
289 unsigned int freq)
290 {
291 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
292 unsigned int reg;
293 unsigned int *rates;
294 int ref, div, refclk;
295
296 switch (clk) {
297 case ARIZONA_CLK_OPCLK:
298 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
299 refclk = priv->sysclk;
300 break;
301 case ARIZONA_CLK_ASYNC_OPCLK:
302 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
303 refclk = priv->asyncclk;
304 break;
305 default:
306 return -EINVAL;
307 }
308
309 if (refclk % 8000)
310 rates = arizona_sysclk_44k1_rates;
311 else
312 rates = arizona_sysclk_48k_rates;
313
314 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
315 rates[ref] <= refclk; ref++) {
316 div = 1;
317 while (rates[ref] / div >= freq && div < 32) {
318 if (rates[ref] / div == freq) {
319 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
320 freq);
321 snd_soc_update_bits(codec, reg,
322 ARIZONA_OPCLK_DIV_MASK |
323 ARIZONA_OPCLK_SEL_MASK,
324 (div <<
325 ARIZONA_OPCLK_DIV_SHIFT) |
326 ref);
327 return 0;
328 }
329 div++;
330 }
331 }
332
333 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
334 return -EINVAL;
335 }
336
337 int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
338 int source, unsigned int freq, int dir)
339 {
340 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
341 struct arizona *arizona = priv->arizona;
342 char *name;
343 unsigned int reg;
344 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
345 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
346 unsigned int *clk;
347
348 switch (clk_id) {
349 case ARIZONA_CLK_SYSCLK:
350 name = "SYSCLK";
351 reg = ARIZONA_SYSTEM_CLOCK_1;
352 clk = &priv->sysclk;
353 mask |= ARIZONA_SYSCLK_FRAC;
354 break;
355 case ARIZONA_CLK_ASYNCCLK:
356 name = "ASYNCCLK";
357 reg = ARIZONA_ASYNC_CLOCK_1;
358 clk = &priv->asyncclk;
359 break;
360 case ARIZONA_CLK_OPCLK:
361 case ARIZONA_CLK_ASYNC_OPCLK:
362 return arizona_set_opclk(codec, clk_id, freq);
363 default:
364 return -EINVAL;
365 }
366
367 switch (freq) {
368 case 5644800:
369 case 6144000:
370 break;
371 case 11289600:
372 case 12288000:
373 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
374 break;
375 case 22579200:
376 case 24576000:
377 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
378 break;
379 case 45158400:
380 case 49152000:
381 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
382 break;
383 case 67737600:
384 case 73728000:
385 val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
386 break;
387 case 90316800:
388 case 98304000:
389 val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
390 break;
391 case 135475200:
392 case 147456000:
393 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
394 break;
395 default:
396 return -EINVAL;
397 }
398
399 *clk = freq;
400
401 if (freq % 6144000)
402 val |= ARIZONA_SYSCLK_FRAC;
403
404 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
405
406 return regmap_update_bits(arizona->regmap, reg, mask, val);
407 }
408 EXPORT_SYMBOL_GPL(arizona_set_sysclk);
409
410 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
411 {
412 struct snd_soc_codec *codec = dai->codec;
413 int lrclk, bclk, mode, base;
414
415 base = dai->driver->base;
416
417 lrclk = 0;
418 bclk = 0;
419
420 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
421 case SND_SOC_DAIFMT_DSP_A:
422 mode = 0;
423 break;
424 case SND_SOC_DAIFMT_DSP_B:
425 mode = 1;
426 break;
427 case SND_SOC_DAIFMT_I2S:
428 mode = 2;
429 break;
430 case SND_SOC_DAIFMT_LEFT_J:
431 mode = 3;
432 break;
433 default:
434 arizona_aif_err(dai, "Unsupported DAI format %d\n",
435 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
436 return -EINVAL;
437 }
438
439 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
440 case SND_SOC_DAIFMT_CBS_CFS:
441 break;
442 case SND_SOC_DAIFMT_CBS_CFM:
443 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
444 break;
445 case SND_SOC_DAIFMT_CBM_CFS:
446 bclk |= ARIZONA_AIF1_BCLK_MSTR;
447 break;
448 case SND_SOC_DAIFMT_CBM_CFM:
449 bclk |= ARIZONA_AIF1_BCLK_MSTR;
450 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
451 break;
452 default:
453 arizona_aif_err(dai, "Unsupported master mode %d\n",
454 fmt & SND_SOC_DAIFMT_MASTER_MASK);
455 return -EINVAL;
456 }
457
458 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
459 case SND_SOC_DAIFMT_NB_NF:
460 break;
461 case SND_SOC_DAIFMT_IB_IF:
462 bclk |= ARIZONA_AIF1_BCLK_INV;
463 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
464 break;
465 case SND_SOC_DAIFMT_IB_NF:
466 bclk |= ARIZONA_AIF1_BCLK_INV;
467 break;
468 case SND_SOC_DAIFMT_NB_IF:
469 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
470 break;
471 default:
472 return -EINVAL;
473 }
474
475 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
476 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
477 bclk);
478 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
479 ARIZONA_AIF1TX_LRCLK_INV |
480 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
481 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
482 ARIZONA_AIF1RX_LRCLK_INV |
483 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
484 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
485 ARIZONA_AIF1_FMT_MASK, mode);
486
487 return 0;
488 }
489
490 static const int arizona_48k_bclk_rates[] = {
491 -1,
492 48000,
493 64000,
494 96000,
495 128000,
496 192000,
497 256000,
498 384000,
499 512000,
500 768000,
501 1024000,
502 1536000,
503 2048000,
504 3072000,
505 4096000,
506 6144000,
507 8192000,
508 12288000,
509 24576000,
510 };
511
512 static const unsigned int arizona_48k_rates[] = {
513 12000,
514 24000,
515 48000,
516 96000,
517 192000,
518 384000,
519 768000,
520 4000,
521 8000,
522 16000,
523 32000,
524 64000,
525 128000,
526 256000,
527 512000,
528 };
529
530 static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
531 .count = ARRAY_SIZE(arizona_48k_rates),
532 .list = arizona_48k_rates,
533 };
534
535 static const int arizona_44k1_bclk_rates[] = {
536 -1,
537 44100,
538 58800,
539 88200,
540 117600,
541 177640,
542 235200,
543 352800,
544 470400,
545 705600,
546 940800,
547 1411200,
548 1881600,
549 2822400,
550 3763200,
551 5644800,
552 7526400,
553 11289600,
554 22579200,
555 };
556
557 static const unsigned int arizona_44k1_rates[] = {
558 11025,
559 22050,
560 44100,
561 88200,
562 176400,
563 352800,
564 705600,
565 };
566
567 static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
568 .count = ARRAY_SIZE(arizona_44k1_rates),
569 .list = arizona_44k1_rates,
570 };
571
572 static int arizona_sr_vals[] = {
573 0,
574 12000,
575 24000,
576 48000,
577 96000,
578 192000,
579 384000,
580 768000,
581 0,
582 11025,
583 22050,
584 44100,
585 88200,
586 176400,
587 352800,
588 705600,
589 4000,
590 8000,
591 16000,
592 32000,
593 64000,
594 128000,
595 256000,
596 512000,
597 };
598
599 static int arizona_startup(struct snd_pcm_substream *substream,
600 struct snd_soc_dai *dai)
601 {
602 struct snd_soc_codec *codec = dai->codec;
603 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
604 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
605 const struct snd_pcm_hw_constraint_list *constraint;
606 unsigned int base_rate;
607
608 switch (dai_priv->clk) {
609 case ARIZONA_CLK_SYSCLK:
610 base_rate = priv->sysclk;
611 break;
612 case ARIZONA_CLK_ASYNCCLK:
613 base_rate = priv->asyncclk;
614 break;
615 default:
616 return 0;
617 }
618
619 if (base_rate % 8000)
620 constraint = &arizona_44k1_constraint;
621 else
622 constraint = &arizona_48k_constraint;
623
624 return snd_pcm_hw_constraint_list(substream->runtime, 0,
625 SNDRV_PCM_HW_PARAM_RATE,
626 constraint);
627 }
628
629 static int arizona_hw_params(struct snd_pcm_substream *substream,
630 struct snd_pcm_hw_params *params,
631 struct snd_soc_dai *dai)
632 {
633 struct snd_soc_codec *codec = dai->codec;
634 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
635 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
636 int base = dai->driver->base;
637 const int *rates;
638 int i;
639 int bclk, lrclk, wl, frame, sr_val;
640
641 if (params_rate(params) % 8000)
642 rates = &arizona_44k1_bclk_rates[0];
643 else
644 rates = &arizona_48k_bclk_rates[0];
645
646 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
647 if (rates[i] >= snd_soc_params_to_bclk(params) &&
648 rates[i] % params_rate(params) == 0) {
649 bclk = i;
650 break;
651 }
652 }
653 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
654 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
655 params_rate(params));
656 return -EINVAL;
657 }
658
659 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
660 if (arizona_sr_vals[i] == params_rate(params))
661 break;
662 if (i == ARRAY_SIZE(arizona_sr_vals)) {
663 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
664 params_rate(params));
665 return -EINVAL;
666 }
667 sr_val = i;
668
669 lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
670
671 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
672 rates[bclk], rates[bclk] / lrclk);
673
674 wl = snd_pcm_format_width(params_format(params));
675 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
676
677 /*
678 * We will need to be more flexible than this in future,
679 * currently we use a single sample rate for SYSCLK.
680 */
681 switch (dai_priv->clk) {
682 case ARIZONA_CLK_SYSCLK:
683 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
684 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
685 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
686 ARIZONA_AIF1_RATE_MASK, 0);
687 break;
688 case ARIZONA_CLK_ASYNCCLK:
689 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
690 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
691 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
692 ARIZONA_AIF1_RATE_MASK, 8);
693 break;
694 default:
695 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
696 return -EINVAL;
697 }
698
699 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
700 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
701 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
702 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
703 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
704 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
705 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
706 ARIZONA_AIF1TX_WL_MASK |
707 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
708 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
709 ARIZONA_AIF1RX_WL_MASK |
710 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
711
712 return 0;
713 }
714
715 static const char *arizona_dai_clk_str(int clk_id)
716 {
717 switch (clk_id) {
718 case ARIZONA_CLK_SYSCLK:
719 return "SYSCLK";
720 case ARIZONA_CLK_ASYNCCLK:
721 return "ASYNCCLK";
722 default:
723 return "Unknown clock";
724 }
725 }
726
727 static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
728 int clk_id, unsigned int freq, int dir)
729 {
730 struct snd_soc_codec *codec = dai->codec;
731 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
732 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
733 struct snd_soc_dapm_route routes[2];
734
735 switch (clk_id) {
736 case ARIZONA_CLK_SYSCLK:
737 case ARIZONA_CLK_ASYNCCLK:
738 break;
739 default:
740 return -EINVAL;
741 }
742
743 if (clk_id == dai_priv->clk)
744 return 0;
745
746 if (dai->active) {
747 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
748 dai->id);
749 return -EBUSY;
750 }
751
752 memset(&routes, 0, sizeof(routes));
753 routes[0].sink = dai->driver->capture.stream_name;
754 routes[1].sink = dai->driver->playback.stream_name;
755
756 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
757 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
758 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
759
760 routes[0].source = arizona_dai_clk_str(clk_id);
761 routes[1].source = arizona_dai_clk_str(clk_id);
762 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
763
764 return snd_soc_dapm_sync(&codec->dapm);
765 }
766
767 const struct snd_soc_dai_ops arizona_dai_ops = {
768 .startup = arizona_startup,
769 .set_fmt = arizona_set_fmt,
770 .hw_params = arizona_hw_params,
771 .set_sysclk = arizona_dai_set_sysclk,
772 };
773 EXPORT_SYMBOL_GPL(arizona_dai_ops);
774
775 int arizona_init_dai(struct arizona_priv *priv, int id)
776 {
777 struct arizona_dai_priv *dai_priv = &priv->dai[id];
778
779 dai_priv->clk = ARIZONA_CLK_SYSCLK;
780
781 return 0;
782 }
783 EXPORT_SYMBOL_GPL(arizona_init_dai);
784
785 static irqreturn_t arizona_fll_lock(int irq, void *data)
786 {
787 struct arizona_fll *fll = data;
788
789 arizona_fll_dbg(fll, "Lock status changed\n");
790
791 complete(&fll->lock);
792
793 return IRQ_HANDLED;
794 }
795
796 static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
797 {
798 struct arizona_fll *fll = data;
799
800 arizona_fll_dbg(fll, "clock OK\n");
801
802 complete(&fll->ok);
803
804 return IRQ_HANDLED;
805 }
806
807 static struct {
808 unsigned int min;
809 unsigned int max;
810 u16 fratio;
811 int ratio;
812 } fll_fratios[] = {
813 { 0, 64000, 4, 16 },
814 { 64000, 128000, 3, 8 },
815 { 128000, 256000, 2, 4 },
816 { 256000, 1000000, 1, 2 },
817 { 1000000, 13500000, 0, 1 },
818 };
819
820 struct arizona_fll_cfg {
821 int n;
822 int theta;
823 int lambda;
824 int refdiv;
825 int outdiv;
826 int fratio;
827 };
828
829 static int arizona_calc_fll(struct arizona_fll *fll,
830 struct arizona_fll_cfg *cfg,
831 unsigned int Fref,
832 unsigned int Fout)
833 {
834 unsigned int target, div, gcd_fll;
835 int i, ratio;
836
837 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
838
839 /* Fref must be <=13.5MHz */
840 div = 1;
841 cfg->refdiv = 0;
842 while ((Fref / div) > 13500000) {
843 div *= 2;
844 cfg->refdiv++;
845
846 if (div > 8) {
847 arizona_fll_err(fll,
848 "Can't scale %dMHz in to <=13.5MHz\n",
849 Fref);
850 return -EINVAL;
851 }
852 }
853
854 /* Apply the division for our remaining calculations */
855 Fref /= div;
856
857 /* Fvco should be over the targt; don't check the upper bound */
858 div = 1;
859 while (Fout * div < 90000000 * fll->vco_mult) {
860 div++;
861 if (div > 7) {
862 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
863 Fout);
864 return -EINVAL;
865 }
866 }
867 target = Fout * div / fll->vco_mult;
868 cfg->outdiv = div;
869
870 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
871
872 /* Find an appropraite FLL_FRATIO and factor it out of the target */
873 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
874 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
875 cfg->fratio = fll_fratios[i].fratio;
876 ratio = fll_fratios[i].ratio;
877 break;
878 }
879 }
880 if (i == ARRAY_SIZE(fll_fratios)) {
881 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
882 Fref);
883 return -EINVAL;
884 }
885
886 cfg->n = target / (ratio * Fref);
887
888 if (target % Fref) {
889 gcd_fll = gcd(target, ratio * Fref);
890 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
891
892 cfg->theta = (target - (cfg->n * ratio * Fref))
893 / gcd_fll;
894 cfg->lambda = (ratio * Fref) / gcd_fll;
895 } else {
896 cfg->theta = 0;
897 cfg->lambda = 0;
898 }
899
900 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
901 cfg->n, cfg->theta, cfg->lambda);
902 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
903 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
904
905 return 0;
906
907 }
908
909 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
910 struct arizona_fll_cfg *cfg, int source)
911 {
912 regmap_update_bits(arizona->regmap, base + 3,
913 ARIZONA_FLL1_THETA_MASK, cfg->theta);
914 regmap_update_bits(arizona->regmap, base + 4,
915 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
916 regmap_update_bits(arizona->regmap, base + 5,
917 ARIZONA_FLL1_FRATIO_MASK,
918 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
919 regmap_update_bits(arizona->regmap, base + 6,
920 ARIZONA_FLL1_CLK_REF_DIV_MASK |
921 ARIZONA_FLL1_CLK_REF_SRC_MASK,
922 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
923 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
924
925 regmap_update_bits(arizona->regmap, base + 2,
926 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
927 ARIZONA_FLL1_CTRL_UPD | cfg->n);
928 }
929
930 int arizona_set_fll(struct arizona_fll *fll, int source,
931 unsigned int Fref, unsigned int Fout)
932 {
933 struct arizona *arizona = fll->arizona;
934 struct arizona_fll_cfg cfg, sync;
935 unsigned int reg, val;
936 int syncsrc;
937 bool ena;
938 int ret;
939
940 if (fll->fref == Fref && fll->fout == Fout)
941 return 0;
942
943 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
944 if (ret != 0) {
945 arizona_fll_err(fll, "Failed to read current state: %d\n",
946 ret);
947 return ret;
948 }
949 ena = reg & ARIZONA_FLL1_ENA;
950
951 if (Fout) {
952 /* Do we have a 32kHz reference? */
953 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
954 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
955 case ARIZONA_CLK_SRC_MCLK1:
956 case ARIZONA_CLK_SRC_MCLK2:
957 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
958 break;
959 default:
960 syncsrc = -1;
961 }
962
963 if (source == syncsrc)
964 syncsrc = -1;
965
966 if (syncsrc >= 0) {
967 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
968 if (ret != 0)
969 return ret;
970
971 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
972 if (ret != 0)
973 return ret;
974 } else {
975 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
976 if (ret != 0)
977 return ret;
978 }
979 } else {
980 regmap_update_bits(arizona->regmap, fll->base + 1,
981 ARIZONA_FLL1_ENA, 0);
982 regmap_update_bits(arizona->regmap, fll->base + 0x11,
983 ARIZONA_FLL1_SYNC_ENA, 0);
984
985 if (ena)
986 pm_runtime_put_autosuspend(arizona->dev);
987
988 return 0;
989 }
990
991 regmap_update_bits(arizona->regmap, fll->base + 5,
992 ARIZONA_FLL1_OUTDIV_MASK,
993 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
994
995 if (syncsrc >= 0) {
996 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
997 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
998 } else {
999 arizona_apply_fll(arizona, fll->base, &cfg, source);
1000 }
1001
1002 if (!ena)
1003 pm_runtime_get(arizona->dev);
1004
1005 /* Clear any pending completions */
1006 try_wait_for_completion(&fll->ok);
1007
1008 regmap_update_bits(arizona->regmap, fll->base + 1,
1009 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
1010 if (syncsrc >= 0)
1011 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1012 ARIZONA_FLL1_SYNC_ENA,
1013 ARIZONA_FLL1_SYNC_ENA);
1014
1015 ret = wait_for_completion_timeout(&fll->ok,
1016 msecs_to_jiffies(25));
1017 if (ret == 0)
1018 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1019
1020 fll->fref = Fref;
1021 fll->fout = Fout;
1022
1023 return 0;
1024 }
1025 EXPORT_SYMBOL_GPL(arizona_set_fll);
1026
1027 int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1028 int ok_irq, struct arizona_fll *fll)
1029 {
1030 int ret;
1031
1032 init_completion(&fll->lock);
1033 init_completion(&fll->ok);
1034
1035 fll->id = id;
1036 fll->base = base;
1037 fll->arizona = arizona;
1038
1039 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1040 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1041 "FLL%d clock OK", id);
1042
1043 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
1044 arizona_fll_lock, fll);
1045 if (ret != 0) {
1046 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
1047 id, ret);
1048 }
1049
1050 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1051 arizona_fll_clock_ok, fll);
1052 if (ret != 0) {
1053 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1054 id, ret);
1055 }
1056
1057 return 0;
1058 }
1059 EXPORT_SYMBOL_GPL(arizona_init_fll);
1060
1061 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1062 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1063 MODULE_LICENSE("GPL");
This page took 0.050775 seconds and 6 git commands to generate.