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