Merge branch 'fixes-for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/coolone...
[linux/fpc-iii.git] / sound / soc / codecs / arizona.c
blob5c9cacaf2d525cddabffd0b416c0695dfadaab99
1 /*
2 * arizona.c - Wolfson Arizona class device shared support
4 * Copyright 2012 Wolfson Microelectronics plc
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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.
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>
20 #include <linux/mfd/arizona/core.h>
21 #include <linux/mfd/arizona/registers.h>
23 #include "arizona.h"
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
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__)
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__)
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 "ASRC1L",
123 "ASRC1R",
124 "ASRC2L",
125 "ASRC2R",
127 EXPORT_SYMBOL_GPL(arizona_mixer_texts);
129 int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
130 0x00, /* None */
131 0x04, /* Tone */
132 0x05,
133 0x06, /* Haptics */
134 0x08, /* AEC */
135 0x0c, /* Noise mixer */
136 0x0d, /* Comfort noise */
137 0x10, /* IN1L */
138 0x11,
139 0x12,
140 0x13,
141 0x14,
142 0x15,
143 0x16,
144 0x17,
145 0x20, /* AIF1RX1 */
146 0x21,
147 0x22,
148 0x23,
149 0x24,
150 0x25,
151 0x26,
152 0x27,
153 0x28, /* AIF2RX1 */
154 0x29,
155 0x30, /* AIF3RX1 */
156 0x31,
157 0x38, /* SLIMRX1 */
158 0x39,
159 0x3a,
160 0x3b,
161 0x3c,
162 0x3d,
163 0x3e,
164 0x3f,
165 0x50, /* EQ1 */
166 0x51,
167 0x52,
168 0x53,
169 0x58, /* DRC1L */
170 0x59,
171 0x5a,
172 0x5b,
173 0x60, /* LHPF1 */
174 0x61,
175 0x62,
176 0x63,
177 0x68, /* DSP1.1 */
178 0x69,
179 0x6a,
180 0x6b,
181 0x6c,
182 0x6d,
183 0x90, /* ASRC1L */
184 0x91,
185 0x92,
186 0x93,
188 EXPORT_SYMBOL_GPL(arizona_mixer_values);
190 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
191 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
193 static const char *arizona_lhpf_mode_text[] = {
194 "Low-pass", "High-pass"
197 const struct soc_enum arizona_lhpf1_mode =
198 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
199 arizona_lhpf_mode_text);
200 EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
202 const struct soc_enum arizona_lhpf2_mode =
203 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
204 arizona_lhpf_mode_text);
205 EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
207 const struct soc_enum arizona_lhpf3_mode =
208 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
209 arizona_lhpf_mode_text);
210 EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
212 const struct soc_enum arizona_lhpf4_mode =
213 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
214 arizona_lhpf_mode_text);
215 EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
217 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
218 int event)
220 return 0;
222 EXPORT_SYMBOL_GPL(arizona_in_ev);
224 int arizona_out_ev(struct snd_soc_dapm_widget *w,
225 struct snd_kcontrol *kcontrol,
226 int event)
228 return 0;
230 EXPORT_SYMBOL_GPL(arizona_out_ev);
232 int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
233 int source, unsigned int freq, int dir)
235 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
236 struct arizona *arizona = priv->arizona;
237 char *name;
238 unsigned int reg;
239 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
240 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
241 unsigned int *clk;
243 switch (clk_id) {
244 case ARIZONA_CLK_SYSCLK:
245 name = "SYSCLK";
246 reg = ARIZONA_SYSTEM_CLOCK_1;
247 clk = &priv->sysclk;
248 mask |= ARIZONA_SYSCLK_FRAC;
249 break;
250 case ARIZONA_CLK_ASYNCCLK:
251 name = "ASYNCCLK";
252 reg = ARIZONA_ASYNC_CLOCK_1;
253 clk = &priv->asyncclk;
254 break;
255 default:
256 return -EINVAL;
259 switch (freq) {
260 case 5644800:
261 case 6144000:
262 break;
263 case 11289600:
264 case 12288000:
265 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
266 break;
267 case 22579200:
268 case 24576000:
269 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
270 break;
271 case 45158400:
272 case 49152000:
273 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
274 break;
275 default:
276 return -EINVAL;
279 *clk = freq;
281 if (freq % 6144000)
282 val |= ARIZONA_SYSCLK_FRAC;
284 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
286 return regmap_update_bits(arizona->regmap, reg, mask, val);
288 EXPORT_SYMBOL_GPL(arizona_set_sysclk);
290 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
292 struct snd_soc_codec *codec = dai->codec;
293 int lrclk, bclk, mode, base;
295 base = dai->driver->base;
297 lrclk = 0;
298 bclk = 0;
300 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
301 case SND_SOC_DAIFMT_DSP_A:
302 mode = 0;
303 break;
304 case SND_SOC_DAIFMT_DSP_B:
305 mode = 1;
306 break;
307 case SND_SOC_DAIFMT_I2S:
308 mode = 2;
309 break;
310 case SND_SOC_DAIFMT_LEFT_J:
311 mode = 3;
312 break;
313 default:
314 arizona_aif_err(dai, "Unsupported DAI format %d\n",
315 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
316 return -EINVAL;
319 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
320 case SND_SOC_DAIFMT_CBS_CFS:
321 break;
322 case SND_SOC_DAIFMT_CBS_CFM:
323 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
324 break;
325 case SND_SOC_DAIFMT_CBM_CFS:
326 bclk |= ARIZONA_AIF1_BCLK_MSTR;
327 break;
328 case SND_SOC_DAIFMT_CBM_CFM:
329 bclk |= ARIZONA_AIF1_BCLK_MSTR;
330 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
331 break;
332 default:
333 arizona_aif_err(dai, "Unsupported master mode %d\n",
334 fmt & SND_SOC_DAIFMT_MASTER_MASK);
335 return -EINVAL;
338 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
339 case SND_SOC_DAIFMT_NB_NF:
340 break;
341 case SND_SOC_DAIFMT_IB_IF:
342 bclk |= ARIZONA_AIF1_BCLK_INV;
343 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
344 break;
345 case SND_SOC_DAIFMT_IB_NF:
346 bclk |= ARIZONA_AIF1_BCLK_INV;
347 break;
348 case SND_SOC_DAIFMT_NB_IF:
349 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
350 break;
351 default:
352 return -EINVAL;
355 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
356 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
357 bclk);
358 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
359 ARIZONA_AIF1TX_LRCLK_INV |
360 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
361 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
362 ARIZONA_AIF1RX_LRCLK_INV |
363 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
364 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
365 ARIZONA_AIF1_FMT_MASK, mode);
367 return 0;
370 static const int arizona_48k_bclk_rates[] = {
372 48000,
373 64000,
374 96000,
375 128000,
376 192000,
377 256000,
378 384000,
379 512000,
380 768000,
381 1024000,
382 1536000,
383 2048000,
384 3072000,
385 4096000,
386 6144000,
387 8192000,
388 12288000,
389 24576000,
392 static const unsigned int arizona_48k_rates[] = {
393 12000,
394 24000,
395 48000,
396 96000,
397 192000,
398 384000,
399 768000,
400 4000,
401 8000,
402 16000,
403 32000,
404 64000,
405 128000,
406 256000,
407 512000,
410 static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
411 .count = ARRAY_SIZE(arizona_48k_rates),
412 .list = arizona_48k_rates,
415 static const int arizona_44k1_bclk_rates[] = {
417 44100,
418 58800,
419 88200,
420 117600,
421 177640,
422 235200,
423 352800,
424 470400,
425 705600,
426 940800,
427 1411200,
428 1881600,
429 2882400,
430 3763200,
431 5644800,
432 7526400,
433 11289600,
434 22579200,
437 static const unsigned int arizona_44k1_rates[] = {
438 11025,
439 22050,
440 44100,
441 88200,
442 176400,
443 352800,
444 705600,
447 static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
448 .count = ARRAY_SIZE(arizona_44k1_rates),
449 .list = arizona_44k1_rates,
452 static int arizona_sr_vals[] = {
454 12000,
455 24000,
456 48000,
457 96000,
458 192000,
459 384000,
460 768000,
462 11025,
463 22050,
464 44100,
465 88200,
466 176400,
467 352800,
468 705600,
469 4000,
470 8000,
471 16000,
472 32000,
473 64000,
474 128000,
475 256000,
476 512000,
479 static int arizona_startup(struct snd_pcm_substream *substream,
480 struct snd_soc_dai *dai)
482 struct snd_soc_codec *codec = dai->codec;
483 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
484 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
485 const struct snd_pcm_hw_constraint_list *constraint;
486 unsigned int base_rate;
488 switch (dai_priv->clk) {
489 case ARIZONA_CLK_SYSCLK:
490 base_rate = priv->sysclk;
491 break;
492 case ARIZONA_CLK_ASYNCCLK:
493 base_rate = priv->asyncclk;
494 break;
495 default:
496 return 0;
499 if (base_rate % 8000)
500 constraint = &arizona_44k1_constraint;
501 else
502 constraint = &arizona_48k_constraint;
504 return snd_pcm_hw_constraint_list(substream->runtime, 0,
505 SNDRV_PCM_HW_PARAM_RATE,
506 constraint);
509 static int arizona_hw_params(struct snd_pcm_substream *substream,
510 struct snd_pcm_hw_params *params,
511 struct snd_soc_dai *dai)
513 struct snd_soc_codec *codec = dai->codec;
514 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
515 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
516 int base = dai->driver->base;
517 const int *rates;
518 int i;
519 int bclk, lrclk, wl, frame, sr_val;
521 if (params_rate(params) % 8000)
522 rates = &arizona_44k1_bclk_rates[0];
523 else
524 rates = &arizona_48k_bclk_rates[0];
526 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
527 if (rates[i] >= snd_soc_params_to_bclk(params) &&
528 rates[i] % params_rate(params) == 0) {
529 bclk = i;
530 break;
533 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
534 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
535 params_rate(params));
536 return -EINVAL;
539 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
540 if (arizona_sr_vals[i] == params_rate(params))
541 break;
542 if (i == ARRAY_SIZE(arizona_sr_vals)) {
543 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
544 params_rate(params));
545 return -EINVAL;
547 sr_val = i;
549 lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
551 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
552 rates[bclk], rates[bclk] / lrclk);
554 wl = snd_pcm_format_width(params_format(params));
555 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
558 * We will need to be more flexible than this in future,
559 * currently we use a single sample rate for SYSCLK.
561 switch (dai_priv->clk) {
562 case ARIZONA_CLK_SYSCLK:
563 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
564 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
565 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
566 ARIZONA_AIF1_RATE_MASK, 0);
567 break;
568 case ARIZONA_CLK_ASYNCCLK:
569 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
570 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
571 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
572 ARIZONA_AIF1_RATE_MASK, 8);
573 break;
574 default:
575 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
576 return -EINVAL;
579 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
580 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
581 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
582 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
583 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
584 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
585 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
586 ARIZONA_AIF1TX_WL_MASK |
587 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
588 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
589 ARIZONA_AIF1RX_WL_MASK |
590 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
592 return 0;
595 static const char *arizona_dai_clk_str(int clk_id)
597 switch (clk_id) {
598 case ARIZONA_CLK_SYSCLK:
599 return "SYSCLK";
600 case ARIZONA_CLK_ASYNCCLK:
601 return "ASYNCCLK";
602 default:
603 return "Unknown clock";
607 static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
608 int clk_id, unsigned int freq, int dir)
610 struct snd_soc_codec *codec = dai->codec;
611 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
612 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
613 struct snd_soc_dapm_route routes[2];
615 switch (clk_id) {
616 case ARIZONA_CLK_SYSCLK:
617 case ARIZONA_CLK_ASYNCCLK:
618 break;
619 default:
620 return -EINVAL;
623 if (clk_id == dai_priv->clk)
624 return 0;
626 if (dai->active) {
627 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
628 dai->id);
629 return -EBUSY;
632 memset(&routes, 0, sizeof(routes));
633 routes[0].sink = dai->driver->capture.stream_name;
634 routes[1].sink = dai->driver->playback.stream_name;
636 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
637 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
638 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
640 routes[0].source = arizona_dai_clk_str(clk_id);
641 routes[1].source = arizona_dai_clk_str(clk_id);
642 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
644 return snd_soc_dapm_sync(&codec->dapm);
647 const struct snd_soc_dai_ops arizona_dai_ops = {
648 .startup = arizona_startup,
649 .set_fmt = arizona_set_fmt,
650 .hw_params = arizona_hw_params,
651 .set_sysclk = arizona_dai_set_sysclk,
653 EXPORT_SYMBOL_GPL(arizona_dai_ops);
655 int arizona_init_dai(struct arizona_priv *priv, int id)
657 struct arizona_dai_priv *dai_priv = &priv->dai[id];
659 dai_priv->clk = ARIZONA_CLK_SYSCLK;
661 return 0;
663 EXPORT_SYMBOL_GPL(arizona_init_dai);
665 static irqreturn_t arizona_fll_lock(int irq, void *data)
667 struct arizona_fll *fll = data;
669 arizona_fll_dbg(fll, "Locked\n");
671 complete(&fll->lock);
673 return IRQ_HANDLED;
676 static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
678 struct arizona_fll *fll = data;
680 arizona_fll_dbg(fll, "clock OK\n");
682 complete(&fll->ok);
684 return IRQ_HANDLED;
687 static struct {
688 unsigned int min;
689 unsigned int max;
690 u16 fratio;
691 int ratio;
692 } fll_fratios[] = {
693 { 0, 64000, 4, 16 },
694 { 64000, 128000, 3, 8 },
695 { 128000, 256000, 2, 4 },
696 { 256000, 1000000, 1, 2 },
697 { 1000000, 13500000, 0, 1 },
700 struct arizona_fll_cfg {
701 int n;
702 int theta;
703 int lambda;
704 int refdiv;
705 int outdiv;
706 int fratio;
709 static int arizona_calc_fll(struct arizona_fll *fll,
710 struct arizona_fll_cfg *cfg,
711 unsigned int Fref,
712 unsigned int Fout)
714 unsigned int target, div, gcd_fll;
715 int i, ratio;
717 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
719 /* Fref must be <=13.5MHz */
720 div = 1;
721 cfg->refdiv = 0;
722 while ((Fref / div) > 13500000) {
723 div *= 2;
724 cfg->refdiv++;
726 if (div > 8) {
727 arizona_fll_err(fll,
728 "Can't scale %dMHz in to <=13.5MHz\n",
729 Fref);
730 return -EINVAL;
734 /* Apply the division for our remaining calculations */
735 Fref /= div;
737 /* Fvco should be over the targt; don't check the upper bound */
738 div = 1;
739 while (Fout * div < 90000000 * fll->vco_mult) {
740 div++;
741 if (div > 7) {
742 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
743 Fout);
744 return -EINVAL;
747 target = Fout * div / fll->vco_mult;
748 cfg->outdiv = div;
750 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
752 /* Find an appropraite FLL_FRATIO and factor it out of the target */
753 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
754 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
755 cfg->fratio = fll_fratios[i].fratio;
756 ratio = fll_fratios[i].ratio;
757 break;
760 if (i == ARRAY_SIZE(fll_fratios)) {
761 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
762 Fref);
763 return -EINVAL;
766 cfg->n = target / (ratio * Fref);
768 if (target % Fref) {
769 gcd_fll = gcd(target, ratio * Fref);
770 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
772 cfg->theta = (target - (cfg->n * ratio * Fref))
773 / gcd_fll;
774 cfg->lambda = (ratio * Fref) / gcd_fll;
775 } else {
776 cfg->theta = 0;
777 cfg->lambda = 0;
780 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
781 cfg->n, cfg->theta, cfg->lambda);
782 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
783 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
785 return 0;
789 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
790 struct arizona_fll_cfg *cfg, int source)
792 regmap_update_bits(arizona->regmap, base + 3,
793 ARIZONA_FLL1_THETA_MASK, cfg->theta);
794 regmap_update_bits(arizona->regmap, base + 4,
795 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
796 regmap_update_bits(arizona->regmap, base + 5,
797 ARIZONA_FLL1_FRATIO_MASK,
798 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
799 regmap_update_bits(arizona->regmap, base + 6,
800 ARIZONA_FLL1_CLK_REF_DIV_MASK |
801 ARIZONA_FLL1_CLK_REF_SRC_MASK,
802 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
803 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
805 regmap_update_bits(arizona->regmap, base + 2,
806 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
807 ARIZONA_FLL1_CTRL_UPD | cfg->n);
810 int arizona_set_fll(struct arizona_fll *fll, int source,
811 unsigned int Fref, unsigned int Fout)
813 struct arizona *arizona = fll->arizona;
814 struct arizona_fll_cfg cfg, sync;
815 unsigned int reg, val;
816 int syncsrc;
817 bool ena;
818 int ret;
820 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
821 if (ret != 0) {
822 arizona_fll_err(fll, "Failed to read current state: %d\n",
823 ret);
824 return ret;
826 ena = reg & ARIZONA_FLL1_ENA;
828 if (Fout) {
829 /* Do we have a 32kHz reference? */
830 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
831 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
832 case ARIZONA_CLK_SRC_MCLK1:
833 case ARIZONA_CLK_SRC_MCLK2:
834 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
835 break;
836 default:
837 syncsrc = -1;
840 if (source == syncsrc)
841 syncsrc = -1;
843 if (syncsrc >= 0) {
844 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
845 if (ret != 0)
846 return ret;
848 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
849 if (ret != 0)
850 return ret;
851 } else {
852 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
853 if (ret != 0)
854 return ret;
856 } else {
857 regmap_update_bits(arizona->regmap, fll->base + 1,
858 ARIZONA_FLL1_ENA, 0);
859 regmap_update_bits(arizona->regmap, fll->base + 0x11,
860 ARIZONA_FLL1_SYNC_ENA, 0);
862 if (ena)
863 pm_runtime_put_autosuspend(arizona->dev);
865 return 0;
868 regmap_update_bits(arizona->regmap, fll->base + 5,
869 ARIZONA_FLL1_OUTDIV_MASK,
870 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
872 if (syncsrc >= 0) {
873 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
874 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
875 } else {
876 arizona_apply_fll(arizona, fll->base, &cfg, source);
879 if (!ena)
880 pm_runtime_get(arizona->dev);
882 /* Clear any pending completions */
883 try_wait_for_completion(&fll->ok);
885 regmap_update_bits(arizona->regmap, fll->base + 1,
886 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
887 if (syncsrc >= 0)
888 regmap_update_bits(arizona->regmap, fll->base + 0x11,
889 ARIZONA_FLL1_SYNC_ENA,
890 ARIZONA_FLL1_SYNC_ENA);
892 ret = wait_for_completion_timeout(&fll->ok,
893 msecs_to_jiffies(25));
894 if (ret == 0)
895 arizona_fll_warn(fll, "Timed out waiting for lock\n");
897 return 0;
899 EXPORT_SYMBOL_GPL(arizona_set_fll);
901 int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
902 int ok_irq, struct arizona_fll *fll)
904 int ret;
906 init_completion(&fll->lock);
907 init_completion(&fll->ok);
909 fll->id = id;
910 fll->base = base;
911 fll->arizona = arizona;
913 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
914 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
915 "FLL%d clock OK", id);
917 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
918 arizona_fll_lock, fll);
919 if (ret != 0) {
920 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
921 id, ret);
924 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
925 arizona_fll_clock_ok, fll);
926 if (ret != 0) {
927 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
928 id, ret);
931 return 0;
933 EXPORT_SYMBOL_GPL(arizona_init_fll);
935 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
936 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
937 MODULE_LICENSE("GPL");