blob: e7d34711412cabb1e3112ef53fa488cb9b339061 [file] [log] [blame]
Mark Brown07ed8732012-06-18 21:08:44 +01001/*
2 * arizona.c - Wolfson Arizona class device shared support
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gcd.h>
14#include <linux/module.h>
15#include <linux/pm_runtime.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/tlv.h>
19
20#include <linux/mfd/arizona/core.h>
21#include <linux/mfd/arizona/registers.h>
22
23#include "arizona.h"
24
25#define ARIZONA_AIF_BCLK_CTRL 0x00
26#define ARIZONA_AIF_TX_PIN_CTRL 0x01
27#define ARIZONA_AIF_RX_PIN_CTRL 0x02
28#define ARIZONA_AIF_RATE_CTRL 0x03
29#define ARIZONA_AIF_FORMAT 0x04
30#define ARIZONA_AIF_TX_BCLK_RATE 0x05
31#define ARIZONA_AIF_RX_BCLK_RATE 0x06
32#define ARIZONA_AIF_FRAME_CTRL_1 0x07
33#define ARIZONA_AIF_FRAME_CTRL_2 0x08
34#define ARIZONA_AIF_FRAME_CTRL_3 0x09
35#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
36#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
37#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
38#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
39#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
40#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
41#define ARIZONA_AIF_FRAME_CTRL_10 0x10
42#define ARIZONA_AIF_FRAME_CTRL_11 0x11
43#define ARIZONA_AIF_FRAME_CTRL_12 0x12
44#define ARIZONA_AIF_FRAME_CTRL_13 0x13
45#define ARIZONA_AIF_FRAME_CTRL_14 0x14
46#define ARIZONA_AIF_FRAME_CTRL_15 0x15
47#define ARIZONA_AIF_FRAME_CTRL_16 0x16
48#define ARIZONA_AIF_FRAME_CTRL_17 0x17
49#define ARIZONA_AIF_FRAME_CTRL_18 0x18
50#define ARIZONA_AIF_TX_ENABLES 0x19
51#define ARIZONA_AIF_RX_ENABLES 0x1A
52#define ARIZONA_AIF_FORCE_WRITE 0x1B
53
54#define arizona_fll_err(_fll, fmt, ...) \
55 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
56#define arizona_fll_warn(_fll, fmt, ...) \
57 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58#define arizona_fll_dbg(_fll, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000059 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010060
61#define arizona_aif_err(_dai, fmt, ...) \
62 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
63#define arizona_aif_warn(_dai, fmt, ...) \
64 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65#define arizona_aif_dbg(_dai, fmt, ...) \
Mark Brown9092a6e2013-02-06 17:58:57 +000066 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
Mark Brown07ed8732012-06-18 21:08:44 +010067
68const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69 "None",
70 "Tone Generator 1",
71 "Tone Generator 2",
72 "Haptics",
73 "AEC",
74 "Mic Mute Mixer",
75 "Noise Generator",
76 "IN1L",
77 "IN1R",
78 "IN2L",
79 "IN2R",
80 "IN3L",
81 "IN3R",
Mark Brownc9c56fd2012-07-09 19:09:01 +010082 "IN4L",
83 "IN4R",
Mark Brown07ed8732012-06-18 21:08:44 +010084 "AIF1RX1",
85 "AIF1RX2",
86 "AIF1RX3",
87 "AIF1RX4",
88 "AIF1RX5",
89 "AIF1RX6",
90 "AIF1RX7",
91 "AIF1RX8",
92 "AIF2RX1",
93 "AIF2RX2",
94 "AIF3RX1",
95 "AIF3RX2",
96 "SLIMRX1",
97 "SLIMRX2",
98 "SLIMRX3",
99 "SLIMRX4",
100 "SLIMRX5",
101 "SLIMRX6",
102 "SLIMRX7",
103 "SLIMRX8",
104 "EQ1",
105 "EQ2",
106 "EQ3",
107 "EQ4",
108 "DRC1L",
109 "DRC1R",
110 "DRC2L",
111 "DRC2R",
112 "LHPF1",
113 "LHPF2",
114 "LHPF3",
115 "LHPF4",
116 "DSP1.1",
117 "DSP1.2",
118 "DSP1.3",
119 "DSP1.4",
120 "DSP1.5",
121 "DSP1.6",
Mark Brownc922cc42012-09-26 16:43:44 +0100122 "DSP2.1",
123 "DSP2.2",
124 "DSP2.3",
125 "DSP2.4",
126 "DSP2.5",
127 "DSP2.6",
128 "DSP3.1",
129 "DSP3.2",
130 "DSP3.3",
131 "DSP3.4",
132 "DSP3.5",
133 "DSP3.6",
134 "DSP4.1",
135 "DSP4.2",
136 "DSP4.3",
137 "DSP4.4",
138 "DSP4.5",
139 "DSP4.6",
Mark Brown07ed8732012-06-18 21:08:44 +0100140 "ASRC1L",
141 "ASRC1R",
142 "ASRC2L",
143 "ASRC2R",
Mark Brown91660bd2012-12-05 20:35:24 +0900144 "ISRC1INT1",
145 "ISRC1INT2",
146 "ISRC1INT3",
147 "ISRC1INT4",
148 "ISRC1DEC1",
149 "ISRC1DEC2",
150 "ISRC1DEC3",
151 "ISRC1DEC4",
152 "ISRC2INT1",
153 "ISRC2INT2",
154 "ISRC2INT3",
155 "ISRC2INT4",
156 "ISRC2DEC1",
157 "ISRC2DEC2",
158 "ISRC2DEC3",
159 "ISRC2DEC4",
160 "ISRC3INT1",
161 "ISRC3INT2",
162 "ISRC3INT3",
163 "ISRC3INT4",
164 "ISRC3DEC1",
165 "ISRC3DEC2",
166 "ISRC3DEC3",
167 "ISRC3DEC4",
Mark Brown07ed8732012-06-18 21:08:44 +0100168};
169EXPORT_SYMBOL_GPL(arizona_mixer_texts);
170
171int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
172 0x00, /* None */
173 0x04, /* Tone */
174 0x05,
175 0x06, /* Haptics */
176 0x08, /* AEC */
177 0x0c, /* Noise mixer */
178 0x0d, /* Comfort noise */
179 0x10, /* IN1L */
180 0x11,
181 0x12,
182 0x13,
183 0x14,
184 0x15,
Mark Brownc9c56fd2012-07-09 19:09:01 +0100185 0x16,
186 0x17,
Mark Brown07ed8732012-06-18 21:08:44 +0100187 0x20, /* AIF1RX1 */
188 0x21,
189 0x22,
190 0x23,
191 0x24,
192 0x25,
193 0x26,
194 0x27,
195 0x28, /* AIF2RX1 */
196 0x29,
197 0x30, /* AIF3RX1 */
198 0x31,
199 0x38, /* SLIMRX1 */
200 0x39,
201 0x3a,
202 0x3b,
203 0x3c,
204 0x3d,
205 0x3e,
206 0x3f,
207 0x50, /* EQ1 */
208 0x51,
209 0x52,
210 0x53,
211 0x58, /* DRC1L */
212 0x59,
213 0x5a,
214 0x5b,
215 0x60, /* LHPF1 */
216 0x61,
217 0x62,
218 0x63,
219 0x68, /* DSP1.1 */
220 0x69,
221 0x6a,
222 0x6b,
223 0x6c,
224 0x6d,
Mark Brownc922cc42012-09-26 16:43:44 +0100225 0x70, /* DSP2.1 */
226 0x71,
227 0x72,
228 0x73,
229 0x74,
230 0x75,
231 0x78, /* DSP3.1 */
232 0x79,
233 0x7a,
234 0x7b,
235 0x7c,
236 0x7d,
237 0x80, /* DSP4.1 */
238 0x81,
239 0x82,
240 0x83,
241 0x84,
242 0x85,
Mark Brown07ed8732012-06-18 21:08:44 +0100243 0x90, /* ASRC1L */
244 0x91,
245 0x92,
246 0x93,
Mark Brown91660bd2012-12-05 20:35:24 +0900247 0xa0, /* ISRC1INT1 */
248 0xa1,
249 0xa2,
250 0xa3,
251 0xa4, /* ISRC1DEC1 */
252 0xa5,
253 0xa6,
254 0xa7,
255 0xa8, /* ISRC2DEC1 */
256 0xa9,
257 0xaa,
258 0xab,
259 0xac, /* ISRC2INT1 */
260 0xad,
261 0xae,
262 0xaf,
263 0xb0, /* ISRC3DEC1 */
264 0xb1,
265 0xb2,
266 0xb3,
267 0xb4, /* ISRC3INT1 */
268 0xb5,
269 0xb6,
270 0xb7,
Mark Brown07ed8732012-06-18 21:08:44 +0100271};
272EXPORT_SYMBOL_GPL(arizona_mixer_values);
273
274const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
275EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
276
Mark Browne853a002012-12-09 12:25:52 +0900277static const char *arizona_vol_ramp_text[] = {
278 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
279 "15ms/6dB", "30ms/6dB",
280};
281
282const struct soc_enum arizona_in_vd_ramp =
283 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
284 ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
285EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
286
287const struct soc_enum arizona_in_vi_ramp =
288 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
289 ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
290EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
291
292const struct soc_enum arizona_out_vd_ramp =
293 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
294 ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
295EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
296
297const struct soc_enum arizona_out_vi_ramp =
298 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
299 ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
300EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
301
Mark Brown07ed8732012-06-18 21:08:44 +0100302static const char *arizona_lhpf_mode_text[] = {
303 "Low-pass", "High-pass"
304};
305
306const struct soc_enum arizona_lhpf1_mode =
307 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
308 arizona_lhpf_mode_text);
309EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
310
311const struct soc_enum arizona_lhpf2_mode =
312 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
313 arizona_lhpf_mode_text);
314EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
315
316const struct soc_enum arizona_lhpf3_mode =
317 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
318 arizona_lhpf_mode_text);
319EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
320
321const struct soc_enum arizona_lhpf4_mode =
322 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
323 arizona_lhpf_mode_text);
324EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
325
Mark Brown845571c2012-12-18 13:47:57 +0000326static const char *arizona_ng_hold_text[] = {
327 "30ms", "120ms", "250ms", "500ms",
328};
329
330const struct soc_enum arizona_ng_hold =
331 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
332 4, arizona_ng_hold_text);
333EXPORT_SYMBOL_GPL(arizona_ng_hold);
334
Mark Brown07ed8732012-06-18 21:08:44 +0100335int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
336 int event)
337{
Mark Brown43cd8bf2013-02-06 16:57:29 +0000338 unsigned int reg;
339
340 if (w->shift % 2)
341 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
342 else
343 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
344
345 switch (event) {
346 case SND_SOC_DAPM_POST_PMU:
347 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
348 break;
349 case SND_SOC_DAPM_PRE_PMD:
350 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE,
351 ARIZONA_IN1L_MUTE);
352 break;
353 }
354
Mark Brown07ed8732012-06-18 21:08:44 +0100355 return 0;
356}
357EXPORT_SYMBOL_GPL(arizona_in_ev);
358
359int arizona_out_ev(struct snd_soc_dapm_widget *w,
360 struct snd_kcontrol *kcontrol,
361 int event)
362{
363 return 0;
364}
365EXPORT_SYMBOL_GPL(arizona_out_ev);
366
Mark Brownf607e312013-02-22 18:36:53 +0000367int arizona_hp_ev(struct snd_soc_dapm_widget *w,
368 struct snd_kcontrol *kcontrol,
369 int event)
370{
371 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
372 unsigned int mask = 1 << w->shift;
373 unsigned int val;
374
375 switch (event) {
376 case SND_SOC_DAPM_POST_PMU:
377 val = mask;
378 break;
379 case SND_SOC_DAPM_PRE_PMD:
380 val = 0;
381 break;
382 default:
383 return -EINVAL;
384 }
385
386 /* Store the desired state for the HP outputs */
387 priv->arizona->hp_ena &= ~mask;
388 priv->arizona->hp_ena |= val;
389
390 /* Force off if HPDET magic is active */
391 if (priv->arizona->hpdet_magic)
392 val = 0;
393
394 snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
395
396 return arizona_out_ev(w, kcontrol, event);
397}
398EXPORT_SYMBOL_GPL(arizona_hp_ev);
399
Mark Browncbd840d2012-08-08 17:52:44 +0100400static unsigned int arizona_sysclk_48k_rates[] = {
401 6144000,
402 12288000,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000403 24576000,
Mark Browncbd840d2012-08-08 17:52:44 +0100404 49152000,
Mark Brownaeaeee12012-09-26 17:50:02 +0100405 73728000,
406 98304000,
407 147456000,
Mark Browncbd840d2012-08-08 17:52:44 +0100408};
409
410static unsigned int arizona_sysclk_44k1_rates[] = {
411 5644800,
412 11289600,
Dimitris Papastamos96e1f182012-11-15 11:41:30 +0000413 22579200,
Mark Browncbd840d2012-08-08 17:52:44 +0100414 45158400,
Mark Brownaeaeee12012-09-26 17:50:02 +0100415 67737600,
416 90316800,
417 135475200,
Mark Browncbd840d2012-08-08 17:52:44 +0100418};
419
420static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
421 unsigned int freq)
422{
423 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
424 unsigned int reg;
425 unsigned int *rates;
426 int ref, div, refclk;
427
428 switch (clk) {
429 case ARIZONA_CLK_OPCLK:
430 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
431 refclk = priv->sysclk;
432 break;
433 case ARIZONA_CLK_ASYNC_OPCLK:
434 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
435 refclk = priv->asyncclk;
436 break;
437 default:
438 return -EINVAL;
439 }
440
441 if (refclk % 8000)
442 rates = arizona_sysclk_44k1_rates;
443 else
444 rates = arizona_sysclk_48k_rates;
445
446 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
447 rates[ref] <= refclk; ref++) {
448 div = 1;
449 while (rates[ref] / div >= freq && div < 32) {
450 if (rates[ref] / div == freq) {
451 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
452 freq);
453 snd_soc_update_bits(codec, reg,
454 ARIZONA_OPCLK_DIV_MASK |
455 ARIZONA_OPCLK_SEL_MASK,
456 (div <<
457 ARIZONA_OPCLK_DIV_SHIFT) |
458 ref);
459 return 0;
460 }
461 div++;
462 }
463 }
464
465 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
466 return -EINVAL;
467}
468
Mark Brown07ed8732012-06-18 21:08:44 +0100469int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
470 int source, unsigned int freq, int dir)
471{
472 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
473 struct arizona *arizona = priv->arizona;
474 char *name;
475 unsigned int reg;
476 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
477 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
478 unsigned int *clk;
479
480 switch (clk_id) {
481 case ARIZONA_CLK_SYSCLK:
482 name = "SYSCLK";
483 reg = ARIZONA_SYSTEM_CLOCK_1;
484 clk = &priv->sysclk;
485 mask |= ARIZONA_SYSCLK_FRAC;
486 break;
487 case ARIZONA_CLK_ASYNCCLK:
488 name = "ASYNCCLK";
489 reg = ARIZONA_ASYNC_CLOCK_1;
490 clk = &priv->asyncclk;
491 break;
Mark Browncbd840d2012-08-08 17:52:44 +0100492 case ARIZONA_CLK_OPCLK:
493 case ARIZONA_CLK_ASYNC_OPCLK:
494 return arizona_set_opclk(codec, clk_id, freq);
Mark Brown07ed8732012-06-18 21:08:44 +0100495 default:
496 return -EINVAL;
497 }
498
499 switch (freq) {
500 case 5644800:
501 case 6144000:
502 break;
503 case 11289600:
504 case 12288000:
505 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
506 break;
507 case 22579200:
508 case 24576000:
509 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
510 break;
511 case 45158400:
512 case 49152000:
513 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
514 break;
Mark Brown38113362012-11-26 16:01:37 +0000515 case 67737600:
516 case 73728000:
517 val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
518 break;
519 case 90316800:
520 case 98304000:
521 val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
522 break;
523 case 135475200:
524 case 147456000:
525 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
526 break;
Mark Brownf2c26d42013-01-21 16:09:36 +0900527 case 0:
528 dev_dbg(arizona->dev, "%s cleared\n", name);
529 *clk = freq;
530 return 0;
Mark Brown07ed8732012-06-18 21:08:44 +0100531 default:
532 return -EINVAL;
533 }
534
535 *clk = freq;
536
537 if (freq % 6144000)
538 val |= ARIZONA_SYSCLK_FRAC;
539
540 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
541
542 return regmap_update_bits(arizona->regmap, reg, mask, val);
543}
544EXPORT_SYMBOL_GPL(arizona_set_sysclk);
545
546static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
547{
548 struct snd_soc_codec *codec = dai->codec;
549 int lrclk, bclk, mode, base;
550
551 base = dai->driver->base;
552
553 lrclk = 0;
554 bclk = 0;
555
556 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
557 case SND_SOC_DAIFMT_DSP_A:
558 mode = 0;
559 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100560 case SND_SOC_DAIFMT_I2S:
561 mode = 2;
562 break;
Mark Brown07ed8732012-06-18 21:08:44 +0100563 default:
564 arizona_aif_err(dai, "Unsupported DAI format %d\n",
565 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
566 return -EINVAL;
567 }
568
569 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
570 case SND_SOC_DAIFMT_CBS_CFS:
571 break;
572 case SND_SOC_DAIFMT_CBS_CFM:
573 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
574 break;
575 case SND_SOC_DAIFMT_CBM_CFS:
576 bclk |= ARIZONA_AIF1_BCLK_MSTR;
577 break;
578 case SND_SOC_DAIFMT_CBM_CFM:
579 bclk |= ARIZONA_AIF1_BCLK_MSTR;
580 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
581 break;
582 default:
583 arizona_aif_err(dai, "Unsupported master mode %d\n",
584 fmt & SND_SOC_DAIFMT_MASTER_MASK);
585 return -EINVAL;
586 }
587
588 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
589 case SND_SOC_DAIFMT_NB_NF:
590 break;
591 case SND_SOC_DAIFMT_IB_IF:
592 bclk |= ARIZONA_AIF1_BCLK_INV;
593 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
594 break;
595 case SND_SOC_DAIFMT_IB_NF:
596 bclk |= ARIZONA_AIF1_BCLK_INV;
597 break;
598 case SND_SOC_DAIFMT_NB_IF:
599 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
600 break;
601 default:
602 return -EINVAL;
603 }
604
605 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
606 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
607 bclk);
608 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
609 ARIZONA_AIF1TX_LRCLK_INV |
610 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
611 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
612 ARIZONA_AIF1RX_LRCLK_INV |
613 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
614 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
615 ARIZONA_AIF1_FMT_MASK, mode);
616
617 return 0;
618}
619
Mark Brown949e6bc2012-07-04 18:58:04 +0100620static const int arizona_48k_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100621 -1,
622 48000,
623 64000,
624 96000,
625 128000,
626 192000,
627 256000,
628 384000,
629 512000,
630 768000,
631 1024000,
632 1536000,
633 2048000,
634 3072000,
635 4096000,
636 6144000,
637 8192000,
638 12288000,
639 24576000,
640};
641
Mark Brown5b2eec32012-07-04 17:32:05 +0100642static const unsigned int arizona_48k_rates[] = {
643 12000,
644 24000,
645 48000,
646 96000,
647 192000,
648 384000,
649 768000,
650 4000,
651 8000,
652 16000,
653 32000,
654 64000,
655 128000,
656 256000,
657 512000,
658};
659
660static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
661 .count = ARRAY_SIZE(arizona_48k_rates),
662 .list = arizona_48k_rates,
663};
664
Mark Brown949e6bc2012-07-04 18:58:04 +0100665static const int arizona_44k1_bclk_rates[] = {
Mark Brown07ed8732012-06-18 21:08:44 +0100666 -1,
667 44100,
668 58800,
669 88200,
670 117600,
671 177640,
672 235200,
673 352800,
674 470400,
675 705600,
676 940800,
677 1411200,
678 1881600,
Heather Lomond4758be32012-09-05 05:02:10 -0400679 2822400,
Mark Brown07ed8732012-06-18 21:08:44 +0100680 3763200,
681 5644800,
682 7526400,
683 11289600,
684 22579200,
685};
686
Mark Brown5b2eec32012-07-04 17:32:05 +0100687static const unsigned int arizona_44k1_rates[] = {
688 11025,
689 22050,
690 44100,
691 88200,
692 176400,
693 352800,
694 705600,
695};
696
697static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
698 .count = ARRAY_SIZE(arizona_44k1_rates),
699 .list = arizona_44k1_rates,
700};
701
Mark Brown07ed8732012-06-18 21:08:44 +0100702static int arizona_sr_vals[] = {
703 0,
704 12000,
705 24000,
706 48000,
707 96000,
708 192000,
709 384000,
710 768000,
711 0,
712 11025,
713 22050,
714 44100,
715 88200,
716 176400,
717 352800,
718 705600,
719 4000,
720 8000,
721 16000,
722 32000,
723 64000,
724 128000,
725 256000,
726 512000,
727};
728
Mark Brown5b2eec32012-07-04 17:32:05 +0100729static int arizona_startup(struct snd_pcm_substream *substream,
730 struct snd_soc_dai *dai)
731{
732 struct snd_soc_codec *codec = dai->codec;
733 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
734 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
735 const struct snd_pcm_hw_constraint_list *constraint;
736 unsigned int base_rate;
737
738 switch (dai_priv->clk) {
739 case ARIZONA_CLK_SYSCLK:
740 base_rate = priv->sysclk;
741 break;
742 case ARIZONA_CLK_ASYNCCLK:
743 base_rate = priv->asyncclk;
744 break;
745 default:
746 return 0;
747 }
748
Mark Brownf2c26d42013-01-21 16:09:36 +0900749 if (base_rate == 0)
750 return 0;
751
Mark Brown5b2eec32012-07-04 17:32:05 +0100752 if (base_rate % 8000)
753 constraint = &arizona_44k1_constraint;
754 else
755 constraint = &arizona_48k_constraint;
756
757 return snd_pcm_hw_constraint_list(substream->runtime, 0,
758 SNDRV_PCM_HW_PARAM_RATE,
759 constraint);
760}
761
Mark Brownb272efc2012-10-10 15:10:08 +0900762static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
763 struct snd_pcm_hw_params *params,
764 struct snd_soc_dai *dai)
Mark Brown07ed8732012-06-18 21:08:44 +0100765{
766 struct snd_soc_codec *codec = dai->codec;
Mark Brownc013b272012-07-04 20:05:57 +0100767 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
768 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown07ed8732012-06-18 21:08:44 +0100769 int base = dai->driver->base;
Mark Brownb272efc2012-10-10 15:10:08 +0900770 int i, sr_val;
771
772 /*
773 * We will need to be more flexible than this in future,
774 * currently we use a single sample rate for SYSCLK.
775 */
776 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
777 if (arizona_sr_vals[i] == params_rate(params))
778 break;
779 if (i == ARRAY_SIZE(arizona_sr_vals)) {
780 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
781 params_rate(params));
782 return -EINVAL;
783 }
784 sr_val = i;
785
786 switch (dai_priv->clk) {
787 case ARIZONA_CLK_SYSCLK:
788 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
789 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
790 if (base)
791 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
792 ARIZONA_AIF1_RATE_MASK, 0);
793 break;
794 case ARIZONA_CLK_ASYNCCLK:
795 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
796 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
797 if (base)
798 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
799 ARIZONA_AIF1_RATE_MASK,
800 8 << ARIZONA_AIF1_RATE_SHIFT);
801 break;
802 default:
803 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
804 return -EINVAL;
805 }
806
807 return 0;
808}
809
Mark Brown07ed8732012-06-18 21:08:44 +0100810static int arizona_hw_params(struct snd_pcm_substream *substream,
811 struct snd_pcm_hw_params *params,
812 struct snd_soc_dai *dai)
813{
814 struct snd_soc_codec *codec = dai->codec;
815 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
Mark Brownc94aa302013-01-17 16:35:14 +0900816 struct arizona *arizona = priv->arizona;
Mark Brown07ed8732012-06-18 21:08:44 +0100817 int base = dai->driver->base;
818 const int *rates;
Mark Brownb272efc2012-10-10 15:10:08 +0900819 int i, ret;
Mark Brownc94aa302013-01-17 16:35:14 +0900820 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
821 int bclk, lrclk, wl, frame, bclk_target;
Mark Brown07ed8732012-06-18 21:08:44 +0100822
823 if (params_rate(params) % 8000)
Mark Brown949e6bc2012-07-04 18:58:04 +0100824 rates = &arizona_44k1_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100825 else
Mark Brown949e6bc2012-07-04 18:58:04 +0100826 rates = &arizona_48k_bclk_rates[0];
Mark Brown07ed8732012-06-18 21:08:44 +0100827
Mark Brownc94aa302013-01-17 16:35:14 +0900828 bclk_target = snd_soc_params_to_bclk(params);
829 if (chan_limit && chan_limit < params_channels(params)) {
830 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
831 bclk_target /= params_channels(params);
832 bclk_target *= chan_limit;
833 }
834
Mark Brown949e6bc2012-07-04 18:58:04 +0100835 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
Mark Brownc94aa302013-01-17 16:35:14 +0900836 if (rates[i] >= bclk_target &&
Mark Brown50017652012-07-04 19:07:09 +0100837 rates[i] % params_rate(params) == 0) {
Mark Brown07ed8732012-06-18 21:08:44 +0100838 bclk = i;
839 break;
840 }
841 }
Mark Brown949e6bc2012-07-04 18:58:04 +0100842 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
Mark Brown07ed8732012-06-18 21:08:44 +0100843 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
844 params_rate(params));
845 return -EINVAL;
846 }
847
Mark Brownb59e0f82013-01-17 14:15:59 +0900848 lrclk = rates[bclk] / params_rate(params);
Mark Brown07ed8732012-06-18 21:08:44 +0100849
850 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
851 rates[bclk], rates[bclk] / lrclk);
852
853 wl = snd_pcm_format_width(params_format(params));
854 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
855
Mark Brownb272efc2012-10-10 15:10:08 +0900856 ret = arizona_hw_params_rate(substream, params, dai);
857 if (ret != 0)
858 return ret;
Mark Brownc013b272012-07-04 20:05:57 +0100859
Mark Brown07ed8732012-06-18 21:08:44 +0100860 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
861 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
862 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
863 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
864 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
865 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
866 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
867 ARIZONA_AIF1TX_WL_MASK |
868 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
869 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
870 ARIZONA_AIF1RX_WL_MASK |
871 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
872
873 return 0;
874}
875
Mark Brown410837a2012-07-05 17:26:59 +0100876static const char *arizona_dai_clk_str(int clk_id)
877{
878 switch (clk_id) {
879 case ARIZONA_CLK_SYSCLK:
880 return "SYSCLK";
881 case ARIZONA_CLK_ASYNCCLK:
882 return "ASYNCCLK";
883 default:
884 return "Unknown clock";
885 }
886}
887
Mark Brown5b2eec32012-07-04 17:32:05 +0100888static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
889 int clk_id, unsigned int freq, int dir)
890{
891 struct snd_soc_codec *codec = dai->codec;
892 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
893 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
Mark Brown410837a2012-07-05 17:26:59 +0100894 struct snd_soc_dapm_route routes[2];
Mark Brown5b2eec32012-07-04 17:32:05 +0100895
896 switch (clk_id) {
897 case ARIZONA_CLK_SYSCLK:
898 case ARIZONA_CLK_ASYNCCLK:
899 break;
900 default:
901 return -EINVAL;
902 }
903
Mark Brown410837a2012-07-05 17:26:59 +0100904 if (clk_id == dai_priv->clk)
905 return 0;
906
907 if (dai->active) {
Mark Brown5b2eec32012-07-04 17:32:05 +0100908 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
909 dai->id);
910 return -EBUSY;
911 }
912
Mark Brownc8d35a62012-12-07 12:49:40 +0900913 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
914 arizona_dai_clk_str(clk_id));
915
Mark Brown410837a2012-07-05 17:26:59 +0100916 memset(&routes, 0, sizeof(routes));
917 routes[0].sink = dai->driver->capture.stream_name;
918 routes[1].sink = dai->driver->playback.stream_name;
Mark Brown5b2eec32012-07-04 17:32:05 +0100919
Mark Brown410837a2012-07-05 17:26:59 +0100920 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
921 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
922 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
923
924 routes[0].source = arizona_dai_clk_str(clk_id);
925 routes[1].source = arizona_dai_clk_str(clk_id);
926 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
927
Mark Brown0c778e82012-12-06 18:22:25 +0900928 dai_priv->clk = clk_id;
929
Mark Brown410837a2012-07-05 17:26:59 +0100930 return snd_soc_dapm_sync(&codec->dapm);
Mark Brown5b2eec32012-07-04 17:32:05 +0100931}
932
Mark Brown01df2592012-12-12 16:22:08 +0900933static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
934{
935 struct snd_soc_codec *codec = dai->codec;
936 int base = dai->driver->base;
937 unsigned int reg;
938
939 if (tristate)
940 reg = ARIZONA_AIF1_TRI;
941 else
942 reg = 0;
943
944 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
945 ARIZONA_AIF1_TRI, reg);
946}
947
Mark Brown07ed8732012-06-18 21:08:44 +0100948const struct snd_soc_dai_ops arizona_dai_ops = {
Mark Brown5b2eec32012-07-04 17:32:05 +0100949 .startup = arizona_startup,
Mark Brown07ed8732012-06-18 21:08:44 +0100950 .set_fmt = arizona_set_fmt,
951 .hw_params = arizona_hw_params,
Mark Brown5b2eec32012-07-04 17:32:05 +0100952 .set_sysclk = arizona_dai_set_sysclk,
Mark Brown01df2592012-12-12 16:22:08 +0900953 .set_tristate = arizona_set_tristate,
Mark Brown07ed8732012-06-18 21:08:44 +0100954};
Mark Browna8379872012-07-09 12:16:41 +0100955EXPORT_SYMBOL_GPL(arizona_dai_ops);
Mark Brown07ed8732012-06-18 21:08:44 +0100956
Mark Brown5b2eec32012-07-04 17:32:05 +0100957int arizona_init_dai(struct arizona_priv *priv, int id)
958{
959 struct arizona_dai_priv *dai_priv = &priv->dai[id];
960
961 dai_priv->clk = ARIZONA_CLK_SYSCLK;
962
963 return 0;
964}
965EXPORT_SYMBOL_GPL(arizona_init_dai);
966
Mark Brown07ed8732012-06-18 21:08:44 +0100967static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
968{
969 struct arizona_fll *fll = data;
970
971 arizona_fll_dbg(fll, "clock OK\n");
972
973 complete(&fll->ok);
974
975 return IRQ_HANDLED;
976}
977
978static struct {
979 unsigned int min;
980 unsigned int max;
981 u16 fratio;
982 int ratio;
983} fll_fratios[] = {
984 { 0, 64000, 4, 16 },
985 { 64000, 128000, 3, 8 },
986 { 128000, 256000, 2, 4 },
987 { 256000, 1000000, 1, 2 },
988 { 1000000, 13500000, 0, 1 },
989};
990
991struct arizona_fll_cfg {
992 int n;
993 int theta;
994 int lambda;
995 int refdiv;
996 int outdiv;
997 int fratio;
998};
999
1000static int arizona_calc_fll(struct arizona_fll *fll,
1001 struct arizona_fll_cfg *cfg,
1002 unsigned int Fref,
1003 unsigned int Fout)
1004{
1005 unsigned int target, div, gcd_fll;
1006 int i, ratio;
1007
1008 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
1009
1010 /* Fref must be <=13.5MHz */
1011 div = 1;
1012 cfg->refdiv = 0;
1013 while ((Fref / div) > 13500000) {
1014 div *= 2;
1015 cfg->refdiv++;
1016
1017 if (div > 8) {
1018 arizona_fll_err(fll,
1019 "Can't scale %dMHz in to <=13.5MHz\n",
1020 Fref);
1021 return -EINVAL;
1022 }
1023 }
1024
1025 /* Apply the division for our remaining calculations */
1026 Fref /= div;
1027
Mark Brown2b4d39f2012-07-10 17:03:46 +01001028 /* Fvco should be over the targt; don't check the upper bound */
Mark Brown07ed8732012-06-18 21:08:44 +01001029 div = 1;
Mark Brown2b4d39f2012-07-10 17:03:46 +01001030 while (Fout * div < 90000000 * fll->vco_mult) {
Mark Brown07ed8732012-06-18 21:08:44 +01001031 div++;
1032 if (div > 7) {
1033 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1034 Fout);
1035 return -EINVAL;
1036 }
1037 }
Mark Brown2b4d39f2012-07-10 17:03:46 +01001038 target = Fout * div / fll->vco_mult;
Mark Brown07ed8732012-06-18 21:08:44 +01001039 cfg->outdiv = div;
1040
1041 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1042
1043 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1044 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1045 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1046 cfg->fratio = fll_fratios[i].fratio;
1047 ratio = fll_fratios[i].ratio;
1048 break;
1049 }
1050 }
1051 if (i == ARRAY_SIZE(fll_fratios)) {
1052 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1053 Fref);
1054 return -EINVAL;
1055 }
1056
1057 cfg->n = target / (ratio * Fref);
1058
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001059 if (target % (ratio * Fref)) {
Mark Brown07ed8732012-06-18 21:08:44 +01001060 gcd_fll = gcd(target, ratio * Fref);
1061 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1062
1063 cfg->theta = (target - (cfg->n * ratio * Fref))
1064 / gcd_fll;
1065 cfg->lambda = (ratio * Fref) / gcd_fll;
1066 } else {
1067 cfg->theta = 0;
1068 cfg->lambda = 0;
1069 }
1070
Ryo Tsutsui01f58152013-02-03 17:18:00 +09001071 /* Round down to 16bit range with cost of accuracy lost.
1072 * Denominator must be bigger than numerator so we only
1073 * take care of it.
1074 */
1075 while (cfg->lambda >= (1 << 16)) {
1076 cfg->theta >>= 1;
1077 cfg->lambda >>= 1;
1078 }
1079
Mark Brown07ed8732012-06-18 21:08:44 +01001080 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1081 cfg->n, cfg->theta, cfg->lambda);
1082 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1083 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
1084
1085 return 0;
1086
1087}
1088
1089static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
1090 struct arizona_fll_cfg *cfg, int source)
1091{
1092 regmap_update_bits(arizona->regmap, base + 3,
1093 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1094 regmap_update_bits(arizona->regmap, base + 4,
1095 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1096 regmap_update_bits(arizona->regmap, base + 5,
1097 ARIZONA_FLL1_FRATIO_MASK,
1098 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1099 regmap_update_bits(arizona->regmap, base + 6,
1100 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1101 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1102 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1103 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1104
1105 regmap_update_bits(arizona->regmap, base + 2,
1106 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1107 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1108}
1109
1110int arizona_set_fll(struct arizona_fll *fll, int source,
1111 unsigned int Fref, unsigned int Fout)
1112{
1113 struct arizona *arizona = fll->arizona;
1114 struct arizona_fll_cfg cfg, sync;
1115 unsigned int reg, val;
1116 int syncsrc;
1117 bool ena;
1118 int ret;
1119
Mark Brown1cbe4bc2012-11-21 14:12:22 +09001120 if (fll->fref == Fref && fll->fout == Fout)
1121 return 0;
1122
Mark Brown07ed8732012-06-18 21:08:44 +01001123 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1124 if (ret != 0) {
1125 arizona_fll_err(fll, "Failed to read current state: %d\n",
1126 ret);
1127 return ret;
1128 }
1129 ena = reg & ARIZONA_FLL1_ENA;
1130
1131 if (Fout) {
1132 /* Do we have a 32kHz reference? */
1133 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1134 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1135 case ARIZONA_CLK_SRC_MCLK1:
1136 case ARIZONA_CLK_SRC_MCLK2:
1137 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
1138 break;
1139 default:
1140 syncsrc = -1;
1141 }
1142
1143 if (source == syncsrc)
1144 syncsrc = -1;
1145
1146 if (syncsrc >= 0) {
1147 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1148 if (ret != 0)
1149 return ret;
1150
1151 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
1152 if (ret != 0)
1153 return ret;
1154 } else {
1155 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
1156 if (ret != 0)
1157 return ret;
1158 }
1159 } else {
1160 regmap_update_bits(arizona->regmap, fll->base + 1,
1161 ARIZONA_FLL1_ENA, 0);
1162 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1163 ARIZONA_FLL1_SYNC_ENA, 0);
1164
1165 if (ena)
1166 pm_runtime_put_autosuspend(arizona->dev);
1167
Mark Brown50fcfe42012-11-28 11:50:34 +00001168 fll->fref = Fref;
1169 fll->fout = Fout;
1170
Mark Brown07ed8732012-06-18 21:08:44 +01001171 return 0;
1172 }
1173
1174 regmap_update_bits(arizona->regmap, fll->base + 5,
1175 ARIZONA_FLL1_OUTDIV_MASK,
1176 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1177
1178 if (syncsrc >= 0) {
1179 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
1180 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
1181 } else {
1182 arizona_apply_fll(arizona, fll->base, &cfg, source);
1183 }
1184
1185 if (!ena)
1186 pm_runtime_get(arizona->dev);
1187
1188 /* Clear any pending completions */
1189 try_wait_for_completion(&fll->ok);
1190
1191 regmap_update_bits(arizona->regmap, fll->base + 1,
1192 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
1193 if (syncsrc >= 0)
1194 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1195 ARIZONA_FLL1_SYNC_ENA,
1196 ARIZONA_FLL1_SYNC_ENA);
1197
1198 ret = wait_for_completion_timeout(&fll->ok,
Mark Brown09871a92012-12-06 15:29:34 +09001199 msecs_to_jiffies(250));
Mark Brown07ed8732012-06-18 21:08:44 +01001200 if (ret == 0)
1201 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1202
Mark Brown1cbe4bc2012-11-21 14:12:22 +09001203 fll->fref = Fref;
1204 fll->fout = Fout;
1205
Mark Brown07ed8732012-06-18 21:08:44 +01001206 return 0;
1207}
1208EXPORT_SYMBOL_GPL(arizona_set_fll);
1209
1210int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1211 int ok_irq, struct arizona_fll *fll)
1212{
1213 int ret;
1214
Mark Brown07ed8732012-06-18 21:08:44 +01001215 init_completion(&fll->ok);
1216
1217 fll->id = id;
1218 fll->base = base;
1219 fll->arizona = arizona;
1220
1221 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1222 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1223 "FLL%d clock OK", id);
1224
Mark Brown07ed8732012-06-18 21:08:44 +01001225 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1226 arizona_fll_clock_ok, fll);
1227 if (ret != 0) {
1228 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1229 id, ret);
1230 }
1231
Charles Keepaxe31c1942013-01-07 16:41:45 +00001232 regmap_update_bits(arizona->regmap, fll->base + 1,
1233 ARIZONA_FLL1_FREERUN, 0);
1234
Mark Brown07ed8732012-06-18 21:08:44 +01001235 return 0;
1236}
1237EXPORT_SYMBOL_GPL(arizona_init_fll);
1238
Mark Brownbc9ab6d2013-01-04 19:31:00 +00001239/**
1240 * arizona_set_output_mode - Set the mode of the specified output
1241 *
1242 * @codec: Device to configure
1243 * @output: Output number
1244 * @diff: True to set the output to differential mode
1245 *
1246 * Some systems use external analogue switches to connect more
1247 * analogue devices to the CODEC than are supported by the device. In
1248 * some systems this requires changing the switched output from single
1249 * ended to differential mode dynamically at runtime, an operation
1250 * supported using this function.
1251 *
1252 * Most systems have a single static configuration and should use
1253 * platform data instead.
1254 */
1255int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1256{
1257 unsigned int reg, val;
1258
1259 if (output < 1 || output > 6)
1260 return -EINVAL;
1261
1262 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1263
1264 if (diff)
1265 val = ARIZONA_OUT1_MONO;
1266 else
1267 val = 0;
1268
1269 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1270}
1271EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1272
Mark Brown07ed8732012-06-18 21:08:44 +01001273MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1274MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1275MODULE_LICENSE("GPL");