blob: 53ddd529769c863e40cc70bd3626d5b2f432821b [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
Mark Brown8f113d72013-03-05 12:08:57 +0800993static struct {
994 unsigned int min;
995 unsigned int max;
996 u16 gain;
997} fll_gains[] = {
998 { 0, 256000, 0 },
999 { 256000, 1000000, 2 },
1000 { 1000000, 13500000, 4 },
1001};
1002
Mark Brown07ed8732012-06-18 21:08:44 +01001003struct arizona_fll_cfg {
1004 int n;
1005 int theta;
1006 int lambda;
1007 int refdiv;
1008 int outdiv;
1009 int fratio;
Mark Brown8f113d72013-03-05 12:08:57 +08001010 int gain;
Mark Brown07ed8732012-06-18 21:08:44 +01001011};
1012
1013static int arizona_calc_fll(struct arizona_fll *fll,
1014 struct arizona_fll_cfg *cfg,
1015 unsigned int Fref,
1016 unsigned int Fout)
1017{
1018 unsigned int target, div, gcd_fll;
1019 int i, ratio;
1020
1021 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
1022
1023 /* Fref must be <=13.5MHz */
1024 div = 1;
1025 cfg->refdiv = 0;
1026 while ((Fref / div) > 13500000) {
1027 div *= 2;
1028 cfg->refdiv++;
1029
1030 if (div > 8) {
1031 arizona_fll_err(fll,
1032 "Can't scale %dMHz in to <=13.5MHz\n",
1033 Fref);
1034 return -EINVAL;
1035 }
1036 }
1037
1038 /* Apply the division for our remaining calculations */
1039 Fref /= div;
1040
Mark Brown2b4d39f2012-07-10 17:03:46 +01001041 /* Fvco should be over the targt; don't check the upper bound */
Mark Brown07ed8732012-06-18 21:08:44 +01001042 div = 1;
Mark Brown2b4d39f2012-07-10 17:03:46 +01001043 while (Fout * div < 90000000 * fll->vco_mult) {
Mark Brown07ed8732012-06-18 21:08:44 +01001044 div++;
1045 if (div > 7) {
1046 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1047 Fout);
1048 return -EINVAL;
1049 }
1050 }
Mark Brown2b4d39f2012-07-10 17:03:46 +01001051 target = Fout * div / fll->vco_mult;
Mark Brown07ed8732012-06-18 21:08:44 +01001052 cfg->outdiv = div;
1053
1054 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1055
1056 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1057 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1058 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1059 cfg->fratio = fll_fratios[i].fratio;
1060 ratio = fll_fratios[i].ratio;
1061 break;
1062 }
1063 }
1064 if (i == ARRAY_SIZE(fll_fratios)) {
1065 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1066 Fref);
1067 return -EINVAL;
1068 }
1069
Mark Brown8f113d72013-03-05 12:08:57 +08001070 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
1071 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
1072 cfg->gain = fll_gains[i].gain;
1073 break;
1074 }
1075 }
1076 if (i == ARRAY_SIZE(fll_gains)) {
1077 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
1078 Fref);
1079 return -EINVAL;
1080 }
1081
Mark Brown07ed8732012-06-18 21:08:44 +01001082 cfg->n = target / (ratio * Fref);
1083
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001084 if (target % (ratio * Fref)) {
Mark Brown07ed8732012-06-18 21:08:44 +01001085 gcd_fll = gcd(target, ratio * Fref);
1086 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1087
1088 cfg->theta = (target - (cfg->n * ratio * Fref))
1089 / gcd_fll;
1090 cfg->lambda = (ratio * Fref) / gcd_fll;
1091 } else {
1092 cfg->theta = 0;
1093 cfg->lambda = 0;
1094 }
1095
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001096 /* Round down to 16bit range with cost of accuracy lost.
1097 * Denominator must be bigger than numerator so we only
1098 * take care of it.
1099 */
1100 while (cfg->lambda >= (1 << 16)) {
1101 cfg->theta >>= 1;
1102 cfg->lambda >>= 1;
1103 }
1104
Mark Brown07ed8732012-06-18 21:08:44 +01001105 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1106 cfg->n, cfg->theta, cfg->lambda);
1107 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1108 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
Mark Brown8f113d72013-03-05 12:08:57 +08001109 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
Mark Brown07ed8732012-06-18 21:08:44 +01001110
1111 return 0;
1112
1113}
1114
1115static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
Mark Brown8f113d72013-03-05 12:08:57 +08001116 struct arizona_fll_cfg *cfg, int source,
1117 bool sync)
Mark Brown07ed8732012-06-18 21:08:44 +01001118{
1119 regmap_update_bits(arizona->regmap, base + 3,
1120 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1121 regmap_update_bits(arizona->regmap, base + 4,
1122 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1123 regmap_update_bits(arizona->regmap, base + 5,
1124 ARIZONA_FLL1_FRATIO_MASK,
1125 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1126 regmap_update_bits(arizona->regmap, base + 6,
1127 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1128 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1129 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1130 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1131
Mark Brown8f113d72013-03-05 12:08:57 +08001132 if (sync)
1133 regmap_update_bits(arizona->regmap, base + 0x7,
1134 ARIZONA_FLL1_GAIN_MASK,
1135 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1136 else
1137 regmap_update_bits(arizona->regmap, base + 0x9,
1138 ARIZONA_FLL1_GAIN_MASK,
1139 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1140
Mark Brown07ed8732012-06-18 21:08:44 +01001141 regmap_update_bits(arizona->regmap, base + 2,
1142 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1143 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1144}
1145
Charles Keepaxd122d6c2013-02-20 17:28:36 +00001146static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1147{
1148 struct arizona *arizona = fll->arizona;
1149 unsigned int reg;
1150 int ret;
1151
1152 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1153 if (ret != 0) {
1154 arizona_fll_err(fll, "Failed to read current state: %d\n",
1155 ret);
1156 return ret;
1157 }
1158
1159 return reg & ARIZONA_FLL1_ENA;
1160}
1161
Charles Keepax35722812013-02-20 17:28:38 +00001162static void arizona_enable_fll(struct arizona_fll *fll,
1163 struct arizona_fll_cfg *ref,
1164 struct arizona_fll_cfg *sync)
1165{
1166 struct arizona *arizona = fll->arizona;
1167 int ret;
1168
Mark Brownff680a12013-03-04 16:00:19 +08001169 /*
1170 * If we have both REFCLK and SYNCCLK then enable both,
1171 * otherwise apply the SYNCCLK settings to REFCLK.
1172 */
1173 if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
1174 regmap_update_bits(arizona->regmap, fll->base + 5,
1175 ARIZONA_FLL1_OUTDIV_MASK,
1176 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
Charles Keepax35722812013-02-20 17:28:38 +00001177
Mark Brown8f113d72013-03-05 12:08:57 +08001178 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
1179 false);
Mark Brownff680a12013-03-04 16:00:19 +08001180 if (fll->sync_src >= 0)
1181 arizona_apply_fll(arizona, fll->base + 0x10, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001182 fll->sync_src, true);
Mark Brownff680a12013-03-04 16:00:19 +08001183 } else if (fll->sync_src >= 0) {
1184 regmap_update_bits(arizona->regmap, fll->base + 5,
1185 ARIZONA_FLL1_OUTDIV_MASK,
1186 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1187
1188 arizona_apply_fll(arizona, fll->base, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001189 fll->sync_src, false);
Mark Browneca2e8e2013-03-06 00:09:59 +08001190
1191 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1192 ARIZONA_FLL1_SYNC_ENA, 0);
Mark Brownff680a12013-03-04 16:00:19 +08001193 } else {
1194 arizona_fll_err(fll, "No clocks provided\n");
1195 return;
1196 }
Charles Keepax35722812013-02-20 17:28:38 +00001197
Mark Brown576411be2013-03-05 12:07:16 +08001198 /*
1199 * Increase the bandwidth if we're not using a low frequency
1200 * sync source.
1201 */
1202 if (fll->sync_src >= 0 && fll->sync_freq > 100000)
1203 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1204 ARIZONA_FLL1_SYNC_BW, 0);
1205 else
1206 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1207 ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
1208
Charles Keepax35722812013-02-20 17:28:38 +00001209 if (!arizona_is_enabled_fll(fll))
1210 pm_runtime_get(arizona->dev);
1211
1212 /* Clear any pending completions */
1213 try_wait_for_completion(&fll->ok);
1214
1215 regmap_update_bits(arizona->regmap, fll->base + 1,
1216 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
Mark Brownff680a12013-03-04 16:00:19 +08001217 if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
1218 fll->ref_src != fll->sync_src)
Charles Keepax35722812013-02-20 17:28:38 +00001219 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1220 ARIZONA_FLL1_SYNC_ENA,
1221 ARIZONA_FLL1_SYNC_ENA);
1222
1223 ret = wait_for_completion_timeout(&fll->ok,
1224 msecs_to_jiffies(250));
1225 if (ret == 0)
1226 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1227}
1228
Charles Keepax76040542013-02-20 17:28:37 +00001229static void arizona_disable_fll(struct arizona_fll *fll)
1230{
1231 struct arizona *arizona = fll->arizona;
1232 bool change;
1233
1234 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1235 ARIZONA_FLL1_ENA, 0, &change);
1236 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1237 ARIZONA_FLL1_SYNC_ENA, 0);
1238
1239 if (change)
1240 pm_runtime_put_autosuspend(arizona->dev);
1241}
1242
Charles Keepaxee929a92013-02-20 17:28:40 +00001243int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1244 unsigned int Fref, unsigned int Fout)
1245{
1246 struct arizona_fll_cfg ref, sync;
1247 int ret;
1248
Charles Keepax1c5617f2013-02-22 17:10:37 +00001249 if (fll->ref_src == source && fll->ref_freq == Fref)
Charles Keepaxee929a92013-02-20 17:28:40 +00001250 return 0;
1251
Charles Keepax1c5617f2013-02-22 17:10:37 +00001252 if (fll->fout) {
1253 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001254 if (ret != 0)
1255 return ret;
1256
1257 if (fll->sync_src >= 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001258 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1259 fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001260 if (ret != 0)
1261 return ret;
1262 }
1263 }
1264
1265 fll->ref_src = source;
1266 fll->ref_freq = Fref;
Charles Keepaxee929a92013-02-20 17:28:40 +00001267
Charles Keepax1c5617f2013-02-22 17:10:37 +00001268 if (fll->fout) {
Charles Keepaxee929a92013-02-20 17:28:40 +00001269 arizona_enable_fll(fll, &ref, &sync);
Charles Keepaxee929a92013-02-20 17:28:40 +00001270 }
1271
1272 return 0;
1273}
1274EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1275
Mark Brown07ed8732012-06-18 21:08:44 +01001276int arizona_set_fll(struct arizona_fll *fll, int source,
1277 unsigned int Fref, unsigned int Fout)
1278{
Charles Keepax9e359c62013-02-20 17:28:35 +00001279 struct arizona_fll_cfg ref, sync;
Mark Brown07ed8732012-06-18 21:08:44 +01001280 int ret;
1281
Mark Brownff680a12013-03-04 16:00:19 +08001282 if (fll->sync_src == source &&
1283 fll->sync_freq == Fref && fll->fout == Fout)
1284 return 0;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001285
Mark Brownff680a12013-03-04 16:00:19 +08001286 if (Fout) {
1287 if (fll->ref_src >= 0) {
1288 ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
1289 Fout);
Charles Keepax9e359c62013-02-20 17:28:35 +00001290 if (ret != 0)
1291 return ret;
1292 }
1293
Mark Brownff680a12013-03-04 16:00:19 +08001294 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1295 if (ret != 0)
1296 return ret;
Charles Keepax9e359c62013-02-20 17:28:35 +00001297 }
Mark Brownff680a12013-03-04 16:00:19 +08001298
1299 fll->sync_src = source;
1300 fll->sync_freq = Fref;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001301 fll->fout = Fout;
Charles Keepax9e359c62013-02-20 17:28:35 +00001302
Mark Brown07ed8732012-06-18 21:08:44 +01001303 if (Fout) {
Charles Keepax35722812013-02-20 17:28:38 +00001304 arizona_enable_fll(fll, &ref, &sync);
Mark Brown07ed8732012-06-18 21:08:44 +01001305 } else {
Charles Keepax76040542013-02-20 17:28:37 +00001306 arizona_disable_fll(fll);
Mark Brown07ed8732012-06-18 21:08:44 +01001307 }
1308
Mark Brown07ed8732012-06-18 21:08:44 +01001309 return 0;
1310}
1311EXPORT_SYMBOL_GPL(arizona_set_fll);
1312
1313int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1314 int ok_irq, struct arizona_fll *fll)
1315{
1316 int ret;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001317 unsigned int val;
Mark Brown07ed8732012-06-18 21:08:44 +01001318
Mark Brown07ed8732012-06-18 21:08:44 +01001319 init_completion(&fll->ok);
1320
1321 fll->id = id;
1322 fll->base = base;
1323 fll->arizona = arizona;
Charles Keepaxf3f11632013-02-20 17:28:41 +00001324 fll->sync_src = ARIZONA_FLL_SRC_NONE;
Mark Brown07ed8732012-06-18 21:08:44 +01001325
Charles Keepax19b34bd2013-02-20 17:28:34 +00001326 /* Configure default refclk to 32kHz if we have one */
1327 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1328 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1329 case ARIZONA_CLK_SRC_MCLK1:
1330 case ARIZONA_CLK_SRC_MCLK2:
1331 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1332 break;
1333 default:
Charles Keepaxf3f11632013-02-20 17:28:41 +00001334 fll->ref_src = ARIZONA_FLL_SRC_NONE;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001335 }
1336 fll->ref_freq = 32768;
1337
Mark Brown07ed8732012-06-18 21:08:44 +01001338 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1339 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1340 "FLL%d clock OK", id);
1341
Mark Brown07ed8732012-06-18 21:08:44 +01001342 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1343 arizona_fll_clock_ok, fll);
1344 if (ret != 0) {
1345 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1346 id, ret);
1347 }
1348
Charles Keepaxe31c1942013-01-07 16:41:45 +00001349 regmap_update_bits(arizona->regmap, fll->base + 1,
1350 ARIZONA_FLL1_FREERUN, 0);
1351
Mark Brown07ed8732012-06-18 21:08:44 +01001352 return 0;
1353}
1354EXPORT_SYMBOL_GPL(arizona_init_fll);
1355
Mark Brownbc9ab6d2013-01-04 19:31:00 +00001356/**
1357 * arizona_set_output_mode - Set the mode of the specified output
1358 *
1359 * @codec: Device to configure
1360 * @output: Output number
1361 * @diff: True to set the output to differential mode
1362 *
1363 * Some systems use external analogue switches to connect more
1364 * analogue devices to the CODEC than are supported by the device. In
1365 * some systems this requires changing the switched output from single
1366 * ended to differential mode dynamically at runtime, an operation
1367 * supported using this function.
1368 *
1369 * Most systems have a single static configuration and should use
1370 * platform data instead.
1371 */
1372int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1373{
1374 unsigned int reg, val;
1375
1376 if (output < 1 || output > 6)
1377 return -EINVAL;
1378
1379 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1380
1381 if (diff)
1382 val = ARIZONA_OUT1_MONO;
1383 else
1384 val = 0;
1385
1386 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1387}
1388EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1389
Mark Brown07ed8732012-06-18 21:08:44 +01001390MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1391MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1392MODULE_LICENSE("GPL");