]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - sound/soc/codecs/arizona.c
Linux 4.4-rc1
[mirror_ubuntu-eoan-kernel.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
07ed873e
MB
313const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
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
421int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
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
dc91428a
MB
558const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
559 "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
560};
561EXPORT_SYMBOL_GPL(arizona_rate_text);
562
563const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
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
ddbce97c
MB
705static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
706{
707 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
708 unsigned int val;
709 int i;
710
711 if (ena)
712 val = ARIZONA_IN_VU;
713 else
714 val = 0;
715
716 for (i = 0; i < priv->num_inputs; i++)
717 snd_soc_update_bits(codec,
718 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
719 ARIZONA_IN_VU, val);
720}
721
002b083b
CK
722bool arizona_input_analog(struct snd_soc_codec *codec, int shift)
723{
724 unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8);
725 unsigned int val = snd_soc_read(codec, reg);
726
727 return !(val & ARIZONA_IN1_MODE_MASK);
728}
729EXPORT_SYMBOL_GPL(arizona_input_analog);
730
07ed873e
MB
731int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
732 int event)
733{
043123fd
LPC
734 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
735 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
43cd8bf1
MB
736 unsigned int reg;
737
738 if (w->shift % 2)
739 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
740 else
741 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
742
743 switch (event) {
ddbce97c
MB
744 case SND_SOC_DAPM_PRE_PMU:
745 priv->in_pending++;
746 break;
43cd8bf1 747 case SND_SOC_DAPM_POST_PMU:
043123fd 748 snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);
ddbce97c
MB
749
750 /* If this is the last input pending then allow VU */
751 priv->in_pending--;
752 if (priv->in_pending == 0) {
753 msleep(1);
043123fd 754 arizona_in_set_vu(codec, 1);
ddbce97c 755 }
43cd8bf1
MB
756 break;
757 case SND_SOC_DAPM_PRE_PMD:
043123fd 758 snd_soc_update_bits(codec, reg,
ddbce97c
MB
759 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
760 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
43cd8bf1 761 break;
ddbce97c
MB
762 case SND_SOC_DAPM_POST_PMD:
763 /* Disable volume updates if no inputs are enabled */
043123fd 764 reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);
ddbce97c 765 if (reg == 0)
043123fd 766 arizona_in_set_vu(codec, 0);
bee261b8
CK
767 break;
768 default:
769 break;
43cd8bf1
MB
770 }
771
07ed873e
MB
772 return 0;
773}
774EXPORT_SYMBOL_GPL(arizona_in_ev);
775
776int arizona_out_ev(struct snd_soc_dapm_widget *w,
777 struct snd_kcontrol *kcontrol,
778 int event)
779{
60d66c9a
MB
780 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
781 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
054e1b48 782
1a2c7d56 783 switch (event) {
e1ae5fba
CK
784 case SND_SOC_DAPM_PRE_PMU:
785 switch (w->shift) {
786 case ARIZONA_OUT1L_ENA_SHIFT:
787 case ARIZONA_OUT1R_ENA_SHIFT:
788 case ARIZONA_OUT2L_ENA_SHIFT:
789 case ARIZONA_OUT2R_ENA_SHIFT:
790 case ARIZONA_OUT3L_ENA_SHIFT:
791 case ARIZONA_OUT3R_ENA_SHIFT:
792 priv->out_up_pending++;
793 priv->out_up_delay += 17;
794 break;
795 default:
796 break;
797 }
798 break;
1a2c7d56
MB
799 case SND_SOC_DAPM_POST_PMU:
800 switch (w->shift) {
801 case ARIZONA_OUT1L_ENA_SHIFT:
802 case ARIZONA_OUT1R_ENA_SHIFT:
803 case ARIZONA_OUT2L_ENA_SHIFT:
804 case ARIZONA_OUT2R_ENA_SHIFT:
805 case ARIZONA_OUT3L_ENA_SHIFT:
806 case ARIZONA_OUT3R_ENA_SHIFT:
e1ae5fba
CK
807 priv->out_up_pending--;
808 if (!priv->out_up_pending) {
809 msleep(priv->out_up_delay);
810 priv->out_up_delay = 0;
811 }
1a2c7d56
MB
812 break;
813
814 default:
815 break;
816 }
817 break;
054e1b48
CK
818 case SND_SOC_DAPM_PRE_PMD:
819 switch (w->shift) {
820 case ARIZONA_OUT1L_ENA_SHIFT:
821 case ARIZONA_OUT1R_ENA_SHIFT:
822 case ARIZONA_OUT2L_ENA_SHIFT:
823 case ARIZONA_OUT2R_ENA_SHIFT:
824 case ARIZONA_OUT3L_ENA_SHIFT:
825 case ARIZONA_OUT3R_ENA_SHIFT:
826 priv->out_down_pending++;
827 priv->out_down_delay++;
828 break;
829 default:
830 break;
831 }
832 break;
833 case SND_SOC_DAPM_POST_PMD:
834 switch (w->shift) {
835 case ARIZONA_OUT1L_ENA_SHIFT:
836 case ARIZONA_OUT1R_ENA_SHIFT:
837 case ARIZONA_OUT2L_ENA_SHIFT:
838 case ARIZONA_OUT2R_ENA_SHIFT:
839 case ARIZONA_OUT3L_ENA_SHIFT:
840 case ARIZONA_OUT3R_ENA_SHIFT:
841 priv->out_down_pending--;
842 if (!priv->out_down_pending) {
843 msleep(priv->out_down_delay);
844 priv->out_down_delay = 0;
845 }
846 break;
847 default:
848 break;
849 }
850 break;
bee261b8
CK
851 default:
852 break;
1a2c7d56
MB
853 }
854
07ed873e
MB
855 return 0;
856}
857EXPORT_SYMBOL_GPL(arizona_out_ev);
858
f607e31c
MB
859int arizona_hp_ev(struct snd_soc_dapm_widget *w,
860 struct snd_kcontrol *kcontrol,
861 int event)
862{
043123fd
LPC
863 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
864 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
3c43c695 865 struct arizona *arizona = priv->arizona;
f607e31c
MB
866 unsigned int mask = 1 << w->shift;
867 unsigned int val;
868
869 switch (event) {
870 case SND_SOC_DAPM_POST_PMU:
871 val = mask;
872 break;
873 case SND_SOC_DAPM_PRE_PMD:
874 val = 0;
875 break;
e1ae5fba 876 case SND_SOC_DAPM_PRE_PMU:
054e1b48
CK
877 case SND_SOC_DAPM_POST_PMD:
878 return arizona_out_ev(w, kcontrol, event);
f607e31c
MB
879 default:
880 return -EINVAL;
881 }
882
883 /* Store the desired state for the HP outputs */
884 priv->arizona->hp_ena &= ~mask;
885 priv->arizona->hp_ena |= val;
886
112bdfaa
CK
887 /* Force off if HPDET clamp is active */
888 if (priv->arizona->hpdet_clamp)
f607e31c
MB
889 val = 0;
890
3c43c695
MB
891 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
892 mask, val);
f607e31c
MB
893
894 return arizona_out_ev(w, kcontrol, event);
895}
896EXPORT_SYMBOL_GPL(arizona_hp_ev);
897
346d9683
RF
898static int arizona_dvfs_enable(struct snd_soc_codec *codec)
899{
900 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
901 struct arizona *arizona = priv->arizona;
902 int ret;
903
904 ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
905 if (ret) {
906 dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
907 return ret;
908 }
909
910 ret = regmap_update_bits(arizona->regmap,
911 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
912 ARIZONA_SUBSYS_MAX_FREQ,
913 ARIZONA_SUBSYS_MAX_FREQ);
914 if (ret) {
915 dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
916 regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
917 return ret;
918 }
919
920 return 0;
921}
922
923static int arizona_dvfs_disable(struct snd_soc_codec *codec)
924{
925 const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
926 struct arizona *arizona = priv->arizona;
927 int ret;
928
929 ret = regmap_update_bits(arizona->regmap,
930 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
931 ARIZONA_SUBSYS_MAX_FREQ, 0);
932 if (ret) {
933 dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
934 return ret;
935 }
936
937 ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
938 if (ret) {
939 dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
940 return ret;
941 }
942
943 return 0;
944}
945
946int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
947{
948 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
949 int ret = 0;
950
951 mutex_lock(&priv->dvfs_lock);
952
953 if (!priv->dvfs_cached && !priv->dvfs_reqs) {
954 ret = arizona_dvfs_enable(codec);
955 if (ret)
956 goto err;
957 }
958
959 priv->dvfs_reqs |= flags;
960err:
961 mutex_unlock(&priv->dvfs_lock);
962 return ret;
963}
964EXPORT_SYMBOL_GPL(arizona_dvfs_up);
965
966int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
967{
968 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
969 unsigned int old_reqs;
970 int ret = 0;
971
972 mutex_lock(&priv->dvfs_lock);
973
974 old_reqs = priv->dvfs_reqs;
975 priv->dvfs_reqs &= ~flags;
976
977 if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
978 ret = arizona_dvfs_disable(codec);
979
980 mutex_unlock(&priv->dvfs_lock);
981 return ret;
982}
983EXPORT_SYMBOL_GPL(arizona_dvfs_down);
984
985int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
986 struct snd_kcontrol *kcontrol, int event)
987{
988 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
989 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
990 int ret = 0;
991
992 mutex_lock(&priv->dvfs_lock);
993
994 switch (event) {
995 case SND_SOC_DAPM_POST_PMU:
996 if (priv->dvfs_reqs)
997 ret = arizona_dvfs_enable(codec);
998
999 priv->dvfs_cached = false;
1000 break;
1001 case SND_SOC_DAPM_PRE_PMD:
1002 /* We must ensure DVFS is disabled before the codec goes into
1003 * suspend so that we are never in an illegal state of DVFS
1004 * enabled without enough DCVDD
1005 */
1006 priv->dvfs_cached = true;
1007
1008 if (priv->dvfs_reqs)
1009 ret = arizona_dvfs_disable(codec);
1010 break;
1011 default:
1012 break;
1013 }
1014
1015 mutex_unlock(&priv->dvfs_lock);
1016 return ret;
1017}
1018EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
1019
1020void arizona_init_dvfs(struct arizona_priv *priv)
1021{
1022 mutex_init(&priv->dvfs_lock);
1023}
1024EXPORT_SYMBOL_GPL(arizona_init_dvfs);
1025
cbd840da
MB
1026static unsigned int arizona_sysclk_48k_rates[] = {
1027 6144000,
1028 12288000,
96e1f18f 1029 24576000,
cbd840da 1030 49152000,
aeaeee1a
MB
1031 73728000,
1032 98304000,
1033 147456000,
cbd840da
MB
1034};
1035
1036static unsigned int arizona_sysclk_44k1_rates[] = {
1037 5644800,
1038 11289600,
96e1f18f 1039 22579200,
cbd840da 1040 45158400,
aeaeee1a
MB
1041 67737600,
1042 90316800,
1043 135475200,
cbd840da
MB
1044};
1045
1046static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
1047 unsigned int freq)
1048{
1049 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1050 unsigned int reg;
1051 unsigned int *rates;
1052 int ref, div, refclk;
1053
1054 switch (clk) {
1055 case ARIZONA_CLK_OPCLK:
1056 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
1057 refclk = priv->sysclk;
1058 break;
1059 case ARIZONA_CLK_ASYNC_OPCLK:
1060 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
1061 refclk = priv->asyncclk;
1062 break;
1063 default:
1064 return -EINVAL;
1065 }
1066
1067 if (refclk % 8000)
1068 rates = arizona_sysclk_44k1_rates;
1069 else
1070 rates = arizona_sysclk_48k_rates;
1071
1072 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
1073 rates[ref] <= refclk; ref++) {
1074 div = 1;
1075 while (rates[ref] / div >= freq && div < 32) {
1076 if (rates[ref] / div == freq) {
1077 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
1078 freq);
1079 snd_soc_update_bits(codec, reg,
1080 ARIZONA_OPCLK_DIV_MASK |
1081 ARIZONA_OPCLK_SEL_MASK,
1082 (div <<
1083 ARIZONA_OPCLK_DIV_SHIFT) |
1084 ref);
1085 return 0;
1086 }
1087 div++;
1088 }
1089 }
1090
1091 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
1092 return -EINVAL;
1093}
1094
07ed873e
MB
1095int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1096 int source, unsigned int freq, int dir)
1097{
1098 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1099 struct arizona *arizona = priv->arizona;
1100 char *name;
1101 unsigned int reg;
1102 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
1103 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
1104 unsigned int *clk;
1105
1106 switch (clk_id) {
1107 case ARIZONA_CLK_SYSCLK:
1108 name = "SYSCLK";
1109 reg = ARIZONA_SYSTEM_CLOCK_1;
1110 clk = &priv->sysclk;
1111 mask |= ARIZONA_SYSCLK_FRAC;
1112 break;
1113 case ARIZONA_CLK_ASYNCCLK:
1114 name = "ASYNCCLK";
1115 reg = ARIZONA_ASYNC_CLOCK_1;
1116 clk = &priv->asyncclk;
1117 break;
cbd840da
MB
1118 case ARIZONA_CLK_OPCLK:
1119 case ARIZONA_CLK_ASYNC_OPCLK:
1120 return arizona_set_opclk(codec, clk_id, freq);
07ed873e
MB
1121 default:
1122 return -EINVAL;
1123 }
1124
1125 switch (freq) {
1126 case 5644800:
1127 case 6144000:
1128 break;
1129 case 11289600:
1130 case 12288000:
3f341f74 1131 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1132 break;
1133 case 22579200:
1134 case 24576000:
3f341f74 1135 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1136 break;
1137 case 45158400:
1138 case 49152000:
3f341f74 1139 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e 1140 break;
38113360
MB
1141 case 67737600:
1142 case 73728000:
3f341f74 1143 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1144 break;
1145 case 90316800:
1146 case 98304000:
3f341f74 1147 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1148 break;
1149 case 135475200:
1150 case 147456000:
3f341f74 1151 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360 1152 break;
f2c26d48
MB
1153 case 0:
1154 dev_dbg(arizona->dev, "%s cleared\n", name);
1155 *clk = freq;
1156 return 0;
07ed873e
MB
1157 default:
1158 return -EINVAL;
1159 }
1160
1161 *clk = freq;
1162
1163 if (freq % 6144000)
1164 val |= ARIZONA_SYSCLK_FRAC;
1165
1166 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
1167
1168 return regmap_update_bits(arizona->regmap, reg, mask, val);
1169}
1170EXPORT_SYMBOL_GPL(arizona_set_sysclk);
1171
1172static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1173{
1174 struct snd_soc_codec *codec = dai->codec;
3c43c695
MB
1175 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1176 struct arizona *arizona = priv->arizona;
07ed873e
MB
1177 int lrclk, bclk, mode, base;
1178
1179 base = dai->driver->base;
1180
1181 lrclk = 0;
1182 bclk = 0;
1183
1184 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1185 case SND_SOC_DAIFMT_DSP_A:
e9c7f34a
RF
1186 mode = ARIZONA_FMT_DSP_MODE_A;
1187 break;
1188 case SND_SOC_DAIFMT_DSP_B:
1189 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1190 != SND_SOC_DAIFMT_CBM_CFM) {
1191 arizona_aif_err(dai, "DSP_B not valid in slave mode\n");
1192 return -EINVAL;
1193 }
1194 mode = ARIZONA_FMT_DSP_MODE_B;
07ed873e 1195 break;
07ed873e 1196 case SND_SOC_DAIFMT_I2S:
e9c7f34a
RF
1197 mode = ARIZONA_FMT_I2S_MODE;
1198 break;
1199 case SND_SOC_DAIFMT_LEFT_J:
1200 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1201 != SND_SOC_DAIFMT_CBM_CFM) {
1202 arizona_aif_err(dai, "LEFT_J not valid in slave mode\n");
1203 return -EINVAL;
1204 }
1205 mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE;
07ed873e 1206 break;
07ed873e
MB
1207 default:
1208 arizona_aif_err(dai, "Unsupported DAI format %d\n",
1209 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1210 return -EINVAL;
1211 }
1212
1213 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1214 case SND_SOC_DAIFMT_CBS_CFS:
1215 break;
1216 case SND_SOC_DAIFMT_CBS_CFM:
1217 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1218 break;
1219 case SND_SOC_DAIFMT_CBM_CFS:
1220 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1221 break;
1222 case SND_SOC_DAIFMT_CBM_CFM:
1223 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1224 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1225 break;
1226 default:
1227 arizona_aif_err(dai, "Unsupported master mode %d\n",
1228 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1229 return -EINVAL;
1230 }
1231
1232 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1233 case SND_SOC_DAIFMT_NB_NF:
1234 break;
1235 case SND_SOC_DAIFMT_IB_IF:
1236 bclk |= ARIZONA_AIF1_BCLK_INV;
1237 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1238 break;
1239 case SND_SOC_DAIFMT_IB_NF:
1240 bclk |= ARIZONA_AIF1_BCLK_INV;
1241 break;
1242 case SND_SOC_DAIFMT_NB_IF:
1243 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1244 break;
1245 default:
1246 return -EINVAL;
1247 }
1248
3c43c695
MB
1249 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
1250 ARIZONA_AIF1_BCLK_INV |
1251 ARIZONA_AIF1_BCLK_MSTR,
1252 bclk);
1253 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
1254 ARIZONA_AIF1TX_LRCLK_INV |
1255 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
1256 regmap_update_bits_async(arizona->regmap,
1257 base + ARIZONA_AIF_RX_PIN_CTRL,
1258 ARIZONA_AIF1RX_LRCLK_INV |
1259 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
1260 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
1261 ARIZONA_AIF1_FMT_MASK, mode);
07ed873e
MB
1262
1263 return 0;
1264}
1265
949e6bc7 1266static const int arizona_48k_bclk_rates[] = {
07ed873e
MB
1267 -1,
1268 48000,
1269 64000,
1270 96000,
1271 128000,
1272 192000,
1273 256000,
1274 384000,
1275 512000,
1276 768000,
1277 1024000,
1278 1536000,
1279 2048000,
1280 3072000,
1281 4096000,
1282 6144000,
1283 8192000,
1284 12288000,
1285 24576000,
1286};
1287
5b2eec3f
MB
1288static const unsigned int arizona_48k_rates[] = {
1289 12000,
1290 24000,
1291 48000,
1292 96000,
1293 192000,
1294 384000,
1295 768000,
1296 4000,
1297 8000,
1298 16000,
1299 32000,
1300 64000,
1301 128000,
1302 256000,
1303 512000,
1304};
1305
1306static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
1307 .count = ARRAY_SIZE(arizona_48k_rates),
1308 .list = arizona_48k_rates,
1309};
1310
949e6bc7 1311static const int arizona_44k1_bclk_rates[] = {
07ed873e
MB
1312 -1,
1313 44100,
1314 58800,
1315 88200,
1316 117600,
1317 177640,
1318 235200,
1319 352800,
1320 470400,
1321 705600,
1322 940800,
1323 1411200,
1324 1881600,
4758be37 1325 2822400,
07ed873e
MB
1326 3763200,
1327 5644800,
1328 7526400,
1329 11289600,
1330 22579200,
1331};
1332
5b2eec3f
MB
1333static const unsigned int arizona_44k1_rates[] = {
1334 11025,
1335 22050,
1336 44100,
1337 88200,
1338 176400,
1339 352800,
1340 705600,
1341};
1342
1343static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
1344 .count = ARRAY_SIZE(arizona_44k1_rates),
1345 .list = arizona_44k1_rates,
1346};
1347
07ed873e
MB
1348static int arizona_sr_vals[] = {
1349 0,
1350 12000,
1351 24000,
1352 48000,
1353 96000,
1354 192000,
1355 384000,
1356 768000,
1357 0,
1358 11025,
1359 22050,
1360 44100,
1361 88200,
1362 176400,
1363 352800,
1364 705600,
1365 4000,
1366 8000,
1367 16000,
1368 32000,
1369 64000,
1370 128000,
1371 256000,
1372 512000,
1373};
1374
5b2eec3f
MB
1375static int arizona_startup(struct snd_pcm_substream *substream,
1376 struct snd_soc_dai *dai)
1377{
1378 struct snd_soc_codec *codec = dai->codec;
1379 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1380 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1381 const struct snd_pcm_hw_constraint_list *constraint;
1382 unsigned int base_rate;
1383
1384 switch (dai_priv->clk) {
1385 case ARIZONA_CLK_SYSCLK:
1386 base_rate = priv->sysclk;
1387 break;
1388 case ARIZONA_CLK_ASYNCCLK:
1389 base_rate = priv->asyncclk;
1390 break;
1391 default:
1392 return 0;
1393 }
1394
f2c26d48
MB
1395 if (base_rate == 0)
1396 return 0;
1397
5b2eec3f
MB
1398 if (base_rate % 8000)
1399 constraint = &arizona_44k1_constraint;
1400 else
1401 constraint = &arizona_48k_constraint;
1402
1403 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1404 SNDRV_PCM_HW_PARAM_RATE,
1405 constraint);
1406}
1407
cc9e9243
CK
1408static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1409 unsigned int rate)
1410{
1411 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1412 struct arizona *arizona = priv->arizona;
8019ff6c 1413 struct reg_sequence dac_comp[] = {
cc9e9243
CK
1414 { 0x80, 0x3 },
1415 { ARIZONA_DAC_COMP_1, 0 },
1416 { ARIZONA_DAC_COMP_2, 0 },
1417 { 0x80, 0x0 },
1418 };
1419
d74bcaae 1420 mutex_lock(&arizona->dac_comp_lock);
cc9e9243
CK
1421
1422 dac_comp[1].def = arizona->dac_comp_coeff;
1423 if (rate >= 176400)
1424 dac_comp[2].def = arizona->dac_comp_enabled;
1425
d74bcaae 1426 mutex_unlock(&arizona->dac_comp_lock);
cc9e9243
CK
1427
1428 regmap_multi_reg_write(arizona->regmap,
1429 dac_comp,
1430 ARRAY_SIZE(dac_comp));
1431}
1432
b272efc8
MB
1433static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1434 struct snd_pcm_hw_params *params,
1435 struct snd_soc_dai *dai)
1436{
1437 struct snd_soc_codec *codec = dai->codec;
1438 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1439 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1440 int base = dai->driver->base;
2c118b4c 1441 int i, sr_val, ret;
b272efc8
MB
1442
1443 /*
1444 * We will need to be more flexible than this in future,
1445 * currently we use a single sample rate for SYSCLK.
1446 */
1447 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1448 if (arizona_sr_vals[i] == params_rate(params))
1449 break;
1450 if (i == ARRAY_SIZE(arizona_sr_vals)) {
1451 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1452 params_rate(params));
1453 return -EINVAL;
1454 }
1455 sr_val = i;
1456
2c118b4c
RF
1457 switch (priv->arizona->type) {
1458 case WM5102:
1459 case WM8997:
1460 if (arizona_sr_vals[sr_val] >= 88200)
1461 ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
1462 else
1463 ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
1464
1465 if (ret) {
1466 arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
1467 return ret;
1468 }
1469 break;
1470 default:
1471 break;
1472 }
1473
b272efc8
MB
1474 switch (dai_priv->clk) {
1475 case ARIZONA_CLK_SYSCLK:
cc9e9243
CK
1476 switch (priv->arizona->type) {
1477 case WM5102:
1478 arizona_wm5102_set_dac_comp(codec,
1479 params_rate(params));
1480 break;
1481 default:
1482 break;
1483 }
1484
b272efc8
MB
1485 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1486 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1487 if (base)
1488 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1489 ARIZONA_AIF1_RATE_MASK, 0);
1490 break;
1491 case ARIZONA_CLK_ASYNCCLK:
1492 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
c24084db 1493 ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val);
b272efc8
MB
1494 if (base)
1495 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1496 ARIZONA_AIF1_RATE_MASK,
1497 8 << ARIZONA_AIF1_RATE_SHIFT);
1498 break;
1499 default:
1500 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1501 return -EINVAL;
1502 }
1503
1504 return 0;
1505}
1506
bedd4b19
RF
1507static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1508 int base, int bclk, int lrclk, int frame)
1509{
1510 int val;
1511
1512 val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1513 if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1514 return true;
1515
1516 val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1517 if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1518 return true;
1519
1520 val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1521 if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1522 ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1523 return true;
1524
1525 return false;
1526}
1527
07ed873e
MB
1528static int arizona_hw_params(struct snd_pcm_substream *substream,
1529 struct snd_pcm_hw_params *params,
1530 struct snd_soc_dai *dai)
1531{
1532 struct snd_soc_codec *codec = dai->codec;
c013b27a 1533 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
c94aa30e 1534 struct arizona *arizona = priv->arizona;
07ed873e
MB
1535 int base = dai->driver->base;
1536 const int *rates;
76bf969e 1537 int i, ret, val;
ed70f3a2 1538 int channels = params_channels(params);
c94aa30e 1539 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
ed70f3a2
CK
1540 int tdm_width = arizona->tdm_width[dai->id - 1];
1541 int tdm_slots = arizona->tdm_slots[dai->id - 1];
c94aa30e 1542 int bclk, lrclk, wl, frame, bclk_target;
bedd4b19
RF
1543 bool reconfig;
1544 unsigned int aif_tx_state, aif_rx_state;
07ed873e
MB
1545
1546 if (params_rate(params) % 8000)
949e6bc7 1547 rates = &arizona_44k1_bclk_rates[0];
07ed873e 1548 else
949e6bc7 1549 rates = &arizona_48k_bclk_rates[0];
07ed873e 1550
5ed68f0a 1551 wl = params_width(params);
d114e5f7 1552
ed70f3a2
CK
1553 if (tdm_slots) {
1554 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
1555 tdm_slots, tdm_width);
1556 bclk_target = tdm_slots * tdm_width * params_rate(params);
1557 channels = tdm_slots;
1558 } else {
1559 bclk_target = snd_soc_params_to_bclk(params);
d114e5f7 1560 tdm_width = wl;
ed70f3a2
CK
1561 }
1562
1563 if (chan_limit && chan_limit < channels) {
c94aa30e 1564 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
ed70f3a2 1565 bclk_target /= channels;
c94aa30e
MB
1566 bclk_target *= chan_limit;
1567 }
1568
ed70f3a2 1569 /* Force multiple of 2 channels for I2S mode */
76bf969e 1570 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
e9c7f34a
RF
1571 val &= ARIZONA_AIF1_FMT_MASK;
1572 if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) {
76bf969e 1573 arizona_aif_dbg(dai, "Forcing stereo mode\n");
ed70f3a2
CK
1574 bclk_target /= channels;
1575 bclk_target *= channels + 1;
76bf969e
MB
1576 }
1577
949e6bc7 1578 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
c94aa30e 1579 if (rates[i] >= bclk_target &&
5001765f 1580 rates[i] % params_rate(params) == 0) {
07ed873e
MB
1581 bclk = i;
1582 break;
1583 }
1584 }
949e6bc7 1585 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
07ed873e
MB
1586 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1587 params_rate(params));
1588 return -EINVAL;
1589 }
1590
b59e0f82 1591 lrclk = rates[bclk] / params_rate(params);
07ed873e
MB
1592
1593 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1594 rates[bclk], rates[bclk] / lrclk);
1595
d114e5f7 1596 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width;
07ed873e 1597
bedd4b19
RF
1598 reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1599
1600 if (reconfig) {
1601 /* Save AIF TX/RX state */
1602 aif_tx_state = snd_soc_read(codec,
1603 base + ARIZONA_AIF_TX_ENABLES);
1604 aif_rx_state = snd_soc_read(codec,
1605 base + ARIZONA_AIF_RX_ENABLES);
1606 /* Disable AIF TX/RX before reconfiguring it */
1607 regmap_update_bits_async(arizona->regmap,
1608 base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1609 regmap_update_bits(arizona->regmap,
1610 base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1611 }
1612
b272efc8
MB
1613 ret = arizona_hw_params_rate(substream, params, dai);
1614 if (ret != 0)
bedd4b19 1615 goto restore_aif;
c013b27a 1616
bedd4b19
RF
1617 if (reconfig) {
1618 regmap_update_bits_async(arizona->regmap,
1619 base + ARIZONA_AIF_BCLK_CTRL,
1620 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1621 regmap_update_bits_async(arizona->regmap,
1622 base + ARIZONA_AIF_TX_BCLK_RATE,
1623 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1624 regmap_update_bits_async(arizona->regmap,
1625 base + ARIZONA_AIF_RX_BCLK_RATE,
1626 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1627 regmap_update_bits_async(arizona->regmap,
1628 base + ARIZONA_AIF_FRAME_CTRL_1,
1629 ARIZONA_AIF1TX_WL_MASK |
1630 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1631 regmap_update_bits(arizona->regmap,
1632 base + ARIZONA_AIF_FRAME_CTRL_2,
1633 ARIZONA_AIF1RX_WL_MASK |
1634 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1635 }
07ed873e 1636
bedd4b19
RF
1637restore_aif:
1638 if (reconfig) {
1639 /* Restore AIF TX/RX state */
1640 regmap_update_bits_async(arizona->regmap,
1641 base + ARIZONA_AIF_TX_ENABLES,
1642 0xff, aif_tx_state);
1643 regmap_update_bits(arizona->regmap,
1644 base + ARIZONA_AIF_RX_ENABLES,
1645 0xff, aif_rx_state);
1646 }
1647 return ret;
07ed873e
MB
1648}
1649
410837a7
MB
1650static const char *arizona_dai_clk_str(int clk_id)
1651{
1652 switch (clk_id) {
1653 case ARIZONA_CLK_SYSCLK:
1654 return "SYSCLK";
1655 case ARIZONA_CLK_ASYNCCLK:
1656 return "ASYNCCLK";
1657 default:
1658 return "Unknown clock";
1659 }
1660}
1661
5b2eec3f
MB
1662static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1663 int clk_id, unsigned int freq, int dir)
1664{
1665 struct snd_soc_codec *codec = dai->codec;
1ac52145 1666 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
5b2eec3f
MB
1667 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1668 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
410837a7 1669 struct snd_soc_dapm_route routes[2];
5b2eec3f
MB
1670
1671 switch (clk_id) {
1672 case ARIZONA_CLK_SYSCLK:
1673 case ARIZONA_CLK_ASYNCCLK:
1674 break;
1675 default:
1676 return -EINVAL;
1677 }
1678
410837a7
MB
1679 if (clk_id == dai_priv->clk)
1680 return 0;
1681
1682 if (dai->active) {
5b2eec3f
MB
1683 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1684 dai->id);
1685 return -EBUSY;
1686 }
1687
c8d35a6a
MB
1688 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1689 arizona_dai_clk_str(clk_id));
1690
410837a7
MB
1691 memset(&routes, 0, sizeof(routes));
1692 routes[0].sink = dai->driver->capture.stream_name;
1693 routes[1].sink = dai->driver->playback.stream_name;
5b2eec3f 1694
410837a7
MB
1695 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1696 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1ac52145 1697 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7
MB
1698
1699 routes[0].source = arizona_dai_clk_str(clk_id);
1700 routes[1].source = arizona_dai_clk_str(clk_id);
1ac52145 1701 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7 1702
0c778e86
MB
1703 dai_priv->clk = clk_id;
1704
1ac52145 1705 return snd_soc_dapm_sync(dapm);
5b2eec3f
MB
1706}
1707
01df259f
MB
1708static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1709{
1710 struct snd_soc_codec *codec = dai->codec;
1711 int base = dai->driver->base;
1712 unsigned int reg;
1713
1714 if (tristate)
1715 reg = ARIZONA_AIF1_TRI;
1716 else
1717 reg = 0;
1718
1719 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1720 ARIZONA_AIF1_TRI, reg);
1721}
1722
ed70f3a2
CK
1723static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
1724 unsigned int base,
1725 int channels, unsigned int mask)
1726{
1727 struct snd_soc_codec *codec = dai->codec;
1728 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1729 struct arizona *arizona = priv->arizona;
1730 int slot, i;
1731
1732 for (i = 0; i < channels; ++i) {
1733 slot = ffs(mask) - 1;
1734 if (slot < 0)
1735 return;
1736
1737 regmap_write(arizona->regmap, base + i, slot);
1738
1739 mask &= ~(1 << slot);
1740 }
1741
1742 if (mask)
1743 arizona_aif_warn(dai, "Too many channels in TDM mask\n");
1744}
1745
1746static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1747 unsigned int rx_mask, int slots, int slot_width)
1748{
1749 struct snd_soc_codec *codec = dai->codec;
1750 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1751 struct arizona *arizona = priv->arizona;
1752 int base = dai->driver->base;
1753 int rx_max_chan = dai->driver->playback.channels_max;
1754 int tx_max_chan = dai->driver->capture.channels_max;
1755
1756 /* Only support TDM for the physical AIFs */
1757 if (dai->id > ARIZONA_MAX_AIF)
1758 return -ENOTSUPP;
1759
1760 if (slots == 0) {
1761 tx_mask = (1 << tx_max_chan) - 1;
1762 rx_mask = (1 << rx_max_chan) - 1;
1763 }
1764
1765 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
1766 tx_max_chan, tx_mask);
1767 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
1768 rx_max_chan, rx_mask);
1769
1770 arizona->tdm_width[dai->id - 1] = slot_width;
1771 arizona->tdm_slots[dai->id - 1] = slots;
1772
1773 return 0;
1774}
1775
07ed873e 1776const struct snd_soc_dai_ops arizona_dai_ops = {
5b2eec3f 1777 .startup = arizona_startup,
07ed873e 1778 .set_fmt = arizona_set_fmt,
ed70f3a2 1779 .set_tdm_slot = arizona_set_tdm_slot,
07ed873e 1780 .hw_params = arizona_hw_params,
5b2eec3f 1781 .set_sysclk = arizona_dai_set_sysclk,
01df259f 1782 .set_tristate = arizona_set_tristate,
07ed873e 1783};
a837987e 1784EXPORT_SYMBOL_GPL(arizona_dai_ops);
07ed873e 1785
bd1dd885
MB
1786const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1787 .startup = arizona_startup,
1788 .hw_params = arizona_hw_params_rate,
1789 .set_sysclk = arizona_dai_set_sysclk,
1790};
1791EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1792
5b2eec3f
MB
1793int arizona_init_dai(struct arizona_priv *priv, int id)
1794{
1795 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1796
1797 dai_priv->clk = ARIZONA_CLK_SYSCLK;
1798
1799 return 0;
1800}
1801EXPORT_SYMBOL_GPL(arizona_init_dai);
1802
07ed873e
MB
1803static struct {
1804 unsigned int min;
1805 unsigned int max;
1806 u16 fratio;
1807 int ratio;
1808} fll_fratios[] = {
1809 { 0, 64000, 4, 16 },
1810 { 64000, 128000, 3, 8 },
1811 { 128000, 256000, 2, 4 },
1812 { 256000, 1000000, 1, 2 },
1813 { 1000000, 13500000, 0, 1 },
1814};
1815
8f113d7d
MB
1816static struct {
1817 unsigned int min;
1818 unsigned int max;
1819 u16 gain;
1820} fll_gains[] = {
1821 { 0, 256000, 0 },
1822 { 256000, 1000000, 2 },
1823 { 1000000, 13500000, 4 },
1824};
1825
07ed873e
MB
1826struct arizona_fll_cfg {
1827 int n;
1828 int theta;
1829 int lambda;
1830 int refdiv;
1831 int outdiv;
1832 int fratio;
8f113d7d 1833 int gain;
07ed873e
MB
1834};
1835
23f785a8
CK
1836static int arizona_validate_fll(struct arizona_fll *fll,
1837 unsigned int Fref,
1838 unsigned int Fout)
07ed873e 1839{
23f785a8
CK
1840 unsigned int Fvco_min;
1841
c8badda8
CK
1842 if (fll->fout && Fout != fll->fout) {
1843 arizona_fll_err(fll,
1844 "Can't change output on active FLL\n");
1845 return -EINVAL;
1846 }
1847
23f785a8
CK
1848 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1849 arizona_fll_err(fll,
1850 "Can't scale %dMHz in to <=13.5MHz\n",
1851 Fref);
1852 return -EINVAL;
1853 }
07ed873e 1854
23f785a8
CK
1855 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1856 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1857 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1858 Fout);
1859 return -EINVAL;
1860 }
1861
1862 return 0;
1863}
1864
d0800342
CK
1865static int arizona_find_fratio(unsigned int Fref, int *fratio)
1866{
1867 int i;
1868
1869 /* Find an appropriate FLL_FRATIO */
1870 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1871 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1872 if (fratio)
1873 *fratio = fll_fratios[i].fratio;
1874 return fll_fratios[i].ratio;
1875 }
1876 }
1877
1878 return -EINVAL;
1879}
1880
1881static int arizona_calc_fratio(struct arizona_fll *fll,
1882 struct arizona_fll_cfg *cfg,
1883 unsigned int target,
1884 unsigned int Fref, bool sync)
1885{
1886 int init_ratio, ratio;
1887 int refdiv, div;
07ed873e 1888
d0800342 1889 /* Fref must be <=13.5MHz, find initial refdiv */
07ed873e
MB
1890 div = 1;
1891 cfg->refdiv = 0;
d0800342 1892 while (Fref > ARIZONA_FLL_MAX_FREF) {
07ed873e 1893 div *= 2;
d0800342 1894 Fref /= 2;
07ed873e
MB
1895 cfg->refdiv++;
1896
d0800342 1897 if (div > ARIZONA_FLL_MAX_REFDIV)
07ed873e 1898 return -EINVAL;
d0800342
CK
1899 }
1900
1901 /* Find an appropriate FLL_FRATIO */
1902 init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
1903 if (init_ratio < 0) {
1904 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1905 Fref);
1906 return init_ratio;
1907 }
1908
1909 switch (fll->arizona->type) {
1910 case WM5110:
575ef7f6 1911 case WM8280:
d0800342
CK
1912 if (fll->arizona->rev < 3 || sync)
1913 return init_ratio;
1914 break;
6ebbce0a
RF
1915 case WM8998:
1916 case WM1814:
1917 if (sync)
1918 return init_ratio;
1919 break;
d0800342
CK
1920 default:
1921 return init_ratio;
1922 }
1923
1924 cfg->fratio = init_ratio - 1;
1925
1926 /* Adjust FRATIO/refdiv to avoid integer mode if possible */
1927 refdiv = cfg->refdiv;
1928
1929 while (div <= ARIZONA_FLL_MAX_REFDIV) {
1930 for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
1931 ratio++) {
35a730a0
CK
1932 if ((ARIZONA_FLL_VCO_CORNER / 2) /
1933 (fll->vco_mult * ratio) < Fref)
29fee829
CK
1934 break;
1935
d0800342
CK
1936 if (target % (ratio * Fref)) {
1937 cfg->refdiv = refdiv;
1938 cfg->fratio = ratio - 1;
1939 return ratio;
1940 }
07ed873e 1941 }
d0800342 1942
4714bc01 1943 for (ratio = init_ratio - 1; ratio > 0; ratio--) {
d0800342
CK
1944 if (target % (ratio * Fref)) {
1945 cfg->refdiv = refdiv;
1946 cfg->fratio = ratio - 1;
1947 return ratio;
1948 }
1949 }
1950
1951 div *= 2;
1952 Fref /= 2;
1953 refdiv++;
1954 init_ratio = arizona_find_fratio(Fref, NULL);
07ed873e
MB
1955 }
1956
d0800342
CK
1957 arizona_fll_warn(fll, "Falling back to integer mode operation\n");
1958 return cfg->fratio + 1;
1959}
1960
07ed873e
MB
1961static int arizona_calc_fll(struct arizona_fll *fll,
1962 struct arizona_fll_cfg *cfg,
d0800342 1963 unsigned int Fref, bool sync)
07ed873e
MB
1964{
1965 unsigned int target, div, gcd_fll;
1966 int i, ratio;
1967
8ccefcd2 1968 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
07ed873e 1969
2b4d39fc 1970 /* Fvco should be over the targt; don't check the upper bound */
f641aec6
CK
1971 div = ARIZONA_FLL_MIN_OUTDIV;
1972 while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
07ed873e 1973 div++;
f641aec6 1974 if (div > ARIZONA_FLL_MAX_OUTDIV)
07ed873e 1975 return -EINVAL;
07ed873e 1976 }
f641aec6 1977 target = fll->fout * div / fll->vco_mult;
07ed873e
MB
1978 cfg->outdiv = div;
1979
1980 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1981
d0800342
CK
1982 /* Find an appropriate FLL_FRATIO and refdiv */
1983 ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
1984 if (ratio < 0)
1985 return ratio;
07ed873e 1986
07ed873e 1987 /* Apply the division for our remaining calculations */
d0800342 1988 Fref = Fref / (1 << cfg->refdiv);
8f113d7d 1989
07ed873e
MB
1990 cfg->n = target / (ratio * Fref);
1991
01f58153 1992 if (target % (ratio * Fref)) {
07ed873e
MB
1993 gcd_fll = gcd(target, ratio * Fref);
1994 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1995
1996 cfg->theta = (target - (cfg->n * ratio * Fref))
1997 / gcd_fll;
1998 cfg->lambda = (ratio * Fref) / gcd_fll;
1999 } else {
2000 cfg->theta = 0;
2001 cfg->lambda = 0;
2002 }
2003
01f58153
RT
2004 /* Round down to 16bit range with cost of accuracy lost.
2005 * Denominator must be bigger than numerator so we only
2006 * take care of it.
2007 */
2008 while (cfg->lambda >= (1 << 16)) {
2009 cfg->theta >>= 1;
2010 cfg->lambda >>= 1;
2011 }
2012
5a3935c7
CK
2013 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
2014 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
2015 cfg->gain = fll_gains[i].gain;
2016 break;
2017 }
2018 }
2019 if (i == ARRAY_SIZE(fll_gains)) {
2020 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
2021 Fref);
2022 return -EINVAL;
2023 }
2024
07ed873e
MB
2025 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
2026 cfg->n, cfg->theta, cfg->lambda);
2027 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
2028 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
8f113d7d 2029 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
07ed873e
MB
2030
2031 return 0;
2032
2033}
2034
2035static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
8f113d7d
MB
2036 struct arizona_fll_cfg *cfg, int source,
2037 bool sync)
07ed873e 2038{
3c43c695
MB
2039 regmap_update_bits_async(arizona->regmap, base + 3,
2040 ARIZONA_FLL1_THETA_MASK, cfg->theta);
2041 regmap_update_bits_async(arizona->regmap, base + 4,
2042 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
2043 regmap_update_bits_async(arizona->regmap, base + 5,
2044 ARIZONA_FLL1_FRATIO_MASK,
2045 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
2046 regmap_update_bits_async(arizona->regmap, base + 6,
2047 ARIZONA_FLL1_CLK_REF_DIV_MASK |
2048 ARIZONA_FLL1_CLK_REF_SRC_MASK,
2049 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
2050 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
07ed873e 2051
61719db8
CK
2052 if (sync) {
2053 regmap_update_bits(arizona->regmap, base + 0x7,
2054 ARIZONA_FLL1_GAIN_MASK,
2055 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2056 } else {
2057 regmap_update_bits(arizona->regmap, base + 0x5,
2058 ARIZONA_FLL1_OUTDIV_MASK,
2059 cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
2060 regmap_update_bits(arizona->regmap, base + 0x9,
2061 ARIZONA_FLL1_GAIN_MASK,
2062 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2063 }
8f113d7d 2064
3c43c695
MB
2065 regmap_update_bits_async(arizona->regmap, base + 2,
2066 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
2067 ARIZONA_FLL1_CTRL_UPD | cfg->n);
07ed873e
MB
2068}
2069
c393aca9 2070static int arizona_is_enabled_fll(struct arizona_fll *fll)
d122d6c9
CK
2071{
2072 struct arizona *arizona = fll->arizona;
2073 unsigned int reg;
2074 int ret;
2075
2076 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
2077 if (ret != 0) {
2078 arizona_fll_err(fll, "Failed to read current state: %d\n",
2079 ret);
2080 return ret;
2081 }
2082
2083 return reg & ARIZONA_FLL1_ENA;
2084}
2085
c393aca9 2086static int arizona_enable_fll(struct arizona_fll *fll)
35722815
CK
2087{
2088 struct arizona *arizona = fll->arizona;
49c60547 2089 bool use_sync = false;
c393aca9 2090 int already_enabled = arizona_is_enabled_fll(fll);
23f785a8 2091 struct arizona_fll_cfg cfg;
0e765971
CK
2092 int i;
2093 unsigned int val;
35722815 2094
c393aca9
CK
2095 if (already_enabled < 0)
2096 return already_enabled;
2097
c8badda8
CK
2098 if (already_enabled) {
2099 /* Facilitate smooth refclk across the transition */
1cf5a330 2100 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
c8badda8
CK
2101 ARIZONA_FLL1_GAIN_MASK, 0);
2102 regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
2103 ARIZONA_FLL1_FREERUN,
2104 ARIZONA_FLL1_FREERUN);
2105 }
2106
ff680a17
MB
2107 /*
2108 * If we have both REFCLK and SYNCCLK then enable both,
2109 * otherwise apply the SYNCCLK settings to REFCLK.
2110 */
49c60547
CK
2111 if (fll->ref_src >= 0 && fll->ref_freq &&
2112 fll->ref_src != fll->sync_src) {
d0800342 2113 arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
ff680a17 2114
23f785a8 2115 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
8f113d7d 2116 false);
49c60547 2117 if (fll->sync_src >= 0) {
d0800342 2118 arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
23f785a8
CK
2119
2120 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
8f113d7d 2121 fll->sync_src, true);
49c60547
CK
2122 use_sync = true;
2123 }
ff680a17 2124 } else if (fll->sync_src >= 0) {
d0800342 2125 arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
ff680a17 2126
23f785a8 2127 arizona_apply_fll(arizona, fll->base, &cfg,
8f113d7d 2128 fll->sync_src, false);
eca2e8e2 2129
3c43c695
MB
2130 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2131 ARIZONA_FLL1_SYNC_ENA, 0);
ff680a17
MB
2132 } else {
2133 arizona_fll_err(fll, "No clocks provided\n");
c393aca9 2134 return -EINVAL;
ff680a17 2135 }
35722815 2136
576411be
MB
2137 /*
2138 * Increase the bandwidth if we're not using a low frequency
2139 * sync source.
2140 */
49c60547 2141 if (use_sync && fll->sync_freq > 100000)
3c43c695
MB
2142 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2143 ARIZONA_FLL1_SYNC_BW, 0);
576411be 2144 else
3c43c695
MB
2145 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2146 ARIZONA_FLL1_SYNC_BW,
2147 ARIZONA_FLL1_SYNC_BW);
576411be 2148
c393aca9 2149 if (!already_enabled)
35722815
CK
2150 pm_runtime_get(arizona->dev);
2151
3c43c695
MB
2152 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2153 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
49c60547 2154 if (use_sync)
3c43c695
MB
2155 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2156 ARIZONA_FLL1_SYNC_ENA,
2157 ARIZONA_FLL1_SYNC_ENA);
35722815 2158
c8badda8
CK
2159 if (already_enabled)
2160 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2161 ARIZONA_FLL1_FREERUN, 0);
2162
0e765971
CK
2163 arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2164 val = 0;
2165 for (i = 0; i < 15; i++) {
2166 if (i < 5)
2167 usleep_range(200, 400);
2168 else
2169 msleep(20);
2170
2171 regmap_read(arizona->regmap,
2172 ARIZONA_INTERRUPT_RAW_STATUS_5,
2173 &val);
2174 if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2175 break;
2176 }
2177 if (i == 15)
35722815 2178 arizona_fll_warn(fll, "Timed out waiting for lock\n");
0e765971
CK
2179 else
2180 arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
c393aca9
CK
2181
2182 return 0;
35722815
CK
2183}
2184
7604054e
CK
2185static void arizona_disable_fll(struct arizona_fll *fll)
2186{
2187 struct arizona *arizona = fll->arizona;
2188 bool change;
2189
3c43c695
MB
2190 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2191 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
7604054e
CK
2192 regmap_update_bits_check(arizona->regmap, fll->base + 1,
2193 ARIZONA_FLL1_ENA, 0, &change);
2194 regmap_update_bits(arizona->regmap, fll->base + 0x11,
2195 ARIZONA_FLL1_SYNC_ENA, 0);
5e39a50b
CK
2196 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2197 ARIZONA_FLL1_FREERUN, 0);
7604054e
CK
2198
2199 if (change)
2200 pm_runtime_put_autosuspend(arizona->dev);
2201}
2202
ee929a97
CK
2203int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
2204 unsigned int Fref, unsigned int Fout)
2205{
c393aca9 2206 int ret = 0;
ee929a97 2207
1c5617fc 2208 if (fll->ref_src == source && fll->ref_freq == Fref)
ee929a97
CK
2209 return 0;
2210
23f785a8
CK
2211 if (fll->fout && Fref > 0) {
2212 ret = arizona_validate_fll(fll, Fref, fll->fout);
2213 if (ret != 0)
2214 return ret;
ee929a97
CK
2215 }
2216
2217 fll->ref_src = source;
2218 fll->ref_freq = Fref;
ee929a97 2219
86cd684f 2220 if (fll->fout && Fref > 0) {
c393aca9 2221 ret = arizona_enable_fll(fll);
ee929a97
CK
2222 }
2223
c393aca9 2224 return ret;
ee929a97
CK
2225}
2226EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
2227
07ed873e
MB
2228int arizona_set_fll(struct arizona_fll *fll, int source,
2229 unsigned int Fref, unsigned int Fout)
2230{
c393aca9 2231 int ret = 0;
07ed873e 2232
ff680a17
MB
2233 if (fll->sync_src == source &&
2234 fll->sync_freq == Fref && fll->fout == Fout)
2235 return 0;
9e359c64 2236
ff680a17
MB
2237 if (Fout) {
2238 if (fll->ref_src >= 0) {
23f785a8 2239 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
9e359c64
CK
2240 if (ret != 0)
2241 return ret;
2242 }
2243
23f785a8 2244 ret = arizona_validate_fll(fll, Fref, Fout);
ff680a17
MB
2245 if (ret != 0)
2246 return ret;
9e359c64 2247 }
ff680a17
MB
2248
2249 fll->sync_src = source;
2250 fll->sync_freq = Fref;
de1e6eed 2251 fll->fout = Fout;
9e359c64 2252
613124ce 2253 if (Fout)
c393aca9 2254 ret = arizona_enable_fll(fll);
613124ce 2255 else
7604054e 2256 arizona_disable_fll(fll);
07ed873e 2257
c393aca9 2258 return ret;
07ed873e
MB
2259}
2260EXPORT_SYMBOL_GPL(arizona_set_fll);
2261
2262int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2263 int ok_irq, struct arizona_fll *fll)
2264{
19b34bdc 2265 unsigned int val;
07ed873e 2266
07ed873e
MB
2267 fll->id = id;
2268 fll->base = base;
2269 fll->arizona = arizona;
f3f1163d 2270 fll->sync_src = ARIZONA_FLL_SRC_NONE;
07ed873e 2271
19b34bdc
CK
2272 /* Configure default refclk to 32kHz if we have one */
2273 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
2274 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
2275 case ARIZONA_CLK_SRC_MCLK1:
2276 case ARIZONA_CLK_SRC_MCLK2:
2277 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
2278 break;
2279 default:
f3f1163d 2280 fll->ref_src = ARIZONA_FLL_SRC_NONE;
19b34bdc
CK
2281 }
2282 fll->ref_freq = 32768;
2283
07ed873e
MB
2284 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
2285 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2286 "FLL%d clock OK", id);
2287
e31c1946
CK
2288 regmap_update_bits(arizona->regmap, fll->base + 1,
2289 ARIZONA_FLL1_FREERUN, 0);
2290
07ed873e
MB
2291 return 0;
2292}
2293EXPORT_SYMBOL_GPL(arizona_init_fll);
2294
bc9ab6d3
MB
2295/**
2296 * arizona_set_output_mode - Set the mode of the specified output
2297 *
2298 * @codec: Device to configure
2299 * @output: Output number
2300 * @diff: True to set the output to differential mode
2301 *
2302 * Some systems use external analogue switches to connect more
2303 * analogue devices to the CODEC than are supported by the device. In
2304 * some systems this requires changing the switched output from single
2305 * ended to differential mode dynamically at runtime, an operation
2306 * supported using this function.
2307 *
2308 * Most systems have a single static configuration and should use
2309 * platform data instead.
2310 */
2311int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
2312{
2313 unsigned int reg, val;
2314
2315 if (output < 1 || output > 6)
2316 return -EINVAL;
2317
2318 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
2319
2320 if (diff)
2321 val = ARIZONA_OUT1_MONO;
2322 else
2323 val = 0;
2324
2325 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
2326}
2327EXPORT_SYMBOL_GPL(arizona_set_output_mode);
2328
336d0442
RF
2329static const struct soc_enum arizona_adsp2_rate_enum[] = {
2330 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
2331 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2332 ARIZONA_RATE_ENUM_SIZE,
2333 arizona_rate_text, arizona_rate_val),
2334 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
2335 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2336 ARIZONA_RATE_ENUM_SIZE,
2337 arizona_rate_text, arizona_rate_val),
2338 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
2339 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2340 ARIZONA_RATE_ENUM_SIZE,
2341 arizona_rate_text, arizona_rate_val),
2342 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
2343 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2344 ARIZONA_RATE_ENUM_SIZE,
2345 arizona_rate_text, arizona_rate_val),
2346};
2347
2348const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2349 SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]),
2350 SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]),
2351 SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]),
2352 SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]),
2353};
2354EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2355
c05d9a8c
CK
2356static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2357{
2358 s16 a = be16_to_cpu(_a);
2359 s16 b = be16_to_cpu(_b);
2360
2361 if (!mode) {
2362 return abs(a) >= 4096;
2363 } else {
2364 if (abs(b) >= 4096)
2365 return true;
2366
2367 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2368 }
2369}
2370
2371int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2372 struct snd_ctl_elem_value *ucontrol)
2373{
2374 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2375 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2376 struct soc_bytes *params = (void *)kcontrol->private_value;
2377 unsigned int val;
2378 __be16 *data;
2379 int len;
2380 int ret;
2381
2382 len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2383
2384 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2385 if (!data)
2386 return -ENOMEM;
2387
2388 data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2389
2390 if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2391 arizona_eq_filter_unstable(true, data[4], data[5]) ||
2392 arizona_eq_filter_unstable(true, data[8], data[9]) ||
2393 arizona_eq_filter_unstable(true, data[12], data[13]) ||
2394 arizona_eq_filter_unstable(false, data[16], data[17])) {
2395 dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2396 ret = -EINVAL;
2397 goto out;
2398 }
2399
2400 ret = regmap_read(arizona->regmap, params->base, &val);
2401 if (ret != 0)
2402 goto out;
2403
2404 val &= ~ARIZONA_EQ1_B1_MODE;
2405 data[0] |= cpu_to_be16(val);
2406
2407 ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2408
2409out:
2410 kfree(data);
2411 return ret;
2412}
2413EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2414
5f8e671a
CK
2415int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2416 struct snd_ctl_elem_value *ucontrol)
2417{
2418 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2419 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2420 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2421 s16 val = be16_to_cpu(*data);
2422
2423 if (abs(val) >= 4096) {
2424 dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2425 return -EINVAL;
2426 }
2427
2428 return snd_soc_bytes_put(kcontrol, ucontrol);
2429}
2430EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2431
07ed873e
MB
2432MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2433MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2434MODULE_LICENSE("GPL");