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