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