blob: 67760b4ea24cb13b4554b6a7c08f68e555be18a4 [file] [log] [blame]
Mark Brown07ed8732012-06-18 21:08:44 +01001/*
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",
82 "AIF1RX1",
83 "AIF1RX2",
84 "AIF1RX3",
85 "AIF1RX4",
86 "AIF1RX5",
87 "AIF1RX6",
88 "AIF1RX7",
89 "AIF1RX8",
90 "AIF2RX1",
91 "AIF2RX2",
92 "AIF3RX1",
93 "AIF3RX2",
94 "SLIMRX1",
95 "SLIMRX2",
96 "SLIMRX3",
97 "SLIMRX4",
98 "SLIMRX5",
99 "SLIMRX6",
100 "SLIMRX7",
101 "SLIMRX8",
102 "EQ1",
103 "EQ2",
104 "EQ3",
105 "EQ4",
106 "DRC1L",
107 "DRC1R",
108 "DRC2L",
109 "DRC2R",
110 "LHPF1",
111 "LHPF2",
112 "LHPF3",
113 "LHPF4",
114 "DSP1.1",
115 "DSP1.2",
116 "DSP1.3",
117 "DSP1.4",
118 "DSP1.5",
119 "DSP1.6",
120 "ASRC1L",
121 "ASRC1R",
122 "ASRC2L",
123 "ASRC2R",
124};
125EXPORT_SYMBOL_GPL(arizona_mixer_texts);
126
127int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
128 0x00, /* None */
129 0x04, /* Tone */
130 0x05,
131 0x06, /* Haptics */
132 0x08, /* AEC */
133 0x0c, /* Noise mixer */
134 0x0d, /* Comfort noise */
135 0x10, /* IN1L */
136 0x11,
137 0x12,
138 0x13,
139 0x14,
140 0x15,
141 0x20, /* AIF1RX1 */
142 0x21,
143 0x22,
144 0x23,
145 0x24,
146 0x25,
147 0x26,
148 0x27,
149 0x28, /* AIF2RX1 */
150 0x29,
151 0x30, /* AIF3RX1 */
152 0x31,
153 0x38, /* SLIMRX1 */
154 0x39,
155 0x3a,
156 0x3b,
157 0x3c,
158 0x3d,
159 0x3e,
160 0x3f,
161 0x50, /* EQ1 */
162 0x51,
163 0x52,
164 0x53,
165 0x58, /* DRC1L */
166 0x59,
167 0x5a,
168 0x5b,
169 0x60, /* LHPF1 */
170 0x61,
171 0x62,
172 0x63,
173 0x68, /* DSP1.1 */
174 0x69,
175 0x6a,
176 0x6b,
177 0x6c,
178 0x6d,
179 0x90, /* ASRC1L */
180 0x91,
181 0x92,
182 0x93,
183};
184EXPORT_SYMBOL_GPL(arizona_mixer_values);
185
186const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
187EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
188
189static const char *arizona_lhpf_mode_text[] = {
190 "Low-pass", "High-pass"
191};
192
193const struct soc_enum arizona_lhpf1_mode =
194 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
195 arizona_lhpf_mode_text);
196EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
197
198const struct soc_enum arizona_lhpf2_mode =
199 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
200 arizona_lhpf_mode_text);
201EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
202
203const struct soc_enum arizona_lhpf3_mode =
204 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
205 arizona_lhpf_mode_text);
206EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
207
208const struct soc_enum arizona_lhpf4_mode =
209 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
210 arizona_lhpf_mode_text);
211EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
212
213int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
214 int event)
215{
216 return 0;
217}
218EXPORT_SYMBOL_GPL(arizona_in_ev);
219
220int arizona_out_ev(struct snd_soc_dapm_widget *w,
221 struct snd_kcontrol *kcontrol,
222 int event)
223{
224 return 0;
225}
226EXPORT_SYMBOL_GPL(arizona_out_ev);
227
228int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
229 int source, unsigned int freq, int dir)
230{
231 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
232 struct arizona *arizona = priv->arizona;
233 char *name;
234 unsigned int reg;
235 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
236 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
237 unsigned int *clk;
238
239 switch (clk_id) {
240 case ARIZONA_CLK_SYSCLK:
241 name = "SYSCLK";
242 reg = ARIZONA_SYSTEM_CLOCK_1;
243 clk = &priv->sysclk;
244 mask |= ARIZONA_SYSCLK_FRAC;
245 break;
246 case ARIZONA_CLK_ASYNCCLK:
247 name = "ASYNCCLK";
248 reg = ARIZONA_ASYNC_CLOCK_1;
249 clk = &priv->asyncclk;
250 break;
251 default:
252 return -EINVAL;
253 }
254
255 switch (freq) {
256 case 5644800:
257 case 6144000:
258 break;
259 case 11289600:
260 case 12288000:
261 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
262 break;
263 case 22579200:
264 case 24576000:
265 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
266 break;
267 case 45158400:
268 case 49152000:
269 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
270 break;
271 default:
272 return -EINVAL;
273 }
274
275 *clk = freq;
276
277 if (freq % 6144000)
278 val |= ARIZONA_SYSCLK_FRAC;
279
280 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
281
282 return regmap_update_bits(arizona->regmap, reg, mask, val);
283}
284EXPORT_SYMBOL_GPL(arizona_set_sysclk);
285
286static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
287{
288 struct snd_soc_codec *codec = dai->codec;
289 int lrclk, bclk, mode, base;
290
291 base = dai->driver->base;
292
293 lrclk = 0;
294 bclk = 0;
295
296 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
297 case SND_SOC_DAIFMT_DSP_A:
298 mode = 0;
299 break;
300 case SND_SOC_DAIFMT_DSP_B:
301 mode = 1;
302 break;
303 case SND_SOC_DAIFMT_I2S:
304 mode = 2;
305 break;
306 case SND_SOC_DAIFMT_LEFT_J:
307 mode = 3;
308 break;
309 default:
310 arizona_aif_err(dai, "Unsupported DAI format %d\n",
311 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
312 return -EINVAL;
313 }
314
315 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
316 case SND_SOC_DAIFMT_CBS_CFS:
317 break;
318 case SND_SOC_DAIFMT_CBS_CFM:
319 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
320 break;
321 case SND_SOC_DAIFMT_CBM_CFS:
322 bclk |= ARIZONA_AIF1_BCLK_MSTR;
323 break;
324 case SND_SOC_DAIFMT_CBM_CFM:
325 bclk |= ARIZONA_AIF1_BCLK_MSTR;
326 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
327 break;
328 default:
329 arizona_aif_err(dai, "Unsupported master mode %d\n",
330 fmt & SND_SOC_DAIFMT_MASTER_MASK);
331 return -EINVAL;
332 }
333
334 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
335 case SND_SOC_DAIFMT_NB_NF:
336 break;
337 case SND_SOC_DAIFMT_IB_IF:
338 bclk |= ARIZONA_AIF1_BCLK_INV;
339 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
340 break;
341 case SND_SOC_DAIFMT_IB_NF:
342 bclk |= ARIZONA_AIF1_BCLK_INV;
343 break;
344 case SND_SOC_DAIFMT_NB_IF:
345 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
346 break;
347 default:
348 return -EINVAL;
349 }
350
351 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
352 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
353 bclk);
354 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
355 ARIZONA_AIF1TX_LRCLK_INV |
356 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
357 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
358 ARIZONA_AIF1RX_LRCLK_INV |
359 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
360 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
361 ARIZONA_AIF1_FMT_MASK, mode);
362
363 return 0;
364}
365
Mark Brown949e6bc2012-07-04 18:58:04 +0100366static const int arizona_48k_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100367 -1,
368 48000,
369 64000,
370 96000,
371 128000,
372 192000,
373 256000,
374 384000,
375 512000,
376 768000,
377 1024000,
378 1536000,
379 2048000,
380 3072000,
381 4096000,
382 6144000,
383 8192000,
384 12288000,
385 24576000,
386};
387
Mark Brown949e6bc2012-07-04 18:58:04 +0100388static const int arizona_44k1_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100389 -1,
390 44100,
391 58800,
392 88200,
393 117600,
394 177640,
395 235200,
396 352800,
397 470400,
398 705600,
399 940800,
400 1411200,
401 1881600,
402 2882400,
403 3763200,
404 5644800,
405 7526400,
406 11289600,
407 22579200,
408};
409
410static int arizona_sr_vals[] = {
411 0,
412 12000,
413 24000,
414 48000,
415 96000,
416 192000,
417 384000,
418 768000,
419 0,
420 11025,
421 22050,
422 44100,
423 88200,
424 176400,
425 352800,
426 705600,
427 4000,
428 8000,
429 16000,
430 32000,
431 64000,
432 128000,
433 256000,
434 512000,
435};
436
437static int arizona_hw_params(struct snd_pcm_substream *substream,
438 struct snd_pcm_hw_params *params,
439 struct snd_soc_dai *dai)
440{
441 struct snd_soc_codec *codec = dai->codec;
442 int base = dai->driver->base;
443 const int *rates;
444 int i;
445 int bclk, lrclk, wl, frame, sr_val;
446
447 if (params_rate(params) % 8000)
Mark Brown949e6bc2012-07-04 18:58:04 +0100448 rates = &arizona_44k1_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100449 else
Mark Brown949e6bc2012-07-04 18:58:04 +0100450 rates = &arizona_48k_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100451
Mark Brown949e6bc2012-07-04 18:58:04 +0100452 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
Mark Brown07ed8732012-06-18 21:08:44 +0100453 if (rates[i] == snd_soc_params_to_bclk(params)) {
454 bclk = i;
455 break;
456 }
457 }
Mark Brown949e6bc2012-07-04 18:58:04 +0100458 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
Mark Brown07ed8732012-06-18 21:08:44 +0100459 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
460 params_rate(params));
461 return -EINVAL;
462 }
463
464 /*
465 * We will need to be more flexible than this in future,
466 * currently we use a single sample rate for the chip.
467 */
468 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
469 if (arizona_sr_vals[i] == params_rate(params))
470 break;
471 if (i == ARRAY_SIZE(arizona_sr_vals)) {
472 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
473 params_rate(params));
474 return -EINVAL;
475 }
476 sr_val = i;
477
478 lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
479
480 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
481 rates[bclk], rates[bclk] / lrclk);
482
483 wl = snd_pcm_format_width(params_format(params));
484 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
485
486 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
487 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
488 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
489 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
490 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
491 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
492 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
493 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
494 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
495 ARIZONA_AIF1TX_WL_MASK |
496 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
497 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
498 ARIZONA_AIF1RX_WL_MASK |
499 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
500
501 return 0;
502}
503
504const struct snd_soc_dai_ops arizona_dai_ops = {
505 .set_fmt = arizona_set_fmt,
506 .hw_params = arizona_hw_params,
507};
508
509static irqreturn_t arizona_fll_lock(int irq, void *data)
510{
511 struct arizona_fll *fll = data;
512
513 arizona_fll_dbg(fll, "Locked\n");
514
515 complete(&fll->lock);
516
517 return IRQ_HANDLED;
518}
519
520static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
521{
522 struct arizona_fll *fll = data;
523
524 arizona_fll_dbg(fll, "clock OK\n");
525
526 complete(&fll->ok);
527
528 return IRQ_HANDLED;
529}
530
531static struct {
532 unsigned int min;
533 unsigned int max;
534 u16 fratio;
535 int ratio;
536} fll_fratios[] = {
537 { 0, 64000, 4, 16 },
538 { 64000, 128000, 3, 8 },
539 { 128000, 256000, 2, 4 },
540 { 256000, 1000000, 1, 2 },
541 { 1000000, 13500000, 0, 1 },
542};
543
544struct arizona_fll_cfg {
545 int n;
546 int theta;
547 int lambda;
548 int refdiv;
549 int outdiv;
550 int fratio;
551};
552
553static int arizona_calc_fll(struct arizona_fll *fll,
554 struct arizona_fll_cfg *cfg,
555 unsigned int Fref,
556 unsigned int Fout)
557{
558 unsigned int target, div, gcd_fll;
559 int i, ratio;
560
561 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
562
563 /* Fref must be <=13.5MHz */
564 div = 1;
565 cfg->refdiv = 0;
566 while ((Fref / div) > 13500000) {
567 div *= 2;
568 cfg->refdiv++;
569
570 if (div > 8) {
571 arizona_fll_err(fll,
572 "Can't scale %dMHz in to <=13.5MHz\n",
573 Fref);
574 return -EINVAL;
575 }
576 }
577
578 /* Apply the division for our remaining calculations */
579 Fref /= div;
580
581 /* Fvco should be 90-100MHz; don't check the upper bound */
582 div = 1;
583 while (Fout * div < 90000000) {
584 div++;
585 if (div > 7) {
586 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
587 Fout);
588 return -EINVAL;
589 }
590 }
591 target = Fout * div;
592 cfg->outdiv = div;
593
594 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
595
596 /* Find an appropraite FLL_FRATIO and factor it out of the target */
597 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
598 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
599 cfg->fratio = fll_fratios[i].fratio;
600 ratio = fll_fratios[i].ratio;
601 break;
602 }
603 }
604 if (i == ARRAY_SIZE(fll_fratios)) {
605 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
606 Fref);
607 return -EINVAL;
608 }
609
610 cfg->n = target / (ratio * Fref);
611
612 if (target % Fref) {
613 gcd_fll = gcd(target, ratio * Fref);
614 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
615
616 cfg->theta = (target - (cfg->n * ratio * Fref))
617 / gcd_fll;
618 cfg->lambda = (ratio * Fref) / gcd_fll;
619 } else {
620 cfg->theta = 0;
621 cfg->lambda = 0;
622 }
623
624 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
625 cfg->n, cfg->theta, cfg->lambda);
626 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
627 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
628
629 return 0;
630
631}
632
633static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
634 struct arizona_fll_cfg *cfg, int source)
635{
636 regmap_update_bits(arizona->regmap, base + 3,
637 ARIZONA_FLL1_THETA_MASK, cfg->theta);
638 regmap_update_bits(arizona->regmap, base + 4,
639 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
640 regmap_update_bits(arizona->regmap, base + 5,
641 ARIZONA_FLL1_FRATIO_MASK,
642 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
643 regmap_update_bits(arizona->regmap, base + 6,
644 ARIZONA_FLL1_CLK_REF_DIV_MASK |
645 ARIZONA_FLL1_CLK_REF_SRC_MASK,
646 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
647 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
648
649 regmap_update_bits(arizona->regmap, base + 2,
650 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
651 ARIZONA_FLL1_CTRL_UPD | cfg->n);
652}
653
654int arizona_set_fll(struct arizona_fll *fll, int source,
655 unsigned int Fref, unsigned int Fout)
656{
657 struct arizona *arizona = fll->arizona;
658 struct arizona_fll_cfg cfg, sync;
659 unsigned int reg, val;
660 int syncsrc;
661 bool ena;
662 int ret;
663
664 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
665 if (ret != 0) {
666 arizona_fll_err(fll, "Failed to read current state: %d\n",
667 ret);
668 return ret;
669 }
670 ena = reg & ARIZONA_FLL1_ENA;
671
672 if (Fout) {
673 /* Do we have a 32kHz reference? */
674 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
675 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
676 case ARIZONA_CLK_SRC_MCLK1:
677 case ARIZONA_CLK_SRC_MCLK2:
678 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
679 break;
680 default:
681 syncsrc = -1;
682 }
683
684 if (source == syncsrc)
685 syncsrc = -1;
686
687 if (syncsrc >= 0) {
688 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
689 if (ret != 0)
690 return ret;
691
692 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
693 if (ret != 0)
694 return ret;
695 } else {
696 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
697 if (ret != 0)
698 return ret;
699 }
700 } else {
701 regmap_update_bits(arizona->regmap, fll->base + 1,
702 ARIZONA_FLL1_ENA, 0);
703 regmap_update_bits(arizona->regmap, fll->base + 0x11,
704 ARIZONA_FLL1_SYNC_ENA, 0);
705
706 if (ena)
707 pm_runtime_put_autosuspend(arizona->dev);
708
709 return 0;
710 }
711
712 regmap_update_bits(arizona->regmap, fll->base + 5,
713 ARIZONA_FLL1_OUTDIV_MASK,
714 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
715
716 if (syncsrc >= 0) {
717 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
718 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
719 } else {
720 arizona_apply_fll(arizona, fll->base, &cfg, source);
721 }
722
723 if (!ena)
724 pm_runtime_get(arizona->dev);
725
726 /* Clear any pending completions */
727 try_wait_for_completion(&fll->ok);
728
729 regmap_update_bits(arizona->regmap, fll->base + 1,
730 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
731 if (syncsrc >= 0)
732 regmap_update_bits(arizona->regmap, fll->base + 0x11,
733 ARIZONA_FLL1_SYNC_ENA,
734 ARIZONA_FLL1_SYNC_ENA);
735
736 ret = wait_for_completion_timeout(&fll->ok,
737 msecs_to_jiffies(25));
738 if (ret == 0)
739 arizona_fll_warn(fll, "Timed out waiting for lock\n");
740
741 return 0;
742}
743EXPORT_SYMBOL_GPL(arizona_set_fll);
744
745int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
746 int ok_irq, struct arizona_fll *fll)
747{
748 int ret;
749
750 init_completion(&fll->lock);
751 init_completion(&fll->ok);
752
753 fll->id = id;
754 fll->base = base;
755 fll->arizona = arizona;
756
757 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
758 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
759 "FLL%d clock OK", id);
760
761 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
762 arizona_fll_lock, fll);
763 if (ret != 0) {
764 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
765 id, ret);
766 }
767
768 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
769 arizona_fll_clock_ok, fll);
770 if (ret != 0) {
771 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
772 id, ret);
773 }
774
775 return 0;
776}
777EXPORT_SYMBOL_GPL(arizona_init_fll);
778
779MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
780MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
781MODULE_LICENSE("GPL");