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