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