blob: e3aee143487ec649dc596a215baa1c7c3fd3871a [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
Mark Brownddbce972013-02-15 17:27:22 +000013#include <linux/delay.h>
Mark Brown07ed8732012-06-18 21:08:44 +010014#include <linux/gcd.h>
15#include <linux/module.h>
16#include <linux/pm_runtime.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/tlv.h>
20
21#include <linux/mfd/arizona/core.h>
22#include <linux/mfd/arizona/registers.h>
23
24#include "arizona.h"
25
26#define ARIZONA_AIF_BCLK_CTRL 0x00
27#define ARIZONA_AIF_TX_PIN_CTRL 0x01
28#define ARIZONA_AIF_RX_PIN_CTRL 0x02
29#define ARIZONA_AIF_RATE_CTRL 0x03
30#define ARIZONA_AIF_FORMAT 0x04
31#define ARIZONA_AIF_TX_BCLK_RATE 0x05
32#define ARIZONA_AIF_RX_BCLK_RATE 0x06
33#define ARIZONA_AIF_FRAME_CTRL_1 0x07
34#define ARIZONA_AIF_FRAME_CTRL_2 0x08
35#define ARIZONA_AIF_FRAME_CTRL_3 0x09
36#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
37#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
38#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
39#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
40#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
41#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
42#define ARIZONA_AIF_FRAME_CTRL_10 0x10
43#define ARIZONA_AIF_FRAME_CTRL_11 0x11
44#define ARIZONA_AIF_FRAME_CTRL_12 0x12
45#define ARIZONA_AIF_FRAME_CTRL_13 0x13
46#define ARIZONA_AIF_FRAME_CTRL_14 0x14
47#define ARIZONA_AIF_FRAME_CTRL_15 0x15
48#define ARIZONA_AIF_FRAME_CTRL_16 0x16
49#define ARIZONA_AIF_FRAME_CTRL_17 0x17
50#define ARIZONA_AIF_FRAME_CTRL_18 0x18
51#define ARIZONA_AIF_TX_ENABLES 0x19
52#define ARIZONA_AIF_RX_ENABLES 0x1A
53#define ARIZONA_AIF_FORCE_WRITE 0x1B
54
55#define arizona_fll_err(_fll, fmt, ...) \
56 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
57#define arizona_fll_warn(_fll, fmt, ...) \
58 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
59#define arizona_fll_dbg(_fll, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000060 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010061
62#define arizona_aif_err(_dai, fmt, ...) \
63 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
64#define arizona_aif_warn(_dai, fmt, ...) \
65 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
66#define arizona_aif_dbg(_dai, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000067 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010068
69const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
70 "None",
71 "Tone Generator 1",
72 "Tone Generator 2",
73 "Haptics",
74 "AEC",
75 "Mic Mute Mixer",
76 "Noise Generator",
77 "IN1L",
78 "IN1R",
79 "IN2L",
80 "IN2R",
81 "IN3L",
82 "IN3R",
Mark Brownc9c56fd2012-07-09 19:09:01 +010083 "IN4L",
84 "IN4R",
Mark Brown07ed8732012-06-18 21:08:44 +010085 "AIF1RX1",
86 "AIF1RX2",
87 "AIF1RX3",
88 "AIF1RX4",
89 "AIF1RX5",
90 "AIF1RX6",
91 "AIF1RX7",
92 "AIF1RX8",
93 "AIF2RX1",
94 "AIF2RX2",
95 "AIF3RX1",
96 "AIF3RX2",
97 "SLIMRX1",
98 "SLIMRX2",
99 "SLIMRX3",
100 "SLIMRX4",
101 "SLIMRX5",
102 "SLIMRX6",
103 "SLIMRX7",
104 "SLIMRX8",
105 "EQ1",
106 "EQ2",
107 "EQ3",
108 "EQ4",
109 "DRC1L",
110 "DRC1R",
111 "DRC2L",
112 "DRC2R",
113 "LHPF1",
114 "LHPF2",
115 "LHPF3",
116 "LHPF4",
117 "DSP1.1",
118 "DSP1.2",
119 "DSP1.3",
120 "DSP1.4",
121 "DSP1.5",
122 "DSP1.6",
Mark Brownc922cc42012-09-26 16:43:44 +0100123 "DSP2.1",
124 "DSP2.2",
125 "DSP2.3",
126 "DSP2.4",
127 "DSP2.5",
128 "DSP2.6",
129 "DSP3.1",
130 "DSP3.2",
131 "DSP3.3",
132 "DSP3.4",
133 "DSP3.5",
134 "DSP3.6",
135 "DSP4.1",
136 "DSP4.2",
137 "DSP4.3",
138 "DSP4.4",
139 "DSP4.5",
140 "DSP4.6",
Mark Brown07ed8732012-06-18 21:08:44 +0100141 "ASRC1L",
142 "ASRC1R",
143 "ASRC2L",
144 "ASRC2R",
Mark Brown91660bd2012-12-05 20:35:24 +0900145 "ISRC1INT1",
146 "ISRC1INT2",
147 "ISRC1INT3",
148 "ISRC1INT4",
149 "ISRC1DEC1",
150 "ISRC1DEC2",
151 "ISRC1DEC3",
152 "ISRC1DEC4",
153 "ISRC2INT1",
154 "ISRC2INT2",
155 "ISRC2INT3",
156 "ISRC2INT4",
157 "ISRC2DEC1",
158 "ISRC2DEC2",
159 "ISRC2DEC3",
160 "ISRC2DEC4",
161 "ISRC3INT1",
162 "ISRC3INT2",
163 "ISRC3INT3",
164 "ISRC3INT4",
165 "ISRC3DEC1",
166 "ISRC3DEC2",
167 "ISRC3DEC3",
168 "ISRC3DEC4",
Mark Brown07ed8732012-06-18 21:08:44 +0100169};
170EXPORT_SYMBOL_GPL(arizona_mixer_texts);
171
172int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
173 0x00, /* None */
174 0x04, /* Tone */
175 0x05,
176 0x06, /* Haptics */
177 0x08, /* AEC */
178 0x0c, /* Noise mixer */
179 0x0d, /* Comfort noise */
180 0x10, /* IN1L */
181 0x11,
182 0x12,
183 0x13,
184 0x14,
185 0x15,
Mark Brownc9c56fd2012-07-09 19:09:01 +0100186 0x16,
187 0x17,
Mark Brown07ed8732012-06-18 21:08:44 +0100188 0x20, /* AIF1RX1 */
189 0x21,
190 0x22,
191 0x23,
192 0x24,
193 0x25,
194 0x26,
195 0x27,
196 0x28, /* AIF2RX1 */
197 0x29,
198 0x30, /* AIF3RX1 */
199 0x31,
200 0x38, /* SLIMRX1 */
201 0x39,
202 0x3a,
203 0x3b,
204 0x3c,
205 0x3d,
206 0x3e,
207 0x3f,
208 0x50, /* EQ1 */
209 0x51,
210 0x52,
211 0x53,
212 0x58, /* DRC1L */
213 0x59,
214 0x5a,
215 0x5b,
216 0x60, /* LHPF1 */
217 0x61,
218 0x62,
219 0x63,
220 0x68, /* DSP1.1 */
221 0x69,
222 0x6a,
223 0x6b,
224 0x6c,
225 0x6d,
Mark Brownc922cc42012-09-26 16:43:44 +0100226 0x70, /* DSP2.1 */
227 0x71,
228 0x72,
229 0x73,
230 0x74,
231 0x75,
232 0x78, /* DSP3.1 */
233 0x79,
234 0x7a,
235 0x7b,
236 0x7c,
237 0x7d,
238 0x80, /* DSP4.1 */
239 0x81,
240 0x82,
241 0x83,
242 0x84,
243 0x85,
Mark Brown07ed8732012-06-18 21:08:44 +0100244 0x90, /* ASRC1L */
245 0x91,
246 0x92,
247 0x93,
Mark Brown91660bd2012-12-05 20:35:24 +0900248 0xa0, /* ISRC1INT1 */
249 0xa1,
250 0xa2,
251 0xa3,
252 0xa4, /* ISRC1DEC1 */
253 0xa5,
254 0xa6,
255 0xa7,
256 0xa8, /* ISRC2DEC1 */
257 0xa9,
258 0xaa,
259 0xab,
260 0xac, /* ISRC2INT1 */
261 0xad,
262 0xae,
263 0xaf,
264 0xb0, /* ISRC3DEC1 */
265 0xb1,
266 0xb2,
267 0xb3,
268 0xb4, /* ISRC3INT1 */
269 0xb5,
270 0xb6,
271 0xb7,
Mark Brown07ed8732012-06-18 21:08:44 +0100272};
273EXPORT_SYMBOL_GPL(arizona_mixer_values);
274
275const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
276EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
277
Mark Browne853a002012-12-09 12:25:52 +0900278static const char *arizona_vol_ramp_text[] = {
279 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
280 "15ms/6dB", "30ms/6dB",
281};
282
283const struct soc_enum arizona_in_vd_ramp =
284 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
285 ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
286EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
287
288const struct soc_enum arizona_in_vi_ramp =
289 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
290 ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
291EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
292
293const struct soc_enum arizona_out_vd_ramp =
294 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
295 ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
296EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
297
298const struct soc_enum arizona_out_vi_ramp =
299 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
300 ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
301EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
302
Mark Brown07ed8732012-06-18 21:08:44 +0100303static const char *arizona_lhpf_mode_text[] = {
304 "Low-pass", "High-pass"
305};
306
307const struct soc_enum arizona_lhpf1_mode =
308 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
309 arizona_lhpf_mode_text);
310EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
311
312const struct soc_enum arizona_lhpf2_mode =
313 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
314 arizona_lhpf_mode_text);
315EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
316
317const struct soc_enum arizona_lhpf3_mode =
318 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
319 arizona_lhpf_mode_text);
320EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
321
322const struct soc_enum arizona_lhpf4_mode =
323 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
324 arizona_lhpf_mode_text);
325EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
326
Mark Brown845571c2012-12-18 13:47:57 +0000327static const char *arizona_ng_hold_text[] = {
328 "30ms", "120ms", "250ms", "500ms",
329};
330
331const struct soc_enum arizona_ng_hold =
332 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
333 4, arizona_ng_hold_text);
334EXPORT_SYMBOL_GPL(arizona_ng_hold);
335
Mark Brownddbce972013-02-15 17:27:22 +0000336static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
337{
338 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
339 unsigned int val;
340 int i;
341
342 if (ena)
343 val = ARIZONA_IN_VU;
344 else
345 val = 0;
346
347 for (i = 0; i < priv->num_inputs; i++)
348 snd_soc_update_bits(codec,
349 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
350 ARIZONA_IN_VU, val);
351}
352
Mark Brown07ed8732012-06-18 21:08:44 +0100353int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
354 int event)
355{
Mark Brownddbce972013-02-15 17:27:22 +0000356 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000357 unsigned int reg;
358
359 if (w->shift % 2)
360 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
361 else
362 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
363
364 switch (event) {
Mark Brownddbce972013-02-15 17:27:22 +0000365 case SND_SOC_DAPM_PRE_PMU:
366 priv->in_pending++;
367 break;
Mark Brown43cd8bf2013-02-06 16:57:29 +0000368 case SND_SOC_DAPM_POST_PMU:
369 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
Mark Brownddbce972013-02-15 17:27:22 +0000370
371 /* If this is the last input pending then allow VU */
372 priv->in_pending--;
373 if (priv->in_pending == 0) {
374 msleep(1);
375 arizona_in_set_vu(w->codec, 1);
376 }
Mark Brown43cd8bf2013-02-06 16:57:29 +0000377 break;
378 case SND_SOC_DAPM_PRE_PMD:
Mark Brownddbce972013-02-15 17:27:22 +0000379 snd_soc_update_bits(w->codec, reg,
380 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
381 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000382 break;
Mark Brownddbce972013-02-15 17:27:22 +0000383 case SND_SOC_DAPM_POST_PMD:
384 /* Disable volume updates if no inputs are enabled */
385 reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
386 if (reg == 0)
387 arizona_in_set_vu(w->codec, 0);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000388 }
389
Mark Brown07ed8732012-06-18 21:08:44 +0100390 return 0;
391}
392EXPORT_SYMBOL_GPL(arizona_in_ev);
393
394int arizona_out_ev(struct snd_soc_dapm_widget *w,
395 struct snd_kcontrol *kcontrol,
396 int event)
397{
398 return 0;
399}
400EXPORT_SYMBOL_GPL(arizona_out_ev);
401
Mark Browncbd840d2012-08-08 17:52:44 +0100402static unsigned int arizona_sysclk_48k_rates[] = {
403 6144000,
404 12288000,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000405 24576000,
Mark Browncbd840d2012-08-08 17:52:44 +0100406 49152000,
Mark Brownaeaeee12012-09-26 17:50:02 +0100407 73728000,
408 98304000,
409 147456000,
Mark Browncbd840d2012-08-08 17:52:44 +0100410};
411
412static unsigned int arizona_sysclk_44k1_rates[] = {
413 5644800,
414 11289600,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000415 22579200,
Mark Browncbd840d2012-08-08 17:52:44 +0100416 45158400,
Mark Brownaeaeee12012-09-26 17:50:02 +0100417 67737600,
418 90316800,
419 135475200,
Mark Browncbd840d2012-08-08 17:52:44 +0100420};
421
422static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
423 unsigned int freq)
424{
425 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
426 unsigned int reg;
427 unsigned int *rates;
428 int ref, div, refclk;
429
430 switch (clk) {
431 case ARIZONA_CLK_OPCLK:
432 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
433 refclk = priv->sysclk;
434 break;
435 case ARIZONA_CLK_ASYNC_OPCLK:
436 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
437 refclk = priv->asyncclk;
438 break;
439 default:
440 return -EINVAL;
441 }
442
443 if (refclk % 8000)
444 rates = arizona_sysclk_44k1_rates;
445 else
446 rates = arizona_sysclk_48k_rates;
447
448 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
449 rates[ref] <= refclk; ref++) {
450 div = 1;
451 while (rates[ref] / div >= freq && div < 32) {
452 if (rates[ref] / div == freq) {
453 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
454 freq);
455 snd_soc_update_bits(codec, reg,
456 ARIZONA_OPCLK_DIV_MASK |
457 ARIZONA_OPCLK_SEL_MASK,
458 (div <<
459 ARIZONA_OPCLK_DIV_SHIFT) |
460 ref);
461 return 0;
462 }
463 div++;
464 }
465 }
466
467 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
468 return -EINVAL;
469}
470
Mark Brown07ed8732012-06-18 21:08:44 +0100471int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
472 int source, unsigned int freq, int dir)
473{
474 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
475 struct arizona *arizona = priv->arizona;
476 char *name;
477 unsigned int reg;
478 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
479 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
480 unsigned int *clk;
481
482 switch (clk_id) {
483 case ARIZONA_CLK_SYSCLK:
484 name = "SYSCLK";
485 reg = ARIZONA_SYSTEM_CLOCK_1;
486 clk = &priv->sysclk;
487 mask |= ARIZONA_SYSCLK_FRAC;
488 break;
489 case ARIZONA_CLK_ASYNCCLK:
490 name = "ASYNCCLK";
491 reg = ARIZONA_ASYNC_CLOCK_1;
492 clk = &priv->asyncclk;
493 break;
Mark Browncbd840d2012-08-08 17:52:44 +0100494 case ARIZONA_CLK_OPCLK:
495 case ARIZONA_CLK_ASYNC_OPCLK:
496 return arizona_set_opclk(codec, clk_id, freq);
Mark Brown07ed8732012-06-18 21:08:44 +0100497 default:
498 return -EINVAL;
499 }
500
501 switch (freq) {
502 case 5644800:
503 case 6144000:
504 break;
505 case 11289600:
506 case 12288000:
507 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
508 break;
509 case 22579200:
510 case 24576000:
511 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
512 break;
513 case 45158400:
514 case 49152000:
515 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
516 break;
Mark Brown38113362012-11-26 16:01:37 +0000517 case 67737600:
518 case 73728000:
519 val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
520 break;
521 case 90316800:
522 case 98304000:
523 val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
524 break;
525 case 135475200:
526 case 147456000:
527 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
528 break;
Mark Brownf2c26d42013-01-21 16:09:36 +0900529 case 0:
530 dev_dbg(arizona->dev, "%s cleared\n", name);
531 *clk = freq;
532 return 0;
Mark Brown07ed8732012-06-18 21:08:44 +0100533 default:
534 return -EINVAL;
535 }
536
537 *clk = freq;
538
539 if (freq % 6144000)
540 val |= ARIZONA_SYSCLK_FRAC;
541
542 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
543
544 return regmap_update_bits(arizona->regmap, reg, mask, val);
545}
546EXPORT_SYMBOL_GPL(arizona_set_sysclk);
547
548static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
549{
550 struct snd_soc_codec *codec = dai->codec;
551 int lrclk, bclk, mode, base;
552
553 base = dai->driver->base;
554
555 lrclk = 0;
556 bclk = 0;
557
558 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
559 case SND_SOC_DAIFMT_DSP_A:
560 mode = 0;
561 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100562 case SND_SOC_DAIFMT_I2S:
563 mode = 2;
564 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100565 default:
566 arizona_aif_err(dai, "Unsupported DAI format %d\n",
567 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
568 return -EINVAL;
569 }
570
571 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
572 case SND_SOC_DAIFMT_CBS_CFS:
573 break;
574 case SND_SOC_DAIFMT_CBS_CFM:
575 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
576 break;
577 case SND_SOC_DAIFMT_CBM_CFS:
578 bclk |= ARIZONA_AIF1_BCLK_MSTR;
579 break;
580 case SND_SOC_DAIFMT_CBM_CFM:
581 bclk |= ARIZONA_AIF1_BCLK_MSTR;
582 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
583 break;
584 default:
585 arizona_aif_err(dai, "Unsupported master mode %d\n",
586 fmt & SND_SOC_DAIFMT_MASTER_MASK);
587 return -EINVAL;
588 }
589
590 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
591 case SND_SOC_DAIFMT_NB_NF:
592 break;
593 case SND_SOC_DAIFMT_IB_IF:
594 bclk |= ARIZONA_AIF1_BCLK_INV;
595 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
596 break;
597 case SND_SOC_DAIFMT_IB_NF:
598 bclk |= ARIZONA_AIF1_BCLK_INV;
599 break;
600 case SND_SOC_DAIFMT_NB_IF:
601 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
602 break;
603 default:
604 return -EINVAL;
605 }
606
607 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
608 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
609 bclk);
610 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
611 ARIZONA_AIF1TX_LRCLK_INV |
612 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
613 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
614 ARIZONA_AIF1RX_LRCLK_INV |
615 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
616 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
617 ARIZONA_AIF1_FMT_MASK, mode);
618
619 return 0;
620}
621
Mark Brown949e6bc2012-07-04 18:58:04 +0100622static const int arizona_48k_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100623 -1,
624 48000,
625 64000,
626 96000,
627 128000,
628 192000,
629 256000,
630 384000,
631 512000,
632 768000,
633 1024000,
634 1536000,
635 2048000,
636 3072000,
637 4096000,
638 6144000,
639 8192000,
640 12288000,
641 24576000,
642};
643
Mark Brown5b2eec32012-07-04 17:32:05 +0100644static const unsigned int arizona_48k_rates[] = {
645 12000,
646 24000,
647 48000,
648 96000,
649 192000,
650 384000,
651 768000,
652 4000,
653 8000,
654 16000,
655 32000,
656 64000,
657 128000,
658 256000,
659 512000,
660};
661
662static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
663 .count = ARRAY_SIZE(arizona_48k_rates),
664 .list = arizona_48k_rates,
665};
666
Mark Brown949e6bc2012-07-04 18:58:04 +0100667static const int arizona_44k1_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100668 -1,
669 44100,
670 58800,
671 88200,
672 117600,
673 177640,
674 235200,
675 352800,
676 470400,
677 705600,
678 940800,
679 1411200,
680 1881600,
Heather Lomond4758be32012-09-05 05:02:10 -0400681 2822400,
Mark Brown07ed8732012-06-18 21:08:44 +0100682 3763200,
683 5644800,
684 7526400,
685 11289600,
686 22579200,
687};
688
Mark Brown5b2eec32012-07-04 17:32:05 +0100689static const unsigned int arizona_44k1_rates[] = {
690 11025,
691 22050,
692 44100,
693 88200,
694 176400,
695 352800,
696 705600,
697};
698
699static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
700 .count = ARRAY_SIZE(arizona_44k1_rates),
701 .list = arizona_44k1_rates,
702};
703
Mark Brown07ed8732012-06-18 21:08:44 +0100704static int arizona_sr_vals[] = {
705 0,
706 12000,
707 24000,
708 48000,
709 96000,
710 192000,
711 384000,
712 768000,
713 0,
714 11025,
715 22050,
716 44100,
717 88200,
718 176400,
719 352800,
720 705600,
721 4000,
722 8000,
723 16000,
724 32000,
725 64000,
726 128000,
727 256000,
728 512000,
729};
730
Mark Brown5b2eec32012-07-04 17:32:05 +0100731static int arizona_startup(struct snd_pcm_substream *substream,
732 struct snd_soc_dai *dai)
733{
734 struct snd_soc_codec *codec = dai->codec;
735 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
736 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
737 const struct snd_pcm_hw_constraint_list *constraint;
738 unsigned int base_rate;
739
740 switch (dai_priv->clk) {
741 case ARIZONA_CLK_SYSCLK:
742 base_rate = priv->sysclk;
743 break;
744 case ARIZONA_CLK_ASYNCCLK:
745 base_rate = priv->asyncclk;
746 break;
747 default:
748 return 0;
749 }
750
Mark Brownf2c26d42013-01-21 16:09:36 +0900751 if (base_rate == 0)
752 return 0;
753
Mark Brown5b2eec32012-07-04 17:32:05 +0100754 if (base_rate % 8000)
755 constraint = &arizona_44k1_constraint;
756 else
757 constraint = &arizona_48k_constraint;
758
759 return snd_pcm_hw_constraint_list(substream->runtime, 0,
760 SNDRV_PCM_HW_PARAM_RATE,
761 constraint);
762}
763
Mark Brownb272efc2012-10-10 15:10:08 +0900764static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
765 struct snd_pcm_hw_params *params,
766 struct snd_soc_dai *dai)
Mark Brown07ed8732012-06-18 21:08:44 +0100767{
768 struct snd_soc_codec *codec = dai->codec;
Mark Brownc013b272012-07-04 20:05:57 +0100769 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
770 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown07ed8732012-06-18 21:08:44 +0100771 int base = dai->driver->base;
Mark Brownb272efc2012-10-10 15:10:08 +0900772 int i, sr_val;
773
774 /*
775 * We will need to be more flexible than this in future,
776 * currently we use a single sample rate for SYSCLK.
777 */
778 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
779 if (arizona_sr_vals[i] == params_rate(params))
780 break;
781 if (i == ARRAY_SIZE(arizona_sr_vals)) {
782 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
783 params_rate(params));
784 return -EINVAL;
785 }
786 sr_val = i;
787
788 switch (dai_priv->clk) {
789 case ARIZONA_CLK_SYSCLK:
790 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
791 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
792 if (base)
793 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
794 ARIZONA_AIF1_RATE_MASK, 0);
795 break;
796 case ARIZONA_CLK_ASYNCCLK:
797 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
798 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
799 if (base)
800 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
801 ARIZONA_AIF1_RATE_MASK,
802 8 << ARIZONA_AIF1_RATE_SHIFT);
803 break;
804 default:
805 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
806 return -EINVAL;
807 }
808
809 return 0;
810}
811
Mark Brown07ed8732012-06-18 21:08:44 +0100812static int arizona_hw_params(struct snd_pcm_substream *substream,
813 struct snd_pcm_hw_params *params,
814 struct snd_soc_dai *dai)
815{
816 struct snd_soc_codec *codec = dai->codec;
817 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
Mark Brownc94aa302013-01-17 16:35:14 +0900818 struct arizona *arizona = priv->arizona;
Mark Brown07ed8732012-06-18 21:08:44 +0100819 int base = dai->driver->base;
820 const int *rates;
Mark Brownb272efc2012-10-10 15:10:08 +0900821 int i, ret;
Mark Brownc94aa302013-01-17 16:35:14 +0900822 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
823 int bclk, lrclk, wl, frame, bclk_target;
Mark Brown07ed8732012-06-18 21:08:44 +0100824
825 if (params_rate(params) % 8000)
Mark Brown949e6bc2012-07-04 18:58:04 +0100826 rates = &arizona_44k1_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100827 else
Mark Brown949e6bc2012-07-04 18:58:04 +0100828 rates = &arizona_48k_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100829
Mark Brownc94aa302013-01-17 16:35:14 +0900830 bclk_target = snd_soc_params_to_bclk(params);
831 if (chan_limit && chan_limit < params_channels(params)) {
832 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
833 bclk_target /= params_channels(params);
834 bclk_target *= chan_limit;
835 }
836
Mark Brown949e6bc2012-07-04 18:58:04 +0100837 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
Mark Brownc94aa302013-01-17 16:35:14 +0900838 if (rates[i] >= bclk_target &&
Mark Brown50017652012-07-04 19:07:09 +0100839 rates[i] % params_rate(params) == 0) {
Mark Brown07ed8732012-06-18 21:08:44 +0100840 bclk = i;
841 break;
842 }
843 }
Mark Brown949e6bc2012-07-04 18:58:04 +0100844 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
Mark Brown07ed8732012-06-18 21:08:44 +0100845 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
846 params_rate(params));
847 return -EINVAL;
848 }
849
Mark Brownb59e0f82013-01-17 14:15:59 +0900850 lrclk = rates[bclk] / params_rate(params);
Mark Brown07ed8732012-06-18 21:08:44 +0100851
852 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
853 rates[bclk], rates[bclk] / lrclk);
854
855 wl = snd_pcm_format_width(params_format(params));
856 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
857
Mark Brownb272efc2012-10-10 15:10:08 +0900858 ret = arizona_hw_params_rate(substream, params, dai);
859 if (ret != 0)
860 return ret;
Mark Brownc013b272012-07-04 20:05:57 +0100861
Mark Brown07ed8732012-06-18 21:08:44 +0100862 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
863 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
864 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
865 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
866 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
867 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
868 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
869 ARIZONA_AIF1TX_WL_MASK |
870 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
871 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
872 ARIZONA_AIF1RX_WL_MASK |
873 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
874
875 return 0;
876}
877
Mark Brown410837a2012-07-05 17:26:59 +0100878static const char *arizona_dai_clk_str(int clk_id)
879{
880 switch (clk_id) {
881 case ARIZONA_CLK_SYSCLK:
882 return "SYSCLK";
883 case ARIZONA_CLK_ASYNCCLK:
884 return "ASYNCCLK";
885 default:
886 return "Unknown clock";
887 }
888}
889
Mark Brown5b2eec32012-07-04 17:32:05 +0100890static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
891 int clk_id, unsigned int freq, int dir)
892{
893 struct snd_soc_codec *codec = dai->codec;
894 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
895 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown410837a2012-07-05 17:26:59 +0100896 struct snd_soc_dapm_route routes[2];
Mark Brown5b2eec32012-07-04 17:32:05 +0100897
898 switch (clk_id) {
899 case ARIZONA_CLK_SYSCLK:
900 case ARIZONA_CLK_ASYNCCLK:
901 break;
902 default:
903 return -EINVAL;
904 }
905
Mark Brown410837a2012-07-05 17:26:59 +0100906 if (clk_id == dai_priv->clk)
907 return 0;
908
909 if (dai->active) {
Mark Brown5b2eec32012-07-04 17:32:05 +0100910 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
911 dai->id);
912 return -EBUSY;
913 }
914
Mark Brownc8d35a62012-12-07 12:49:40 +0900915 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
916 arizona_dai_clk_str(clk_id));
917
Mark Brown410837a2012-07-05 17:26:59 +0100918 memset(&routes, 0, sizeof(routes));
919 routes[0].sink = dai->driver->capture.stream_name;
920 routes[1].sink = dai->driver->playback.stream_name;
Mark Brown5b2eec32012-07-04 17:32:05 +0100921
Mark Brown410837a2012-07-05 17:26:59 +0100922 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
923 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
924 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
925
926 routes[0].source = arizona_dai_clk_str(clk_id);
927 routes[1].source = arizona_dai_clk_str(clk_id);
928 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
929
Mark Brown0c778e82012-12-06 18:22:25 +0900930 dai_priv->clk = clk_id;
931
Mark Brown410837a2012-07-05 17:26:59 +0100932 return snd_soc_dapm_sync(&codec->dapm);
Mark Brown5b2eec32012-07-04 17:32:05 +0100933}
934
Mark Brown01df2592012-12-12 16:22:08 +0900935static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
936{
937 struct snd_soc_codec *codec = dai->codec;
938 int base = dai->driver->base;
939 unsigned int reg;
940
941 if (tristate)
942 reg = ARIZONA_AIF1_TRI;
943 else
944 reg = 0;
945
946 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
947 ARIZONA_AIF1_TRI, reg);
948}
949
Mark Brown07ed8732012-06-18 21:08:44 +0100950const struct snd_soc_dai_ops arizona_dai_ops = {
Mark Brown5b2eec32012-07-04 17:32:05 +0100951 .startup = arizona_startup,
Mark Brown07ed8732012-06-18 21:08:44 +0100952 .set_fmt = arizona_set_fmt,
953 .hw_params = arizona_hw_params,
Mark Brown5b2eec32012-07-04 17:32:05 +0100954 .set_sysclk = arizona_dai_set_sysclk,
Mark Brown01df2592012-12-12 16:22:08 +0900955 .set_tristate = arizona_set_tristate,
Mark Brown07ed8732012-06-18 21:08:44 +0100956};
Mark Browna8379872012-07-09 12:16:41 +0100957EXPORT_SYMBOL_GPL(arizona_dai_ops);
Mark Brown07ed8732012-06-18 21:08:44 +0100958
Mark Brown5b2eec32012-07-04 17:32:05 +0100959int arizona_init_dai(struct arizona_priv *priv, int id)
960{
961 struct arizona_dai_priv *dai_priv = &priv->dai[id];
962
963 dai_priv->clk = ARIZONA_CLK_SYSCLK;
964
965 return 0;
966}
967EXPORT_SYMBOL_GPL(arizona_init_dai);
968
Mark Brown07ed8732012-06-18 21:08:44 +0100969static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
970{
971 struct arizona_fll *fll = data;
972
973 arizona_fll_dbg(fll, "clock OK\n");
974
975 complete(&fll->ok);
976
977 return IRQ_HANDLED;
978}
979
980static struct {
981 unsigned int min;
982 unsigned int max;
983 u16 fratio;
984 int ratio;
985} fll_fratios[] = {
986 { 0, 64000, 4, 16 },
987 { 64000, 128000, 3, 8 },
988 { 128000, 256000, 2, 4 },
989 { 256000, 1000000, 1, 2 },
990 { 1000000, 13500000, 0, 1 },
991};
992
993struct arizona_fll_cfg {
994 int n;
995 int theta;
996 int lambda;
997 int refdiv;
998 int outdiv;
999 int fratio;
1000};
1001
1002static int arizona_calc_fll(struct arizona_fll *fll,
1003 struct arizona_fll_cfg *cfg,
1004 unsigned int Fref,
1005 unsigned int Fout)
1006{
1007 unsigned int target, div, gcd_fll;
1008 int i, ratio;
1009
1010 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
1011
1012 /* Fref must be <=13.5MHz */
1013 div = 1;
1014 cfg->refdiv = 0;
1015 while ((Fref / div) > 13500000) {
1016 div *= 2;
1017 cfg->refdiv++;
1018
1019 if (div > 8) {
1020 arizona_fll_err(fll,
1021 "Can't scale %dMHz in to <=13.5MHz\n",
1022 Fref);
1023 return -EINVAL;
1024 }
1025 }
1026
1027 /* Apply the division for our remaining calculations */
1028 Fref /= div;
1029
Mark Brown2b4d39f2012-07-10 17:03:46 +01001030 /* Fvco should be over the targt; don't check the upper bound */
Mark Brown07ed8732012-06-18 21:08:44 +01001031 div = 1;
Mark Brown2b4d39f2012-07-10 17:03:46 +01001032 while (Fout * div < 90000000 * fll->vco_mult) {
Mark Brown07ed8732012-06-18 21:08:44 +01001033 div++;
1034 if (div > 7) {
1035 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1036 Fout);
1037 return -EINVAL;
1038 }
1039 }
Mark Brown2b4d39f2012-07-10 17:03:46 +01001040 target = Fout * div / fll->vco_mult;
Mark Brown07ed8732012-06-18 21:08:44 +01001041 cfg->outdiv = div;
1042
1043 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1044
1045 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1046 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1047 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1048 cfg->fratio = fll_fratios[i].fratio;
1049 ratio = fll_fratios[i].ratio;
1050 break;
1051 }
1052 }
1053 if (i == ARRAY_SIZE(fll_fratios)) {
1054 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1055 Fref);
1056 return -EINVAL;
1057 }
1058
1059 cfg->n = target / (ratio * Fref);
1060
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001061 if (target % (ratio * Fref)) {
Mark Brown07ed8732012-06-18 21:08:44 +01001062 gcd_fll = gcd(target, ratio * Fref);
1063 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1064
1065 cfg->theta = (target - (cfg->n * ratio * Fref))
1066 / gcd_fll;
1067 cfg->lambda = (ratio * Fref) / gcd_fll;
1068 } else {
1069 cfg->theta = 0;
1070 cfg->lambda = 0;
1071 }
1072
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001073 /* Round down to 16bit range with cost of accuracy lost.
1074 * Denominator must be bigger than numerator so we only
1075 * take care of it.
1076 */
1077 while (cfg->lambda >= (1 << 16)) {
1078 cfg->theta >>= 1;
1079 cfg->lambda >>= 1;
1080 }
1081
Mark Brown07ed8732012-06-18 21:08:44 +01001082 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1083 cfg->n, cfg->theta, cfg->lambda);
1084 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1085 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
1086
1087 return 0;
1088
1089}
1090
1091static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
1092 struct arizona_fll_cfg *cfg, int source)
1093{
1094 regmap_update_bits(arizona->regmap, base + 3,
1095 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1096 regmap_update_bits(arizona->regmap, base + 4,
1097 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1098 regmap_update_bits(arizona->regmap, base + 5,
1099 ARIZONA_FLL1_FRATIO_MASK,
1100 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1101 regmap_update_bits(arizona->regmap, base + 6,
1102 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1103 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1104 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1105 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1106
1107 regmap_update_bits(arizona->regmap, base + 2,
1108 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1109 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1110}
1111
Charles Keepaxd122d6c2013-02-20 17:28:36 +00001112static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1113{
1114 struct arizona *arizona = fll->arizona;
1115 unsigned int reg;
1116 int ret;
1117
1118 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1119 if (ret != 0) {
1120 arizona_fll_err(fll, "Failed to read current state: %d\n",
1121 ret);
1122 return ret;
1123 }
1124
1125 return reg & ARIZONA_FLL1_ENA;
1126}
1127
Charles Keepax35722812013-02-20 17:28:38 +00001128static void arizona_enable_fll(struct arizona_fll *fll,
1129 struct arizona_fll_cfg *ref,
1130 struct arizona_fll_cfg *sync)
1131{
1132 struct arizona *arizona = fll->arizona;
1133 int ret;
1134
Mark Brownff680a12013-03-04 16:00:19 +08001135 /*
1136 * If we have both REFCLK and SYNCCLK then enable both,
1137 * otherwise apply the SYNCCLK settings to REFCLK.
1138 */
1139 if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
1140 regmap_update_bits(arizona->regmap, fll->base + 5,
1141 ARIZONA_FLL1_OUTDIV_MASK,
1142 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
Charles Keepax35722812013-02-20 17:28:38 +00001143
Mark Brownff680a12013-03-04 16:00:19 +08001144 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src);
1145 if (fll->sync_src >= 0)
1146 arizona_apply_fll(arizona, fll->base + 0x10, sync,
1147 fll->sync_src);
1148 } else if (fll->sync_src >= 0) {
1149 regmap_update_bits(arizona->regmap, fll->base + 5,
1150 ARIZONA_FLL1_OUTDIV_MASK,
1151 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1152
1153 arizona_apply_fll(arizona, fll->base, sync,
Charles Keepax35722812013-02-20 17:28:38 +00001154 fll->sync_src);
Mark Brownff680a12013-03-04 16:00:19 +08001155 } else {
1156 arizona_fll_err(fll, "No clocks provided\n");
1157 return;
1158 }
Charles Keepax35722812013-02-20 17:28:38 +00001159
Mark Brown576411be2013-03-05 12:07:16 +08001160 /*
1161 * Increase the bandwidth if we're not using a low frequency
1162 * sync source.
1163 */
1164 if (fll->sync_src >= 0 && fll->sync_freq > 100000)
1165 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1166 ARIZONA_FLL1_SYNC_BW, 0);
1167 else
1168 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1169 ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
1170
Charles Keepax35722812013-02-20 17:28:38 +00001171 if (!arizona_is_enabled_fll(fll))
1172 pm_runtime_get(arizona->dev);
1173
1174 /* Clear any pending completions */
1175 try_wait_for_completion(&fll->ok);
1176
1177 regmap_update_bits(arizona->regmap, fll->base + 1,
1178 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
Mark Brownff680a12013-03-04 16:00:19 +08001179 if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
1180 fll->ref_src != fll->sync_src)
Charles Keepax35722812013-02-20 17:28:38 +00001181 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1182 ARIZONA_FLL1_SYNC_ENA,
1183 ARIZONA_FLL1_SYNC_ENA);
1184
1185 ret = wait_for_completion_timeout(&fll->ok,
1186 msecs_to_jiffies(250));
1187 if (ret == 0)
1188 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1189}
1190
Charles Keepax76040542013-02-20 17:28:37 +00001191static void arizona_disable_fll(struct arizona_fll *fll)
1192{
1193 struct arizona *arizona = fll->arizona;
1194 bool change;
1195
1196 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1197 ARIZONA_FLL1_ENA, 0, &change);
1198 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1199 ARIZONA_FLL1_SYNC_ENA, 0);
1200
1201 if (change)
1202 pm_runtime_put_autosuspend(arizona->dev);
1203}
1204
Charles Keepaxee929a92013-02-20 17:28:40 +00001205int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1206 unsigned int Fref, unsigned int Fout)
1207{
1208 struct arizona_fll_cfg ref, sync;
1209 int ret;
1210
Charles Keepax1c5617f2013-02-22 17:10:37 +00001211 if (fll->ref_src == source && fll->ref_freq == Fref)
Charles Keepaxee929a92013-02-20 17:28:40 +00001212 return 0;
1213
Charles Keepax1c5617f2013-02-22 17:10:37 +00001214 if (fll->fout) {
1215 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001216 if (ret != 0)
1217 return ret;
1218
1219 if (fll->sync_src >= 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001220 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1221 fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001222 if (ret != 0)
1223 return ret;
1224 }
1225 }
1226
1227 fll->ref_src = source;
1228 fll->ref_freq = Fref;
Charles Keepaxee929a92013-02-20 17:28:40 +00001229
Charles Keepax1c5617f2013-02-22 17:10:37 +00001230 if (fll->fout) {
Charles Keepaxee929a92013-02-20 17:28:40 +00001231 arizona_enable_fll(fll, &ref, &sync);
Charles Keepaxee929a92013-02-20 17:28:40 +00001232 }
1233
1234 return 0;
1235}
1236EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1237
Mark Brown07ed8732012-06-18 21:08:44 +01001238int arizona_set_fll(struct arizona_fll *fll, int source,
1239 unsigned int Fref, unsigned int Fout)
1240{
Charles Keepax9e359c62013-02-20 17:28:35 +00001241 struct arizona_fll_cfg ref, sync;
Mark Brown07ed8732012-06-18 21:08:44 +01001242 int ret;
1243
Mark Brownff680a12013-03-04 16:00:19 +08001244 if (fll->sync_src == source &&
1245 fll->sync_freq == Fref && fll->fout == Fout)
1246 return 0;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001247
Mark Brownff680a12013-03-04 16:00:19 +08001248 if (Fout) {
1249 if (fll->ref_src >= 0) {
1250 ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
1251 Fout);
Charles Keepax9e359c62013-02-20 17:28:35 +00001252 if (ret != 0)
1253 return ret;
1254 }
1255
Mark Brownff680a12013-03-04 16:00:19 +08001256 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1257 if (ret != 0)
1258 return ret;
Charles Keepax9e359c62013-02-20 17:28:35 +00001259 }
Mark Brownff680a12013-03-04 16:00:19 +08001260
1261 fll->sync_src = source;
1262 fll->sync_freq = Fref;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001263 fll->fout = Fout;
Charles Keepax9e359c62013-02-20 17:28:35 +00001264
Mark Brown07ed8732012-06-18 21:08:44 +01001265 if (Fout) {
Charles Keepax35722812013-02-20 17:28:38 +00001266 arizona_enable_fll(fll, &ref, &sync);
Mark Brown07ed8732012-06-18 21:08:44 +01001267 } else {
Charles Keepax76040542013-02-20 17:28:37 +00001268 arizona_disable_fll(fll);
Mark Brown07ed8732012-06-18 21:08:44 +01001269 }
1270
Mark Brown07ed8732012-06-18 21:08:44 +01001271 return 0;
1272}
1273EXPORT_SYMBOL_GPL(arizona_set_fll);
1274
1275int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1276 int ok_irq, struct arizona_fll *fll)
1277{
1278 int ret;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001279 unsigned int val;
Mark Brown07ed8732012-06-18 21:08:44 +01001280
Mark Brown07ed8732012-06-18 21:08:44 +01001281 init_completion(&fll->ok);
1282
1283 fll->id = id;
1284 fll->base = base;
1285 fll->arizona = arizona;
Charles Keepaxf3f11632013-02-20 17:28:41 +00001286 fll->sync_src = ARIZONA_FLL_SRC_NONE;
Mark Brown07ed8732012-06-18 21:08:44 +01001287
Charles Keepax19b34bd2013-02-20 17:28:34 +00001288 /* Configure default refclk to 32kHz if we have one */
1289 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1290 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1291 case ARIZONA_CLK_SRC_MCLK1:
1292 case ARIZONA_CLK_SRC_MCLK2:
1293 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1294 break;
1295 default:
Charles Keepaxf3f11632013-02-20 17:28:41 +00001296 fll->ref_src = ARIZONA_FLL_SRC_NONE;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001297 }
1298 fll->ref_freq = 32768;
1299
Mark Brown07ed8732012-06-18 21:08:44 +01001300 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1301 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1302 "FLL%d clock OK", id);
1303
Mark Brown07ed8732012-06-18 21:08:44 +01001304 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1305 arizona_fll_clock_ok, fll);
1306 if (ret != 0) {
1307 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1308 id, ret);
1309 }
1310
Charles Keepaxe31c1942013-01-07 16:41:45 +00001311 regmap_update_bits(arizona->regmap, fll->base + 1,
1312 ARIZONA_FLL1_FREERUN, 0);
1313
Mark Brown07ed8732012-06-18 21:08:44 +01001314 return 0;
1315}
1316EXPORT_SYMBOL_GPL(arizona_init_fll);
1317
Mark Brownbc9ab6d2013-01-04 19:31:00 +00001318/**
1319 * arizona_set_output_mode - Set the mode of the specified output
1320 *
1321 * @codec: Device to configure
1322 * @output: Output number
1323 * @diff: True to set the output to differential mode
1324 *
1325 * Some systems use external analogue switches to connect more
1326 * analogue devices to the CODEC than are supported by the device. In
1327 * some systems this requires changing the switched output from single
1328 * ended to differential mode dynamically at runtime, an operation
1329 * supported using this function.
1330 *
1331 * Most systems have a single static configuration and should use
1332 * platform data instead.
1333 */
1334int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1335{
1336 unsigned int reg, val;
1337
1338 if (output < 1 || output > 6)
1339 return -EINVAL;
1340
1341 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1342
1343 if (diff)
1344 val = ARIZONA_OUT1_MONO;
1345 else
1346 val = 0;
1347
1348 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1349}
1350EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1351
Mark Brown07ed8732012-06-18 21:08:44 +01001352MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1353MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1354MODULE_LICENSE("GPL");