blob: 2b0803ec82347b560f8aed278ab5a6e557b3d3bf [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:
Mark Brown3f341f72013-03-08 15:22:29 +0800507 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100508 break;
509 case 22579200:
510 case 24576000:
Mark Brown3f341f72013-03-08 15:22:29 +0800511 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100512 break;
513 case 45158400:
514 case 49152000:
Mark Brown3f341f72013-03-08 15:22:29 +0800515 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100516 break;
Mark Brown38113362012-11-26 16:01:37 +0000517 case 67737600:
518 case 73728000:
Mark Brown3f341f72013-03-08 15:22:29 +0800519 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000520 break;
521 case 90316800:
522 case 98304000:
Mark Brown3f341f72013-03-08 15:22:29 +0800523 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000524 break;
525 case 135475200:
526 case 147456000:
Mark Brown3f341f72013-03-08 15:22:29 +0800527 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000528 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 Brown76bf9692013-03-05 14:17:47 +0800821 int i, ret, val;
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 Brown76bf9692013-03-05 14:17:47 +0800837 /* Force stereo for I2S mode */
838 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
839 if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
840 arizona_aif_dbg(dai, "Forcing stereo mode\n");
841 bclk_target *= 2;
842 }
843
Mark Brown949e6bc2012-07-04 18:58:04 +0100844 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
Mark Brownc94aa302013-01-17 16:35:14 +0900845 if (rates[i] >= bclk_target &&
Mark Brown50017652012-07-04 19:07:09 +0100846 rates[i] % params_rate(params) == 0) {
Mark Brown07ed8732012-06-18 21:08:44 +0100847 bclk = i;
848 break;
849 }
850 }
Mark Brown949e6bc2012-07-04 18:58:04 +0100851 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
Mark Brown07ed8732012-06-18 21:08:44 +0100852 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
853 params_rate(params));
854 return -EINVAL;
855 }
856
Mark Brownb59e0f82013-01-17 14:15:59 +0900857 lrclk = rates[bclk] / params_rate(params);
Mark Brown07ed8732012-06-18 21:08:44 +0100858
859 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
860 rates[bclk], rates[bclk] / lrclk);
861
862 wl = snd_pcm_format_width(params_format(params));
863 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
864
Mark Brownb272efc2012-10-10 15:10:08 +0900865 ret = arizona_hw_params_rate(substream, params, dai);
866 if (ret != 0)
867 return ret;
Mark Brownc013b272012-07-04 20:05:57 +0100868
Mark Brown07ed8732012-06-18 21:08:44 +0100869 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
870 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
871 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
872 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
873 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
874 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
875 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
876 ARIZONA_AIF1TX_WL_MASK |
877 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
878 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
879 ARIZONA_AIF1RX_WL_MASK |
880 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
881
882 return 0;
883}
884
Mark Brown410837a2012-07-05 17:26:59 +0100885static const char *arizona_dai_clk_str(int clk_id)
886{
887 switch (clk_id) {
888 case ARIZONA_CLK_SYSCLK:
889 return "SYSCLK";
890 case ARIZONA_CLK_ASYNCCLK:
891 return "ASYNCCLK";
892 default:
893 return "Unknown clock";
894 }
895}
896
Mark Brown5b2eec32012-07-04 17:32:05 +0100897static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
898 int clk_id, unsigned int freq, int dir)
899{
900 struct snd_soc_codec *codec = dai->codec;
901 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
902 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown410837a2012-07-05 17:26:59 +0100903 struct snd_soc_dapm_route routes[2];
Mark Brown5b2eec32012-07-04 17:32:05 +0100904
905 switch (clk_id) {
906 case ARIZONA_CLK_SYSCLK:
907 case ARIZONA_CLK_ASYNCCLK:
908 break;
909 default:
910 return -EINVAL;
911 }
912
Mark Brown410837a2012-07-05 17:26:59 +0100913 if (clk_id == dai_priv->clk)
914 return 0;
915
916 if (dai->active) {
Mark Brown5b2eec32012-07-04 17:32:05 +0100917 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
918 dai->id);
919 return -EBUSY;
920 }
921
Mark Brownc8d35a62012-12-07 12:49:40 +0900922 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
923 arizona_dai_clk_str(clk_id));
924
Mark Brown410837a2012-07-05 17:26:59 +0100925 memset(&routes, 0, sizeof(routes));
926 routes[0].sink = dai->driver->capture.stream_name;
927 routes[1].sink = dai->driver->playback.stream_name;
Mark Brown5b2eec32012-07-04 17:32:05 +0100928
Mark Brown410837a2012-07-05 17:26:59 +0100929 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
930 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
931 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
932
933 routes[0].source = arizona_dai_clk_str(clk_id);
934 routes[1].source = arizona_dai_clk_str(clk_id);
935 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
936
Mark Brown0c778e82012-12-06 18:22:25 +0900937 dai_priv->clk = clk_id;
938
Mark Brown410837a2012-07-05 17:26:59 +0100939 return snd_soc_dapm_sync(&codec->dapm);
Mark Brown5b2eec32012-07-04 17:32:05 +0100940}
941
Mark Brown01df2592012-12-12 16:22:08 +0900942static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
943{
944 struct snd_soc_codec *codec = dai->codec;
945 int base = dai->driver->base;
946 unsigned int reg;
947
948 if (tristate)
949 reg = ARIZONA_AIF1_TRI;
950 else
951 reg = 0;
952
953 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
954 ARIZONA_AIF1_TRI, reg);
955}
956
Mark Brown07ed8732012-06-18 21:08:44 +0100957const struct snd_soc_dai_ops arizona_dai_ops = {
Mark Brown5b2eec32012-07-04 17:32:05 +0100958 .startup = arizona_startup,
Mark Brown07ed8732012-06-18 21:08:44 +0100959 .set_fmt = arizona_set_fmt,
960 .hw_params = arizona_hw_params,
Mark Brown5b2eec32012-07-04 17:32:05 +0100961 .set_sysclk = arizona_dai_set_sysclk,
Mark Brown01df2592012-12-12 16:22:08 +0900962 .set_tristate = arizona_set_tristate,
Mark Brown07ed8732012-06-18 21:08:44 +0100963};
Mark Browna8379872012-07-09 12:16:41 +0100964EXPORT_SYMBOL_GPL(arizona_dai_ops);
Mark Brown07ed8732012-06-18 21:08:44 +0100965
Mark Brown5b2eec32012-07-04 17:32:05 +0100966int arizona_init_dai(struct arizona_priv *priv, int id)
967{
968 struct arizona_dai_priv *dai_priv = &priv->dai[id];
969
970 dai_priv->clk = ARIZONA_CLK_SYSCLK;
971
972 return 0;
973}
974EXPORT_SYMBOL_GPL(arizona_init_dai);
975
Mark Brown07ed8732012-06-18 21:08:44 +0100976static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
977{
978 struct arizona_fll *fll = data;
979
980 arizona_fll_dbg(fll, "clock OK\n");
981
982 complete(&fll->ok);
983
984 return IRQ_HANDLED;
985}
986
987static struct {
988 unsigned int min;
989 unsigned int max;
990 u16 fratio;
991 int ratio;
992} fll_fratios[] = {
993 { 0, 64000, 4, 16 },
994 { 64000, 128000, 3, 8 },
995 { 128000, 256000, 2, 4 },
996 { 256000, 1000000, 1, 2 },
997 { 1000000, 13500000, 0, 1 },
998};
999
Mark Brown8f113d72013-03-05 12:08:57 +08001000static struct {
1001 unsigned int min;
1002 unsigned int max;
1003 u16 gain;
1004} fll_gains[] = {
1005 { 0, 256000, 0 },
1006 { 256000, 1000000, 2 },
1007 { 1000000, 13500000, 4 },
1008};
1009
Mark Brown07ed8732012-06-18 21:08:44 +01001010struct arizona_fll_cfg {
1011 int n;
1012 int theta;
1013 int lambda;
1014 int refdiv;
1015 int outdiv;
1016 int fratio;
Mark Brown8f113d72013-03-05 12:08:57 +08001017 int gain;
Mark Brown07ed8732012-06-18 21:08:44 +01001018};
1019
1020static int arizona_calc_fll(struct arizona_fll *fll,
1021 struct arizona_fll_cfg *cfg,
1022 unsigned int Fref,
1023 unsigned int Fout)
1024{
1025 unsigned int target, div, gcd_fll;
1026 int i, ratio;
1027
1028 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
1029
1030 /* Fref must be <=13.5MHz */
1031 div = 1;
1032 cfg->refdiv = 0;
1033 while ((Fref / div) > 13500000) {
1034 div *= 2;
1035 cfg->refdiv++;
1036
1037 if (div > 8) {
1038 arizona_fll_err(fll,
1039 "Can't scale %dMHz in to <=13.5MHz\n",
1040 Fref);
1041 return -EINVAL;
1042 }
1043 }
1044
1045 /* Apply the division for our remaining calculations */
1046 Fref /= div;
1047
Mark Brown2b4d39f2012-07-10 17:03:46 +01001048 /* Fvco should be over the targt; don't check the upper bound */
Mark Brown07ed8732012-06-18 21:08:44 +01001049 div = 1;
Mark Brown2b4d39f2012-07-10 17:03:46 +01001050 while (Fout * div < 90000000 * fll->vco_mult) {
Mark Brown07ed8732012-06-18 21:08:44 +01001051 div++;
1052 if (div > 7) {
1053 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1054 Fout);
1055 return -EINVAL;
1056 }
1057 }
Mark Brown2b4d39f2012-07-10 17:03:46 +01001058 target = Fout * div / fll->vco_mult;
Mark Brown07ed8732012-06-18 21:08:44 +01001059 cfg->outdiv = div;
1060
1061 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1062
1063 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1064 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1065 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1066 cfg->fratio = fll_fratios[i].fratio;
1067 ratio = fll_fratios[i].ratio;
1068 break;
1069 }
1070 }
1071 if (i == ARRAY_SIZE(fll_fratios)) {
1072 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1073 Fref);
1074 return -EINVAL;
1075 }
1076
Mark Brown8f113d72013-03-05 12:08:57 +08001077 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
1078 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
1079 cfg->gain = fll_gains[i].gain;
1080 break;
1081 }
1082 }
1083 if (i == ARRAY_SIZE(fll_gains)) {
1084 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
1085 Fref);
1086 return -EINVAL;
1087 }
1088
Mark Brown07ed8732012-06-18 21:08:44 +01001089 cfg->n = target / (ratio * Fref);
1090
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001091 if (target % (ratio * Fref)) {
Mark Brown07ed8732012-06-18 21:08:44 +01001092 gcd_fll = gcd(target, ratio * Fref);
1093 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1094
1095 cfg->theta = (target - (cfg->n * ratio * Fref))
1096 / gcd_fll;
1097 cfg->lambda = (ratio * Fref) / gcd_fll;
1098 } else {
1099 cfg->theta = 0;
1100 cfg->lambda = 0;
1101 }
1102
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001103 /* Round down to 16bit range with cost of accuracy lost.
1104 * Denominator must be bigger than numerator so we only
1105 * take care of it.
1106 */
1107 while (cfg->lambda >= (1 << 16)) {
1108 cfg->theta >>= 1;
1109 cfg->lambda >>= 1;
1110 }
1111
Mark Brown07ed8732012-06-18 21:08:44 +01001112 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1113 cfg->n, cfg->theta, cfg->lambda);
1114 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1115 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
Mark Brown8f113d72013-03-05 12:08:57 +08001116 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
Mark Brown07ed8732012-06-18 21:08:44 +01001117
1118 return 0;
1119
1120}
1121
1122static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
Mark Brown8f113d72013-03-05 12:08:57 +08001123 struct arizona_fll_cfg *cfg, int source,
1124 bool sync)
Mark Brown07ed8732012-06-18 21:08:44 +01001125{
1126 regmap_update_bits(arizona->regmap, base + 3,
1127 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1128 regmap_update_bits(arizona->regmap, base + 4,
1129 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1130 regmap_update_bits(arizona->regmap, base + 5,
1131 ARIZONA_FLL1_FRATIO_MASK,
1132 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1133 regmap_update_bits(arizona->regmap, base + 6,
1134 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1135 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1136 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1137 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1138
Mark Brown8f113d72013-03-05 12:08:57 +08001139 if (sync)
1140 regmap_update_bits(arizona->regmap, base + 0x7,
1141 ARIZONA_FLL1_GAIN_MASK,
1142 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1143 else
1144 regmap_update_bits(arizona->regmap, base + 0x9,
1145 ARIZONA_FLL1_GAIN_MASK,
1146 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1147
Mark Brown07ed8732012-06-18 21:08:44 +01001148 regmap_update_bits(arizona->regmap, base + 2,
1149 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1150 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1151}
1152
Charles Keepaxd122d6c2013-02-20 17:28:36 +00001153static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1154{
1155 struct arizona *arizona = fll->arizona;
1156 unsigned int reg;
1157 int ret;
1158
1159 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1160 if (ret != 0) {
1161 arizona_fll_err(fll, "Failed to read current state: %d\n",
1162 ret);
1163 return ret;
1164 }
1165
1166 return reg & ARIZONA_FLL1_ENA;
1167}
1168
Charles Keepax35722812013-02-20 17:28:38 +00001169static void arizona_enable_fll(struct arizona_fll *fll,
1170 struct arizona_fll_cfg *ref,
1171 struct arizona_fll_cfg *sync)
1172{
1173 struct arizona *arizona = fll->arizona;
1174 int ret;
1175
Mark Brownff680a12013-03-04 16:00:19 +08001176 /*
1177 * If we have both REFCLK and SYNCCLK then enable both,
1178 * otherwise apply the SYNCCLK settings to REFCLK.
1179 */
1180 if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
1181 regmap_update_bits(arizona->regmap, fll->base + 5,
1182 ARIZONA_FLL1_OUTDIV_MASK,
1183 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
Charles Keepax35722812013-02-20 17:28:38 +00001184
Mark Brown8f113d72013-03-05 12:08:57 +08001185 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
1186 false);
Mark Brownff680a12013-03-04 16:00:19 +08001187 if (fll->sync_src >= 0)
1188 arizona_apply_fll(arizona, fll->base + 0x10, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001189 fll->sync_src, true);
Mark Brownff680a12013-03-04 16:00:19 +08001190 } else if (fll->sync_src >= 0) {
1191 regmap_update_bits(arizona->regmap, fll->base + 5,
1192 ARIZONA_FLL1_OUTDIV_MASK,
1193 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1194
1195 arizona_apply_fll(arizona, fll->base, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001196 fll->sync_src, false);
Mark Browneca2e8e2013-03-06 00:09:59 +08001197
1198 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1199 ARIZONA_FLL1_SYNC_ENA, 0);
Mark Brownff680a12013-03-04 16:00:19 +08001200 } else {
1201 arizona_fll_err(fll, "No clocks provided\n");
1202 return;
1203 }
Charles Keepax35722812013-02-20 17:28:38 +00001204
Mark Brown576411be2013-03-05 12:07:16 +08001205 /*
1206 * Increase the bandwidth if we're not using a low frequency
1207 * sync source.
1208 */
1209 if (fll->sync_src >= 0 && fll->sync_freq > 100000)
1210 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1211 ARIZONA_FLL1_SYNC_BW, 0);
1212 else
1213 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1214 ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
1215
Charles Keepax35722812013-02-20 17:28:38 +00001216 if (!arizona_is_enabled_fll(fll))
1217 pm_runtime_get(arizona->dev);
1218
1219 /* Clear any pending completions */
1220 try_wait_for_completion(&fll->ok);
1221
1222 regmap_update_bits(arizona->regmap, fll->base + 1,
1223 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
Mark Brownff680a12013-03-04 16:00:19 +08001224 if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
1225 fll->ref_src != fll->sync_src)
Charles Keepax35722812013-02-20 17:28:38 +00001226 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1227 ARIZONA_FLL1_SYNC_ENA,
1228 ARIZONA_FLL1_SYNC_ENA);
1229
1230 ret = wait_for_completion_timeout(&fll->ok,
1231 msecs_to_jiffies(250));
1232 if (ret == 0)
1233 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1234}
1235
Charles Keepax76040542013-02-20 17:28:37 +00001236static void arizona_disable_fll(struct arizona_fll *fll)
1237{
1238 struct arizona *arizona = fll->arizona;
1239 bool change;
1240
1241 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1242 ARIZONA_FLL1_ENA, 0, &change);
1243 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1244 ARIZONA_FLL1_SYNC_ENA, 0);
1245
1246 if (change)
1247 pm_runtime_put_autosuspend(arizona->dev);
1248}
1249
Charles Keepaxee929a92013-02-20 17:28:40 +00001250int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1251 unsigned int Fref, unsigned int Fout)
1252{
1253 struct arizona_fll_cfg ref, sync;
1254 int ret;
1255
Charles Keepax1c5617f2013-02-22 17:10:37 +00001256 if (fll->ref_src == source && fll->ref_freq == Fref)
Charles Keepaxee929a92013-02-20 17:28:40 +00001257 return 0;
1258
Mark Brown86cd6842013-03-07 16:14:04 +08001259 if (fll->fout && Fref > 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001260 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001261 if (ret != 0)
1262 return ret;
1263
1264 if (fll->sync_src >= 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001265 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1266 fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001267 if (ret != 0)
1268 return ret;
1269 }
1270 }
1271
1272 fll->ref_src = source;
1273 fll->ref_freq = Fref;
Charles Keepaxee929a92013-02-20 17:28:40 +00001274
Mark Brown86cd6842013-03-07 16:14:04 +08001275 if (fll->fout && Fref > 0) {
Charles Keepaxee929a92013-02-20 17:28:40 +00001276 arizona_enable_fll(fll, &ref, &sync);
Charles Keepaxee929a92013-02-20 17:28:40 +00001277 }
1278
1279 return 0;
1280}
1281EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1282
Mark Brown07ed8732012-06-18 21:08:44 +01001283int arizona_set_fll(struct arizona_fll *fll, int source,
1284 unsigned int Fref, unsigned int Fout)
1285{
Charles Keepax9e359c62013-02-20 17:28:35 +00001286 struct arizona_fll_cfg ref, sync;
Mark Brown07ed8732012-06-18 21:08:44 +01001287 int ret;
1288
Mark Brownff680a12013-03-04 16:00:19 +08001289 if (fll->sync_src == source &&
1290 fll->sync_freq == Fref && fll->fout == Fout)
1291 return 0;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001292
Mark Brownff680a12013-03-04 16:00:19 +08001293 if (Fout) {
1294 if (fll->ref_src >= 0) {
1295 ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
1296 Fout);
Charles Keepax9e359c62013-02-20 17:28:35 +00001297 if (ret != 0)
1298 return ret;
1299 }
1300
Mark Brownff680a12013-03-04 16:00:19 +08001301 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1302 if (ret != 0)
1303 return ret;
Charles Keepax9e359c62013-02-20 17:28:35 +00001304 }
Mark Brownff680a12013-03-04 16:00:19 +08001305
1306 fll->sync_src = source;
1307 fll->sync_freq = Fref;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001308 fll->fout = Fout;
Charles Keepax9e359c62013-02-20 17:28:35 +00001309
Mark Brown07ed8732012-06-18 21:08:44 +01001310 if (Fout) {
Charles Keepax35722812013-02-20 17:28:38 +00001311 arizona_enable_fll(fll, &ref, &sync);
Mark Brown07ed8732012-06-18 21:08:44 +01001312 } else {
Charles Keepax76040542013-02-20 17:28:37 +00001313 arizona_disable_fll(fll);
Mark Brown07ed8732012-06-18 21:08:44 +01001314 }
1315
Mark Brown07ed8732012-06-18 21:08:44 +01001316 return 0;
1317}
1318EXPORT_SYMBOL_GPL(arizona_set_fll);
1319
1320int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1321 int ok_irq, struct arizona_fll *fll)
1322{
1323 int ret;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001324 unsigned int val;
Mark Brown07ed8732012-06-18 21:08:44 +01001325
Mark Brown07ed8732012-06-18 21:08:44 +01001326 init_completion(&fll->ok);
1327
1328 fll->id = id;
1329 fll->base = base;
1330 fll->arizona = arizona;
Charles Keepaxf3f11632013-02-20 17:28:41 +00001331 fll->sync_src = ARIZONA_FLL_SRC_NONE;
Mark Brown07ed8732012-06-18 21:08:44 +01001332
Charles Keepax19b34bd2013-02-20 17:28:34 +00001333 /* Configure default refclk to 32kHz if we have one */
1334 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1335 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1336 case ARIZONA_CLK_SRC_MCLK1:
1337 case ARIZONA_CLK_SRC_MCLK2:
1338 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1339 break;
1340 default:
Charles Keepaxf3f11632013-02-20 17:28:41 +00001341 fll->ref_src = ARIZONA_FLL_SRC_NONE;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001342 }
1343 fll->ref_freq = 32768;
1344
Mark Brown07ed8732012-06-18 21:08:44 +01001345 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1346 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1347 "FLL%d clock OK", id);
1348
Mark Brown07ed8732012-06-18 21:08:44 +01001349 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1350 arizona_fll_clock_ok, fll);
1351 if (ret != 0) {
1352 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1353 id, ret);
1354 }
1355
Charles Keepaxe31c1942013-01-07 16:41:45 +00001356 regmap_update_bits(arizona->regmap, fll->base + 1,
1357 ARIZONA_FLL1_FREERUN, 0);
1358
Mark Brown07ed8732012-06-18 21:08:44 +01001359 return 0;
1360}
1361EXPORT_SYMBOL_GPL(arizona_init_fll);
1362
Mark Brownbc9ab6d2013-01-04 19:31:00 +00001363/**
1364 * arizona_set_output_mode - Set the mode of the specified output
1365 *
1366 * @codec: Device to configure
1367 * @output: Output number
1368 * @diff: True to set the output to differential mode
1369 *
1370 * Some systems use external analogue switches to connect more
1371 * analogue devices to the CODEC than are supported by the device. In
1372 * some systems this requires changing the switched output from single
1373 * ended to differential mode dynamically at runtime, an operation
1374 * supported using this function.
1375 *
1376 * Most systems have a single static configuration and should use
1377 * platform data instead.
1378 */
1379int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1380{
1381 unsigned int reg, val;
1382
1383 if (output < 1 || output > 6)
1384 return -EINVAL;
1385
1386 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1387
1388 if (diff)
1389 val = ARIZONA_OUT1_MONO;
1390 else
1391 val = 0;
1392
1393 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1394}
1395EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1396
Mark Brown07ed8732012-06-18 21:08:44 +01001397MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1398MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1399MODULE_LICENSE("GPL");