ASoC: arizona: Add debug prints for output power up/down times
[linux-2.6-block.git] / sound / soc / codecs / arizona.c
CommitLineData
07ed873e
MB
1/*
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
ddbce97c 13#include <linux/delay.h>
07ed873e
MB
14#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
d0800342 55#define ARIZONA_FLL_VCO_CORNER 141900000
87383ac5
CK
56#define ARIZONA_FLL_MAX_FREF 13500000
57#define ARIZONA_FLL_MIN_FVCO 90000000
d0800342 58#define ARIZONA_FLL_MAX_FRATIO 16
87383ac5
CK
59#define ARIZONA_FLL_MAX_REFDIV 8
60#define ARIZONA_FLL_MIN_OUTDIV 2
61#define ARIZONA_FLL_MAX_OUTDIV 7
62
e9c7f34a
RF
63#define ARIZONA_FMT_DSP_MODE_A 0
64#define ARIZONA_FMT_DSP_MODE_B 1
65#define ARIZONA_FMT_I2S_MODE 2
66#define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3
67
07ed873e
MB
68#define arizona_fll_err(_fll, fmt, ...) \
69 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
70#define arizona_fll_warn(_fll, fmt, ...) \
71 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
72#define arizona_fll_dbg(_fll, fmt, ...) \
9092a6ea 73 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
07ed873e
MB
74
75#define arizona_aif_err(_dai, fmt, ...) \
76 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
77#define arizona_aif_warn(_dai, fmt, ...) \
78 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
79#define arizona_aif_dbg(_dai, fmt, ...) \
9092a6ea 80 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
07ed873e 81
56447e13
MB
82static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
83 struct snd_kcontrol *kcontrol,
84 int event)
85{
043123fd 86 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
56447e13 87 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
f4a76e7c 88 int val;
56447e13 89
56447e13 90 switch (event) {
56447e13 91 case SND_SOC_DAPM_POST_PMU:
f4a76e7c 92 val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
c0fe2c5b 93 if (val & ARIZONA_SPK_OVERHEAT_STS) {
f4a76e7c
MB
94 dev_crit(arizona->dev,
95 "Speaker not enabled due to temperature\n");
96 return -EBUSY;
97 }
98
3c43c695
MB
99 regmap_update_bits_async(arizona->regmap,
100 ARIZONA_OUTPUT_ENABLES_1,
101 1 << w->shift, 1 << w->shift);
56447e13
MB
102 break;
103 case SND_SOC_DAPM_PRE_PMD:
3c43c695
MB
104 regmap_update_bits_async(arizona->regmap,
105 ARIZONA_OUTPUT_ENABLES_1,
106 1 << w->shift, 0);
56447e13 107 break;
bee261b8
CK
108 default:
109 break;
56447e13
MB
110 }
111
112 return 0;
113}
114
899817e2
MB
115static irqreturn_t arizona_thermal_warn(int irq, void *data)
116{
117 struct arizona *arizona = data;
118 unsigned int val;
119 int ret;
120
121 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
122 &val);
123 if (ret != 0) {
124 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
125 ret);
c0fe2c5b 126 } else if (val & ARIZONA_SPK_OVERHEAT_WARN_STS) {
899817e2
MB
127 dev_crit(arizona->dev, "Thermal warning\n");
128 }
129
130 return IRQ_HANDLED;
131}
132
133static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
134{
135 struct arizona *arizona = data;
136 unsigned int val;
137 int ret;
138
139 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
140 &val);
141 if (ret != 0) {
142 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
143 ret);
c0fe2c5b 144 } else if (val & ARIZONA_SPK_OVERHEAT_STS) {
899817e2 145 dev_crit(arizona->dev, "Thermal shutdown\n");
f4a76e7c
MB
146 ret = regmap_update_bits(arizona->regmap,
147 ARIZONA_OUTPUT_ENABLES_1,
148 ARIZONA_OUT4L_ENA |
149 ARIZONA_OUT4R_ENA, 0);
150 if (ret != 0)
151 dev_crit(arizona->dev,
152 "Failed to disable speaker outputs: %d\n",
153 ret);
899817e2
MB
154 }
155
156 return IRQ_HANDLED;
157}
158
56447e13 159static const struct snd_soc_dapm_widget arizona_spkl =
f4a76e7c 160 SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
56447e13
MB
161 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
162 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
163
164static const struct snd_soc_dapm_widget arizona_spkr =
f4a76e7c 165 SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
56447e13
MB
166 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
167 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
168
169int arizona_init_spk(struct snd_soc_codec *codec)
170{
1ac52145 171 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
899817e2
MB
172 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
173 struct arizona *arizona = priv->arizona;
56447e13
MB
174 int ret;
175
1ac52145 176 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1);
56447e13
MB
177 if (ret != 0)
178 return ret;
179
40843aea
CK
180 switch (arizona->type) {
181 case WM8997:
43b27d72
RF
182 case CS47L24:
183 case WM1831:
40843aea
CK
184 break;
185 default:
1ac52145 186 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
40843aea
CK
187 if (ret != 0)
188 return ret;
189 break;
190 }
56447e13 191
c0fe2c5b 192 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
899817e2
MB
193 "Thermal warning", arizona_thermal_warn,
194 arizona);
195 if (ret != 0)
196 dev_err(arizona->dev,
197 "Failed to get thermal warning IRQ: %d\n",
198 ret);
199
c0fe2c5b 200 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT,
899817e2
MB
201 "Thermal shutdown", arizona_thermal_shutdown,
202 arizona);
203 if (ret != 0)
204 dev_err(arizona->dev,
205 "Failed to get thermal shutdown IRQ: %d\n",
206 ret);
207
56447e13
MB
208 return 0;
209}
210EXPORT_SYMBOL_GPL(arizona_init_spk);
211
54dca701
CK
212int arizona_free_spk(struct snd_soc_codec *codec)
213{
214 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
215 struct arizona *arizona = priv->arizona;
216
217 arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
218 arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
219
220 return 0;
221}
222EXPORT_SYMBOL_GPL(arizona_free_spk);
223
b60f363b
CK
224static const struct snd_soc_dapm_route arizona_mono_routes[] = {
225 { "OUT1R", NULL, "OUT1L" },
226 { "OUT2R", NULL, "OUT2L" },
227 { "OUT3R", NULL, "OUT3L" },
228 { "OUT4R", NULL, "OUT4L" },
229 { "OUT5R", NULL, "OUT5L" },
230 { "OUT6R", NULL, "OUT6L" },
231};
232
233int arizona_init_mono(struct snd_soc_codec *codec)
234{
1ac52145 235 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
b60f363b
CK
236 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
237 struct arizona *arizona = priv->arizona;
238 int i;
239
240 for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
241 if (arizona->pdata.out_mono[i])
1ac52145 242 snd_soc_dapm_add_routes(dapm,
b60f363b
CK
243 &arizona_mono_routes[i], 1);
244 }
245
246 return 0;
247}
248EXPORT_SYMBOL_GPL(arizona_init_mono);
249
b63144e6
CK
250int arizona_init_gpio(struct snd_soc_codec *codec)
251{
1ac52145 252 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
b63144e6
CK
253 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
254 struct arizona *arizona = priv->arizona;
255 int i;
256
257 switch (arizona->type) {
258 case WM5110:
575ef7f6 259 case WM8280:
1ac52145 260 snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
b79fae60
CK
261 break;
262 default:
263 break;
b63144e6
CK
264 }
265
1ac52145 266 snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
b63144e6
CK
267
268 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
269 switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
270 case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
1ac52145 271 snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
b63144e6
CK
272 break;
273 case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
1ac52145 274 snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
b63144e6
CK
275 break;
276 default:
277 break;
278 }
279 }
280
281 return 0;
282}
283EXPORT_SYMBOL_GPL(arizona_init_gpio);
284
2230c49f
CK
285int arizona_init_notifiers(struct snd_soc_codec *codec)
286{
287 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
288 struct arizona *arizona = priv->arizona;
289
290 BLOCKING_INIT_NOTIFIER_HEAD(&arizona->notifier);
291
292 return 0;
293}
294EXPORT_SYMBOL_GPL(arizona_init_notifiers);
295
141bc6a6 296const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
07ed873e
MB
297 "None",
298 "Tone Generator 1",
299 "Tone Generator 2",
300 "Haptics",
301 "AEC",
6ebbce0a 302 "AEC2",
07ed873e
MB
303 "Mic Mute Mixer",
304 "Noise Generator",
305 "IN1L",
306 "IN1R",
307 "IN2L",
308 "IN2R",
309 "IN3L",
310 "IN3R",
c9c56fd0
MB
311 "IN4L",
312 "IN4R",
07ed873e
MB
313 "AIF1RX1",
314 "AIF1RX2",
315 "AIF1RX3",
316 "AIF1RX4",
317 "AIF1RX5",
318 "AIF1RX6",
319 "AIF1RX7",
320 "AIF1RX8",
321 "AIF2RX1",
322 "AIF2RX2",
e64001e8
RF
323 "AIF2RX3",
324 "AIF2RX4",
325 "AIF2RX5",
326 "AIF2RX6",
07ed873e
MB
327 "AIF3RX1",
328 "AIF3RX2",
329 "SLIMRX1",
330 "SLIMRX2",
331 "SLIMRX3",
332 "SLIMRX4",
333 "SLIMRX5",
334 "SLIMRX6",
335 "SLIMRX7",
336 "SLIMRX8",
337 "EQ1",
338 "EQ2",
339 "EQ3",
340 "EQ4",
341 "DRC1L",
342 "DRC1R",
343 "DRC2L",
344 "DRC2R",
345 "LHPF1",
346 "LHPF2",
347 "LHPF3",
348 "LHPF4",
349 "DSP1.1",
350 "DSP1.2",
351 "DSP1.3",
352 "DSP1.4",
353 "DSP1.5",
354 "DSP1.6",
c922cc4c
MB
355 "DSP2.1",
356 "DSP2.2",
357 "DSP2.3",
358 "DSP2.4",
359 "DSP2.5",
360 "DSP2.6",
361 "DSP3.1",
362 "DSP3.2",
363 "DSP3.3",
364 "DSP3.4",
365 "DSP3.5",
366 "DSP3.6",
367 "DSP4.1",
368 "DSP4.2",
369 "DSP4.3",
370 "DSP4.4",
371 "DSP4.5",
372 "DSP4.6",
07ed873e
MB
373 "ASRC1L",
374 "ASRC1R",
375 "ASRC2L",
376 "ASRC2R",
91660bd6
MB
377 "ISRC1INT1",
378 "ISRC1INT2",
379 "ISRC1INT3",
380 "ISRC1INT4",
381 "ISRC1DEC1",
382 "ISRC1DEC2",
383 "ISRC1DEC3",
384 "ISRC1DEC4",
385 "ISRC2INT1",
386 "ISRC2INT2",
387 "ISRC2INT3",
388 "ISRC2INT4",
389 "ISRC2DEC1",
390 "ISRC2DEC2",
391 "ISRC2DEC3",
392 "ISRC2DEC4",
393 "ISRC3INT1",
394 "ISRC3INT2",
395 "ISRC3INT3",
396 "ISRC3INT4",
397 "ISRC3DEC1",
398 "ISRC3DEC2",
399 "ISRC3DEC3",
400 "ISRC3DEC4",
07ed873e
MB
401};
402EXPORT_SYMBOL_GPL(arizona_mixer_texts);
403
141bc6a6 404unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
07ed873e
MB
405 0x00, /* None */
406 0x04, /* Tone */
407 0x05,
408 0x06, /* Haptics */
409 0x08, /* AEC */
6ebbce0a 410 0x09, /* AEC2 */
07ed873e
MB
411 0x0c, /* Noise mixer */
412 0x0d, /* Comfort noise */
413 0x10, /* IN1L */
414 0x11,
415 0x12,
416 0x13,
417 0x14,
418 0x15,
c9c56fd0
MB
419 0x16,
420 0x17,
07ed873e
MB
421 0x20, /* AIF1RX1 */
422 0x21,
423 0x22,
424 0x23,
425 0x24,
426 0x25,
427 0x26,
428 0x27,
429 0x28, /* AIF2RX1 */
430 0x29,
e64001e8
RF
431 0x2a,
432 0x2b,
433 0x2c,
434 0x2d,
07ed873e
MB
435 0x30, /* AIF3RX1 */
436 0x31,
437 0x38, /* SLIMRX1 */
438 0x39,
439 0x3a,
440 0x3b,
441 0x3c,
442 0x3d,
443 0x3e,
444 0x3f,
445 0x50, /* EQ1 */
446 0x51,
447 0x52,
448 0x53,
449 0x58, /* DRC1L */
450 0x59,
451 0x5a,
452 0x5b,
453 0x60, /* LHPF1 */
454 0x61,
455 0x62,
456 0x63,
457 0x68, /* DSP1.1 */
458 0x69,
459 0x6a,
460 0x6b,
461 0x6c,
462 0x6d,
c922cc4c
MB
463 0x70, /* DSP2.1 */
464 0x71,
465 0x72,
466 0x73,
467 0x74,
468 0x75,
469 0x78, /* DSP3.1 */
470 0x79,
471 0x7a,
472 0x7b,
473 0x7c,
474 0x7d,
475 0x80, /* DSP4.1 */
476 0x81,
477 0x82,
478 0x83,
479 0x84,
480 0x85,
07ed873e
MB
481 0x90, /* ASRC1L */
482 0x91,
483 0x92,
484 0x93,
91660bd6
MB
485 0xa0, /* ISRC1INT1 */
486 0xa1,
487 0xa2,
488 0xa3,
489 0xa4, /* ISRC1DEC1 */
490 0xa5,
491 0xa6,
492 0xa7,
493 0xa8, /* ISRC2DEC1 */
494 0xa9,
495 0xaa,
496 0xab,
497 0xac, /* ISRC2INT1 */
498 0xad,
499 0xae,
500 0xaf,
501 0xb0, /* ISRC3DEC1 */
502 0xb1,
503 0xb2,
504 0xb3,
505 0xb4, /* ISRC3INT1 */
506 0xb5,
507 0xb6,
508 0xb7,
07ed873e
MB
509};
510EXPORT_SYMBOL_GPL(arizona_mixer_values);
511
512const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
513EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
514
6ebbce0a
RF
515const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
516 "12kHz", "24kHz", "48kHz", "96kHz", "192kHz",
517 "11.025kHz", "22.05kHz", "44.1kHz", "88.2kHz", "176.4kHz",
518 "4kHz", "8kHz", "16kHz", "32kHz",
519};
520EXPORT_SYMBOL_GPL(arizona_sample_rate_text);
521
522const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
523 0x01, 0x02, 0x03, 0x04, 0x05, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
524 0x10, 0x11, 0x12, 0x13,
525};
526EXPORT_SYMBOL_GPL(arizona_sample_rate_val);
527
528const char *arizona_sample_rate_val_to_name(unsigned int rate_val)
529{
530 int i;
531
532 for (i = 0; i < ARRAY_SIZE(arizona_sample_rate_val); ++i) {
533 if (arizona_sample_rate_val[i] == rate_val)
534 return arizona_sample_rate_text[i];
535 }
536
537 return "Illegal";
538}
539EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name);
540
141bc6a6 541const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
dc91428a
MB
542 "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
543};
544EXPORT_SYMBOL_GPL(arizona_rate_text);
545
141bc6a6 546const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
dc91428a
MB
547 0, 1, 2, 8,
548};
549EXPORT_SYMBOL_GPL(arizona_rate_val);
550
551
fbedc8cb
CK
552const struct soc_enum arizona_isrc_fsh[] = {
553 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1,
554 ARIZONA_ISRC1_FSH_SHIFT, 0xf,
555 ARIZONA_RATE_ENUM_SIZE,
556 arizona_rate_text, arizona_rate_val),
557 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1,
558 ARIZONA_ISRC2_FSH_SHIFT, 0xf,
559 ARIZONA_RATE_ENUM_SIZE,
560 arizona_rate_text, arizona_rate_val),
561 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1,
562 ARIZONA_ISRC3_FSH_SHIFT, 0xf,
563 ARIZONA_RATE_ENUM_SIZE,
564 arizona_rate_text, arizona_rate_val),
565};
566EXPORT_SYMBOL_GPL(arizona_isrc_fsh);
567
dc91428a
MB
568const struct soc_enum arizona_isrc_fsl[] = {
569 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
570 ARIZONA_ISRC1_FSL_SHIFT, 0xf,
571 ARIZONA_RATE_ENUM_SIZE,
572 arizona_rate_text, arizona_rate_val),
573 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
574 ARIZONA_ISRC2_FSL_SHIFT, 0xf,
575 ARIZONA_RATE_ENUM_SIZE,
576 arizona_rate_text, arizona_rate_val),
577 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
578 ARIZONA_ISRC3_FSL_SHIFT, 0xf,
579 ARIZONA_RATE_ENUM_SIZE,
580 arizona_rate_text, arizona_rate_val),
581};
582EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
583
56d37d85
CK
584const struct soc_enum arizona_asrc_rate1 =
585 SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1,
586 ARIZONA_ASRC_RATE1_SHIFT, 0xf,
587 ARIZONA_RATE_ENUM_SIZE - 1,
588 arizona_rate_text, arizona_rate_val);
589EXPORT_SYMBOL_GPL(arizona_asrc_rate1);
590
a3178a3e 591static const char * const arizona_vol_ramp_text[] = {
e853a00f
MB
592 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
593 "15ms/6dB", "30ms/6dB",
594};
595
27ca2c30
TI
596SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp,
597 ARIZONA_INPUT_VOLUME_RAMP,
598 ARIZONA_IN_VD_RAMP_SHIFT,
599 arizona_vol_ramp_text);
e853a00f
MB
600EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
601
27ca2c30
TI
602SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp,
603 ARIZONA_INPUT_VOLUME_RAMP,
604 ARIZONA_IN_VI_RAMP_SHIFT,
605 arizona_vol_ramp_text);
e853a00f
MB
606EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
607
27ca2c30
TI
608SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp,
609 ARIZONA_OUTPUT_VOLUME_RAMP,
610 ARIZONA_OUT_VD_RAMP_SHIFT,
611 arizona_vol_ramp_text);
e853a00f
MB
612EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
613
27ca2c30
TI
614SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp,
615 ARIZONA_OUTPUT_VOLUME_RAMP,
616 ARIZONA_OUT_VI_RAMP_SHIFT,
617 arizona_vol_ramp_text);
e853a00f
MB
618EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
619
a3178a3e 620static const char * const arizona_lhpf_mode_text[] = {
07ed873e
MB
621 "Low-pass", "High-pass"
622};
623
27ca2c30
TI
624SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode,
625 ARIZONA_HPLPF1_1,
626 ARIZONA_LHPF1_MODE_SHIFT,
627 arizona_lhpf_mode_text);
07ed873e
MB
628EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
629
27ca2c30
TI
630SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode,
631 ARIZONA_HPLPF2_1,
632 ARIZONA_LHPF2_MODE_SHIFT,
633 arizona_lhpf_mode_text);
07ed873e
MB
634EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
635
27ca2c30
TI
636SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode,
637 ARIZONA_HPLPF3_1,
638 ARIZONA_LHPF3_MODE_SHIFT,
639 arizona_lhpf_mode_text);
07ed873e
MB
640EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
641
27ca2c30
TI
642SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode,
643 ARIZONA_HPLPF4_1,
644 ARIZONA_LHPF4_MODE_SHIFT,
645 arizona_lhpf_mode_text);
07ed873e
MB
646EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
647
a3178a3e 648static const char * const arizona_ng_hold_text[] = {
845571cc
MB
649 "30ms", "120ms", "250ms", "500ms",
650};
651
27ca2c30
TI
652SOC_ENUM_SINGLE_DECL(arizona_ng_hold,
653 ARIZONA_NOISE_GATE_CONTROL,
654 ARIZONA_NGATE_HOLD_SHIFT,
655 arizona_ng_hold_text);
845571cc
MB
656EXPORT_SYMBOL_GPL(arizona_ng_hold);
657
254dc326
CK
658static const char * const arizona_in_hpf_cut_text[] = {
659 "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
660};
661
27ca2c30
TI
662SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum,
663 ARIZONA_HPF_CONTROL,
664 ARIZONA_IN_HPF_CUT_SHIFT,
665 arizona_in_hpf_cut_text);
254dc326
CK
666EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
667
c7f38435 668static const char * const arizona_in_dmic_osr_text[] = {
ef326f4b 669 "1.536MHz", "3.072MHz", "6.144MHz", "768kHz",
c7f38435
CK
670};
671
672const struct soc_enum arizona_in_dmic_osr[] = {
673 SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
674 ARRAY_SIZE(arizona_in_dmic_osr_text),
675 arizona_in_dmic_osr_text),
676 SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
677 ARRAY_SIZE(arizona_in_dmic_osr_text),
678 arizona_in_dmic_osr_text),
679 SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
680 ARRAY_SIZE(arizona_in_dmic_osr_text),
681 arizona_in_dmic_osr_text),
682 SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
683 ARRAY_SIZE(arizona_in_dmic_osr_text),
684 arizona_in_dmic_osr_text),
685};
686EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
687
d190106d
CK
688static const char * const arizona_anc_input_src_text[] = {
689 "None", "IN1", "IN2", "IN3", "IN4",
690};
691
692static const char * const arizona_anc_channel_src_text[] = {
693 "None", "Left", "Right", "Combine",
694};
695
696const struct soc_enum arizona_anc_input_src[] = {
697 SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
698 ARIZONA_IN_RXANCL_SEL_SHIFT,
699 ARRAY_SIZE(arizona_anc_input_src_text),
700 arizona_anc_input_src_text),
701 SOC_ENUM_SINGLE(ARIZONA_FCL_ADC_REFORMATTER_CONTROL,
702 ARIZONA_FCL_MIC_MODE_SEL,
703 ARRAY_SIZE(arizona_anc_channel_src_text),
704 arizona_anc_channel_src_text),
705 SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
706 ARIZONA_IN_RXANCR_SEL_SHIFT,
707 ARRAY_SIZE(arizona_anc_input_src_text),
708 arizona_anc_input_src_text),
709 SOC_ENUM_SINGLE(ARIZONA_FCR_ADC_REFORMATTER_CONTROL,
710 ARIZONA_FCR_MIC_MODE_SEL,
711 ARRAY_SIZE(arizona_anc_channel_src_text),
712 arizona_anc_channel_src_text),
713};
714EXPORT_SYMBOL_GPL(arizona_anc_input_src);
715
716static const char * const arizona_anc_ng_texts[] = {
717 "None",
718 "Internal",
719 "External",
720};
721
722SOC_ENUM_SINGLE_DECL(arizona_anc_ng_enum, SND_SOC_NOPM, 0,
723 arizona_anc_ng_texts);
724EXPORT_SYMBOL_GPL(arizona_anc_ng_enum);
725
726static const char * const arizona_output_anc_src_text[] = {
727 "None", "RXANCL", "RXANCR",
728};
729
730const struct soc_enum arizona_output_anc_src[] = {
731 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
732 ARIZONA_OUT1L_ANC_SRC_SHIFT,
733 ARRAY_SIZE(arizona_output_anc_src_text),
734 arizona_output_anc_src_text),
735 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1R,
736 ARIZONA_OUT1R_ANC_SRC_SHIFT,
737 ARRAY_SIZE(arizona_output_anc_src_text),
738 arizona_output_anc_src_text),
739 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
740 ARIZONA_OUT2L_ANC_SRC_SHIFT,
741 ARRAY_SIZE(arizona_output_anc_src_text),
742 arizona_output_anc_src_text),
743 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2R,
744 ARIZONA_OUT2R_ANC_SRC_SHIFT,
745 ARRAY_SIZE(arizona_output_anc_src_text),
746 arizona_output_anc_src_text),
747 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
748 ARIZONA_OUT3L_ANC_SRC_SHIFT,
749 ARRAY_SIZE(arizona_output_anc_src_text),
750 arizona_output_anc_src_text),
751 SOC_ENUM_SINGLE(ARIZONA_DAC_VOLUME_LIMIT_3R,
752 ARIZONA_OUT3R_ANC_SRC_SHIFT,
753 ARRAY_SIZE(arizona_output_anc_src_text),
754 arizona_output_anc_src_text),
755 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4L,
756 ARIZONA_OUT4L_ANC_SRC_SHIFT,
757 ARRAY_SIZE(arizona_output_anc_src_text),
758 arizona_output_anc_src_text),
759 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4R,
760 ARIZONA_OUT4R_ANC_SRC_SHIFT,
761 ARRAY_SIZE(arizona_output_anc_src_text),
762 arizona_output_anc_src_text),
763 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5L,
764 ARIZONA_OUT5L_ANC_SRC_SHIFT,
765 ARRAY_SIZE(arizona_output_anc_src_text),
766 arizona_output_anc_src_text),
767 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5R,
768 ARIZONA_OUT5R_ANC_SRC_SHIFT,
769 ARRAY_SIZE(arizona_output_anc_src_text),
770 arizona_output_anc_src_text),
771 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6L,
772 ARIZONA_OUT6L_ANC_SRC_SHIFT,
773 ARRAY_SIZE(arizona_output_anc_src_text),
774 arizona_output_anc_src_text),
775 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6R,
776 ARIZONA_OUT6R_ANC_SRC_SHIFT,
777 ARRAY_SIZE(arizona_output_anc_src_text),
778 arizona_output_anc_src_text),
779};
780EXPORT_SYMBOL_GPL(arizona_output_anc_src);
781
97126ce8
CK
782const struct snd_kcontrol_new arizona_voice_trigger_switch[] = {
783 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
784 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 1, 1, 0),
785 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 2, 1, 0),
786 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 3, 1, 0),
787};
788EXPORT_SYMBOL_GPL(arizona_voice_trigger_switch);
789
ddbce97c
MB
790static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
791{
792 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
793 unsigned int val;
794 int i;
795
796 if (ena)
797 val = ARIZONA_IN_VU;
798 else
799 val = 0;
800
801 for (i = 0; i < priv->num_inputs; i++)
802 snd_soc_update_bits(codec,
803 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
804 ARIZONA_IN_VU, val);
805}
806
002b083b
CK
807bool arizona_input_analog(struct snd_soc_codec *codec, int shift)
808{
809 unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8);
810 unsigned int val = snd_soc_read(codec, reg);
811
812 return !(val & ARIZONA_IN1_MODE_MASK);
813}
814EXPORT_SYMBOL_GPL(arizona_input_analog);
815
07ed873e
MB
816int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
817 int event)
818{
043123fd
LPC
819 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
820 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
43cd8bf1
MB
821 unsigned int reg;
822
823 if (w->shift % 2)
824 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
825 else
826 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
827
828 switch (event) {
ddbce97c
MB
829 case SND_SOC_DAPM_PRE_PMU:
830 priv->in_pending++;
831 break;
43cd8bf1 832 case SND_SOC_DAPM_POST_PMU:
043123fd 833 snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);
ddbce97c
MB
834
835 /* If this is the last input pending then allow VU */
836 priv->in_pending--;
837 if (priv->in_pending == 0) {
838 msleep(1);
043123fd 839 arizona_in_set_vu(codec, 1);
ddbce97c 840 }
43cd8bf1
MB
841 break;
842 case SND_SOC_DAPM_PRE_PMD:
043123fd 843 snd_soc_update_bits(codec, reg,
ddbce97c
MB
844 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
845 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
43cd8bf1 846 break;
ddbce97c
MB
847 case SND_SOC_DAPM_POST_PMD:
848 /* Disable volume updates if no inputs are enabled */
043123fd 849 reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);
ddbce97c 850 if (reg == 0)
043123fd 851 arizona_in_set_vu(codec, 0);
bee261b8
CK
852 break;
853 default:
854 break;
43cd8bf1
MB
855 }
856
07ed873e
MB
857 return 0;
858}
859EXPORT_SYMBOL_GPL(arizona_in_ev);
860
861int arizona_out_ev(struct snd_soc_dapm_widget *w,
862 struct snd_kcontrol *kcontrol,
863 int event)
864{
60d66c9a
MB
865 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
866 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
054e1b48 867
1a2c7d56 868 switch (event) {
e1ae5fba
CK
869 case SND_SOC_DAPM_PRE_PMU:
870 switch (w->shift) {
871 case ARIZONA_OUT1L_ENA_SHIFT:
872 case ARIZONA_OUT1R_ENA_SHIFT:
873 case ARIZONA_OUT2L_ENA_SHIFT:
874 case ARIZONA_OUT2R_ENA_SHIFT:
875 case ARIZONA_OUT3L_ENA_SHIFT:
876 case ARIZONA_OUT3R_ENA_SHIFT:
877 priv->out_up_pending++;
878 priv->out_up_delay += 17;
879 break;
880 default:
881 break;
882 }
883 break;
1a2c7d56
MB
884 case SND_SOC_DAPM_POST_PMU:
885 switch (w->shift) {
886 case ARIZONA_OUT1L_ENA_SHIFT:
887 case ARIZONA_OUT1R_ENA_SHIFT:
888 case ARIZONA_OUT2L_ENA_SHIFT:
889 case ARIZONA_OUT2R_ENA_SHIFT:
890 case ARIZONA_OUT3L_ENA_SHIFT:
891 case ARIZONA_OUT3R_ENA_SHIFT:
e1ae5fba
CK
892 priv->out_up_pending--;
893 if (!priv->out_up_pending) {
d605bd02
CK
894 dev_dbg(codec->dev, "Power up delay: %d\n",
895 priv->out_up_delay);
e1ae5fba
CK
896 msleep(priv->out_up_delay);
897 priv->out_up_delay = 0;
898 }
1a2c7d56
MB
899 break;
900
901 default:
902 break;
903 }
904 break;
054e1b48
CK
905 case SND_SOC_DAPM_PRE_PMD:
906 switch (w->shift) {
907 case ARIZONA_OUT1L_ENA_SHIFT:
908 case ARIZONA_OUT1R_ENA_SHIFT:
909 case ARIZONA_OUT2L_ENA_SHIFT:
910 case ARIZONA_OUT2R_ENA_SHIFT:
911 case ARIZONA_OUT3L_ENA_SHIFT:
912 case ARIZONA_OUT3R_ENA_SHIFT:
913 priv->out_down_pending++;
914 priv->out_down_delay++;
915 break;
916 default:
917 break;
918 }
919 break;
920 case SND_SOC_DAPM_POST_PMD:
921 switch (w->shift) {
922 case ARIZONA_OUT1L_ENA_SHIFT:
923 case ARIZONA_OUT1R_ENA_SHIFT:
924 case ARIZONA_OUT2L_ENA_SHIFT:
925 case ARIZONA_OUT2R_ENA_SHIFT:
926 case ARIZONA_OUT3L_ENA_SHIFT:
927 case ARIZONA_OUT3R_ENA_SHIFT:
928 priv->out_down_pending--;
929 if (!priv->out_down_pending) {
d605bd02
CK
930 dev_dbg(codec->dev, "Power down delay: %d\n",
931 priv->out_down_delay);
054e1b48
CK
932 msleep(priv->out_down_delay);
933 priv->out_down_delay = 0;
934 }
935 break;
936 default:
937 break;
938 }
939 break;
bee261b8
CK
940 default:
941 break;
1a2c7d56
MB
942 }
943
07ed873e
MB
944 return 0;
945}
946EXPORT_SYMBOL_GPL(arizona_out_ev);
947
f607e31c
MB
948int arizona_hp_ev(struct snd_soc_dapm_widget *w,
949 struct snd_kcontrol *kcontrol,
950 int event)
951{
043123fd
LPC
952 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
953 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
3c43c695 954 struct arizona *arizona = priv->arizona;
f607e31c
MB
955 unsigned int mask = 1 << w->shift;
956 unsigned int val;
957
958 switch (event) {
959 case SND_SOC_DAPM_POST_PMU:
960 val = mask;
961 break;
962 case SND_SOC_DAPM_PRE_PMD:
963 val = 0;
964 break;
e1ae5fba 965 case SND_SOC_DAPM_PRE_PMU:
054e1b48
CK
966 case SND_SOC_DAPM_POST_PMD:
967 return arizona_out_ev(w, kcontrol, event);
f607e31c
MB
968 default:
969 return -EINVAL;
970 }
971
972 /* Store the desired state for the HP outputs */
973 priv->arizona->hp_ena &= ~mask;
974 priv->arizona->hp_ena |= val;
975
112bdfaa
CK
976 /* Force off if HPDET clamp is active */
977 if (priv->arizona->hpdet_clamp)
f607e31c
MB
978 val = 0;
979
3c43c695
MB
980 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
981 mask, val);
f607e31c
MB
982
983 return arizona_out_ev(w, kcontrol, event);
984}
985EXPORT_SYMBOL_GPL(arizona_hp_ev);
986
346d9683
RF
987static int arizona_dvfs_enable(struct snd_soc_codec *codec)
988{
989 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
990 struct arizona *arizona = priv->arizona;
991 int ret;
992
993 ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
994 if (ret) {
995 dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
996 return ret;
997 }
998
999 ret = regmap_update_bits(arizona->regmap,
1000 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1001 ARIZONA_SUBSYS_MAX_FREQ,
1002 ARIZONA_SUBSYS_MAX_FREQ);
1003 if (ret) {
1004 dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
1005 regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1006 return ret;
1007 }
1008
1009 return 0;
1010}
1011
1012static int arizona_dvfs_disable(struct snd_soc_codec *codec)
1013{
1014 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1015 struct arizona *arizona = priv->arizona;
1016 int ret;
1017
1018 ret = regmap_update_bits(arizona->regmap,
1019 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1020 ARIZONA_SUBSYS_MAX_FREQ, 0);
1021 if (ret) {
1022 dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
1023 return ret;
1024 }
1025
1026 ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1027 if (ret) {
1028 dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
1029 return ret;
1030 }
1031
1032 return 0;
1033}
1034
1035int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
1036{
1037 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1038 int ret = 0;
1039
1040 mutex_lock(&priv->dvfs_lock);
1041
1042 if (!priv->dvfs_cached && !priv->dvfs_reqs) {
1043 ret = arizona_dvfs_enable(codec);
1044 if (ret)
1045 goto err;
1046 }
1047
1048 priv->dvfs_reqs |= flags;
1049err:
1050 mutex_unlock(&priv->dvfs_lock);
1051 return ret;
1052}
1053EXPORT_SYMBOL_GPL(arizona_dvfs_up);
1054
1055int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
1056{
1057 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1058 unsigned int old_reqs;
1059 int ret = 0;
1060
1061 mutex_lock(&priv->dvfs_lock);
1062
1063 old_reqs = priv->dvfs_reqs;
1064 priv->dvfs_reqs &= ~flags;
1065
1066 if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
1067 ret = arizona_dvfs_disable(codec);
1068
1069 mutex_unlock(&priv->dvfs_lock);
1070 return ret;
1071}
1072EXPORT_SYMBOL_GPL(arizona_dvfs_down);
1073
1074int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
1075 struct snd_kcontrol *kcontrol, int event)
1076{
1077 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1078 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1079 int ret = 0;
1080
1081 mutex_lock(&priv->dvfs_lock);
1082
1083 switch (event) {
1084 case SND_SOC_DAPM_POST_PMU:
1085 if (priv->dvfs_reqs)
1086 ret = arizona_dvfs_enable(codec);
1087
1088 priv->dvfs_cached = false;
1089 break;
1090 case SND_SOC_DAPM_PRE_PMD:
1091 /* We must ensure DVFS is disabled before the codec goes into
1092 * suspend so that we are never in an illegal state of DVFS
1093 * enabled without enough DCVDD
1094 */
1095 priv->dvfs_cached = true;
1096
1097 if (priv->dvfs_reqs)
1098 ret = arizona_dvfs_disable(codec);
1099 break;
1100 default:
1101 break;
1102 }
1103
1104 mutex_unlock(&priv->dvfs_lock);
1105 return ret;
1106}
1107EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
1108
1109void arizona_init_dvfs(struct arizona_priv *priv)
1110{
1111 mutex_init(&priv->dvfs_lock);
1112}
1113EXPORT_SYMBOL_GPL(arizona_init_dvfs);
1114
d190106d
CK
1115int arizona_anc_ev(struct snd_soc_dapm_widget *w,
1116 struct snd_kcontrol *kcontrol,
1117 int event)
1118{
1119 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
d190106d
CK
1120 unsigned int val;
1121
1122 switch (event) {
1123 case SND_SOC_DAPM_POST_PMU:
1124 val = 1 << w->shift;
1125 break;
1126 case SND_SOC_DAPM_PRE_PMD:
1127 val = 1 << (w->shift + 1);
1128 break;
1129 default:
1130 return 0;
1131 }
1132
2ab8e744 1133 snd_soc_write(codec, ARIZONA_CLOCK_CONTROL, val);
d190106d
CK
1134
1135 return 0;
1136}
1137EXPORT_SYMBOL_GPL(arizona_anc_ev);
1138
341604ad 1139static unsigned int arizona_opclk_ref_48k_rates[] = {
cbd840da
MB
1140 6144000,
1141 12288000,
96e1f18f 1142 24576000,
cbd840da
MB
1143 49152000,
1144};
1145
341604ad 1146static unsigned int arizona_opclk_ref_44k1_rates[] = {
cbd840da
MB
1147 5644800,
1148 11289600,
96e1f18f 1149 22579200,
cbd840da
MB
1150 45158400,
1151};
1152
1153static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
1154 unsigned int freq)
1155{
1156 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1157 unsigned int reg;
1158 unsigned int *rates;
1159 int ref, div, refclk;
1160
1161 switch (clk) {
1162 case ARIZONA_CLK_OPCLK:
1163 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
1164 refclk = priv->sysclk;
1165 break;
1166 case ARIZONA_CLK_ASYNC_OPCLK:
1167 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
1168 refclk = priv->asyncclk;
1169 break;
1170 default:
1171 return -EINVAL;
1172 }
1173
1174 if (refclk % 8000)
341604ad 1175 rates = arizona_opclk_ref_44k1_rates;
cbd840da 1176 else
341604ad 1177 rates = arizona_opclk_ref_48k_rates;
cbd840da 1178
341604ad 1179 for (ref = 0; ref < ARRAY_SIZE(arizona_opclk_ref_48k_rates) &&
cbd840da
MB
1180 rates[ref] <= refclk; ref++) {
1181 div = 1;
1182 while (rates[ref] / div >= freq && div < 32) {
1183 if (rates[ref] / div == freq) {
1184 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
1185 freq);
1186 snd_soc_update_bits(codec, reg,
1187 ARIZONA_OPCLK_DIV_MASK |
1188 ARIZONA_OPCLK_SEL_MASK,
1189 (div <<
1190 ARIZONA_OPCLK_DIV_SHIFT) |
1191 ref);
1192 return 0;
1193 }
1194 div++;
1195 }
1196 }
1197
1198 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
1199 return -EINVAL;
1200}
1201
07ed873e
MB
1202int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1203 int source, unsigned int freq, int dir)
1204{
1205 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1206 struct arizona *arizona = priv->arizona;
1207 char *name;
1208 unsigned int reg;
1209 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
1210 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
1f0e1eae 1211 int *clk;
07ed873e
MB
1212
1213 switch (clk_id) {
1214 case ARIZONA_CLK_SYSCLK:
1215 name = "SYSCLK";
1216 reg = ARIZONA_SYSTEM_CLOCK_1;
1217 clk = &priv->sysclk;
1218 mask |= ARIZONA_SYSCLK_FRAC;
1219 break;
1220 case ARIZONA_CLK_ASYNCCLK:
1221 name = "ASYNCCLK";
1222 reg = ARIZONA_ASYNC_CLOCK_1;
1223 clk = &priv->asyncclk;
1224 break;
cbd840da
MB
1225 case ARIZONA_CLK_OPCLK:
1226 case ARIZONA_CLK_ASYNC_OPCLK:
1227 return arizona_set_opclk(codec, clk_id, freq);
07ed873e
MB
1228 default:
1229 return -EINVAL;
1230 }
1231
1232 switch (freq) {
1233 case 5644800:
1234 case 6144000:
1235 break;
1236 case 11289600:
1237 case 12288000:
3f341f74 1238 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1239 break;
1240 case 22579200:
1241 case 24576000:
3f341f74 1242 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1243 break;
1244 case 45158400:
1245 case 49152000:
3f341f74 1246 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e 1247 break;
38113360
MB
1248 case 67737600:
1249 case 73728000:
3f341f74 1250 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1251 break;
1252 case 90316800:
1253 case 98304000:
3f341f74 1254 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1255 break;
1256 case 135475200:
1257 case 147456000:
3f341f74 1258 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360 1259 break;
f2c26d48
MB
1260 case 0:
1261 dev_dbg(arizona->dev, "%s cleared\n", name);
1262 *clk = freq;
1263 return 0;
07ed873e
MB
1264 default:
1265 return -EINVAL;
1266 }
1267
1268 *clk = freq;
1269
1270 if (freq % 6144000)
1271 val |= ARIZONA_SYSCLK_FRAC;
1272
1273 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
1274
1275 return regmap_update_bits(arizona->regmap, reg, mask, val);
1276}
1277EXPORT_SYMBOL_GPL(arizona_set_sysclk);
1278
1279static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1280{
1281 struct snd_soc_codec *codec = dai->codec;
3c43c695
MB
1282 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1283 struct arizona *arizona = priv->arizona;
07ed873e
MB
1284 int lrclk, bclk, mode, base;
1285
1286 base = dai->driver->base;
1287
1288 lrclk = 0;
1289 bclk = 0;
1290
1291 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1292 case SND_SOC_DAIFMT_DSP_A:
e9c7f34a
RF
1293 mode = ARIZONA_FMT_DSP_MODE_A;
1294 break;
1295 case SND_SOC_DAIFMT_DSP_B:
1296 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1297 != SND_SOC_DAIFMT_CBM_CFM) {
1298 arizona_aif_err(dai, "DSP_B not valid in slave mode\n");
1299 return -EINVAL;
1300 }
1301 mode = ARIZONA_FMT_DSP_MODE_B;
07ed873e 1302 break;
07ed873e 1303 case SND_SOC_DAIFMT_I2S:
e9c7f34a
RF
1304 mode = ARIZONA_FMT_I2S_MODE;
1305 break;
1306 case SND_SOC_DAIFMT_LEFT_J:
1307 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1308 != SND_SOC_DAIFMT_CBM_CFM) {
1309 arizona_aif_err(dai, "LEFT_J not valid in slave mode\n");
1310 return -EINVAL;
1311 }
1312 mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE;
07ed873e 1313 break;
07ed873e
MB
1314 default:
1315 arizona_aif_err(dai, "Unsupported DAI format %d\n",
1316 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1317 return -EINVAL;
1318 }
1319
1320 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1321 case SND_SOC_DAIFMT_CBS_CFS:
1322 break;
1323 case SND_SOC_DAIFMT_CBS_CFM:
1324 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1325 break;
1326 case SND_SOC_DAIFMT_CBM_CFS:
1327 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1328 break;
1329 case SND_SOC_DAIFMT_CBM_CFM:
1330 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1331 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1332 break;
1333 default:
1334 arizona_aif_err(dai, "Unsupported master mode %d\n",
1335 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1336 return -EINVAL;
1337 }
1338
1339 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1340 case SND_SOC_DAIFMT_NB_NF:
1341 break;
1342 case SND_SOC_DAIFMT_IB_IF:
1343 bclk |= ARIZONA_AIF1_BCLK_INV;
1344 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1345 break;
1346 case SND_SOC_DAIFMT_IB_NF:
1347 bclk |= ARIZONA_AIF1_BCLK_INV;
1348 break;
1349 case SND_SOC_DAIFMT_NB_IF:
1350 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1351 break;
1352 default:
1353 return -EINVAL;
1354 }
1355
3c43c695
MB
1356 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
1357 ARIZONA_AIF1_BCLK_INV |
1358 ARIZONA_AIF1_BCLK_MSTR,
1359 bclk);
1360 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
1361 ARIZONA_AIF1TX_LRCLK_INV |
1362 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
1363 regmap_update_bits_async(arizona->regmap,
1364 base + ARIZONA_AIF_RX_PIN_CTRL,
1365 ARIZONA_AIF1RX_LRCLK_INV |
1366 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
1367 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
1368 ARIZONA_AIF1_FMT_MASK, mode);
07ed873e
MB
1369
1370 return 0;
1371}
1372
949e6bc7 1373static const int arizona_48k_bclk_rates[] = {
07ed873e
MB
1374 -1,
1375 48000,
1376 64000,
1377 96000,
1378 128000,
1379 192000,
1380 256000,
1381 384000,
1382 512000,
1383 768000,
1384 1024000,
1385 1536000,
1386 2048000,
1387 3072000,
1388 4096000,
1389 6144000,
1390 8192000,
1391 12288000,
1392 24576000,
1393};
1394
949e6bc7 1395static const int arizona_44k1_bclk_rates[] = {
07ed873e
MB
1396 -1,
1397 44100,
1398 58800,
1399 88200,
1400 117600,
1401 177640,
1402 235200,
1403 352800,
1404 470400,
1405 705600,
1406 940800,
1407 1411200,
1408 1881600,
4758be37 1409 2822400,
07ed873e
MB
1410 3763200,
1411 5644800,
1412 7526400,
1413 11289600,
1414 22579200,
1415};
1416
d81221ff 1417static const unsigned int arizona_sr_vals[] = {
07ed873e
MB
1418 0,
1419 12000,
1420 24000,
1421 48000,
1422 96000,
1423 192000,
1424 384000,
1425 768000,
1426 0,
1427 11025,
1428 22050,
1429 44100,
1430 88200,
1431 176400,
1432 352800,
1433 705600,
1434 4000,
1435 8000,
1436 16000,
1437 32000,
1438 64000,
1439 128000,
1440 256000,
1441 512000,
1442};
1443
d81221ff
CK
1444#define ARIZONA_48K_RATE_MASK 0x0F003E
1445#define ARIZONA_44K1_RATE_MASK 0x003E00
1446#define ARIZONA_RATE_MASK (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK)
1447
1448static const struct snd_pcm_hw_constraint_list arizona_constraint = {
1449 .count = ARRAY_SIZE(arizona_sr_vals),
1450 .list = arizona_sr_vals,
1451};
1452
5b2eec3f
MB
1453static int arizona_startup(struct snd_pcm_substream *substream,
1454 struct snd_soc_dai *dai)
1455{
1456 struct snd_soc_codec *codec = dai->codec;
1457 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1458 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
5b2eec3f
MB
1459 unsigned int base_rate;
1460
26eb5a9a
CK
1461 if (!substream->runtime)
1462 return 0;
1463
5b2eec3f
MB
1464 switch (dai_priv->clk) {
1465 case ARIZONA_CLK_SYSCLK:
1466 base_rate = priv->sysclk;
1467 break;
1468 case ARIZONA_CLK_ASYNCCLK:
1469 base_rate = priv->asyncclk;
1470 break;
1471 default:
1472 return 0;
1473 }
1474
f2c26d48 1475 if (base_rate == 0)
d81221ff
CK
1476 dai_priv->constraint.mask = ARIZONA_RATE_MASK;
1477 else if (base_rate % 8000)
1478 dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK;
5b2eec3f 1479 else
d81221ff 1480 dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK;
5b2eec3f
MB
1481
1482 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1483 SNDRV_PCM_HW_PARAM_RATE,
d81221ff 1484 &dai_priv->constraint);
5b2eec3f
MB
1485}
1486
cc9e9243
CK
1487static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1488 unsigned int rate)
1489{
1490 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1491 struct arizona *arizona = priv->arizona;
8019ff6c 1492 struct reg_sequence dac_comp[] = {
cc9e9243
CK
1493 { 0x80, 0x3 },
1494 { ARIZONA_DAC_COMP_1, 0 },
1495 { ARIZONA_DAC_COMP_2, 0 },
1496 { 0x80, 0x0 },
1497 };
1498
d74bcaae 1499 mutex_lock(&arizona->dac_comp_lock);
cc9e9243
CK
1500
1501 dac_comp[1].def = arizona->dac_comp_coeff;
1502 if (rate >= 176400)
1503 dac_comp[2].def = arizona->dac_comp_enabled;
1504
d74bcaae 1505 mutex_unlock(&arizona->dac_comp_lock);
cc9e9243
CK
1506
1507 regmap_multi_reg_write(arizona->regmap,
1508 dac_comp,
1509 ARRAY_SIZE(dac_comp));
1510}
1511
b272efc8
MB
1512static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1513 struct snd_pcm_hw_params *params,
1514 struct snd_soc_dai *dai)
1515{
1516 struct snd_soc_codec *codec = dai->codec;
1517 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1518 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1519 int base = dai->driver->base;
2c118b4c 1520 int i, sr_val, ret;
b272efc8
MB
1521
1522 /*
1523 * We will need to be more flexible than this in future,
1524 * currently we use a single sample rate for SYSCLK.
1525 */
1526 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1527 if (arizona_sr_vals[i] == params_rate(params))
1528 break;
1529 if (i == ARRAY_SIZE(arizona_sr_vals)) {
1530 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1531 params_rate(params));
1532 return -EINVAL;
1533 }
1534 sr_val = i;
1535
2c118b4c
RF
1536 switch (priv->arizona->type) {
1537 case WM5102:
1538 case WM8997:
1539 if (arizona_sr_vals[sr_val] >= 88200)
1540 ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
1541 else
1542 ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
1543
1544 if (ret) {
1545 arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
1546 return ret;
1547 }
1548 break;
1549 default:
1550 break;
1551 }
1552
b272efc8
MB
1553 switch (dai_priv->clk) {
1554 case ARIZONA_CLK_SYSCLK:
cc9e9243
CK
1555 switch (priv->arizona->type) {
1556 case WM5102:
1557 arizona_wm5102_set_dac_comp(codec,
1558 params_rate(params));
1559 break;
1560 default:
1561 break;
1562 }
1563
b272efc8
MB
1564 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1565 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1566 if (base)
1567 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1568 ARIZONA_AIF1_RATE_MASK, 0);
1569 break;
1570 case ARIZONA_CLK_ASYNCCLK:
1571 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
c24084db 1572 ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val);
b272efc8
MB
1573 if (base)
1574 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1575 ARIZONA_AIF1_RATE_MASK,
1576 8 << ARIZONA_AIF1_RATE_SHIFT);
1577 break;
1578 default:
1579 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1580 return -EINVAL;
1581 }
1582
1583 return 0;
1584}
1585
bedd4b19
RF
1586static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1587 int base, int bclk, int lrclk, int frame)
1588{
1589 int val;
1590
1591 val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1592 if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1593 return true;
1594
1595 val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1596 if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1597 return true;
1598
1599 val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1600 if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1601 ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1602 return true;
1603
1604 return false;
1605}
1606
07ed873e
MB
1607static int arizona_hw_params(struct snd_pcm_substream *substream,
1608 struct snd_pcm_hw_params *params,
1609 struct snd_soc_dai *dai)
1610{
1611 struct snd_soc_codec *codec = dai->codec;
c013b27a 1612 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
c94aa30e 1613 struct arizona *arizona = priv->arizona;
07ed873e
MB
1614 int base = dai->driver->base;
1615 const int *rates;
76bf969e 1616 int i, ret, val;
ed70f3a2 1617 int channels = params_channels(params);
c94aa30e 1618 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
ed70f3a2
CK
1619 int tdm_width = arizona->tdm_width[dai->id - 1];
1620 int tdm_slots = arizona->tdm_slots[dai->id - 1];
c94aa30e 1621 int bclk, lrclk, wl, frame, bclk_target;
bedd4b19
RF
1622 bool reconfig;
1623 unsigned int aif_tx_state, aif_rx_state;
07ed873e 1624
e73694d8 1625 if (params_rate(params) % 4000)
949e6bc7 1626 rates = &arizona_44k1_bclk_rates[0];
07ed873e 1627 else
949e6bc7 1628 rates = &arizona_48k_bclk_rates[0];
07ed873e 1629
5ed68f0a 1630 wl = params_width(params);
d114e5f7 1631
ed70f3a2
CK
1632 if (tdm_slots) {
1633 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
1634 tdm_slots, tdm_width);
1635 bclk_target = tdm_slots * tdm_width * params_rate(params);
1636 channels = tdm_slots;
1637 } else {
1638 bclk_target = snd_soc_params_to_bclk(params);
d114e5f7 1639 tdm_width = wl;
ed70f3a2
CK
1640 }
1641
1642 if (chan_limit && chan_limit < channels) {
c94aa30e 1643 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
ed70f3a2 1644 bclk_target /= channels;
c94aa30e
MB
1645 bclk_target *= chan_limit;
1646 }
1647
ed70f3a2 1648 /* Force multiple of 2 channels for I2S mode */
76bf969e 1649 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
e9c7f34a
RF
1650 val &= ARIZONA_AIF1_FMT_MASK;
1651 if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) {
76bf969e 1652 arizona_aif_dbg(dai, "Forcing stereo mode\n");
ed70f3a2
CK
1653 bclk_target /= channels;
1654 bclk_target *= channels + 1;
76bf969e
MB
1655 }
1656
949e6bc7 1657 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
c94aa30e 1658 if (rates[i] >= bclk_target &&
5001765f 1659 rates[i] % params_rate(params) == 0) {
07ed873e
MB
1660 bclk = i;
1661 break;
1662 }
1663 }
949e6bc7 1664 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
07ed873e
MB
1665 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1666 params_rate(params));
1667 return -EINVAL;
1668 }
1669
b59e0f82 1670 lrclk = rates[bclk] / params_rate(params);
07ed873e
MB
1671
1672 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1673 rates[bclk], rates[bclk] / lrclk);
1674
d114e5f7 1675 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width;
07ed873e 1676
bedd4b19
RF
1677 reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1678
1679 if (reconfig) {
1680 /* Save AIF TX/RX state */
1681 aif_tx_state = snd_soc_read(codec,
1682 base + ARIZONA_AIF_TX_ENABLES);
1683 aif_rx_state = snd_soc_read(codec,
1684 base + ARIZONA_AIF_RX_ENABLES);
1685 /* Disable AIF TX/RX before reconfiguring it */
1686 regmap_update_bits_async(arizona->regmap,
1687 base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1688 regmap_update_bits(arizona->regmap,
1689 base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1690 }
1691
b272efc8
MB
1692 ret = arizona_hw_params_rate(substream, params, dai);
1693 if (ret != 0)
bedd4b19 1694 goto restore_aif;
c013b27a 1695
bedd4b19
RF
1696 if (reconfig) {
1697 regmap_update_bits_async(arizona->regmap,
1698 base + ARIZONA_AIF_BCLK_CTRL,
1699 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1700 regmap_update_bits_async(arizona->regmap,
1701 base + ARIZONA_AIF_TX_BCLK_RATE,
1702 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1703 regmap_update_bits_async(arizona->regmap,
1704 base + ARIZONA_AIF_RX_BCLK_RATE,
1705 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1706 regmap_update_bits_async(arizona->regmap,
1707 base + ARIZONA_AIF_FRAME_CTRL_1,
1708 ARIZONA_AIF1TX_WL_MASK |
1709 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1710 regmap_update_bits(arizona->regmap,
1711 base + ARIZONA_AIF_FRAME_CTRL_2,
1712 ARIZONA_AIF1RX_WL_MASK |
1713 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1714 }
07ed873e 1715
bedd4b19
RF
1716restore_aif:
1717 if (reconfig) {
1718 /* Restore AIF TX/RX state */
1719 regmap_update_bits_async(arizona->regmap,
1720 base + ARIZONA_AIF_TX_ENABLES,
1721 0xff, aif_tx_state);
1722 regmap_update_bits(arizona->regmap,
1723 base + ARIZONA_AIF_RX_ENABLES,
1724 0xff, aif_rx_state);
1725 }
1726 return ret;
07ed873e
MB
1727}
1728
410837a7
MB
1729static const char *arizona_dai_clk_str(int clk_id)
1730{
1731 switch (clk_id) {
1732 case ARIZONA_CLK_SYSCLK:
1733 return "SYSCLK";
1734 case ARIZONA_CLK_ASYNCCLK:
1735 return "ASYNCCLK";
1736 default:
1737 return "Unknown clock";
1738 }
1739}
1740
5b2eec3f
MB
1741static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1742 int clk_id, unsigned int freq, int dir)
1743{
1744 struct snd_soc_codec *codec = dai->codec;
1ac52145 1745 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
5b2eec3f
MB
1746 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1747 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
410837a7 1748 struct snd_soc_dapm_route routes[2];
5b2eec3f
MB
1749
1750 switch (clk_id) {
1751 case ARIZONA_CLK_SYSCLK:
1752 case ARIZONA_CLK_ASYNCCLK:
1753 break;
1754 default:
1755 return -EINVAL;
1756 }
1757
410837a7
MB
1758 if (clk_id == dai_priv->clk)
1759 return 0;
1760
1761 if (dai->active) {
5b2eec3f
MB
1762 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1763 dai->id);
1764 return -EBUSY;
1765 }
1766
c8d35a6a
MB
1767 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1768 arizona_dai_clk_str(clk_id));
1769
410837a7
MB
1770 memset(&routes, 0, sizeof(routes));
1771 routes[0].sink = dai->driver->capture.stream_name;
1772 routes[1].sink = dai->driver->playback.stream_name;
5b2eec3f 1773
410837a7
MB
1774 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1775 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1ac52145 1776 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7
MB
1777
1778 routes[0].source = arizona_dai_clk_str(clk_id);
1779 routes[1].source = arizona_dai_clk_str(clk_id);
1ac52145 1780 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7 1781
0c778e86
MB
1782 dai_priv->clk = clk_id;
1783
1ac52145 1784 return snd_soc_dapm_sync(dapm);
5b2eec3f
MB
1785}
1786
01df259f
MB
1787static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1788{
1789 struct snd_soc_codec *codec = dai->codec;
1790 int base = dai->driver->base;
1791 unsigned int reg;
1792
1793 if (tristate)
1794 reg = ARIZONA_AIF1_TRI;
1795 else
1796 reg = 0;
1797
1798 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1799 ARIZONA_AIF1_TRI, reg);
1800}
1801
ed70f3a2
CK
1802static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
1803 unsigned int base,
1804 int channels, unsigned int mask)
1805{
1806 struct snd_soc_codec *codec = dai->codec;
1807 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1808 struct arizona *arizona = priv->arizona;
1809 int slot, i;
1810
1811 for (i = 0; i < channels; ++i) {
1812 slot = ffs(mask) - 1;
1813 if (slot < 0)
1814 return;
1815
1816 regmap_write(arizona->regmap, base + i, slot);
1817
1818 mask &= ~(1 << slot);
1819 }
1820
1821 if (mask)
1822 arizona_aif_warn(dai, "Too many channels in TDM mask\n");
1823}
1824
1825static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1826 unsigned int rx_mask, int slots, int slot_width)
1827{
1828 struct snd_soc_codec *codec = dai->codec;
1829 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1830 struct arizona *arizona = priv->arizona;
1831 int base = dai->driver->base;
1832 int rx_max_chan = dai->driver->playback.channels_max;
1833 int tx_max_chan = dai->driver->capture.channels_max;
1834
1835 /* Only support TDM for the physical AIFs */
1836 if (dai->id > ARIZONA_MAX_AIF)
1837 return -ENOTSUPP;
1838
1839 if (slots == 0) {
1840 tx_mask = (1 << tx_max_chan) - 1;
1841 rx_mask = (1 << rx_max_chan) - 1;
1842 }
1843
1844 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
1845 tx_max_chan, tx_mask);
1846 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
1847 rx_max_chan, rx_mask);
1848
1849 arizona->tdm_width[dai->id - 1] = slot_width;
1850 arizona->tdm_slots[dai->id - 1] = slots;
1851
1852 return 0;
1853}
1854
07ed873e 1855const struct snd_soc_dai_ops arizona_dai_ops = {
5b2eec3f 1856 .startup = arizona_startup,
07ed873e 1857 .set_fmt = arizona_set_fmt,
ed70f3a2 1858 .set_tdm_slot = arizona_set_tdm_slot,
07ed873e 1859 .hw_params = arizona_hw_params,
5b2eec3f 1860 .set_sysclk = arizona_dai_set_sysclk,
01df259f 1861 .set_tristate = arizona_set_tristate,
07ed873e 1862};
a837987e 1863EXPORT_SYMBOL_GPL(arizona_dai_ops);
07ed873e 1864
bd1dd885
MB
1865const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1866 .startup = arizona_startup,
1867 .hw_params = arizona_hw_params_rate,
1868 .set_sysclk = arizona_dai_set_sysclk,
1869};
1870EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1871
5b2eec3f
MB
1872int arizona_init_dai(struct arizona_priv *priv, int id)
1873{
1874 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1875
1876 dai_priv->clk = ARIZONA_CLK_SYSCLK;
d81221ff 1877 dai_priv->constraint = arizona_constraint;
5b2eec3f
MB
1878
1879 return 0;
1880}
1881EXPORT_SYMBOL_GPL(arizona_init_dai);
1882
07ed873e
MB
1883static struct {
1884 unsigned int min;
1885 unsigned int max;
1886 u16 fratio;
1887 int ratio;
1888} fll_fratios[] = {
1889 { 0, 64000, 4, 16 },
1890 { 64000, 128000, 3, 8 },
1891 { 128000, 256000, 2, 4 },
1892 { 256000, 1000000, 1, 2 },
1893 { 1000000, 13500000, 0, 1 },
1894};
1895
01582a84
RF
1896static const unsigned int pseudo_fref_max[ARIZONA_FLL_MAX_FRATIO] = {
1897 13500000,
1898 6144000,
1899 6144000,
1900 3072000,
1901 3072000,
1902 2822400,
1903 2822400,
1904 1536000,
1905 1536000,
1906 1536000,
1907 1536000,
1908 1536000,
1909 1536000,
1910 1536000,
1911 1536000,
1912 768000,
1913};
1914
8f113d7d
MB
1915static struct {
1916 unsigned int min;
1917 unsigned int max;
1918 u16 gain;
1919} fll_gains[] = {
1920 { 0, 256000, 0 },
1921 { 256000, 1000000, 2 },
1922 { 1000000, 13500000, 4 },
1923};
1924
07ed873e
MB
1925struct arizona_fll_cfg {
1926 int n;
1927 int theta;
1928 int lambda;
1929 int refdiv;
1930 int outdiv;
1931 int fratio;
8f113d7d 1932 int gain;
07ed873e
MB
1933};
1934
23f785a8
CK
1935static int arizona_validate_fll(struct arizona_fll *fll,
1936 unsigned int Fref,
1937 unsigned int Fout)
07ed873e 1938{
23f785a8
CK
1939 unsigned int Fvco_min;
1940
c8badda8
CK
1941 if (fll->fout && Fout != fll->fout) {
1942 arizona_fll_err(fll,
1943 "Can't change output on active FLL\n");
1944 return -EINVAL;
1945 }
1946
23f785a8
CK
1947 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1948 arizona_fll_err(fll,
1949 "Can't scale %dMHz in to <=13.5MHz\n",
1950 Fref);
1951 return -EINVAL;
1952 }
07ed873e 1953
23f785a8
CK
1954 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1955 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1956 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1957 Fout);
1958 return -EINVAL;
1959 }
1960
1961 return 0;
1962}
1963
d0800342
CK
1964static int arizona_find_fratio(unsigned int Fref, int *fratio)
1965{
1966 int i;
1967
1968 /* Find an appropriate FLL_FRATIO */
1969 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1970 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1971 if (fratio)
1972 *fratio = fll_fratios[i].fratio;
1973 return fll_fratios[i].ratio;
1974 }
1975 }
1976
1977 return -EINVAL;
1978}
1979
1980static int arizona_calc_fratio(struct arizona_fll *fll,
1981 struct arizona_fll_cfg *cfg,
1982 unsigned int target,
1983 unsigned int Fref, bool sync)
1984{
1985 int init_ratio, ratio;
1986 int refdiv, div;
07ed873e 1987
d0800342 1988 /* Fref must be <=13.5MHz, find initial refdiv */
07ed873e
MB
1989 div = 1;
1990 cfg->refdiv = 0;
d0800342 1991 while (Fref > ARIZONA_FLL_MAX_FREF) {
07ed873e 1992 div *= 2;
d0800342 1993 Fref /= 2;
07ed873e
MB
1994 cfg->refdiv++;
1995
d0800342 1996 if (div > ARIZONA_FLL_MAX_REFDIV)
07ed873e 1997 return -EINVAL;
d0800342
CK
1998 }
1999
2000 /* Find an appropriate FLL_FRATIO */
2001 init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
2002 if (init_ratio < 0) {
2003 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
2004 Fref);
2005 return init_ratio;
2006 }
2007
2008 switch (fll->arizona->type) {
3451eb48
RF
2009 case WM5102:
2010 case WM8997:
2011 return init_ratio;
d0800342 2012 case WM5110:
575ef7f6 2013 case WM8280:
d0800342
CK
2014 if (fll->arizona->rev < 3 || sync)
2015 return init_ratio;
2016 break;
3451eb48 2017 default:
6ebbce0a
RF
2018 if (sync)
2019 return init_ratio;
2020 break;
d0800342
CK
2021 }
2022
2023 cfg->fratio = init_ratio - 1;
2024
2025 /* Adjust FRATIO/refdiv to avoid integer mode if possible */
2026 refdiv = cfg->refdiv;
2027
01582a84
RF
2028 arizona_fll_dbg(fll, "pseudo: initial ratio=%u fref=%u refdiv=%u\n",
2029 init_ratio, Fref, refdiv);
2030
d0800342 2031 while (div <= ARIZONA_FLL_MAX_REFDIV) {
8e42db1e
RF
2032 /* start from init_ratio because this may already give a
2033 * fractional N.K
2034 */
2035 for (ratio = init_ratio; ratio > 0; ratio--) {
2036 if (target % (ratio * Fref)) {
2037 cfg->refdiv = refdiv;
2038 cfg->fratio = ratio - 1;
2039 arizona_fll_dbg(fll,
2040 "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2041 Fref, refdiv, div, ratio);
2042 return ratio;
2043 }
2044 }
2045
2046 for (ratio = init_ratio + 1; ratio <= ARIZONA_FLL_MAX_FRATIO;
d0800342 2047 ratio++) {
35a730a0 2048 if ((ARIZONA_FLL_VCO_CORNER / 2) /
01582a84
RF
2049 (fll->vco_mult * ratio) < Fref) {
2050 arizona_fll_dbg(fll, "pseudo: hit VCO corner\n");
29fee829 2051 break;
01582a84
RF
2052 }
2053
2054 if (Fref > pseudo_fref_max[ratio - 1]) {
2055 arizona_fll_dbg(fll,
2056 "pseudo: exceeded max fref(%u) for ratio=%u\n",
2057 pseudo_fref_max[ratio - 1],
2058 ratio);
2059 break;
2060 }
29fee829 2061
d0800342
CK
2062 if (target % (ratio * Fref)) {
2063 cfg->refdiv = refdiv;
2064 cfg->fratio = ratio - 1;
01582a84
RF
2065 arizona_fll_dbg(fll,
2066 "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2067 Fref, refdiv, div, ratio);
d0800342 2068 return ratio;
d0800342
CK
2069 }
2070 }
2071
2072 div *= 2;
2073 Fref /= 2;
2074 refdiv++;
2075 init_ratio = arizona_find_fratio(Fref, NULL);
01582a84
RF
2076 arizona_fll_dbg(fll,
2077 "pseudo: change fref=%u refdiv=%d(%d) ratio=%u\n",
2078 Fref, refdiv, div, init_ratio);
07ed873e
MB
2079 }
2080
d0800342
CK
2081 arizona_fll_warn(fll, "Falling back to integer mode operation\n");
2082 return cfg->fratio + 1;
2083}
2084
07ed873e
MB
2085static int arizona_calc_fll(struct arizona_fll *fll,
2086 struct arizona_fll_cfg *cfg,
d0800342 2087 unsigned int Fref, bool sync)
07ed873e
MB
2088{
2089 unsigned int target, div, gcd_fll;
2090 int i, ratio;
2091
8ccefcd2 2092 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
07ed873e 2093
2b4d39fc 2094 /* Fvco should be over the targt; don't check the upper bound */
f641aec6
CK
2095 div = ARIZONA_FLL_MIN_OUTDIV;
2096 while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
07ed873e 2097 div++;
f641aec6 2098 if (div > ARIZONA_FLL_MAX_OUTDIV)
07ed873e 2099 return -EINVAL;
07ed873e 2100 }
f641aec6 2101 target = fll->fout * div / fll->vco_mult;
07ed873e
MB
2102 cfg->outdiv = div;
2103
2104 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
2105
d0800342
CK
2106 /* Find an appropriate FLL_FRATIO and refdiv */
2107 ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
2108 if (ratio < 0)
2109 return ratio;
07ed873e 2110
07ed873e 2111 /* Apply the division for our remaining calculations */
d0800342 2112 Fref = Fref / (1 << cfg->refdiv);
8f113d7d 2113
07ed873e
MB
2114 cfg->n = target / (ratio * Fref);
2115
01f58153 2116 if (target % (ratio * Fref)) {
07ed873e
MB
2117 gcd_fll = gcd(target, ratio * Fref);
2118 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
2119
2120 cfg->theta = (target - (cfg->n * ratio * Fref))
2121 / gcd_fll;
2122 cfg->lambda = (ratio * Fref) / gcd_fll;
2123 } else {
2124 cfg->theta = 0;
2125 cfg->lambda = 0;
2126 }
2127
01f58153
RT
2128 /* Round down to 16bit range with cost of accuracy lost.
2129 * Denominator must be bigger than numerator so we only
2130 * take care of it.
2131 */
2132 while (cfg->lambda >= (1 << 16)) {
2133 cfg->theta >>= 1;
2134 cfg->lambda >>= 1;
2135 }
2136
5a3935c7
CK
2137 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
2138 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
2139 cfg->gain = fll_gains[i].gain;
2140 break;
2141 }
2142 }
2143 if (i == ARRAY_SIZE(fll_gains)) {
2144 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
2145 Fref);
2146 return -EINVAL;
2147 }
2148
2595b7fe 2149 arizona_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
07ed873e 2150 cfg->n, cfg->theta, cfg->lambda);
2595b7fe
RF
2151 arizona_fll_dbg(fll, "FRATIO=0x%x(%d) OUTDIV=%d REFCLK_DIV=0x%x(%d)\n",
2152 cfg->fratio, ratio, cfg->outdiv,
2153 cfg->refdiv, 1 << cfg->refdiv);
2154 arizona_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
07ed873e
MB
2155
2156 return 0;
2157
2158}
2159
2160static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
8f113d7d
MB
2161 struct arizona_fll_cfg *cfg, int source,
2162 bool sync)
07ed873e 2163{
3c43c695
MB
2164 regmap_update_bits_async(arizona->regmap, base + 3,
2165 ARIZONA_FLL1_THETA_MASK, cfg->theta);
2166 regmap_update_bits_async(arizona->regmap, base + 4,
2167 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
2168 regmap_update_bits_async(arizona->regmap, base + 5,
2169 ARIZONA_FLL1_FRATIO_MASK,
2170 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
2171 regmap_update_bits_async(arizona->regmap, base + 6,
2172 ARIZONA_FLL1_CLK_REF_DIV_MASK |
2173 ARIZONA_FLL1_CLK_REF_SRC_MASK,
2174 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
2175 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
07ed873e 2176
61719db8
CK
2177 if (sync) {
2178 regmap_update_bits(arizona->regmap, base + 0x7,
2179 ARIZONA_FLL1_GAIN_MASK,
2180 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2181 } else {
2182 regmap_update_bits(arizona->regmap, base + 0x5,
2183 ARIZONA_FLL1_OUTDIV_MASK,
2184 cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
2185 regmap_update_bits(arizona->regmap, base + 0x9,
2186 ARIZONA_FLL1_GAIN_MASK,
2187 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2188 }
8f113d7d 2189
3c43c695
MB
2190 regmap_update_bits_async(arizona->regmap, base + 2,
2191 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
2192 ARIZONA_FLL1_CTRL_UPD | cfg->n);
07ed873e
MB
2193}
2194
62bb7104 2195static int arizona_is_enabled_fll(struct arizona_fll *fll, int base)
d122d6c9
CK
2196{
2197 struct arizona *arizona = fll->arizona;
2198 unsigned int reg;
2199 int ret;
2200
62bb7104 2201 ret = regmap_read(arizona->regmap, base + 1, &reg);
d122d6c9
CK
2202 if (ret != 0) {
2203 arizona_fll_err(fll, "Failed to read current state: %d\n",
2204 ret);
2205 return ret;
2206 }
2207
2208 return reg & ARIZONA_FLL1_ENA;
2209}
2210
c393aca9 2211static int arizona_enable_fll(struct arizona_fll *fll)
35722815
CK
2212{
2213 struct arizona *arizona = fll->arizona;
49c60547 2214 bool use_sync = false;
62bb7104 2215 int already_enabled = arizona_is_enabled_fll(fll, fll->base);
0f72a8a3 2216 int sync_enabled = arizona_is_enabled_fll(fll, fll->base + 0x10);
23f785a8 2217 struct arizona_fll_cfg cfg;
0e765971
CK
2218 int i;
2219 unsigned int val;
35722815 2220
c393aca9
CK
2221 if (already_enabled < 0)
2222 return already_enabled;
0f72a8a3
CK
2223 if (sync_enabled < 0)
2224 return sync_enabled;
c393aca9 2225
c8badda8
CK
2226 if (already_enabled) {
2227 /* Facilitate smooth refclk across the transition */
1cf5a330 2228 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
c8badda8 2229 ARIZONA_FLL1_GAIN_MASK, 0);
800f297e
CK
2230 regmap_update_bits(fll->arizona->regmap, fll->base + 1,
2231 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
2232 udelay(32);
c8badda8
CK
2233 }
2234
ff680a17
MB
2235 /*
2236 * If we have both REFCLK and SYNCCLK then enable both,
2237 * otherwise apply the SYNCCLK settings to REFCLK.
2238 */
49c60547
CK
2239 if (fll->ref_src >= 0 && fll->ref_freq &&
2240 fll->ref_src != fll->sync_src) {
d0800342 2241 arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
ff680a17 2242
23f785a8 2243 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
8f113d7d 2244 false);
49c60547 2245 if (fll->sync_src >= 0) {
d0800342 2246 arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
23f785a8
CK
2247
2248 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
8f113d7d 2249 fll->sync_src, true);
49c60547
CK
2250 use_sync = true;
2251 }
ff680a17 2252 } else if (fll->sync_src >= 0) {
d0800342 2253 arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
ff680a17 2254
23f785a8 2255 arizona_apply_fll(arizona, fll->base, &cfg,
8f113d7d 2256 fll->sync_src, false);
eca2e8e2 2257
3c43c695
MB
2258 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2259 ARIZONA_FLL1_SYNC_ENA, 0);
ff680a17
MB
2260 } else {
2261 arizona_fll_err(fll, "No clocks provided\n");
c393aca9 2262 return -EINVAL;
ff680a17 2263 }
35722815 2264
0f72a8a3
CK
2265 if (already_enabled && !!sync_enabled != use_sync)
2266 arizona_fll_warn(fll, "Synchroniser changed on active FLL\n");
2267
576411be
MB
2268 /*
2269 * Increase the bandwidth if we're not using a low frequency
2270 * sync source.
2271 */
49c60547 2272 if (use_sync && fll->sync_freq > 100000)
3c43c695
MB
2273 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2274 ARIZONA_FLL1_SYNC_BW, 0);
576411be 2275 else
3c43c695
MB
2276 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2277 ARIZONA_FLL1_SYNC_BW,
2278 ARIZONA_FLL1_SYNC_BW);
576411be 2279
c393aca9 2280 if (!already_enabled)
35722815
CK
2281 pm_runtime_get(arizona->dev);
2282
49c60547 2283 if (use_sync)
3c43c695
MB
2284 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2285 ARIZONA_FLL1_SYNC_ENA,
2286 ARIZONA_FLL1_SYNC_ENA);
0f72a8a3
CK
2287 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2288 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
35722815 2289
c8badda8
CK
2290 if (already_enabled)
2291 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2292 ARIZONA_FLL1_FREERUN, 0);
2293
0e765971
CK
2294 arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2295 val = 0;
2296 for (i = 0; i < 15; i++) {
2297 if (i < 5)
2298 usleep_range(200, 400);
2299 else
2300 msleep(20);
2301
2302 regmap_read(arizona->regmap,
2303 ARIZONA_INTERRUPT_RAW_STATUS_5,
2304 &val);
2305 if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2306 break;
2307 }
2308 if (i == 15)
35722815 2309 arizona_fll_warn(fll, "Timed out waiting for lock\n");
0e765971
CK
2310 else
2311 arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
c393aca9
CK
2312
2313 return 0;
35722815
CK
2314}
2315
7604054e
CK
2316static void arizona_disable_fll(struct arizona_fll *fll)
2317{
2318 struct arizona *arizona = fll->arizona;
2319 bool change;
2320
3c43c695
MB
2321 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2322 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
7604054e
CK
2323 regmap_update_bits_check(arizona->regmap, fll->base + 1,
2324 ARIZONA_FLL1_ENA, 0, &change);
2325 regmap_update_bits(arizona->regmap, fll->base + 0x11,
2326 ARIZONA_FLL1_SYNC_ENA, 0);
5e39a50b
CK
2327 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2328 ARIZONA_FLL1_FREERUN, 0);
7604054e
CK
2329
2330 if (change)
2331 pm_runtime_put_autosuspend(arizona->dev);
2332}
2333
ee929a97
CK
2334int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
2335 unsigned int Fref, unsigned int Fout)
2336{
c393aca9 2337 int ret = 0;
ee929a97 2338
1c5617fc 2339 if (fll->ref_src == source && fll->ref_freq == Fref)
ee929a97
CK
2340 return 0;
2341
23f785a8
CK
2342 if (fll->fout && Fref > 0) {
2343 ret = arizona_validate_fll(fll, Fref, fll->fout);
2344 if (ret != 0)
2345 return ret;
ee929a97
CK
2346 }
2347
2348 fll->ref_src = source;
2349 fll->ref_freq = Fref;
ee929a97 2350
86cd684f 2351 if (fll->fout && Fref > 0) {
c393aca9 2352 ret = arizona_enable_fll(fll);
ee929a97
CK
2353 }
2354
c393aca9 2355 return ret;
ee929a97
CK
2356}
2357EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
2358
07ed873e
MB
2359int arizona_set_fll(struct arizona_fll *fll, int source,
2360 unsigned int Fref, unsigned int Fout)
2361{
c393aca9 2362 int ret = 0;
07ed873e 2363
ff680a17
MB
2364 if (fll->sync_src == source &&
2365 fll->sync_freq == Fref && fll->fout == Fout)
2366 return 0;
9e359c64 2367
ff680a17
MB
2368 if (Fout) {
2369 if (fll->ref_src >= 0) {
23f785a8 2370 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
9e359c64
CK
2371 if (ret != 0)
2372 return ret;
2373 }
2374
23f785a8 2375 ret = arizona_validate_fll(fll, Fref, Fout);
ff680a17
MB
2376 if (ret != 0)
2377 return ret;
9e359c64 2378 }
ff680a17
MB
2379
2380 fll->sync_src = source;
2381 fll->sync_freq = Fref;
de1e6eed 2382 fll->fout = Fout;
9e359c64 2383
613124ce 2384 if (Fout)
c393aca9 2385 ret = arizona_enable_fll(fll);
613124ce 2386 else
7604054e 2387 arizona_disable_fll(fll);
07ed873e 2388
c393aca9 2389 return ret;
07ed873e
MB
2390}
2391EXPORT_SYMBOL_GPL(arizona_set_fll);
2392
2393int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2394 int ok_irq, struct arizona_fll *fll)
2395{
19b34bdc 2396 unsigned int val;
07ed873e 2397
07ed873e
MB
2398 fll->id = id;
2399 fll->base = base;
2400 fll->arizona = arizona;
f3f1163d 2401 fll->sync_src = ARIZONA_FLL_SRC_NONE;
07ed873e 2402
19b34bdc
CK
2403 /* Configure default refclk to 32kHz if we have one */
2404 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
2405 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
2406 case ARIZONA_CLK_SRC_MCLK1:
2407 case ARIZONA_CLK_SRC_MCLK2:
2408 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
2409 break;
2410 default:
f3f1163d 2411 fll->ref_src = ARIZONA_FLL_SRC_NONE;
19b34bdc
CK
2412 }
2413 fll->ref_freq = 32768;
2414
07ed873e
MB
2415 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
2416 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2417 "FLL%d clock OK", id);
2418
e31c1946
CK
2419 regmap_update_bits(arizona->regmap, fll->base + 1,
2420 ARIZONA_FLL1_FREERUN, 0);
2421
07ed873e
MB
2422 return 0;
2423}
2424EXPORT_SYMBOL_GPL(arizona_init_fll);
2425
bc9ab6d3
MB
2426/**
2427 * arizona_set_output_mode - Set the mode of the specified output
2428 *
2429 * @codec: Device to configure
2430 * @output: Output number
2431 * @diff: True to set the output to differential mode
2432 *
2433 * Some systems use external analogue switches to connect more
2434 * analogue devices to the CODEC than are supported by the device. In
2435 * some systems this requires changing the switched output from single
2436 * ended to differential mode dynamically at runtime, an operation
2437 * supported using this function.
2438 *
2439 * Most systems have a single static configuration and should use
2440 * platform data instead.
2441 */
2442int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
2443{
2444 unsigned int reg, val;
2445
2446 if (output < 1 || output > 6)
2447 return -EINVAL;
2448
2449 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
2450
2451 if (diff)
2452 val = ARIZONA_OUT1_MONO;
2453 else
2454 val = 0;
2455
2456 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
2457}
2458EXPORT_SYMBOL_GPL(arizona_set_output_mode);
2459
336d0442
RF
2460static const struct soc_enum arizona_adsp2_rate_enum[] = {
2461 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
2462 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2463 ARIZONA_RATE_ENUM_SIZE,
2464 arizona_rate_text, arizona_rate_val),
2465 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
2466 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2467 ARIZONA_RATE_ENUM_SIZE,
2468 arizona_rate_text, arizona_rate_val),
2469 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
2470 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2471 ARIZONA_RATE_ENUM_SIZE,
2472 arizona_rate_text, arizona_rate_val),
2473 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
2474 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2475 ARIZONA_RATE_ENUM_SIZE,
2476 arizona_rate_text, arizona_rate_val),
2477};
2478
2479const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2480 SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]),
2481 SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]),
2482 SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]),
2483 SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]),
2484};
2485EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2486
c05d9a8c
CK
2487static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2488{
2489 s16 a = be16_to_cpu(_a);
2490 s16 b = be16_to_cpu(_b);
2491
2492 if (!mode) {
2493 return abs(a) >= 4096;
2494 } else {
2495 if (abs(b) >= 4096)
2496 return true;
2497
2498 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2499 }
2500}
2501
2502int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2503 struct snd_ctl_elem_value *ucontrol)
2504{
2505 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2506 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2507 struct soc_bytes *params = (void *)kcontrol->private_value;
2508 unsigned int val;
2509 __be16 *data;
2510 int len;
2511 int ret;
2512
2513 len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2514
2515 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2516 if (!data)
2517 return -ENOMEM;
2518
2519 data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2520
2521 if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2522 arizona_eq_filter_unstable(true, data[4], data[5]) ||
2523 arizona_eq_filter_unstable(true, data[8], data[9]) ||
2524 arizona_eq_filter_unstable(true, data[12], data[13]) ||
2525 arizona_eq_filter_unstable(false, data[16], data[17])) {
2526 dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2527 ret = -EINVAL;
2528 goto out;
2529 }
2530
2531 ret = regmap_read(arizona->regmap, params->base, &val);
2532 if (ret != 0)
2533 goto out;
2534
2535 val &= ~ARIZONA_EQ1_B1_MODE;
2536 data[0] |= cpu_to_be16(val);
2537
2538 ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2539
2540out:
2541 kfree(data);
2542 return ret;
2543}
2544EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2545
5f8e671a
CK
2546int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2547 struct snd_ctl_elem_value *ucontrol)
2548{
2549 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2550 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2551 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2552 s16 val = be16_to_cpu(*data);
2553
2554 if (abs(val) >= 4096) {
2555 dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2556 return -EINVAL;
2557 }
2558
2559 return snd_soc_bytes_put(kcontrol, ucontrol);
2560}
2561EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2562
2230c49f
CK
2563int arizona_register_notifier(struct snd_soc_codec *codec,
2564 struct notifier_block *nb,
2565 int (*notify)(struct notifier_block *nb,
2566 unsigned long action, void *data))
2567{
2568 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2569 struct arizona *arizona = priv->arizona;
2570
2571 nb->notifier_call = notify;
2572
2573 return blocking_notifier_chain_register(&arizona->notifier, nb);
2574}
2575EXPORT_SYMBOL_GPL(arizona_register_notifier);
2576
2577int arizona_unregister_notifier(struct snd_soc_codec *codec,
2578 struct notifier_block *nb)
2579{
2580 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
2581 struct arizona *arizona = priv->arizona;
2582
2583 return blocking_notifier_chain_unregister(&arizona->notifier, nb);
2584}
2585EXPORT_SYMBOL_GPL(arizona_unregister_notifier);
2586
07ed873e
MB
2587MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2588MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2589MODULE_LICENSE("GPL");