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