blob: 009810b8c667ebb03c9f4dc669edea6144c5f43d [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>
Mark Brown56447e12013-01-10 14:45:58 +000017#include <linux/delay.h>
Mark Brown07ed8732012-06-18 21:08:44 +010018#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/tlv.h>
21
22#include <linux/mfd/arizona/core.h>
23#include <linux/mfd/arizona/registers.h>
24
25#include "arizona.h"
26
27#define ARIZONA_AIF_BCLK_CTRL 0x00
28#define ARIZONA_AIF_TX_PIN_CTRL 0x01
29#define ARIZONA_AIF_RX_PIN_CTRL 0x02
30#define ARIZONA_AIF_RATE_CTRL 0x03
31#define ARIZONA_AIF_FORMAT 0x04
32#define ARIZONA_AIF_TX_BCLK_RATE 0x05
33#define ARIZONA_AIF_RX_BCLK_RATE 0x06
34#define ARIZONA_AIF_FRAME_CTRL_1 0x07
35#define ARIZONA_AIF_FRAME_CTRL_2 0x08
36#define ARIZONA_AIF_FRAME_CTRL_3 0x09
37#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
38#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
39#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
40#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
41#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
42#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
43#define ARIZONA_AIF_FRAME_CTRL_10 0x10
44#define ARIZONA_AIF_FRAME_CTRL_11 0x11
45#define ARIZONA_AIF_FRAME_CTRL_12 0x12
46#define ARIZONA_AIF_FRAME_CTRL_13 0x13
47#define ARIZONA_AIF_FRAME_CTRL_14 0x14
48#define ARIZONA_AIF_FRAME_CTRL_15 0x15
49#define ARIZONA_AIF_FRAME_CTRL_16 0x16
50#define ARIZONA_AIF_FRAME_CTRL_17 0x17
51#define ARIZONA_AIF_FRAME_CTRL_18 0x18
52#define ARIZONA_AIF_TX_ENABLES 0x19
53#define ARIZONA_AIF_RX_ENABLES 0x1A
54#define ARIZONA_AIF_FORCE_WRITE 0x1B
55
56#define arizona_fll_err(_fll, fmt, ...) \
57 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58#define arizona_fll_warn(_fll, fmt, ...) \
59 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
60#define arizona_fll_dbg(_fll, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000061 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010062
63#define arizona_aif_err(_dai, fmt, ...) \
64 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65#define arizona_aif_warn(_dai, fmt, ...) \
66 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67#define arizona_aif_dbg(_dai, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000068 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010069
Mark Brown56447e12013-01-10 14:45:58 +000070static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
71 struct snd_kcontrol *kcontrol,
72 int event)
73{
74 struct snd_soc_codec *codec = w->codec;
75 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
76 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
77 bool manual_ena = false;
78
79 switch (arizona->type) {
80 case WM5102:
81 switch (arizona->rev) {
82 case 0:
83 break;
84 default:
85 manual_ena = true;
86 break;
87 }
88 default:
89 break;
90 }
91
92 switch (event) {
93 case SND_SOC_DAPM_PRE_PMU:
94 if (!priv->spk_ena && manual_ena) {
95 snd_soc_write(codec, 0x4f5, 0x25a);
96 priv->spk_ena_pending = true;
97 }
98 break;
99 case SND_SOC_DAPM_POST_PMU:
100 if (priv->spk_ena_pending) {
101 msleep(75);
102 snd_soc_write(codec, 0x4f5, 0xda);
103 priv->spk_ena_pending = false;
104 priv->spk_ena++;
105 }
106 break;
107 case SND_SOC_DAPM_PRE_PMD:
108 if (manual_ena) {
109 priv->spk_ena--;
110 if (!priv->spk_ena)
111 snd_soc_write(codec, 0x4f5, 0x25a);
112 }
113 break;
114 case SND_SOC_DAPM_POST_PMD:
115 if (manual_ena) {
116 if (!priv->spk_ena)
117 snd_soc_write(codec, 0x4f5, 0x0da);
118 }
119 break;
120 }
121
122 return 0;
123}
124
125static const struct snd_soc_dapm_widget arizona_spkl =
126 SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
127 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
128 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
129
130static const struct snd_soc_dapm_widget arizona_spkr =
131 SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
132 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
133 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
134
135int arizona_init_spk(struct snd_soc_codec *codec)
136{
137 int ret;
138
139 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
140 if (ret != 0)
141 return ret;
142
143 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1);
144 if (ret != 0)
145 return ret;
146
147 return 0;
148}
149EXPORT_SYMBOL_GPL(arizona_init_spk);
150
Mark Brown07ed8732012-06-18 21:08:44 +0100151const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
152 "None",
153 "Tone Generator 1",
154 "Tone Generator 2",
155 "Haptics",
156 "AEC",
157 "Mic Mute Mixer",
158 "Noise Generator",
159 "IN1L",
160 "IN1R",
161 "IN2L",
162 "IN2R",
163 "IN3L",
164 "IN3R",
Mark Brownc9c56fd2012-07-09 19:09:01 +0100165 "IN4L",
166 "IN4R",
Mark Brown07ed8732012-06-18 21:08:44 +0100167 "AIF1RX1",
168 "AIF1RX2",
169 "AIF1RX3",
170 "AIF1RX4",
171 "AIF1RX5",
172 "AIF1RX6",
173 "AIF1RX7",
174 "AIF1RX8",
175 "AIF2RX1",
176 "AIF2RX2",
177 "AIF3RX1",
178 "AIF3RX2",
179 "SLIMRX1",
180 "SLIMRX2",
181 "SLIMRX3",
182 "SLIMRX4",
183 "SLIMRX5",
184 "SLIMRX6",
185 "SLIMRX7",
186 "SLIMRX8",
187 "EQ1",
188 "EQ2",
189 "EQ3",
190 "EQ4",
191 "DRC1L",
192 "DRC1R",
193 "DRC2L",
194 "DRC2R",
195 "LHPF1",
196 "LHPF2",
197 "LHPF3",
198 "LHPF4",
199 "DSP1.1",
200 "DSP1.2",
201 "DSP1.3",
202 "DSP1.4",
203 "DSP1.5",
204 "DSP1.6",
Mark Brownc922cc42012-09-26 16:43:44 +0100205 "DSP2.1",
206 "DSP2.2",
207 "DSP2.3",
208 "DSP2.4",
209 "DSP2.5",
210 "DSP2.6",
211 "DSP3.1",
212 "DSP3.2",
213 "DSP3.3",
214 "DSP3.4",
215 "DSP3.5",
216 "DSP3.6",
217 "DSP4.1",
218 "DSP4.2",
219 "DSP4.3",
220 "DSP4.4",
221 "DSP4.5",
222 "DSP4.6",
Mark Brown07ed8732012-06-18 21:08:44 +0100223 "ASRC1L",
224 "ASRC1R",
225 "ASRC2L",
226 "ASRC2R",
Mark Brown91660bd2012-12-05 20:35:24 +0900227 "ISRC1INT1",
228 "ISRC1INT2",
229 "ISRC1INT3",
230 "ISRC1INT4",
231 "ISRC1DEC1",
232 "ISRC1DEC2",
233 "ISRC1DEC3",
234 "ISRC1DEC4",
235 "ISRC2INT1",
236 "ISRC2INT2",
237 "ISRC2INT3",
238 "ISRC2INT4",
239 "ISRC2DEC1",
240 "ISRC2DEC2",
241 "ISRC2DEC3",
242 "ISRC2DEC4",
243 "ISRC3INT1",
244 "ISRC3INT2",
245 "ISRC3INT3",
246 "ISRC3INT4",
247 "ISRC3DEC1",
248 "ISRC3DEC2",
249 "ISRC3DEC3",
250 "ISRC3DEC4",
Mark Brown07ed8732012-06-18 21:08:44 +0100251};
252EXPORT_SYMBOL_GPL(arizona_mixer_texts);
253
254int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
255 0x00, /* None */
256 0x04, /* Tone */
257 0x05,
258 0x06, /* Haptics */
259 0x08, /* AEC */
260 0x0c, /* Noise mixer */
261 0x0d, /* Comfort noise */
262 0x10, /* IN1L */
263 0x11,
264 0x12,
265 0x13,
266 0x14,
267 0x15,
Mark Brownc9c56fd2012-07-09 19:09:01 +0100268 0x16,
269 0x17,
Mark Brown07ed8732012-06-18 21:08:44 +0100270 0x20, /* AIF1RX1 */
271 0x21,
272 0x22,
273 0x23,
274 0x24,
275 0x25,
276 0x26,
277 0x27,
278 0x28, /* AIF2RX1 */
279 0x29,
280 0x30, /* AIF3RX1 */
281 0x31,
282 0x38, /* SLIMRX1 */
283 0x39,
284 0x3a,
285 0x3b,
286 0x3c,
287 0x3d,
288 0x3e,
289 0x3f,
290 0x50, /* EQ1 */
291 0x51,
292 0x52,
293 0x53,
294 0x58, /* DRC1L */
295 0x59,
296 0x5a,
297 0x5b,
298 0x60, /* LHPF1 */
299 0x61,
300 0x62,
301 0x63,
302 0x68, /* DSP1.1 */
303 0x69,
304 0x6a,
305 0x6b,
306 0x6c,
307 0x6d,
Mark Brownc922cc42012-09-26 16:43:44 +0100308 0x70, /* DSP2.1 */
309 0x71,
310 0x72,
311 0x73,
312 0x74,
313 0x75,
314 0x78, /* DSP3.1 */
315 0x79,
316 0x7a,
317 0x7b,
318 0x7c,
319 0x7d,
320 0x80, /* DSP4.1 */
321 0x81,
322 0x82,
323 0x83,
324 0x84,
325 0x85,
Mark Brown07ed8732012-06-18 21:08:44 +0100326 0x90, /* ASRC1L */
327 0x91,
328 0x92,
329 0x93,
Mark Brown91660bd2012-12-05 20:35:24 +0900330 0xa0, /* ISRC1INT1 */
331 0xa1,
332 0xa2,
333 0xa3,
334 0xa4, /* ISRC1DEC1 */
335 0xa5,
336 0xa6,
337 0xa7,
338 0xa8, /* ISRC2DEC1 */
339 0xa9,
340 0xaa,
341 0xab,
342 0xac, /* ISRC2INT1 */
343 0xad,
344 0xae,
345 0xaf,
346 0xb0, /* ISRC3DEC1 */
347 0xb1,
348 0xb2,
349 0xb3,
350 0xb4, /* ISRC3INT1 */
351 0xb5,
352 0xb6,
353 0xb7,
Mark Brown07ed8732012-06-18 21:08:44 +0100354};
355EXPORT_SYMBOL_GPL(arizona_mixer_values);
356
357const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
358EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
359
Mark Browne853a002012-12-09 12:25:52 +0900360static const char *arizona_vol_ramp_text[] = {
361 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
362 "15ms/6dB", "30ms/6dB",
363};
364
365const struct soc_enum arizona_in_vd_ramp =
366 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
367 ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
368EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
369
370const struct soc_enum arizona_in_vi_ramp =
371 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
372 ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
373EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
374
375const struct soc_enum arizona_out_vd_ramp =
376 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
377 ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
378EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
379
380const struct soc_enum arizona_out_vi_ramp =
381 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
382 ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
383EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
384
Mark Brown07ed8732012-06-18 21:08:44 +0100385static const char *arizona_lhpf_mode_text[] = {
386 "Low-pass", "High-pass"
387};
388
389const struct soc_enum arizona_lhpf1_mode =
390 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
391 arizona_lhpf_mode_text);
392EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
393
394const struct soc_enum arizona_lhpf2_mode =
395 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
396 arizona_lhpf_mode_text);
397EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
398
399const struct soc_enum arizona_lhpf3_mode =
400 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
401 arizona_lhpf_mode_text);
402EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
403
404const struct soc_enum arizona_lhpf4_mode =
405 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
406 arizona_lhpf_mode_text);
407EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
408
Mark Brown845571c2012-12-18 13:47:57 +0000409static const char *arizona_ng_hold_text[] = {
410 "30ms", "120ms", "250ms", "500ms",
411};
412
413const struct soc_enum arizona_ng_hold =
414 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
415 4, arizona_ng_hold_text);
416EXPORT_SYMBOL_GPL(arizona_ng_hold);
417
Mark Brownddbce972013-02-15 17:27:22 +0000418static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
419{
420 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
421 unsigned int val;
422 int i;
423
424 if (ena)
425 val = ARIZONA_IN_VU;
426 else
427 val = 0;
428
429 for (i = 0; i < priv->num_inputs; i++)
430 snd_soc_update_bits(codec,
431 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
432 ARIZONA_IN_VU, val);
433}
434
Mark Brown07ed8732012-06-18 21:08:44 +0100435int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
436 int event)
437{
Mark Brownddbce972013-02-15 17:27:22 +0000438 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000439 unsigned int reg;
440
441 if (w->shift % 2)
442 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
443 else
444 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
445
446 switch (event) {
Mark Brownddbce972013-02-15 17:27:22 +0000447 case SND_SOC_DAPM_PRE_PMU:
448 priv->in_pending++;
449 break;
Mark Brown43cd8bf2013-02-06 16:57:29 +0000450 case SND_SOC_DAPM_POST_PMU:
451 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
Mark Brownddbce972013-02-15 17:27:22 +0000452
453 /* If this is the last input pending then allow VU */
454 priv->in_pending--;
455 if (priv->in_pending == 0) {
456 msleep(1);
457 arizona_in_set_vu(w->codec, 1);
458 }
Mark Brown43cd8bf2013-02-06 16:57:29 +0000459 break;
460 case SND_SOC_DAPM_PRE_PMD:
Mark Brownddbce972013-02-15 17:27:22 +0000461 snd_soc_update_bits(w->codec, reg,
462 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
463 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000464 break;
Mark Brownddbce972013-02-15 17:27:22 +0000465 case SND_SOC_DAPM_POST_PMD:
466 /* Disable volume updates if no inputs are enabled */
467 reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
468 if (reg == 0)
469 arizona_in_set_vu(w->codec, 0);
Mark Brown43cd8bf2013-02-06 16:57:29 +0000470 }
471
Mark Brown07ed8732012-06-18 21:08:44 +0100472 return 0;
473}
474EXPORT_SYMBOL_GPL(arizona_in_ev);
475
476int arizona_out_ev(struct snd_soc_dapm_widget *w,
477 struct snd_kcontrol *kcontrol,
478 int event)
479{
480 return 0;
481}
482EXPORT_SYMBOL_GPL(arizona_out_ev);
483
Mark Browncbd840d2012-08-08 17:52:44 +0100484static unsigned int arizona_sysclk_48k_rates[] = {
485 6144000,
486 12288000,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000487 24576000,
Mark Browncbd840d2012-08-08 17:52:44 +0100488 49152000,
Mark Brownaeaeee12012-09-26 17:50:02 +0100489 73728000,
490 98304000,
491 147456000,
Mark Browncbd840d2012-08-08 17:52:44 +0100492};
493
494static unsigned int arizona_sysclk_44k1_rates[] = {
495 5644800,
496 11289600,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000497 22579200,
Mark Browncbd840d2012-08-08 17:52:44 +0100498 45158400,
Mark Brownaeaeee12012-09-26 17:50:02 +0100499 67737600,
500 90316800,
501 135475200,
Mark Browncbd840d2012-08-08 17:52:44 +0100502};
503
504static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
505 unsigned int freq)
506{
507 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
508 unsigned int reg;
509 unsigned int *rates;
510 int ref, div, refclk;
511
512 switch (clk) {
513 case ARIZONA_CLK_OPCLK:
514 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
515 refclk = priv->sysclk;
516 break;
517 case ARIZONA_CLK_ASYNC_OPCLK:
518 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
519 refclk = priv->asyncclk;
520 break;
521 default:
522 return -EINVAL;
523 }
524
525 if (refclk % 8000)
526 rates = arizona_sysclk_44k1_rates;
527 else
528 rates = arizona_sysclk_48k_rates;
529
530 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
531 rates[ref] <= refclk; ref++) {
532 div = 1;
533 while (rates[ref] / div >= freq && div < 32) {
534 if (rates[ref] / div == freq) {
535 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
536 freq);
537 snd_soc_update_bits(codec, reg,
538 ARIZONA_OPCLK_DIV_MASK |
539 ARIZONA_OPCLK_SEL_MASK,
540 (div <<
541 ARIZONA_OPCLK_DIV_SHIFT) |
542 ref);
543 return 0;
544 }
545 div++;
546 }
547 }
548
549 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
550 return -EINVAL;
551}
552
Mark Brown07ed8732012-06-18 21:08:44 +0100553int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
554 int source, unsigned int freq, int dir)
555{
556 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
557 struct arizona *arizona = priv->arizona;
558 char *name;
559 unsigned int reg;
560 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
561 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
562 unsigned int *clk;
563
564 switch (clk_id) {
565 case ARIZONA_CLK_SYSCLK:
566 name = "SYSCLK";
567 reg = ARIZONA_SYSTEM_CLOCK_1;
568 clk = &priv->sysclk;
569 mask |= ARIZONA_SYSCLK_FRAC;
570 break;
571 case ARIZONA_CLK_ASYNCCLK:
572 name = "ASYNCCLK";
573 reg = ARIZONA_ASYNC_CLOCK_1;
574 clk = &priv->asyncclk;
575 break;
Mark Browncbd840d2012-08-08 17:52:44 +0100576 case ARIZONA_CLK_OPCLK:
577 case ARIZONA_CLK_ASYNC_OPCLK:
578 return arizona_set_opclk(codec, clk_id, freq);
Mark Brown07ed8732012-06-18 21:08:44 +0100579 default:
580 return -EINVAL;
581 }
582
583 switch (freq) {
584 case 5644800:
585 case 6144000:
586 break;
587 case 11289600:
588 case 12288000:
Mark Brown3f341f72013-03-08 15:22:29 +0800589 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100590 break;
591 case 22579200:
592 case 24576000:
Mark Brown3f341f72013-03-08 15:22:29 +0800593 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100594 break;
595 case 45158400:
596 case 49152000:
Mark Brown3f341f72013-03-08 15:22:29 +0800597 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown07ed8732012-06-18 21:08:44 +0100598 break;
Mark Brown38113362012-11-26 16:01:37 +0000599 case 67737600:
600 case 73728000:
Mark Brown3f341f72013-03-08 15:22:29 +0800601 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000602 break;
603 case 90316800:
604 case 98304000:
Mark Brown3f341f72013-03-08 15:22:29 +0800605 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000606 break;
607 case 135475200:
608 case 147456000:
Mark Brown3f341f72013-03-08 15:22:29 +0800609 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
Mark Brown38113362012-11-26 16:01:37 +0000610 break;
Mark Brownf2c26d42013-01-21 16:09:36 +0900611 case 0:
612 dev_dbg(arizona->dev, "%s cleared\n", name);
613 *clk = freq;
614 return 0;
Mark Brown07ed8732012-06-18 21:08:44 +0100615 default:
616 return -EINVAL;
617 }
618
619 *clk = freq;
620
621 if (freq % 6144000)
622 val |= ARIZONA_SYSCLK_FRAC;
623
624 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
625
626 return regmap_update_bits(arizona->regmap, reg, mask, val);
627}
628EXPORT_SYMBOL_GPL(arizona_set_sysclk);
629
630static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
631{
632 struct snd_soc_codec *codec = dai->codec;
633 int lrclk, bclk, mode, base;
634
635 base = dai->driver->base;
636
637 lrclk = 0;
638 bclk = 0;
639
640 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
641 case SND_SOC_DAIFMT_DSP_A:
642 mode = 0;
643 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100644 case SND_SOC_DAIFMT_I2S:
645 mode = 2;
646 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100647 default:
648 arizona_aif_err(dai, "Unsupported DAI format %d\n",
649 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
650 return -EINVAL;
651 }
652
653 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
654 case SND_SOC_DAIFMT_CBS_CFS:
655 break;
656 case SND_SOC_DAIFMT_CBS_CFM:
657 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
658 break;
659 case SND_SOC_DAIFMT_CBM_CFS:
660 bclk |= ARIZONA_AIF1_BCLK_MSTR;
661 break;
662 case SND_SOC_DAIFMT_CBM_CFM:
663 bclk |= ARIZONA_AIF1_BCLK_MSTR;
664 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
665 break;
666 default:
667 arizona_aif_err(dai, "Unsupported master mode %d\n",
668 fmt & SND_SOC_DAIFMT_MASTER_MASK);
669 return -EINVAL;
670 }
671
672 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
673 case SND_SOC_DAIFMT_NB_NF:
674 break;
675 case SND_SOC_DAIFMT_IB_IF:
676 bclk |= ARIZONA_AIF1_BCLK_INV;
677 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
678 break;
679 case SND_SOC_DAIFMT_IB_NF:
680 bclk |= ARIZONA_AIF1_BCLK_INV;
681 break;
682 case SND_SOC_DAIFMT_NB_IF:
683 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
684 break;
685 default:
686 return -EINVAL;
687 }
688
689 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
690 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
691 bclk);
692 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
693 ARIZONA_AIF1TX_LRCLK_INV |
694 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
695 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
696 ARIZONA_AIF1RX_LRCLK_INV |
697 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
698 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
699 ARIZONA_AIF1_FMT_MASK, mode);
700
701 return 0;
702}
703
Mark Brown949e6bc2012-07-04 18:58:04 +0100704static const int arizona_48k_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100705 -1,
706 48000,
707 64000,
708 96000,
709 128000,
710 192000,
711 256000,
712 384000,
713 512000,
714 768000,
715 1024000,
716 1536000,
717 2048000,
718 3072000,
719 4096000,
720 6144000,
721 8192000,
722 12288000,
723 24576000,
724};
725
Mark Brown5b2eec32012-07-04 17:32:05 +0100726static const unsigned int arizona_48k_rates[] = {
727 12000,
728 24000,
729 48000,
730 96000,
731 192000,
732 384000,
733 768000,
734 4000,
735 8000,
736 16000,
737 32000,
738 64000,
739 128000,
740 256000,
741 512000,
742};
743
744static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
745 .count = ARRAY_SIZE(arizona_48k_rates),
746 .list = arizona_48k_rates,
747};
748
Mark Brown949e6bc2012-07-04 18:58:04 +0100749static const int arizona_44k1_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100750 -1,
751 44100,
752 58800,
753 88200,
754 117600,
755 177640,
756 235200,
757 352800,
758 470400,
759 705600,
760 940800,
761 1411200,
762 1881600,
Heather Lomond4758be32012-09-05 05:02:10 -0400763 2822400,
Mark Brown07ed8732012-06-18 21:08:44 +0100764 3763200,
765 5644800,
766 7526400,
767 11289600,
768 22579200,
769};
770
Mark Brown5b2eec32012-07-04 17:32:05 +0100771static const unsigned int arizona_44k1_rates[] = {
772 11025,
773 22050,
774 44100,
775 88200,
776 176400,
777 352800,
778 705600,
779};
780
781static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
782 .count = ARRAY_SIZE(arizona_44k1_rates),
783 .list = arizona_44k1_rates,
784};
785
Mark Brown07ed8732012-06-18 21:08:44 +0100786static int arizona_sr_vals[] = {
787 0,
788 12000,
789 24000,
790 48000,
791 96000,
792 192000,
793 384000,
794 768000,
795 0,
796 11025,
797 22050,
798 44100,
799 88200,
800 176400,
801 352800,
802 705600,
803 4000,
804 8000,
805 16000,
806 32000,
807 64000,
808 128000,
809 256000,
810 512000,
811};
812
Mark Brown5b2eec32012-07-04 17:32:05 +0100813static int arizona_startup(struct snd_pcm_substream *substream,
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);
818 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
819 const struct snd_pcm_hw_constraint_list *constraint;
820 unsigned int base_rate;
821
822 switch (dai_priv->clk) {
823 case ARIZONA_CLK_SYSCLK:
824 base_rate = priv->sysclk;
825 break;
826 case ARIZONA_CLK_ASYNCCLK:
827 base_rate = priv->asyncclk;
828 break;
829 default:
830 return 0;
831 }
832
Mark Brownf2c26d42013-01-21 16:09:36 +0900833 if (base_rate == 0)
834 return 0;
835
Mark Brown5b2eec32012-07-04 17:32:05 +0100836 if (base_rate % 8000)
837 constraint = &arizona_44k1_constraint;
838 else
839 constraint = &arizona_48k_constraint;
840
841 return snd_pcm_hw_constraint_list(substream->runtime, 0,
842 SNDRV_PCM_HW_PARAM_RATE,
843 constraint);
844}
845
Mark Brownb272efc2012-10-10 15:10:08 +0900846static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
847 struct snd_pcm_hw_params *params,
848 struct snd_soc_dai *dai)
Mark Brown07ed8732012-06-18 21:08:44 +0100849{
850 struct snd_soc_codec *codec = dai->codec;
Mark Brownc013b272012-07-04 20:05:57 +0100851 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
852 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown07ed8732012-06-18 21:08:44 +0100853 int base = dai->driver->base;
Mark Brownb272efc2012-10-10 15:10:08 +0900854 int i, sr_val;
855
856 /*
857 * We will need to be more flexible than this in future,
858 * currently we use a single sample rate for SYSCLK.
859 */
860 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
861 if (arizona_sr_vals[i] == params_rate(params))
862 break;
863 if (i == ARRAY_SIZE(arizona_sr_vals)) {
864 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
865 params_rate(params));
866 return -EINVAL;
867 }
868 sr_val = i;
869
870 switch (dai_priv->clk) {
871 case ARIZONA_CLK_SYSCLK:
872 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
873 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
874 if (base)
875 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
876 ARIZONA_AIF1_RATE_MASK, 0);
877 break;
878 case ARIZONA_CLK_ASYNCCLK:
879 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
880 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
881 if (base)
882 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
883 ARIZONA_AIF1_RATE_MASK,
884 8 << ARIZONA_AIF1_RATE_SHIFT);
885 break;
886 default:
887 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
888 return -EINVAL;
889 }
890
891 return 0;
892}
893
Mark Brown07ed8732012-06-18 21:08:44 +0100894static int arizona_hw_params(struct snd_pcm_substream *substream,
895 struct snd_pcm_hw_params *params,
896 struct snd_soc_dai *dai)
897{
898 struct snd_soc_codec *codec = dai->codec;
899 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
Mark Brownc94aa302013-01-17 16:35:14 +0900900 struct arizona *arizona = priv->arizona;
Mark Brown07ed8732012-06-18 21:08:44 +0100901 int base = dai->driver->base;
902 const int *rates;
Mark Brown76bf9692013-03-05 14:17:47 +0800903 int i, ret, val;
Mark Brownc94aa302013-01-17 16:35:14 +0900904 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
905 int bclk, lrclk, wl, frame, bclk_target;
Mark Brown07ed8732012-06-18 21:08:44 +0100906
907 if (params_rate(params) % 8000)
Mark Brown949e6bc2012-07-04 18:58:04 +0100908 rates = &arizona_44k1_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100909 else
Mark Brown949e6bc2012-07-04 18:58:04 +0100910 rates = &arizona_48k_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100911
Mark Brownc94aa302013-01-17 16:35:14 +0900912 bclk_target = snd_soc_params_to_bclk(params);
913 if (chan_limit && chan_limit < params_channels(params)) {
914 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
915 bclk_target /= params_channels(params);
916 bclk_target *= chan_limit;
917 }
918
Mark Brown76bf9692013-03-05 14:17:47 +0800919 /* Force stereo for I2S mode */
920 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
921 if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
922 arizona_aif_dbg(dai, "Forcing stereo mode\n");
923 bclk_target *= 2;
924 }
925
Mark Brown949e6bc2012-07-04 18:58:04 +0100926 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
Mark Brownc94aa302013-01-17 16:35:14 +0900927 if (rates[i] >= bclk_target &&
Mark Brown50017652012-07-04 19:07:09 +0100928 rates[i] % params_rate(params) == 0) {
Mark Brown07ed8732012-06-18 21:08:44 +0100929 bclk = i;
930 break;
931 }
932 }
Mark Brown949e6bc2012-07-04 18:58:04 +0100933 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
Mark Brown07ed8732012-06-18 21:08:44 +0100934 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
935 params_rate(params));
936 return -EINVAL;
937 }
938
Mark Brownb59e0f82013-01-17 14:15:59 +0900939 lrclk = rates[bclk] / params_rate(params);
Mark Brown07ed8732012-06-18 21:08:44 +0100940
941 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
942 rates[bclk], rates[bclk] / lrclk);
943
944 wl = snd_pcm_format_width(params_format(params));
945 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
946
Mark Brownb272efc2012-10-10 15:10:08 +0900947 ret = arizona_hw_params_rate(substream, params, dai);
948 if (ret != 0)
949 return ret;
Mark Brownc013b272012-07-04 20:05:57 +0100950
Mark Brown07ed8732012-06-18 21:08:44 +0100951 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
952 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
953 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
954 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
955 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
956 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
957 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
958 ARIZONA_AIF1TX_WL_MASK |
959 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
960 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
961 ARIZONA_AIF1RX_WL_MASK |
962 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
963
964 return 0;
965}
966
Mark Brown410837a2012-07-05 17:26:59 +0100967static const char *arizona_dai_clk_str(int clk_id)
968{
969 switch (clk_id) {
970 case ARIZONA_CLK_SYSCLK:
971 return "SYSCLK";
972 case ARIZONA_CLK_ASYNCCLK:
973 return "ASYNCCLK";
974 default:
975 return "Unknown clock";
976 }
977}
978
Mark Brown5b2eec32012-07-04 17:32:05 +0100979static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
980 int clk_id, unsigned int freq, int dir)
981{
982 struct snd_soc_codec *codec = dai->codec;
983 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
984 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown410837a2012-07-05 17:26:59 +0100985 struct snd_soc_dapm_route routes[2];
Mark Brown5b2eec32012-07-04 17:32:05 +0100986
987 switch (clk_id) {
988 case ARIZONA_CLK_SYSCLK:
989 case ARIZONA_CLK_ASYNCCLK:
990 break;
991 default:
992 return -EINVAL;
993 }
994
Mark Brown410837a2012-07-05 17:26:59 +0100995 if (clk_id == dai_priv->clk)
996 return 0;
997
998 if (dai->active) {
Mark Brown5b2eec32012-07-04 17:32:05 +0100999 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1000 dai->id);
1001 return -EBUSY;
1002 }
1003
Mark Brownc8d35a62012-12-07 12:49:40 +09001004 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1005 arizona_dai_clk_str(clk_id));
1006
Mark Brown410837a2012-07-05 17:26:59 +01001007 memset(&routes, 0, sizeof(routes));
1008 routes[0].sink = dai->driver->capture.stream_name;
1009 routes[1].sink = dai->driver->playback.stream_name;
Mark Brown5b2eec32012-07-04 17:32:05 +01001010
Mark Brown410837a2012-07-05 17:26:59 +01001011 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1012 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1013 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
1014
1015 routes[0].source = arizona_dai_clk_str(clk_id);
1016 routes[1].source = arizona_dai_clk_str(clk_id);
1017 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
1018
Mark Brown0c778e82012-12-06 18:22:25 +09001019 dai_priv->clk = clk_id;
1020
Mark Brown410837a2012-07-05 17:26:59 +01001021 return snd_soc_dapm_sync(&codec->dapm);
Mark Brown5b2eec32012-07-04 17:32:05 +01001022}
1023
Mark Brown01df2592012-12-12 16:22:08 +09001024static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1025{
1026 struct snd_soc_codec *codec = dai->codec;
1027 int base = dai->driver->base;
1028 unsigned int reg;
1029
1030 if (tristate)
1031 reg = ARIZONA_AIF1_TRI;
1032 else
1033 reg = 0;
1034
1035 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1036 ARIZONA_AIF1_TRI, reg);
1037}
1038
Mark Brown07ed8732012-06-18 21:08:44 +01001039const struct snd_soc_dai_ops arizona_dai_ops = {
Mark Brown5b2eec32012-07-04 17:32:05 +01001040 .startup = arizona_startup,
Mark Brown07ed8732012-06-18 21:08:44 +01001041 .set_fmt = arizona_set_fmt,
1042 .hw_params = arizona_hw_params,
Mark Brown5b2eec32012-07-04 17:32:05 +01001043 .set_sysclk = arizona_dai_set_sysclk,
Mark Brown01df2592012-12-12 16:22:08 +09001044 .set_tristate = arizona_set_tristate,
Mark Brown07ed8732012-06-18 21:08:44 +01001045};
Mark Browna8379872012-07-09 12:16:41 +01001046EXPORT_SYMBOL_GPL(arizona_dai_ops);
Mark Brown07ed8732012-06-18 21:08:44 +01001047
Mark Brown5b2eec32012-07-04 17:32:05 +01001048int arizona_init_dai(struct arizona_priv *priv, int id)
1049{
1050 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1051
1052 dai_priv->clk = ARIZONA_CLK_SYSCLK;
1053
1054 return 0;
1055}
1056EXPORT_SYMBOL_GPL(arizona_init_dai);
1057
Mark Brown07ed8732012-06-18 21:08:44 +01001058static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
1059{
1060 struct arizona_fll *fll = data;
1061
1062 arizona_fll_dbg(fll, "clock OK\n");
1063
1064 complete(&fll->ok);
1065
1066 return IRQ_HANDLED;
1067}
1068
1069static struct {
1070 unsigned int min;
1071 unsigned int max;
1072 u16 fratio;
1073 int ratio;
1074} fll_fratios[] = {
1075 { 0, 64000, 4, 16 },
1076 { 64000, 128000, 3, 8 },
1077 { 128000, 256000, 2, 4 },
1078 { 256000, 1000000, 1, 2 },
1079 { 1000000, 13500000, 0, 1 },
1080};
1081
Mark Brown8f113d72013-03-05 12:08:57 +08001082static struct {
1083 unsigned int min;
1084 unsigned int max;
1085 u16 gain;
1086} fll_gains[] = {
1087 { 0, 256000, 0 },
1088 { 256000, 1000000, 2 },
1089 { 1000000, 13500000, 4 },
1090};
1091
Mark Brown07ed8732012-06-18 21:08:44 +01001092struct arizona_fll_cfg {
1093 int n;
1094 int theta;
1095 int lambda;
1096 int refdiv;
1097 int outdiv;
1098 int fratio;
Mark Brown8f113d72013-03-05 12:08:57 +08001099 int gain;
Mark Brown07ed8732012-06-18 21:08:44 +01001100};
1101
1102static int arizona_calc_fll(struct arizona_fll *fll,
1103 struct arizona_fll_cfg *cfg,
1104 unsigned int Fref,
1105 unsigned int Fout)
1106{
1107 unsigned int target, div, gcd_fll;
1108 int i, ratio;
1109
1110 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
1111
1112 /* Fref must be <=13.5MHz */
1113 div = 1;
1114 cfg->refdiv = 0;
1115 while ((Fref / div) > 13500000) {
1116 div *= 2;
1117 cfg->refdiv++;
1118
1119 if (div > 8) {
1120 arizona_fll_err(fll,
1121 "Can't scale %dMHz in to <=13.5MHz\n",
1122 Fref);
1123 return -EINVAL;
1124 }
1125 }
1126
1127 /* Apply the division for our remaining calculations */
1128 Fref /= div;
1129
Mark Brown2b4d39f2012-07-10 17:03:46 +01001130 /* Fvco should be over the targt; don't check the upper bound */
Mark Brown07ed8732012-06-18 21:08:44 +01001131 div = 1;
Mark Brown2b4d39f2012-07-10 17:03:46 +01001132 while (Fout * div < 90000000 * fll->vco_mult) {
Mark Brown07ed8732012-06-18 21:08:44 +01001133 div++;
1134 if (div > 7) {
1135 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1136 Fout);
1137 return -EINVAL;
1138 }
1139 }
Mark Brown2b4d39f2012-07-10 17:03:46 +01001140 target = Fout * div / fll->vco_mult;
Mark Brown07ed8732012-06-18 21:08:44 +01001141 cfg->outdiv = div;
1142
1143 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1144
1145 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1146 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1147 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1148 cfg->fratio = fll_fratios[i].fratio;
1149 ratio = fll_fratios[i].ratio;
1150 break;
1151 }
1152 }
1153 if (i == ARRAY_SIZE(fll_fratios)) {
1154 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1155 Fref);
1156 return -EINVAL;
1157 }
1158
Mark Brown8f113d72013-03-05 12:08:57 +08001159 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
1160 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
1161 cfg->gain = fll_gains[i].gain;
1162 break;
1163 }
1164 }
1165 if (i == ARRAY_SIZE(fll_gains)) {
1166 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
1167 Fref);
1168 return -EINVAL;
1169 }
1170
Mark Brown07ed8732012-06-18 21:08:44 +01001171 cfg->n = target / (ratio * Fref);
1172
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001173 if (target % (ratio * Fref)) {
Mark Brown07ed8732012-06-18 21:08:44 +01001174 gcd_fll = gcd(target, ratio * Fref);
1175 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1176
1177 cfg->theta = (target - (cfg->n * ratio * Fref))
1178 / gcd_fll;
1179 cfg->lambda = (ratio * Fref) / gcd_fll;
1180 } else {
1181 cfg->theta = 0;
1182 cfg->lambda = 0;
1183 }
1184
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001185 /* Round down to 16bit range with cost of accuracy lost.
1186 * Denominator must be bigger than numerator so we only
1187 * take care of it.
1188 */
1189 while (cfg->lambda >= (1 << 16)) {
1190 cfg->theta >>= 1;
1191 cfg->lambda >>= 1;
1192 }
1193
Mark Brown07ed8732012-06-18 21:08:44 +01001194 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1195 cfg->n, cfg->theta, cfg->lambda);
1196 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1197 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
Mark Brown8f113d72013-03-05 12:08:57 +08001198 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
Mark Brown07ed8732012-06-18 21:08:44 +01001199
1200 return 0;
1201
1202}
1203
1204static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
Mark Brown8f113d72013-03-05 12:08:57 +08001205 struct arizona_fll_cfg *cfg, int source,
1206 bool sync)
Mark Brown07ed8732012-06-18 21:08:44 +01001207{
1208 regmap_update_bits(arizona->regmap, base + 3,
1209 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1210 regmap_update_bits(arizona->regmap, base + 4,
1211 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1212 regmap_update_bits(arizona->regmap, base + 5,
1213 ARIZONA_FLL1_FRATIO_MASK,
1214 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1215 regmap_update_bits(arizona->regmap, base + 6,
1216 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1217 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1218 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1219 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1220
Mark Brown8f113d72013-03-05 12:08:57 +08001221 if (sync)
1222 regmap_update_bits(arizona->regmap, base + 0x7,
1223 ARIZONA_FLL1_GAIN_MASK,
1224 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1225 else
1226 regmap_update_bits(arizona->regmap, base + 0x9,
1227 ARIZONA_FLL1_GAIN_MASK,
1228 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1229
Mark Brown07ed8732012-06-18 21:08:44 +01001230 regmap_update_bits(arizona->regmap, base + 2,
1231 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1232 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1233}
1234
Charles Keepaxd122d6c2013-02-20 17:28:36 +00001235static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1236{
1237 struct arizona *arizona = fll->arizona;
1238 unsigned int reg;
1239 int ret;
1240
1241 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1242 if (ret != 0) {
1243 arizona_fll_err(fll, "Failed to read current state: %d\n",
1244 ret);
1245 return ret;
1246 }
1247
1248 return reg & ARIZONA_FLL1_ENA;
1249}
1250
Charles Keepax35722812013-02-20 17:28:38 +00001251static void arizona_enable_fll(struct arizona_fll *fll,
1252 struct arizona_fll_cfg *ref,
1253 struct arizona_fll_cfg *sync)
1254{
1255 struct arizona *arizona = fll->arizona;
1256 int ret;
1257
Mark Brownff680a12013-03-04 16:00:19 +08001258 /*
1259 * If we have both REFCLK and SYNCCLK then enable both,
1260 * otherwise apply the SYNCCLK settings to REFCLK.
1261 */
1262 if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
1263 regmap_update_bits(arizona->regmap, fll->base + 5,
1264 ARIZONA_FLL1_OUTDIV_MASK,
1265 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
Charles Keepax35722812013-02-20 17:28:38 +00001266
Mark Brown8f113d72013-03-05 12:08:57 +08001267 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
1268 false);
Mark Brownff680a12013-03-04 16:00:19 +08001269 if (fll->sync_src >= 0)
1270 arizona_apply_fll(arizona, fll->base + 0x10, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001271 fll->sync_src, true);
Mark Brownff680a12013-03-04 16:00:19 +08001272 } else if (fll->sync_src >= 0) {
1273 regmap_update_bits(arizona->regmap, fll->base + 5,
1274 ARIZONA_FLL1_OUTDIV_MASK,
1275 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1276
1277 arizona_apply_fll(arizona, fll->base, sync,
Mark Brown8f113d72013-03-05 12:08:57 +08001278 fll->sync_src, false);
Mark Browneca2e8e2013-03-06 00:09:59 +08001279
1280 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1281 ARIZONA_FLL1_SYNC_ENA, 0);
Mark Brownff680a12013-03-04 16:00:19 +08001282 } else {
1283 arizona_fll_err(fll, "No clocks provided\n");
1284 return;
1285 }
Charles Keepax35722812013-02-20 17:28:38 +00001286
Mark Brown576411be2013-03-05 12:07:16 +08001287 /*
1288 * Increase the bandwidth if we're not using a low frequency
1289 * sync source.
1290 */
1291 if (fll->sync_src >= 0 && fll->sync_freq > 100000)
1292 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1293 ARIZONA_FLL1_SYNC_BW, 0);
1294 else
1295 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1296 ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
1297
Charles Keepax35722812013-02-20 17:28:38 +00001298 if (!arizona_is_enabled_fll(fll))
1299 pm_runtime_get(arizona->dev);
1300
1301 /* Clear any pending completions */
1302 try_wait_for_completion(&fll->ok);
1303
1304 regmap_update_bits(arizona->regmap, fll->base + 1,
1305 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
Mark Brownff680a12013-03-04 16:00:19 +08001306 if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
1307 fll->ref_src != fll->sync_src)
Charles Keepax35722812013-02-20 17:28:38 +00001308 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1309 ARIZONA_FLL1_SYNC_ENA,
1310 ARIZONA_FLL1_SYNC_ENA);
1311
1312 ret = wait_for_completion_timeout(&fll->ok,
1313 msecs_to_jiffies(250));
1314 if (ret == 0)
1315 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1316}
1317
Charles Keepax76040542013-02-20 17:28:37 +00001318static void arizona_disable_fll(struct arizona_fll *fll)
1319{
1320 struct arizona *arizona = fll->arizona;
1321 bool change;
1322
1323 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1324 ARIZONA_FLL1_ENA, 0, &change);
1325 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1326 ARIZONA_FLL1_SYNC_ENA, 0);
1327
1328 if (change)
1329 pm_runtime_put_autosuspend(arizona->dev);
1330}
1331
Charles Keepaxee929a92013-02-20 17:28:40 +00001332int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1333 unsigned int Fref, unsigned int Fout)
1334{
1335 struct arizona_fll_cfg ref, sync;
1336 int ret;
1337
Charles Keepax1c5617f2013-02-22 17:10:37 +00001338 if (fll->ref_src == source && fll->ref_freq == Fref)
Charles Keepaxee929a92013-02-20 17:28:40 +00001339 return 0;
1340
Mark Brown86cd6842013-03-07 16:14:04 +08001341 if (fll->fout && Fref > 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001342 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001343 if (ret != 0)
1344 return ret;
1345
1346 if (fll->sync_src >= 0) {
Charles Keepax1c5617f2013-02-22 17:10:37 +00001347 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1348 fll->fout);
Charles Keepaxee929a92013-02-20 17:28:40 +00001349 if (ret != 0)
1350 return ret;
1351 }
1352 }
1353
1354 fll->ref_src = source;
1355 fll->ref_freq = Fref;
Charles Keepaxee929a92013-02-20 17:28:40 +00001356
Mark Brown86cd6842013-03-07 16:14:04 +08001357 if (fll->fout && Fref > 0) {
Charles Keepaxee929a92013-02-20 17:28:40 +00001358 arizona_enable_fll(fll, &ref, &sync);
Charles Keepaxee929a92013-02-20 17:28:40 +00001359 }
1360
1361 return 0;
1362}
1363EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1364
Mark Brown07ed8732012-06-18 21:08:44 +01001365int arizona_set_fll(struct arizona_fll *fll, int source,
1366 unsigned int Fref, unsigned int Fout)
1367{
Charles Keepax9e359c62013-02-20 17:28:35 +00001368 struct arizona_fll_cfg ref, sync;
Mark Brown07ed8732012-06-18 21:08:44 +01001369 int ret;
1370
Mark Brownff680a12013-03-04 16:00:19 +08001371 if (fll->sync_src == source &&
1372 fll->sync_freq == Fref && fll->fout == Fout)
1373 return 0;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001374
Mark Brownff680a12013-03-04 16:00:19 +08001375 if (Fout) {
1376 if (fll->ref_src >= 0) {
1377 ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
1378 Fout);
Charles Keepax9e359c62013-02-20 17:28:35 +00001379 if (ret != 0)
1380 return ret;
1381 }
1382
Mark Brownff680a12013-03-04 16:00:19 +08001383 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1384 if (ret != 0)
1385 return ret;
Charles Keepax9e359c62013-02-20 17:28:35 +00001386 }
Mark Brownff680a12013-03-04 16:00:19 +08001387
1388 fll->sync_src = source;
1389 fll->sync_freq = Fref;
Charles Keepaxde1e6ee2013-02-20 17:28:39 +00001390 fll->fout = Fout;
Charles Keepax9e359c62013-02-20 17:28:35 +00001391
Mark Brown07ed8732012-06-18 21:08:44 +01001392 if (Fout) {
Charles Keepax35722812013-02-20 17:28:38 +00001393 arizona_enable_fll(fll, &ref, &sync);
Mark Brown07ed8732012-06-18 21:08:44 +01001394 } else {
Charles Keepax76040542013-02-20 17:28:37 +00001395 arizona_disable_fll(fll);
Mark Brown07ed8732012-06-18 21:08:44 +01001396 }
1397
Mark Brown07ed8732012-06-18 21:08:44 +01001398 return 0;
1399}
1400EXPORT_SYMBOL_GPL(arizona_set_fll);
1401
1402int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1403 int ok_irq, struct arizona_fll *fll)
1404{
1405 int ret;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001406 unsigned int val;
Mark Brown07ed8732012-06-18 21:08:44 +01001407
Mark Brown07ed8732012-06-18 21:08:44 +01001408 init_completion(&fll->ok);
1409
1410 fll->id = id;
1411 fll->base = base;
1412 fll->arizona = arizona;
Charles Keepaxf3f11632013-02-20 17:28:41 +00001413 fll->sync_src = ARIZONA_FLL_SRC_NONE;
Mark Brown07ed8732012-06-18 21:08:44 +01001414
Charles Keepax19b34bd2013-02-20 17:28:34 +00001415 /* Configure default refclk to 32kHz if we have one */
1416 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1417 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1418 case ARIZONA_CLK_SRC_MCLK1:
1419 case ARIZONA_CLK_SRC_MCLK2:
1420 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1421 break;
1422 default:
Charles Keepaxf3f11632013-02-20 17:28:41 +00001423 fll->ref_src = ARIZONA_FLL_SRC_NONE;
Charles Keepax19b34bd2013-02-20 17:28:34 +00001424 }
1425 fll->ref_freq = 32768;
1426
Mark Brown07ed8732012-06-18 21:08:44 +01001427 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1428 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1429 "FLL%d clock OK", id);
1430
Mark Brown07ed8732012-06-18 21:08:44 +01001431 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1432 arizona_fll_clock_ok, fll);
1433 if (ret != 0) {
1434 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1435 id, ret);
1436 }
1437
Charles Keepaxe31c1942013-01-07 16:41:45 +00001438 regmap_update_bits(arizona->regmap, fll->base + 1,
1439 ARIZONA_FLL1_FREERUN, 0);
1440
Mark Brown07ed8732012-06-18 21:08:44 +01001441 return 0;
1442}
1443EXPORT_SYMBOL_GPL(arizona_init_fll);
1444
Mark Brownbc9ab6d2013-01-04 19:31:00 +00001445/**
1446 * arizona_set_output_mode - Set the mode of the specified output
1447 *
1448 * @codec: Device to configure
1449 * @output: Output number
1450 * @diff: True to set the output to differential mode
1451 *
1452 * Some systems use external analogue switches to connect more
1453 * analogue devices to the CODEC than are supported by the device. In
1454 * some systems this requires changing the switched output from single
1455 * ended to differential mode dynamically at runtime, an operation
1456 * supported using this function.
1457 *
1458 * Most systems have a single static configuration and should use
1459 * platform data instead.
1460 */
1461int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1462{
1463 unsigned int reg, val;
1464
1465 if (output < 1 || output > 6)
1466 return -EINVAL;
1467
1468 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1469
1470 if (diff)
1471 val = ARIZONA_OUT1_MONO;
1472 else
1473 val = 0;
1474
1475 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1476}
1477EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1478
Mark Brown07ed8732012-06-18 21:08:44 +01001479MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1480MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1481MODULE_LICENSE("GPL");