ASoC: wm5110: Add noise gate control
[deliverable/linux.git] / sound / soc / codecs / arizona.c
CommitLineData
07ed873e
MB
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
68const 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",
c9c56fd0
MB
82 "IN4L",
83 "IN4R",
07ed873e
MB
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",
c922cc4c
MB
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",
07ed873e
MB
140 "ASRC1L",
141 "ASRC1R",
142 "ASRC2L",
143 "ASRC2R",
144};
145EXPORT_SYMBOL_GPL(arizona_mixer_texts);
146
147int 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,
c9c56fd0
MB
161 0x16,
162 0x17,
07ed873e
MB
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,
c922cc4c
MB
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,
07ed873e
MB
219 0x90, /* ASRC1L */
220 0x91,
221 0x92,
222 0x93,
223};
224EXPORT_SYMBOL_GPL(arizona_mixer_values);
225
226const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
227EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
228
e853a00f
MB
229static const char *arizona_vol_ramp_text[] = {
230 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
231 "15ms/6dB", "30ms/6dB",
232};
233
234const struct soc_enum arizona_in_vd_ramp =
235 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
236 ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
237EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
238
239const struct soc_enum arizona_in_vi_ramp =
240 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
241 ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
242EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
243
244const struct soc_enum arizona_out_vd_ramp =
245 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
246 ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
247EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
248
249const struct soc_enum arizona_out_vi_ramp =
250 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
251 ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
252EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
253
07ed873e
MB
254static const char *arizona_lhpf_mode_text[] = {
255 "Low-pass", "High-pass"
256};
257
258const struct soc_enum arizona_lhpf1_mode =
259 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
260 arizona_lhpf_mode_text);
261EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
262
263const struct soc_enum arizona_lhpf2_mode =
264 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
265 arizona_lhpf_mode_text);
266EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
267
268const struct soc_enum arizona_lhpf3_mode =
269 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
270 arizona_lhpf_mode_text);
271EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
272
273const struct soc_enum arizona_lhpf4_mode =
274 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
275 arizona_lhpf_mode_text);
276EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
277
845571cc
MB
278static const char *arizona_ng_hold_text[] = {
279 "30ms", "120ms", "250ms", "500ms",
280};
281
282const struct soc_enum arizona_ng_hold =
283 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
284 4, arizona_ng_hold_text);
285EXPORT_SYMBOL_GPL(arizona_ng_hold);
286
07ed873e
MB
287int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
288 int event)
289{
290 return 0;
291}
292EXPORT_SYMBOL_GPL(arizona_in_ev);
293
294int arizona_out_ev(struct snd_soc_dapm_widget *w,
295 struct snd_kcontrol *kcontrol,
296 int event)
297{
298 return 0;
299}
300EXPORT_SYMBOL_GPL(arizona_out_ev);
301
cbd840da
MB
302static unsigned int arizona_sysclk_48k_rates[] = {
303 6144000,
304 12288000,
96e1f18f 305 24576000,
cbd840da 306 49152000,
aeaeee1a
MB
307 73728000,
308 98304000,
309 147456000,
cbd840da
MB
310};
311
312static unsigned int arizona_sysclk_44k1_rates[] = {
313 5644800,
314 11289600,
96e1f18f 315 22579200,
cbd840da 316 45158400,
aeaeee1a
MB
317 67737600,
318 90316800,
319 135475200,
cbd840da
MB
320};
321
322static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
323 unsigned int freq)
324{
325 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
326 unsigned int reg;
327 unsigned int *rates;
328 int ref, div, refclk;
329
330 switch (clk) {
331 case ARIZONA_CLK_OPCLK:
332 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
333 refclk = priv->sysclk;
334 break;
335 case ARIZONA_CLK_ASYNC_OPCLK:
336 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
337 refclk = priv->asyncclk;
338 break;
339 default:
340 return -EINVAL;
341 }
342
343 if (refclk % 8000)
344 rates = arizona_sysclk_44k1_rates;
345 else
346 rates = arizona_sysclk_48k_rates;
347
348 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
349 rates[ref] <= refclk; ref++) {
350 div = 1;
351 while (rates[ref] / div >= freq && div < 32) {
352 if (rates[ref] / div == freq) {
353 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
354 freq);
355 snd_soc_update_bits(codec, reg,
356 ARIZONA_OPCLK_DIV_MASK |
357 ARIZONA_OPCLK_SEL_MASK,
358 (div <<
359 ARIZONA_OPCLK_DIV_SHIFT) |
360 ref);
361 return 0;
362 }
363 div++;
364 }
365 }
366
367 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
368 return -EINVAL;
369}
370
07ed873e
MB
371int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
372 int source, unsigned int freq, int dir)
373{
374 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
375 struct arizona *arizona = priv->arizona;
376 char *name;
377 unsigned int reg;
378 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
379 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
380 unsigned int *clk;
381
382 switch (clk_id) {
383 case ARIZONA_CLK_SYSCLK:
384 name = "SYSCLK";
385 reg = ARIZONA_SYSTEM_CLOCK_1;
386 clk = &priv->sysclk;
387 mask |= ARIZONA_SYSCLK_FRAC;
388 break;
389 case ARIZONA_CLK_ASYNCCLK:
390 name = "ASYNCCLK";
391 reg = ARIZONA_ASYNC_CLOCK_1;
392 clk = &priv->asyncclk;
393 break;
cbd840da
MB
394 case ARIZONA_CLK_OPCLK:
395 case ARIZONA_CLK_ASYNC_OPCLK:
396 return arizona_set_opclk(codec, clk_id, freq);
07ed873e
MB
397 default:
398 return -EINVAL;
399 }
400
401 switch (freq) {
402 case 5644800:
403 case 6144000:
404 break;
405 case 11289600:
406 case 12288000:
407 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
408 break;
409 case 22579200:
410 case 24576000:
411 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
412 break;
413 case 45158400:
414 case 49152000:
415 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
416 break;
38113360
MB
417 case 67737600:
418 case 73728000:
419 val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
420 break;
421 case 90316800:
422 case 98304000:
423 val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
424 break;
425 case 135475200:
426 case 147456000:
427 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
428 break;
07ed873e
MB
429 default:
430 return -EINVAL;
431 }
432
433 *clk = freq;
434
435 if (freq % 6144000)
436 val |= ARIZONA_SYSCLK_FRAC;
437
438 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
439
440 return regmap_update_bits(arizona->regmap, reg, mask, val);
441}
442EXPORT_SYMBOL_GPL(arizona_set_sysclk);
443
444static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
445{
446 struct snd_soc_codec *codec = dai->codec;
447 int lrclk, bclk, mode, base;
448
449 base = dai->driver->base;
450
451 lrclk = 0;
452 bclk = 0;
453
454 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
455 case SND_SOC_DAIFMT_DSP_A:
456 mode = 0;
457 break;
458 case SND_SOC_DAIFMT_DSP_B:
459 mode = 1;
460 break;
461 case SND_SOC_DAIFMT_I2S:
462 mode = 2;
463 break;
464 case SND_SOC_DAIFMT_LEFT_J:
465 mode = 3;
466 break;
467 default:
468 arizona_aif_err(dai, "Unsupported DAI format %d\n",
469 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
470 return -EINVAL;
471 }
472
473 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
474 case SND_SOC_DAIFMT_CBS_CFS:
475 break;
476 case SND_SOC_DAIFMT_CBS_CFM:
477 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
478 break;
479 case SND_SOC_DAIFMT_CBM_CFS:
480 bclk |= ARIZONA_AIF1_BCLK_MSTR;
481 break;
482 case SND_SOC_DAIFMT_CBM_CFM:
483 bclk |= ARIZONA_AIF1_BCLK_MSTR;
484 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
485 break;
486 default:
487 arizona_aif_err(dai, "Unsupported master mode %d\n",
488 fmt & SND_SOC_DAIFMT_MASTER_MASK);
489 return -EINVAL;
490 }
491
492 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
493 case SND_SOC_DAIFMT_NB_NF:
494 break;
495 case SND_SOC_DAIFMT_IB_IF:
496 bclk |= ARIZONA_AIF1_BCLK_INV;
497 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
498 break;
499 case SND_SOC_DAIFMT_IB_NF:
500 bclk |= ARIZONA_AIF1_BCLK_INV;
501 break;
502 case SND_SOC_DAIFMT_NB_IF:
503 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
504 break;
505 default:
506 return -EINVAL;
507 }
508
509 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
510 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
511 bclk);
512 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
513 ARIZONA_AIF1TX_LRCLK_INV |
514 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
515 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
516 ARIZONA_AIF1RX_LRCLK_INV |
517 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
518 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
519 ARIZONA_AIF1_FMT_MASK, mode);
520
521 return 0;
522}
523
949e6bc7 524static const int arizona_48k_bclk_rates[] = {
07ed873e
MB
525 -1,
526 48000,
527 64000,
528 96000,
529 128000,
530 192000,
531 256000,
532 384000,
533 512000,
534 768000,
535 1024000,
536 1536000,
537 2048000,
538 3072000,
539 4096000,
540 6144000,
541 8192000,
542 12288000,
543 24576000,
544};
545
5b2eec3f
MB
546static const unsigned int arizona_48k_rates[] = {
547 12000,
548 24000,
549 48000,
550 96000,
551 192000,
552 384000,
553 768000,
554 4000,
555 8000,
556 16000,
557 32000,
558 64000,
559 128000,
560 256000,
561 512000,
562};
563
564static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
565 .count = ARRAY_SIZE(arizona_48k_rates),
566 .list = arizona_48k_rates,
567};
568
949e6bc7 569static const int arizona_44k1_bclk_rates[] = {
07ed873e
MB
570 -1,
571 44100,
572 58800,
573 88200,
574 117600,
575 177640,
576 235200,
577 352800,
578 470400,
579 705600,
580 940800,
581 1411200,
582 1881600,
4758be37 583 2822400,
07ed873e
MB
584 3763200,
585 5644800,
586 7526400,
587 11289600,
588 22579200,
589};
590
5b2eec3f
MB
591static const unsigned int arizona_44k1_rates[] = {
592 11025,
593 22050,
594 44100,
595 88200,
596 176400,
597 352800,
598 705600,
599};
600
601static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
602 .count = ARRAY_SIZE(arizona_44k1_rates),
603 .list = arizona_44k1_rates,
604};
605
07ed873e
MB
606static int arizona_sr_vals[] = {
607 0,
608 12000,
609 24000,
610 48000,
611 96000,
612 192000,
613 384000,
614 768000,
615 0,
616 11025,
617 22050,
618 44100,
619 88200,
620 176400,
621 352800,
622 705600,
623 4000,
624 8000,
625 16000,
626 32000,
627 64000,
628 128000,
629 256000,
630 512000,
631};
632
5b2eec3f
MB
633static int arizona_startup(struct snd_pcm_substream *substream,
634 struct snd_soc_dai *dai)
635{
636 struct snd_soc_codec *codec = dai->codec;
637 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
638 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
639 const struct snd_pcm_hw_constraint_list *constraint;
640 unsigned int base_rate;
641
642 switch (dai_priv->clk) {
643 case ARIZONA_CLK_SYSCLK:
644 base_rate = priv->sysclk;
645 break;
646 case ARIZONA_CLK_ASYNCCLK:
647 base_rate = priv->asyncclk;
648 break;
649 default:
650 return 0;
651 }
652
653 if (base_rate % 8000)
654 constraint = &arizona_44k1_constraint;
655 else
656 constraint = &arizona_48k_constraint;
657
658 return snd_pcm_hw_constraint_list(substream->runtime, 0,
659 SNDRV_PCM_HW_PARAM_RATE,
660 constraint);
661}
662
07ed873e
MB
663static int arizona_hw_params(struct snd_pcm_substream *substream,
664 struct snd_pcm_hw_params *params,
665 struct snd_soc_dai *dai)
666{
667 struct snd_soc_codec *codec = dai->codec;
c013b27a
MB
668 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
669 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
07ed873e
MB
670 int base = dai->driver->base;
671 const int *rates;
672 int i;
673 int bclk, lrclk, wl, frame, sr_val;
674
675 if (params_rate(params) % 8000)
949e6bc7 676 rates = &arizona_44k1_bclk_rates[0];
07ed873e 677 else
949e6bc7 678 rates = &arizona_48k_bclk_rates[0];
07ed873e 679
949e6bc7 680 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
5001765f
MB
681 if (rates[i] >= snd_soc_params_to_bclk(params) &&
682 rates[i] % params_rate(params) == 0) {
07ed873e
MB
683 bclk = i;
684 break;
685 }
686 }
949e6bc7 687 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
07ed873e
MB
688 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
689 params_rate(params));
690 return -EINVAL;
691 }
692
07ed873e
MB
693 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
694 if (arizona_sr_vals[i] == params_rate(params))
695 break;
696 if (i == ARRAY_SIZE(arizona_sr_vals)) {
697 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
698 params_rate(params));
699 return -EINVAL;
700 }
701 sr_val = i;
702
703 lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
704
705 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
706 rates[bclk], rates[bclk] / lrclk);
707
708 wl = snd_pcm_format_width(params_format(params));
709 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
710
c013b27a
MB
711 /*
712 * We will need to be more flexible than this in future,
713 * currently we use a single sample rate for SYSCLK.
714 */
715 switch (dai_priv->clk) {
716 case ARIZONA_CLK_SYSCLK:
717 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
718 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
719 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
720 ARIZONA_AIF1_RATE_MASK, 0);
721 break;
722 case ARIZONA_CLK_ASYNCCLK:
723 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
724 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
725 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
726 ARIZONA_AIF1_RATE_MASK, 8);
727 break;
728 default:
729 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
730 return -EINVAL;
731 }
732
07ed873e
MB
733 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
734 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
735 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
736 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
737 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
738 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
739 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
740 ARIZONA_AIF1TX_WL_MASK |
741 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
742 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
743 ARIZONA_AIF1RX_WL_MASK |
744 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
745
746 return 0;
747}
748
410837a7
MB
749static const char *arizona_dai_clk_str(int clk_id)
750{
751 switch (clk_id) {
752 case ARIZONA_CLK_SYSCLK:
753 return "SYSCLK";
754 case ARIZONA_CLK_ASYNCCLK:
755 return "ASYNCCLK";
756 default:
757 return "Unknown clock";
758 }
759}
760
5b2eec3f
MB
761static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
762 int clk_id, unsigned int freq, int dir)
763{
764 struct snd_soc_codec *codec = dai->codec;
765 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
766 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
410837a7 767 struct snd_soc_dapm_route routes[2];
5b2eec3f
MB
768
769 switch (clk_id) {
770 case ARIZONA_CLK_SYSCLK:
771 case ARIZONA_CLK_ASYNCCLK:
772 break;
773 default:
774 return -EINVAL;
775 }
776
410837a7
MB
777 if (clk_id == dai_priv->clk)
778 return 0;
779
780 if (dai->active) {
5b2eec3f
MB
781 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
782 dai->id);
783 return -EBUSY;
784 }
785
c8d35a6a
MB
786 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
787 arizona_dai_clk_str(clk_id));
788
410837a7
MB
789 memset(&routes, 0, sizeof(routes));
790 routes[0].sink = dai->driver->capture.stream_name;
791 routes[1].sink = dai->driver->playback.stream_name;
5b2eec3f 792
410837a7
MB
793 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
794 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
795 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
796
797 routes[0].source = arizona_dai_clk_str(clk_id);
798 routes[1].source = arizona_dai_clk_str(clk_id);
799 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
800
0c778e86
MB
801 dai_priv->clk = clk_id;
802
410837a7 803 return snd_soc_dapm_sync(&codec->dapm);
5b2eec3f
MB
804}
805
07ed873e 806const struct snd_soc_dai_ops arizona_dai_ops = {
5b2eec3f 807 .startup = arizona_startup,
07ed873e
MB
808 .set_fmt = arizona_set_fmt,
809 .hw_params = arizona_hw_params,
5b2eec3f 810 .set_sysclk = arizona_dai_set_sysclk,
07ed873e 811};
a837987e 812EXPORT_SYMBOL_GPL(arizona_dai_ops);
07ed873e 813
5b2eec3f
MB
814int arizona_init_dai(struct arizona_priv *priv, int id)
815{
816 struct arizona_dai_priv *dai_priv = &priv->dai[id];
817
818 dai_priv->clk = ARIZONA_CLK_SYSCLK;
819
820 return 0;
821}
822EXPORT_SYMBOL_GPL(arizona_init_dai);
823
07ed873e
MB
824static irqreturn_t arizona_fll_lock(int irq, void *data)
825{
826 struct arizona_fll *fll = data;
827
6b315958 828 arizona_fll_dbg(fll, "Lock status changed\n");
07ed873e
MB
829
830 complete(&fll->lock);
831
832 return IRQ_HANDLED;
833}
834
835static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
836{
837 struct arizona_fll *fll = data;
838
839 arizona_fll_dbg(fll, "clock OK\n");
840
841 complete(&fll->ok);
842
843 return IRQ_HANDLED;
844}
845
846static struct {
847 unsigned int min;
848 unsigned int max;
849 u16 fratio;
850 int ratio;
851} fll_fratios[] = {
852 { 0, 64000, 4, 16 },
853 { 64000, 128000, 3, 8 },
854 { 128000, 256000, 2, 4 },
855 { 256000, 1000000, 1, 2 },
856 { 1000000, 13500000, 0, 1 },
857};
858
859struct arizona_fll_cfg {
860 int n;
861 int theta;
862 int lambda;
863 int refdiv;
864 int outdiv;
865 int fratio;
866};
867
868static int arizona_calc_fll(struct arizona_fll *fll,
869 struct arizona_fll_cfg *cfg,
870 unsigned int Fref,
871 unsigned int Fout)
872{
873 unsigned int target, div, gcd_fll;
874 int i, ratio;
875
876 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
877
878 /* Fref must be <=13.5MHz */
879 div = 1;
880 cfg->refdiv = 0;
881 while ((Fref / div) > 13500000) {
882 div *= 2;
883 cfg->refdiv++;
884
885 if (div > 8) {
886 arizona_fll_err(fll,
887 "Can't scale %dMHz in to <=13.5MHz\n",
888 Fref);
889 return -EINVAL;
890 }
891 }
892
893 /* Apply the division for our remaining calculations */
894 Fref /= div;
895
2b4d39fc 896 /* Fvco should be over the targt; don't check the upper bound */
07ed873e 897 div = 1;
2b4d39fc 898 while (Fout * div < 90000000 * fll->vco_mult) {
07ed873e
MB
899 div++;
900 if (div > 7) {
901 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
902 Fout);
903 return -EINVAL;
904 }
905 }
2b4d39fc 906 target = Fout * div / fll->vco_mult;
07ed873e
MB
907 cfg->outdiv = div;
908
909 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
910
911 /* Find an appropraite FLL_FRATIO and factor it out of the target */
912 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
913 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
914 cfg->fratio = fll_fratios[i].fratio;
915 ratio = fll_fratios[i].ratio;
916 break;
917 }
918 }
919 if (i == ARRAY_SIZE(fll_fratios)) {
920 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
921 Fref);
922 return -EINVAL;
923 }
924
925 cfg->n = target / (ratio * Fref);
926
927 if (target % Fref) {
928 gcd_fll = gcd(target, ratio * Fref);
929 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
930
931 cfg->theta = (target - (cfg->n * ratio * Fref))
932 / gcd_fll;
933 cfg->lambda = (ratio * Fref) / gcd_fll;
934 } else {
935 cfg->theta = 0;
936 cfg->lambda = 0;
937 }
938
939 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
940 cfg->n, cfg->theta, cfg->lambda);
941 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
942 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
943
944 return 0;
945
946}
947
948static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
949 struct arizona_fll_cfg *cfg, int source)
950{
951 regmap_update_bits(arizona->regmap, base + 3,
952 ARIZONA_FLL1_THETA_MASK, cfg->theta);
953 regmap_update_bits(arizona->regmap, base + 4,
954 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
955 regmap_update_bits(arizona->regmap, base + 5,
956 ARIZONA_FLL1_FRATIO_MASK,
957 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
958 regmap_update_bits(arizona->regmap, base + 6,
959 ARIZONA_FLL1_CLK_REF_DIV_MASK |
960 ARIZONA_FLL1_CLK_REF_SRC_MASK,
961 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
962 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
963
964 regmap_update_bits(arizona->regmap, base + 2,
965 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
966 ARIZONA_FLL1_CTRL_UPD | cfg->n);
967}
968
969int arizona_set_fll(struct arizona_fll *fll, int source,
970 unsigned int Fref, unsigned int Fout)
971{
972 struct arizona *arizona = fll->arizona;
973 struct arizona_fll_cfg cfg, sync;
974 unsigned int reg, val;
975 int syncsrc;
976 bool ena;
977 int ret;
978
1cbe4bca
MB
979 if (fll->fref == Fref && fll->fout == Fout)
980 return 0;
981
07ed873e
MB
982 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
983 if (ret != 0) {
984 arizona_fll_err(fll, "Failed to read current state: %d\n",
985 ret);
986 return ret;
987 }
988 ena = reg & ARIZONA_FLL1_ENA;
989
990 if (Fout) {
991 /* Do we have a 32kHz reference? */
992 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
993 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
994 case ARIZONA_CLK_SRC_MCLK1:
995 case ARIZONA_CLK_SRC_MCLK2:
996 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
997 break;
998 default:
999 syncsrc = -1;
1000 }
1001
1002 if (source == syncsrc)
1003 syncsrc = -1;
1004
1005 if (syncsrc >= 0) {
1006 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1007 if (ret != 0)
1008 return ret;
1009
1010 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
1011 if (ret != 0)
1012 return ret;
1013 } else {
1014 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
1015 if (ret != 0)
1016 return ret;
1017 }
1018 } else {
1019 regmap_update_bits(arizona->regmap, fll->base + 1,
1020 ARIZONA_FLL1_ENA, 0);
1021 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1022 ARIZONA_FLL1_SYNC_ENA, 0);
1023
1024 if (ena)
1025 pm_runtime_put_autosuspend(arizona->dev);
1026
50fcfe45
MB
1027 fll->fref = Fref;
1028 fll->fout = Fout;
1029
07ed873e
MB
1030 return 0;
1031 }
1032
1033 regmap_update_bits(arizona->regmap, fll->base + 5,
1034 ARIZONA_FLL1_OUTDIV_MASK,
1035 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1036
1037 if (syncsrc >= 0) {
1038 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
1039 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
1040 } else {
1041 arizona_apply_fll(arizona, fll->base, &cfg, source);
1042 }
1043
1044 if (!ena)
1045 pm_runtime_get(arizona->dev);
1046
1047 /* Clear any pending completions */
1048 try_wait_for_completion(&fll->ok);
1049
1050 regmap_update_bits(arizona->regmap, fll->base + 1,
1051 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
1052 if (syncsrc >= 0)
1053 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1054 ARIZONA_FLL1_SYNC_ENA,
1055 ARIZONA_FLL1_SYNC_ENA);
1056
1057 ret = wait_for_completion_timeout(&fll->ok,
09871a94 1058 msecs_to_jiffies(250));
07ed873e
MB
1059 if (ret == 0)
1060 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1061
1cbe4bca
MB
1062 fll->fref = Fref;
1063 fll->fout = Fout;
1064
07ed873e
MB
1065 return 0;
1066}
1067EXPORT_SYMBOL_GPL(arizona_set_fll);
1068
1069int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1070 int ok_irq, struct arizona_fll *fll)
1071{
1072 int ret;
1073
1074 init_completion(&fll->lock);
1075 init_completion(&fll->ok);
1076
1077 fll->id = id;
1078 fll->base = base;
1079 fll->arizona = arizona;
1080
1081 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1082 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1083 "FLL%d clock OK", id);
1084
1085 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
1086 arizona_fll_lock, fll);
1087 if (ret != 0) {
1088 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
1089 id, ret);
1090 }
1091
1092 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1093 arizona_fll_clock_ok, fll);
1094 if (ret != 0) {
1095 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1096 id, ret);
1097 }
1098
1099 return 0;
1100}
1101EXPORT_SYMBOL_GPL(arizona_init_fll);
1102
1103MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1104MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1105MODULE_LICENSE("GPL");
This page took 0.11327 seconds and 5 git commands to generate.