Merge tag 'for-f2fs-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[deliverable/linux.git] / sound / soc / codecs / arizona.c
CommitLineData
07ed873e
MB
1/*
2 * arizona.c - Wolfson Arizona class device shared support
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
ddbce97c 13#include <linux/delay.h>
07ed873e
MB
14#include <linux/gcd.h>
15#include <linux/module.h>
16#include <linux/pm_runtime.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/tlv.h>
20
21#include <linux/mfd/arizona/core.h>
22#include <linux/mfd/arizona/registers.h>
23
24#include "arizona.h"
25
26#define ARIZONA_AIF_BCLK_CTRL 0x00
27#define ARIZONA_AIF_TX_PIN_CTRL 0x01
28#define ARIZONA_AIF_RX_PIN_CTRL 0x02
29#define ARIZONA_AIF_RATE_CTRL 0x03
30#define ARIZONA_AIF_FORMAT 0x04
31#define ARIZONA_AIF_TX_BCLK_RATE 0x05
32#define ARIZONA_AIF_RX_BCLK_RATE 0x06
33#define ARIZONA_AIF_FRAME_CTRL_1 0x07
34#define ARIZONA_AIF_FRAME_CTRL_2 0x08
35#define ARIZONA_AIF_FRAME_CTRL_3 0x09
36#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
37#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
38#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
39#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
40#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
41#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
42#define ARIZONA_AIF_FRAME_CTRL_10 0x10
43#define ARIZONA_AIF_FRAME_CTRL_11 0x11
44#define ARIZONA_AIF_FRAME_CTRL_12 0x12
45#define ARIZONA_AIF_FRAME_CTRL_13 0x13
46#define ARIZONA_AIF_FRAME_CTRL_14 0x14
47#define ARIZONA_AIF_FRAME_CTRL_15 0x15
48#define ARIZONA_AIF_FRAME_CTRL_16 0x16
49#define ARIZONA_AIF_FRAME_CTRL_17 0x17
50#define ARIZONA_AIF_FRAME_CTRL_18 0x18
51#define ARIZONA_AIF_TX_ENABLES 0x19
52#define ARIZONA_AIF_RX_ENABLES 0x1A
53#define ARIZONA_AIF_FORCE_WRITE 0x1B
54
d0800342 55#define ARIZONA_FLL_VCO_CORNER 141900000
87383ac5
CK
56#define ARIZONA_FLL_MAX_FREF 13500000
57#define ARIZONA_FLL_MIN_FVCO 90000000
d0800342 58#define ARIZONA_FLL_MAX_FRATIO 16
87383ac5
CK
59#define ARIZONA_FLL_MAX_REFDIV 8
60#define ARIZONA_FLL_MIN_OUTDIV 2
61#define ARIZONA_FLL_MAX_OUTDIV 7
62
e9c7f34a
RF
63#define ARIZONA_FMT_DSP_MODE_A 0
64#define ARIZONA_FMT_DSP_MODE_B 1
65#define ARIZONA_FMT_I2S_MODE 2
66#define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3
67
07ed873e
MB
68#define arizona_fll_err(_fll, fmt, ...) \
69 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
70#define arizona_fll_warn(_fll, fmt, ...) \
71 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
72#define arizona_fll_dbg(_fll, fmt, ...) \
9092a6ea 73 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
07ed873e
MB
74
75#define arizona_aif_err(_dai, fmt, ...) \
76 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
77#define arizona_aif_warn(_dai, fmt, ...) \
78 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
79#define arizona_aif_dbg(_dai, fmt, ...) \
9092a6ea 80 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
07ed873e 81
56447e13
MB
82static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
83 struct snd_kcontrol *kcontrol,
84 int event)
85{
043123fd 86 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
56447e13
MB
87 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
88 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
89 bool manual_ena = false;
f4a76e7c 90 int val;
56447e13
MB
91
92 switch (arizona->type) {
93 case WM5102:
94 switch (arizona->rev) {
95 case 0:
96 break;
97 default:
98 manual_ena = true;
99 break;
100 }
101 default:
102 break;
103 }
104
105 switch (event) {
106 case SND_SOC_DAPM_PRE_PMU:
107 if (!priv->spk_ena && manual_ena) {
3c43c695 108 regmap_write_async(arizona->regmap, 0x4f5, 0x25a);
56447e13
MB
109 priv->spk_ena_pending = true;
110 }
111 break;
112 case SND_SOC_DAPM_POST_PMU:
f4a76e7c 113 val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
c0fe2c5b 114 if (val & ARIZONA_SPK_OVERHEAT_STS) {
f4a76e7c
MB
115 dev_crit(arizona->dev,
116 "Speaker not enabled due to temperature\n");
117 return -EBUSY;
118 }
119
3c43c695
MB
120 regmap_update_bits_async(arizona->regmap,
121 ARIZONA_OUTPUT_ENABLES_1,
122 1 << w->shift, 1 << w->shift);
f4a76e7c 123
56447e13
MB
124 if (priv->spk_ena_pending) {
125 msleep(75);
3c43c695 126 regmap_write_async(arizona->regmap, 0x4f5, 0xda);
56447e13
MB
127 priv->spk_ena_pending = false;
128 priv->spk_ena++;
129 }
130 break;
131 case SND_SOC_DAPM_PRE_PMD:
132 if (manual_ena) {
133 priv->spk_ena--;
134 if (!priv->spk_ena)
3c43c695
MB
135 regmap_write_async(arizona->regmap,
136 0x4f5, 0x25a);
56447e13 137 }
f4a76e7c 138
3c43c695
MB
139 regmap_update_bits_async(arizona->regmap,
140 ARIZONA_OUTPUT_ENABLES_1,
141 1 << w->shift, 0);
56447e13
MB
142 break;
143 case SND_SOC_DAPM_POST_PMD:
144 if (manual_ena) {
145 if (!priv->spk_ena)
3c43c695
MB
146 regmap_write_async(arizona->regmap,
147 0x4f5, 0x0da);
56447e13
MB
148 }
149 break;
bee261b8
CK
150 default:
151 break;
56447e13
MB
152 }
153
154 return 0;
155}
156
899817e2
MB
157static irqreturn_t arizona_thermal_warn(int irq, void *data)
158{
159 struct arizona *arizona = data;
160 unsigned int val;
161 int ret;
162
163 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
164 &val);
165 if (ret != 0) {
166 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
167 ret);
c0fe2c5b 168 } else if (val & ARIZONA_SPK_OVERHEAT_WARN_STS) {
899817e2
MB
169 dev_crit(arizona->dev, "Thermal warning\n");
170 }
171
172 return IRQ_HANDLED;
173}
174
175static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
176{
177 struct arizona *arizona = data;
178 unsigned int val;
179 int ret;
180
181 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
182 &val);
183 if (ret != 0) {
184 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
185 ret);
c0fe2c5b 186 } else if (val & ARIZONA_SPK_OVERHEAT_STS) {
899817e2 187 dev_crit(arizona->dev, "Thermal shutdown\n");
f4a76e7c
MB
188 ret = regmap_update_bits(arizona->regmap,
189 ARIZONA_OUTPUT_ENABLES_1,
190 ARIZONA_OUT4L_ENA |
191 ARIZONA_OUT4R_ENA, 0);
192 if (ret != 0)
193 dev_crit(arizona->dev,
194 "Failed to disable speaker outputs: %d\n",
195 ret);
899817e2
MB
196 }
197
198 return IRQ_HANDLED;
199}
200
56447e13 201static const struct snd_soc_dapm_widget arizona_spkl =
f4a76e7c 202 SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
56447e13
MB
203 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
204 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
205
206static const struct snd_soc_dapm_widget arizona_spkr =
f4a76e7c 207 SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
56447e13
MB
208 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
209 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
210
211int arizona_init_spk(struct snd_soc_codec *codec)
212{
1ac52145 213 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
899817e2
MB
214 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
215 struct arizona *arizona = priv->arizona;
56447e13
MB
216 int ret;
217
1ac52145 218 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1);
56447e13
MB
219 if (ret != 0)
220 return ret;
221
40843aea
CK
222 switch (arizona->type) {
223 case WM8997:
224 break;
225 default:
1ac52145 226 ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
40843aea
CK
227 if (ret != 0)
228 return ret;
229 break;
230 }
56447e13 231
c0fe2c5b 232 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
899817e2
MB
233 "Thermal warning", arizona_thermal_warn,
234 arizona);
235 if (ret != 0)
236 dev_err(arizona->dev,
237 "Failed to get thermal warning IRQ: %d\n",
238 ret);
239
c0fe2c5b 240 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT,
899817e2
MB
241 "Thermal shutdown", arizona_thermal_shutdown,
242 arizona);
243 if (ret != 0)
244 dev_err(arizona->dev,
245 "Failed to get thermal shutdown IRQ: %d\n",
246 ret);
247
56447e13
MB
248 return 0;
249}
250EXPORT_SYMBOL_GPL(arizona_init_spk);
251
b60f363b
CK
252static const struct snd_soc_dapm_route arizona_mono_routes[] = {
253 { "OUT1R", NULL, "OUT1L" },
254 { "OUT2R", NULL, "OUT2L" },
255 { "OUT3R", NULL, "OUT3L" },
256 { "OUT4R", NULL, "OUT4L" },
257 { "OUT5R", NULL, "OUT5L" },
258 { "OUT6R", NULL, "OUT6L" },
259};
260
261int arizona_init_mono(struct snd_soc_codec *codec)
262{
1ac52145 263 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
b60f363b
CK
264 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
265 struct arizona *arizona = priv->arizona;
266 int i;
267
268 for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
269 if (arizona->pdata.out_mono[i])
1ac52145 270 snd_soc_dapm_add_routes(dapm,
b60f363b
CK
271 &arizona_mono_routes[i], 1);
272 }
273
274 return 0;
275}
276EXPORT_SYMBOL_GPL(arizona_init_mono);
277
b63144e6
CK
278int arizona_init_gpio(struct snd_soc_codec *codec)
279{
1ac52145 280 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
b63144e6
CK
281 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
282 struct arizona *arizona = priv->arizona;
283 int i;
284
285 switch (arizona->type) {
286 case WM5110:
575ef7f6 287 case WM8280:
1ac52145 288 snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
b79fae60
CK
289 break;
290 default:
291 break;
b63144e6
CK
292 }
293
1ac52145 294 snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
b63144e6
CK
295
296 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
297 switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
298 case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
1ac52145 299 snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
b63144e6
CK
300 break;
301 case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
1ac52145 302 snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
b63144e6
CK
303 break;
304 default:
305 break;
306 }
307 }
308
309 return 0;
310}
311EXPORT_SYMBOL_GPL(arizona_init_gpio);
312
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
341604ad 1026static unsigned int arizona_opclk_ref_48k_rates[] = {
cbd840da
MB
1027 6144000,
1028 12288000,
96e1f18f 1029 24576000,
cbd840da
MB
1030 49152000,
1031};
1032
341604ad 1033static unsigned int arizona_opclk_ref_44k1_rates[] = {
cbd840da
MB
1034 5644800,
1035 11289600,
96e1f18f 1036 22579200,
cbd840da
MB
1037 45158400,
1038};
1039
1040static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
1041 unsigned int freq)
1042{
1043 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1044 unsigned int reg;
1045 unsigned int *rates;
1046 int ref, div, refclk;
1047
1048 switch (clk) {
1049 case ARIZONA_CLK_OPCLK:
1050 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
1051 refclk = priv->sysclk;
1052 break;
1053 case ARIZONA_CLK_ASYNC_OPCLK:
1054 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
1055 refclk = priv->asyncclk;
1056 break;
1057 default:
1058 return -EINVAL;
1059 }
1060
1061 if (refclk % 8000)
341604ad 1062 rates = arizona_opclk_ref_44k1_rates;
cbd840da 1063 else
341604ad 1064 rates = arizona_opclk_ref_48k_rates;
cbd840da 1065
341604ad 1066 for (ref = 0; ref < ARRAY_SIZE(arizona_opclk_ref_48k_rates) &&
cbd840da
MB
1067 rates[ref] <= refclk; ref++) {
1068 div = 1;
1069 while (rates[ref] / div >= freq && div < 32) {
1070 if (rates[ref] / div == freq) {
1071 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
1072 freq);
1073 snd_soc_update_bits(codec, reg,
1074 ARIZONA_OPCLK_DIV_MASK |
1075 ARIZONA_OPCLK_SEL_MASK,
1076 (div <<
1077 ARIZONA_OPCLK_DIV_SHIFT) |
1078 ref);
1079 return 0;
1080 }
1081 div++;
1082 }
1083 }
1084
1085 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
1086 return -EINVAL;
1087}
1088
07ed873e
MB
1089int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1090 int source, unsigned int freq, int dir)
1091{
1092 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1093 struct arizona *arizona = priv->arizona;
1094 char *name;
1095 unsigned int reg;
1096 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
1097 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
1098 unsigned int *clk;
1099
1100 switch (clk_id) {
1101 case ARIZONA_CLK_SYSCLK:
1102 name = "SYSCLK";
1103 reg = ARIZONA_SYSTEM_CLOCK_1;
1104 clk = &priv->sysclk;
1105 mask |= ARIZONA_SYSCLK_FRAC;
1106 break;
1107 case ARIZONA_CLK_ASYNCCLK:
1108 name = "ASYNCCLK";
1109 reg = ARIZONA_ASYNC_CLOCK_1;
1110 clk = &priv->asyncclk;
1111 break;
cbd840da
MB
1112 case ARIZONA_CLK_OPCLK:
1113 case ARIZONA_CLK_ASYNC_OPCLK:
1114 return arizona_set_opclk(codec, clk_id, freq);
07ed873e
MB
1115 default:
1116 return -EINVAL;
1117 }
1118
1119 switch (freq) {
1120 case 5644800:
1121 case 6144000:
1122 break;
1123 case 11289600:
1124 case 12288000:
3f341f74 1125 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1126 break;
1127 case 22579200:
1128 case 24576000:
3f341f74 1129 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
1130 break;
1131 case 45158400:
1132 case 49152000:
3f341f74 1133 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e 1134 break;
38113360
MB
1135 case 67737600:
1136 case 73728000:
3f341f74 1137 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1138 break;
1139 case 90316800:
1140 case 98304000:
3f341f74 1141 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
1142 break;
1143 case 135475200:
1144 case 147456000:
3f341f74 1145 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360 1146 break;
f2c26d48
MB
1147 case 0:
1148 dev_dbg(arizona->dev, "%s cleared\n", name);
1149 *clk = freq;
1150 return 0;
07ed873e
MB
1151 default:
1152 return -EINVAL;
1153 }
1154
1155 *clk = freq;
1156
1157 if (freq % 6144000)
1158 val |= ARIZONA_SYSCLK_FRAC;
1159
1160 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
1161
1162 return regmap_update_bits(arizona->regmap, reg, mask, val);
1163}
1164EXPORT_SYMBOL_GPL(arizona_set_sysclk);
1165
1166static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1167{
1168 struct snd_soc_codec *codec = dai->codec;
3c43c695
MB
1169 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1170 struct arizona *arizona = priv->arizona;
07ed873e
MB
1171 int lrclk, bclk, mode, base;
1172
1173 base = dai->driver->base;
1174
1175 lrclk = 0;
1176 bclk = 0;
1177
1178 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1179 case SND_SOC_DAIFMT_DSP_A:
e9c7f34a
RF
1180 mode = ARIZONA_FMT_DSP_MODE_A;
1181 break;
1182 case SND_SOC_DAIFMT_DSP_B:
1183 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1184 != SND_SOC_DAIFMT_CBM_CFM) {
1185 arizona_aif_err(dai, "DSP_B not valid in slave mode\n");
1186 return -EINVAL;
1187 }
1188 mode = ARIZONA_FMT_DSP_MODE_B;
07ed873e 1189 break;
07ed873e 1190 case SND_SOC_DAIFMT_I2S:
e9c7f34a
RF
1191 mode = ARIZONA_FMT_I2S_MODE;
1192 break;
1193 case SND_SOC_DAIFMT_LEFT_J:
1194 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1195 != SND_SOC_DAIFMT_CBM_CFM) {
1196 arizona_aif_err(dai, "LEFT_J not valid in slave mode\n");
1197 return -EINVAL;
1198 }
1199 mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE;
07ed873e 1200 break;
07ed873e
MB
1201 default:
1202 arizona_aif_err(dai, "Unsupported DAI format %d\n",
1203 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1204 return -EINVAL;
1205 }
1206
1207 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1208 case SND_SOC_DAIFMT_CBS_CFS:
1209 break;
1210 case SND_SOC_DAIFMT_CBS_CFM:
1211 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1212 break;
1213 case SND_SOC_DAIFMT_CBM_CFS:
1214 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1215 break;
1216 case SND_SOC_DAIFMT_CBM_CFM:
1217 bclk |= ARIZONA_AIF1_BCLK_MSTR;
1218 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1219 break;
1220 default:
1221 arizona_aif_err(dai, "Unsupported master mode %d\n",
1222 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1223 return -EINVAL;
1224 }
1225
1226 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1227 case SND_SOC_DAIFMT_NB_NF:
1228 break;
1229 case SND_SOC_DAIFMT_IB_IF:
1230 bclk |= ARIZONA_AIF1_BCLK_INV;
1231 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1232 break;
1233 case SND_SOC_DAIFMT_IB_NF:
1234 bclk |= ARIZONA_AIF1_BCLK_INV;
1235 break;
1236 case SND_SOC_DAIFMT_NB_IF:
1237 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1238 break;
1239 default:
1240 return -EINVAL;
1241 }
1242
3c43c695
MB
1243 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
1244 ARIZONA_AIF1_BCLK_INV |
1245 ARIZONA_AIF1_BCLK_MSTR,
1246 bclk);
1247 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
1248 ARIZONA_AIF1TX_LRCLK_INV |
1249 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
1250 regmap_update_bits_async(arizona->regmap,
1251 base + ARIZONA_AIF_RX_PIN_CTRL,
1252 ARIZONA_AIF1RX_LRCLK_INV |
1253 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
1254 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
1255 ARIZONA_AIF1_FMT_MASK, mode);
07ed873e
MB
1256
1257 return 0;
1258}
1259
949e6bc7 1260static const int arizona_48k_bclk_rates[] = {
07ed873e
MB
1261 -1,
1262 48000,
1263 64000,
1264 96000,
1265 128000,
1266 192000,
1267 256000,
1268 384000,
1269 512000,
1270 768000,
1271 1024000,
1272 1536000,
1273 2048000,
1274 3072000,
1275 4096000,
1276 6144000,
1277 8192000,
1278 12288000,
1279 24576000,
1280};
1281
5b2eec3f
MB
1282static const unsigned int arizona_48k_rates[] = {
1283 12000,
1284 24000,
1285 48000,
1286 96000,
1287 192000,
1288 384000,
1289 768000,
1290 4000,
1291 8000,
1292 16000,
1293 32000,
1294 64000,
1295 128000,
1296 256000,
1297 512000,
1298};
1299
1300static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
1301 .count = ARRAY_SIZE(arizona_48k_rates),
1302 .list = arizona_48k_rates,
1303};
1304
949e6bc7 1305static const int arizona_44k1_bclk_rates[] = {
07ed873e
MB
1306 -1,
1307 44100,
1308 58800,
1309 88200,
1310 117600,
1311 177640,
1312 235200,
1313 352800,
1314 470400,
1315 705600,
1316 940800,
1317 1411200,
1318 1881600,
4758be37 1319 2822400,
07ed873e
MB
1320 3763200,
1321 5644800,
1322 7526400,
1323 11289600,
1324 22579200,
1325};
1326
5b2eec3f
MB
1327static const unsigned int arizona_44k1_rates[] = {
1328 11025,
1329 22050,
1330 44100,
1331 88200,
1332 176400,
1333 352800,
1334 705600,
1335};
1336
1337static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
1338 .count = ARRAY_SIZE(arizona_44k1_rates),
1339 .list = arizona_44k1_rates,
1340};
1341
07ed873e
MB
1342static int arizona_sr_vals[] = {
1343 0,
1344 12000,
1345 24000,
1346 48000,
1347 96000,
1348 192000,
1349 384000,
1350 768000,
1351 0,
1352 11025,
1353 22050,
1354 44100,
1355 88200,
1356 176400,
1357 352800,
1358 705600,
1359 4000,
1360 8000,
1361 16000,
1362 32000,
1363 64000,
1364 128000,
1365 256000,
1366 512000,
1367};
1368
5b2eec3f
MB
1369static int arizona_startup(struct snd_pcm_substream *substream,
1370 struct snd_soc_dai *dai)
1371{
1372 struct snd_soc_codec *codec = dai->codec;
1373 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1374 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1375 const struct snd_pcm_hw_constraint_list *constraint;
1376 unsigned int base_rate;
1377
1378 switch (dai_priv->clk) {
1379 case ARIZONA_CLK_SYSCLK:
1380 base_rate = priv->sysclk;
1381 break;
1382 case ARIZONA_CLK_ASYNCCLK:
1383 base_rate = priv->asyncclk;
1384 break;
1385 default:
1386 return 0;
1387 }
1388
f2c26d48
MB
1389 if (base_rate == 0)
1390 return 0;
1391
5b2eec3f
MB
1392 if (base_rate % 8000)
1393 constraint = &arizona_44k1_constraint;
1394 else
1395 constraint = &arizona_48k_constraint;
1396
1397 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1398 SNDRV_PCM_HW_PARAM_RATE,
1399 constraint);
1400}
1401
cc9e9243
CK
1402static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1403 unsigned int rate)
1404{
1405 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1406 struct arizona *arizona = priv->arizona;
8019ff6c 1407 struct reg_sequence dac_comp[] = {
cc9e9243
CK
1408 { 0x80, 0x3 },
1409 { ARIZONA_DAC_COMP_1, 0 },
1410 { ARIZONA_DAC_COMP_2, 0 },
1411 { 0x80, 0x0 },
1412 };
1413
d74bcaae 1414 mutex_lock(&arizona->dac_comp_lock);
cc9e9243
CK
1415
1416 dac_comp[1].def = arizona->dac_comp_coeff;
1417 if (rate >= 176400)
1418 dac_comp[2].def = arizona->dac_comp_enabled;
1419
d74bcaae 1420 mutex_unlock(&arizona->dac_comp_lock);
cc9e9243
CK
1421
1422 regmap_multi_reg_write(arizona->regmap,
1423 dac_comp,
1424 ARRAY_SIZE(dac_comp));
1425}
1426
b272efc8
MB
1427static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1428 struct snd_pcm_hw_params *params,
1429 struct snd_soc_dai *dai)
1430{
1431 struct snd_soc_codec *codec = dai->codec;
1432 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1433 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1434 int base = dai->driver->base;
2c118b4c 1435 int i, sr_val, ret;
b272efc8
MB
1436
1437 /*
1438 * We will need to be more flexible than this in future,
1439 * currently we use a single sample rate for SYSCLK.
1440 */
1441 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1442 if (arizona_sr_vals[i] == params_rate(params))
1443 break;
1444 if (i == ARRAY_SIZE(arizona_sr_vals)) {
1445 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1446 params_rate(params));
1447 return -EINVAL;
1448 }
1449 sr_val = i;
1450
2c118b4c
RF
1451 switch (priv->arizona->type) {
1452 case WM5102:
1453 case WM8997:
1454 if (arizona_sr_vals[sr_val] >= 88200)
1455 ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
1456 else
1457 ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
1458
1459 if (ret) {
1460 arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
1461 return ret;
1462 }
1463 break;
1464 default:
1465 break;
1466 }
1467
b272efc8
MB
1468 switch (dai_priv->clk) {
1469 case ARIZONA_CLK_SYSCLK:
cc9e9243
CK
1470 switch (priv->arizona->type) {
1471 case WM5102:
1472 arizona_wm5102_set_dac_comp(codec,
1473 params_rate(params));
1474 break;
1475 default:
1476 break;
1477 }
1478
b272efc8
MB
1479 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1480 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1481 if (base)
1482 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1483 ARIZONA_AIF1_RATE_MASK, 0);
1484 break;
1485 case ARIZONA_CLK_ASYNCCLK:
1486 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
c24084db 1487 ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val);
b272efc8
MB
1488 if (base)
1489 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1490 ARIZONA_AIF1_RATE_MASK,
1491 8 << ARIZONA_AIF1_RATE_SHIFT);
1492 break;
1493 default:
1494 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1495 return -EINVAL;
1496 }
1497
1498 return 0;
1499}
1500
bedd4b19
RF
1501static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1502 int base, int bclk, int lrclk, int frame)
1503{
1504 int val;
1505
1506 val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1507 if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1508 return true;
1509
1510 val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1511 if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1512 return true;
1513
1514 val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1515 if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1516 ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1517 return true;
1518
1519 return false;
1520}
1521
07ed873e
MB
1522static int arizona_hw_params(struct snd_pcm_substream *substream,
1523 struct snd_pcm_hw_params *params,
1524 struct snd_soc_dai *dai)
1525{
1526 struct snd_soc_codec *codec = dai->codec;
c013b27a 1527 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
c94aa30e 1528 struct arizona *arizona = priv->arizona;
07ed873e
MB
1529 int base = dai->driver->base;
1530 const int *rates;
76bf969e 1531 int i, ret, val;
ed70f3a2 1532 int channels = params_channels(params);
c94aa30e 1533 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
ed70f3a2
CK
1534 int tdm_width = arizona->tdm_width[dai->id - 1];
1535 int tdm_slots = arizona->tdm_slots[dai->id - 1];
c94aa30e 1536 int bclk, lrclk, wl, frame, bclk_target;
bedd4b19
RF
1537 bool reconfig;
1538 unsigned int aif_tx_state, aif_rx_state;
07ed873e 1539
e73694d8 1540 if (params_rate(params) % 4000)
949e6bc7 1541 rates = &arizona_44k1_bclk_rates[0];
07ed873e 1542 else
949e6bc7 1543 rates = &arizona_48k_bclk_rates[0];
07ed873e 1544
5ed68f0a 1545 wl = params_width(params);
d114e5f7 1546
ed70f3a2
CK
1547 if (tdm_slots) {
1548 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
1549 tdm_slots, tdm_width);
1550 bclk_target = tdm_slots * tdm_width * params_rate(params);
1551 channels = tdm_slots;
1552 } else {
1553 bclk_target = snd_soc_params_to_bclk(params);
d114e5f7 1554 tdm_width = wl;
ed70f3a2
CK
1555 }
1556
1557 if (chan_limit && chan_limit < channels) {
c94aa30e 1558 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
ed70f3a2 1559 bclk_target /= channels;
c94aa30e
MB
1560 bclk_target *= chan_limit;
1561 }
1562
ed70f3a2 1563 /* Force multiple of 2 channels for I2S mode */
76bf969e 1564 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
e9c7f34a
RF
1565 val &= ARIZONA_AIF1_FMT_MASK;
1566 if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) {
76bf969e 1567 arizona_aif_dbg(dai, "Forcing stereo mode\n");
ed70f3a2
CK
1568 bclk_target /= channels;
1569 bclk_target *= channels + 1;
76bf969e
MB
1570 }
1571
949e6bc7 1572 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
c94aa30e 1573 if (rates[i] >= bclk_target &&
5001765f 1574 rates[i] % params_rate(params) == 0) {
07ed873e
MB
1575 bclk = i;
1576 break;
1577 }
1578 }
949e6bc7 1579 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
07ed873e
MB
1580 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1581 params_rate(params));
1582 return -EINVAL;
1583 }
1584
b59e0f82 1585 lrclk = rates[bclk] / params_rate(params);
07ed873e
MB
1586
1587 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1588 rates[bclk], rates[bclk] / lrclk);
1589
d114e5f7 1590 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width;
07ed873e 1591
bedd4b19
RF
1592 reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1593
1594 if (reconfig) {
1595 /* Save AIF TX/RX state */
1596 aif_tx_state = snd_soc_read(codec,
1597 base + ARIZONA_AIF_TX_ENABLES);
1598 aif_rx_state = snd_soc_read(codec,
1599 base + ARIZONA_AIF_RX_ENABLES);
1600 /* Disable AIF TX/RX before reconfiguring it */
1601 regmap_update_bits_async(arizona->regmap,
1602 base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1603 regmap_update_bits(arizona->regmap,
1604 base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1605 }
1606
b272efc8
MB
1607 ret = arizona_hw_params_rate(substream, params, dai);
1608 if (ret != 0)
bedd4b19 1609 goto restore_aif;
c013b27a 1610
bedd4b19
RF
1611 if (reconfig) {
1612 regmap_update_bits_async(arizona->regmap,
1613 base + ARIZONA_AIF_BCLK_CTRL,
1614 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1615 regmap_update_bits_async(arizona->regmap,
1616 base + ARIZONA_AIF_TX_BCLK_RATE,
1617 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1618 regmap_update_bits_async(arizona->regmap,
1619 base + ARIZONA_AIF_RX_BCLK_RATE,
1620 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1621 regmap_update_bits_async(arizona->regmap,
1622 base + ARIZONA_AIF_FRAME_CTRL_1,
1623 ARIZONA_AIF1TX_WL_MASK |
1624 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1625 regmap_update_bits(arizona->regmap,
1626 base + ARIZONA_AIF_FRAME_CTRL_2,
1627 ARIZONA_AIF1RX_WL_MASK |
1628 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1629 }
07ed873e 1630
bedd4b19
RF
1631restore_aif:
1632 if (reconfig) {
1633 /* Restore AIF TX/RX state */
1634 regmap_update_bits_async(arizona->regmap,
1635 base + ARIZONA_AIF_TX_ENABLES,
1636 0xff, aif_tx_state);
1637 regmap_update_bits(arizona->regmap,
1638 base + ARIZONA_AIF_RX_ENABLES,
1639 0xff, aif_rx_state);
1640 }
1641 return ret;
07ed873e
MB
1642}
1643
410837a7
MB
1644static const char *arizona_dai_clk_str(int clk_id)
1645{
1646 switch (clk_id) {
1647 case ARIZONA_CLK_SYSCLK:
1648 return "SYSCLK";
1649 case ARIZONA_CLK_ASYNCCLK:
1650 return "ASYNCCLK";
1651 default:
1652 return "Unknown clock";
1653 }
1654}
1655
5b2eec3f
MB
1656static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1657 int clk_id, unsigned int freq, int dir)
1658{
1659 struct snd_soc_codec *codec = dai->codec;
1ac52145 1660 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
5b2eec3f
MB
1661 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1662 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
410837a7 1663 struct snd_soc_dapm_route routes[2];
5b2eec3f
MB
1664
1665 switch (clk_id) {
1666 case ARIZONA_CLK_SYSCLK:
1667 case ARIZONA_CLK_ASYNCCLK:
1668 break;
1669 default:
1670 return -EINVAL;
1671 }
1672
410837a7
MB
1673 if (clk_id == dai_priv->clk)
1674 return 0;
1675
1676 if (dai->active) {
5b2eec3f
MB
1677 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1678 dai->id);
1679 return -EBUSY;
1680 }
1681
c8d35a6a
MB
1682 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1683 arizona_dai_clk_str(clk_id));
1684
410837a7
MB
1685 memset(&routes, 0, sizeof(routes));
1686 routes[0].sink = dai->driver->capture.stream_name;
1687 routes[1].sink = dai->driver->playback.stream_name;
5b2eec3f 1688
410837a7
MB
1689 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1690 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1ac52145 1691 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7
MB
1692
1693 routes[0].source = arizona_dai_clk_str(clk_id);
1694 routes[1].source = arizona_dai_clk_str(clk_id);
1ac52145 1695 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
410837a7 1696
0c778e86
MB
1697 dai_priv->clk = clk_id;
1698
1ac52145 1699 return snd_soc_dapm_sync(dapm);
5b2eec3f
MB
1700}
1701
01df259f
MB
1702static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1703{
1704 struct snd_soc_codec *codec = dai->codec;
1705 int base = dai->driver->base;
1706 unsigned int reg;
1707
1708 if (tristate)
1709 reg = ARIZONA_AIF1_TRI;
1710 else
1711 reg = 0;
1712
1713 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1714 ARIZONA_AIF1_TRI, reg);
1715}
1716
ed70f3a2
CK
1717static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
1718 unsigned int base,
1719 int channels, unsigned int mask)
1720{
1721 struct snd_soc_codec *codec = dai->codec;
1722 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1723 struct arizona *arizona = priv->arizona;
1724 int slot, i;
1725
1726 for (i = 0; i < channels; ++i) {
1727 slot = ffs(mask) - 1;
1728 if (slot < 0)
1729 return;
1730
1731 regmap_write(arizona->regmap, base + i, slot);
1732
1733 mask &= ~(1 << slot);
1734 }
1735
1736 if (mask)
1737 arizona_aif_warn(dai, "Too many channels in TDM mask\n");
1738}
1739
1740static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1741 unsigned int rx_mask, int slots, int slot_width)
1742{
1743 struct snd_soc_codec *codec = dai->codec;
1744 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1745 struct arizona *arizona = priv->arizona;
1746 int base = dai->driver->base;
1747 int rx_max_chan = dai->driver->playback.channels_max;
1748 int tx_max_chan = dai->driver->capture.channels_max;
1749
1750 /* Only support TDM for the physical AIFs */
1751 if (dai->id > ARIZONA_MAX_AIF)
1752 return -ENOTSUPP;
1753
1754 if (slots == 0) {
1755 tx_mask = (1 << tx_max_chan) - 1;
1756 rx_mask = (1 << rx_max_chan) - 1;
1757 }
1758
1759 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
1760 tx_max_chan, tx_mask);
1761 arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
1762 rx_max_chan, rx_mask);
1763
1764 arizona->tdm_width[dai->id - 1] = slot_width;
1765 arizona->tdm_slots[dai->id - 1] = slots;
1766
1767 return 0;
1768}
1769
07ed873e 1770const struct snd_soc_dai_ops arizona_dai_ops = {
5b2eec3f 1771 .startup = arizona_startup,
07ed873e 1772 .set_fmt = arizona_set_fmt,
ed70f3a2 1773 .set_tdm_slot = arizona_set_tdm_slot,
07ed873e 1774 .hw_params = arizona_hw_params,
5b2eec3f 1775 .set_sysclk = arizona_dai_set_sysclk,
01df259f 1776 .set_tristate = arizona_set_tristate,
07ed873e 1777};
a837987e 1778EXPORT_SYMBOL_GPL(arizona_dai_ops);
07ed873e 1779
bd1dd885
MB
1780const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1781 .startup = arizona_startup,
1782 .hw_params = arizona_hw_params_rate,
1783 .set_sysclk = arizona_dai_set_sysclk,
1784};
1785EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1786
5b2eec3f
MB
1787int arizona_init_dai(struct arizona_priv *priv, int id)
1788{
1789 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1790
1791 dai_priv->clk = ARIZONA_CLK_SYSCLK;
1792
1793 return 0;
1794}
1795EXPORT_SYMBOL_GPL(arizona_init_dai);
1796
07ed873e
MB
1797static struct {
1798 unsigned int min;
1799 unsigned int max;
1800 u16 fratio;
1801 int ratio;
1802} fll_fratios[] = {
1803 { 0, 64000, 4, 16 },
1804 { 64000, 128000, 3, 8 },
1805 { 128000, 256000, 2, 4 },
1806 { 256000, 1000000, 1, 2 },
1807 { 1000000, 13500000, 0, 1 },
1808};
1809
8f113d7d
MB
1810static struct {
1811 unsigned int min;
1812 unsigned int max;
1813 u16 gain;
1814} fll_gains[] = {
1815 { 0, 256000, 0 },
1816 { 256000, 1000000, 2 },
1817 { 1000000, 13500000, 4 },
1818};
1819
07ed873e
MB
1820struct arizona_fll_cfg {
1821 int n;
1822 int theta;
1823 int lambda;
1824 int refdiv;
1825 int outdiv;
1826 int fratio;
8f113d7d 1827 int gain;
07ed873e
MB
1828};
1829
23f785a8
CK
1830static int arizona_validate_fll(struct arizona_fll *fll,
1831 unsigned int Fref,
1832 unsigned int Fout)
07ed873e 1833{
23f785a8
CK
1834 unsigned int Fvco_min;
1835
c8badda8
CK
1836 if (fll->fout && Fout != fll->fout) {
1837 arizona_fll_err(fll,
1838 "Can't change output on active FLL\n");
1839 return -EINVAL;
1840 }
1841
23f785a8
CK
1842 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1843 arizona_fll_err(fll,
1844 "Can't scale %dMHz in to <=13.5MHz\n",
1845 Fref);
1846 return -EINVAL;
1847 }
07ed873e 1848
23f785a8
CK
1849 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1850 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1851 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1852 Fout);
1853 return -EINVAL;
1854 }
1855
1856 return 0;
1857}
1858
d0800342
CK
1859static int arizona_find_fratio(unsigned int Fref, int *fratio)
1860{
1861 int i;
1862
1863 /* Find an appropriate FLL_FRATIO */
1864 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1865 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1866 if (fratio)
1867 *fratio = fll_fratios[i].fratio;
1868 return fll_fratios[i].ratio;
1869 }
1870 }
1871
1872 return -EINVAL;
1873}
1874
1875static int arizona_calc_fratio(struct arizona_fll *fll,
1876 struct arizona_fll_cfg *cfg,
1877 unsigned int target,
1878 unsigned int Fref, bool sync)
1879{
1880 int init_ratio, ratio;
1881 int refdiv, div;
07ed873e 1882
d0800342 1883 /* Fref must be <=13.5MHz, find initial refdiv */
07ed873e
MB
1884 div = 1;
1885 cfg->refdiv = 0;
d0800342 1886 while (Fref > ARIZONA_FLL_MAX_FREF) {
07ed873e 1887 div *= 2;
d0800342 1888 Fref /= 2;
07ed873e
MB
1889 cfg->refdiv++;
1890
d0800342 1891 if (div > ARIZONA_FLL_MAX_REFDIV)
07ed873e 1892 return -EINVAL;
d0800342
CK
1893 }
1894
1895 /* Find an appropriate FLL_FRATIO */
1896 init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
1897 if (init_ratio < 0) {
1898 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1899 Fref);
1900 return init_ratio;
1901 }
1902
1903 switch (fll->arizona->type) {
1904 case WM5110:
575ef7f6 1905 case WM8280:
d0800342
CK
1906 if (fll->arizona->rev < 3 || sync)
1907 return init_ratio;
1908 break;
6ebbce0a
RF
1909 case WM8998:
1910 case WM1814:
1911 if (sync)
1912 return init_ratio;
1913 break;
d0800342
CK
1914 default:
1915 return init_ratio;
1916 }
1917
1918 cfg->fratio = init_ratio - 1;
1919
1920 /* Adjust FRATIO/refdiv to avoid integer mode if possible */
1921 refdiv = cfg->refdiv;
1922
1923 while (div <= ARIZONA_FLL_MAX_REFDIV) {
1924 for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
1925 ratio++) {
35a730a0
CK
1926 if ((ARIZONA_FLL_VCO_CORNER / 2) /
1927 (fll->vco_mult * ratio) < Fref)
29fee829
CK
1928 break;
1929
d0800342
CK
1930 if (target % (ratio * Fref)) {
1931 cfg->refdiv = refdiv;
1932 cfg->fratio = ratio - 1;
1933 return ratio;
1934 }
07ed873e 1935 }
d0800342 1936
4714bc01 1937 for (ratio = init_ratio - 1; ratio > 0; ratio--) {
d0800342
CK
1938 if (target % (ratio * Fref)) {
1939 cfg->refdiv = refdiv;
1940 cfg->fratio = ratio - 1;
1941 return ratio;
1942 }
1943 }
1944
1945 div *= 2;
1946 Fref /= 2;
1947 refdiv++;
1948 init_ratio = arizona_find_fratio(Fref, NULL);
07ed873e
MB
1949 }
1950
d0800342
CK
1951 arizona_fll_warn(fll, "Falling back to integer mode operation\n");
1952 return cfg->fratio + 1;
1953}
1954
07ed873e
MB
1955static int arizona_calc_fll(struct arizona_fll *fll,
1956 struct arizona_fll_cfg *cfg,
d0800342 1957 unsigned int Fref, bool sync)
07ed873e
MB
1958{
1959 unsigned int target, div, gcd_fll;
1960 int i, ratio;
1961
8ccefcd2 1962 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
07ed873e 1963
2b4d39fc 1964 /* Fvco should be over the targt; don't check the upper bound */
f641aec6
CK
1965 div = ARIZONA_FLL_MIN_OUTDIV;
1966 while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
07ed873e 1967 div++;
f641aec6 1968 if (div > ARIZONA_FLL_MAX_OUTDIV)
07ed873e 1969 return -EINVAL;
07ed873e 1970 }
f641aec6 1971 target = fll->fout * div / fll->vco_mult;
07ed873e
MB
1972 cfg->outdiv = div;
1973
1974 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1975
d0800342
CK
1976 /* Find an appropriate FLL_FRATIO and refdiv */
1977 ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
1978 if (ratio < 0)
1979 return ratio;
07ed873e 1980
07ed873e 1981 /* Apply the division for our remaining calculations */
d0800342 1982 Fref = Fref / (1 << cfg->refdiv);
8f113d7d 1983
07ed873e
MB
1984 cfg->n = target / (ratio * Fref);
1985
01f58153 1986 if (target % (ratio * Fref)) {
07ed873e
MB
1987 gcd_fll = gcd(target, ratio * Fref);
1988 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1989
1990 cfg->theta = (target - (cfg->n * ratio * Fref))
1991 / gcd_fll;
1992 cfg->lambda = (ratio * Fref) / gcd_fll;
1993 } else {
1994 cfg->theta = 0;
1995 cfg->lambda = 0;
1996 }
1997
01f58153
RT
1998 /* Round down to 16bit range with cost of accuracy lost.
1999 * Denominator must be bigger than numerator so we only
2000 * take care of it.
2001 */
2002 while (cfg->lambda >= (1 << 16)) {
2003 cfg->theta >>= 1;
2004 cfg->lambda >>= 1;
2005 }
2006
5a3935c7
CK
2007 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
2008 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
2009 cfg->gain = fll_gains[i].gain;
2010 break;
2011 }
2012 }
2013 if (i == ARRAY_SIZE(fll_gains)) {
2014 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
2015 Fref);
2016 return -EINVAL;
2017 }
2018
07ed873e
MB
2019 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
2020 cfg->n, cfg->theta, cfg->lambda);
2021 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
2022 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
8f113d7d 2023 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
07ed873e
MB
2024
2025 return 0;
2026
2027}
2028
2029static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
8f113d7d
MB
2030 struct arizona_fll_cfg *cfg, int source,
2031 bool sync)
07ed873e 2032{
3c43c695
MB
2033 regmap_update_bits_async(arizona->regmap, base + 3,
2034 ARIZONA_FLL1_THETA_MASK, cfg->theta);
2035 regmap_update_bits_async(arizona->regmap, base + 4,
2036 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
2037 regmap_update_bits_async(arizona->regmap, base + 5,
2038 ARIZONA_FLL1_FRATIO_MASK,
2039 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
2040 regmap_update_bits_async(arizona->regmap, base + 6,
2041 ARIZONA_FLL1_CLK_REF_DIV_MASK |
2042 ARIZONA_FLL1_CLK_REF_SRC_MASK,
2043 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
2044 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
07ed873e 2045
61719db8
CK
2046 if (sync) {
2047 regmap_update_bits(arizona->regmap, base + 0x7,
2048 ARIZONA_FLL1_GAIN_MASK,
2049 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2050 } else {
2051 regmap_update_bits(arizona->regmap, base + 0x5,
2052 ARIZONA_FLL1_OUTDIV_MASK,
2053 cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
2054 regmap_update_bits(arizona->regmap, base + 0x9,
2055 ARIZONA_FLL1_GAIN_MASK,
2056 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2057 }
8f113d7d 2058
3c43c695
MB
2059 regmap_update_bits_async(arizona->regmap, base + 2,
2060 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
2061 ARIZONA_FLL1_CTRL_UPD | cfg->n);
07ed873e
MB
2062}
2063
c393aca9 2064static int arizona_is_enabled_fll(struct arizona_fll *fll)
d122d6c9
CK
2065{
2066 struct arizona *arizona = fll->arizona;
2067 unsigned int reg;
2068 int ret;
2069
2070 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
2071 if (ret != 0) {
2072 arizona_fll_err(fll, "Failed to read current state: %d\n",
2073 ret);
2074 return ret;
2075 }
2076
2077 return reg & ARIZONA_FLL1_ENA;
2078}
2079
c393aca9 2080static int arizona_enable_fll(struct arizona_fll *fll)
35722815
CK
2081{
2082 struct arizona *arizona = fll->arizona;
49c60547 2083 bool use_sync = false;
c393aca9 2084 int already_enabled = arizona_is_enabled_fll(fll);
23f785a8 2085 struct arizona_fll_cfg cfg;
0e765971
CK
2086 int i;
2087 unsigned int val;
35722815 2088
c393aca9
CK
2089 if (already_enabled < 0)
2090 return already_enabled;
2091
c8badda8
CK
2092 if (already_enabled) {
2093 /* Facilitate smooth refclk across the transition */
1cf5a330 2094 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
c8badda8
CK
2095 ARIZONA_FLL1_GAIN_MASK, 0);
2096 regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
2097 ARIZONA_FLL1_FREERUN,
2098 ARIZONA_FLL1_FREERUN);
2099 }
2100
ff680a17
MB
2101 /*
2102 * If we have both REFCLK and SYNCCLK then enable both,
2103 * otherwise apply the SYNCCLK settings to REFCLK.
2104 */
49c60547
CK
2105 if (fll->ref_src >= 0 && fll->ref_freq &&
2106 fll->ref_src != fll->sync_src) {
d0800342 2107 arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
ff680a17 2108
23f785a8 2109 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
8f113d7d 2110 false);
49c60547 2111 if (fll->sync_src >= 0) {
d0800342 2112 arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
23f785a8
CK
2113
2114 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
8f113d7d 2115 fll->sync_src, true);
49c60547
CK
2116 use_sync = true;
2117 }
ff680a17 2118 } else if (fll->sync_src >= 0) {
d0800342 2119 arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
ff680a17 2120
23f785a8 2121 arizona_apply_fll(arizona, fll->base, &cfg,
8f113d7d 2122 fll->sync_src, false);
eca2e8e2 2123
3c43c695
MB
2124 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2125 ARIZONA_FLL1_SYNC_ENA, 0);
ff680a17
MB
2126 } else {
2127 arizona_fll_err(fll, "No clocks provided\n");
c393aca9 2128 return -EINVAL;
ff680a17 2129 }
35722815 2130
576411be
MB
2131 /*
2132 * Increase the bandwidth if we're not using a low frequency
2133 * sync source.
2134 */
49c60547 2135 if (use_sync && fll->sync_freq > 100000)
3c43c695
MB
2136 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2137 ARIZONA_FLL1_SYNC_BW, 0);
576411be 2138 else
3c43c695
MB
2139 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2140 ARIZONA_FLL1_SYNC_BW,
2141 ARIZONA_FLL1_SYNC_BW);
576411be 2142
c393aca9 2143 if (!already_enabled)
35722815
CK
2144 pm_runtime_get(arizona->dev);
2145
3c43c695
MB
2146 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2147 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
49c60547 2148 if (use_sync)
3c43c695
MB
2149 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2150 ARIZONA_FLL1_SYNC_ENA,
2151 ARIZONA_FLL1_SYNC_ENA);
35722815 2152
c8badda8
CK
2153 if (already_enabled)
2154 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2155 ARIZONA_FLL1_FREERUN, 0);
2156
0e765971
CK
2157 arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2158 val = 0;
2159 for (i = 0; i < 15; i++) {
2160 if (i < 5)
2161 usleep_range(200, 400);
2162 else
2163 msleep(20);
2164
2165 regmap_read(arizona->regmap,
2166 ARIZONA_INTERRUPT_RAW_STATUS_5,
2167 &val);
2168 if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2169 break;
2170 }
2171 if (i == 15)
35722815 2172 arizona_fll_warn(fll, "Timed out waiting for lock\n");
0e765971
CK
2173 else
2174 arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
c393aca9
CK
2175
2176 return 0;
35722815
CK
2177}
2178
7604054e
CK
2179static void arizona_disable_fll(struct arizona_fll *fll)
2180{
2181 struct arizona *arizona = fll->arizona;
2182 bool change;
2183
3c43c695
MB
2184 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2185 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
7604054e
CK
2186 regmap_update_bits_check(arizona->regmap, fll->base + 1,
2187 ARIZONA_FLL1_ENA, 0, &change);
2188 regmap_update_bits(arizona->regmap, fll->base + 0x11,
2189 ARIZONA_FLL1_SYNC_ENA, 0);
5e39a50b
CK
2190 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2191 ARIZONA_FLL1_FREERUN, 0);
7604054e
CK
2192
2193 if (change)
2194 pm_runtime_put_autosuspend(arizona->dev);
2195}
2196
ee929a97
CK
2197int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
2198 unsigned int Fref, unsigned int Fout)
2199{
c393aca9 2200 int ret = 0;
ee929a97 2201
1c5617fc 2202 if (fll->ref_src == source && fll->ref_freq == Fref)
ee929a97
CK
2203 return 0;
2204
23f785a8
CK
2205 if (fll->fout && Fref > 0) {
2206 ret = arizona_validate_fll(fll, Fref, fll->fout);
2207 if (ret != 0)
2208 return ret;
ee929a97
CK
2209 }
2210
2211 fll->ref_src = source;
2212 fll->ref_freq = Fref;
ee929a97 2213
86cd684f 2214 if (fll->fout && Fref > 0) {
c393aca9 2215 ret = arizona_enable_fll(fll);
ee929a97
CK
2216 }
2217
c393aca9 2218 return ret;
ee929a97
CK
2219}
2220EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
2221
07ed873e
MB
2222int arizona_set_fll(struct arizona_fll *fll, int source,
2223 unsigned int Fref, unsigned int Fout)
2224{
c393aca9 2225 int ret = 0;
07ed873e 2226
ff680a17
MB
2227 if (fll->sync_src == source &&
2228 fll->sync_freq == Fref && fll->fout == Fout)
2229 return 0;
9e359c64 2230
ff680a17
MB
2231 if (Fout) {
2232 if (fll->ref_src >= 0) {
23f785a8 2233 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
9e359c64
CK
2234 if (ret != 0)
2235 return ret;
2236 }
2237
23f785a8 2238 ret = arizona_validate_fll(fll, Fref, Fout);
ff680a17
MB
2239 if (ret != 0)
2240 return ret;
9e359c64 2241 }
ff680a17
MB
2242
2243 fll->sync_src = source;
2244 fll->sync_freq = Fref;
de1e6eed 2245 fll->fout = Fout;
9e359c64 2246
613124ce 2247 if (Fout)
c393aca9 2248 ret = arizona_enable_fll(fll);
613124ce 2249 else
7604054e 2250 arizona_disable_fll(fll);
07ed873e 2251
c393aca9 2252 return ret;
07ed873e
MB
2253}
2254EXPORT_SYMBOL_GPL(arizona_set_fll);
2255
2256int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2257 int ok_irq, struct arizona_fll *fll)
2258{
19b34bdc 2259 unsigned int val;
07ed873e 2260
07ed873e
MB
2261 fll->id = id;
2262 fll->base = base;
2263 fll->arizona = arizona;
f3f1163d 2264 fll->sync_src = ARIZONA_FLL_SRC_NONE;
07ed873e 2265
19b34bdc
CK
2266 /* Configure default refclk to 32kHz if we have one */
2267 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
2268 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
2269 case ARIZONA_CLK_SRC_MCLK1:
2270 case ARIZONA_CLK_SRC_MCLK2:
2271 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
2272 break;
2273 default:
f3f1163d 2274 fll->ref_src = ARIZONA_FLL_SRC_NONE;
19b34bdc
CK
2275 }
2276 fll->ref_freq = 32768;
2277
07ed873e
MB
2278 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
2279 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2280 "FLL%d clock OK", id);
2281
e31c1946
CK
2282 regmap_update_bits(arizona->regmap, fll->base + 1,
2283 ARIZONA_FLL1_FREERUN, 0);
2284
07ed873e
MB
2285 return 0;
2286}
2287EXPORT_SYMBOL_GPL(arizona_init_fll);
2288
bc9ab6d3
MB
2289/**
2290 * arizona_set_output_mode - Set the mode of the specified output
2291 *
2292 * @codec: Device to configure
2293 * @output: Output number
2294 * @diff: True to set the output to differential mode
2295 *
2296 * Some systems use external analogue switches to connect more
2297 * analogue devices to the CODEC than are supported by the device. In
2298 * some systems this requires changing the switched output from single
2299 * ended to differential mode dynamically at runtime, an operation
2300 * supported using this function.
2301 *
2302 * Most systems have a single static configuration and should use
2303 * platform data instead.
2304 */
2305int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
2306{
2307 unsigned int reg, val;
2308
2309 if (output < 1 || output > 6)
2310 return -EINVAL;
2311
2312 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
2313
2314 if (diff)
2315 val = ARIZONA_OUT1_MONO;
2316 else
2317 val = 0;
2318
2319 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
2320}
2321EXPORT_SYMBOL_GPL(arizona_set_output_mode);
2322
336d0442
RF
2323static const struct soc_enum arizona_adsp2_rate_enum[] = {
2324 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
2325 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2326 ARIZONA_RATE_ENUM_SIZE,
2327 arizona_rate_text, arizona_rate_val),
2328 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
2329 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2330 ARIZONA_RATE_ENUM_SIZE,
2331 arizona_rate_text, arizona_rate_val),
2332 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
2333 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2334 ARIZONA_RATE_ENUM_SIZE,
2335 arizona_rate_text, arizona_rate_val),
2336 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
2337 ARIZONA_DSP1_RATE_SHIFT, 0xf,
2338 ARIZONA_RATE_ENUM_SIZE,
2339 arizona_rate_text, arizona_rate_val),
2340};
2341
2342const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2343 SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]),
2344 SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]),
2345 SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]),
2346 SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]),
2347};
2348EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2349
c05d9a8c
CK
2350static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2351{
2352 s16 a = be16_to_cpu(_a);
2353 s16 b = be16_to_cpu(_b);
2354
2355 if (!mode) {
2356 return abs(a) >= 4096;
2357 } else {
2358 if (abs(b) >= 4096)
2359 return true;
2360
2361 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2362 }
2363}
2364
2365int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2366 struct snd_ctl_elem_value *ucontrol)
2367{
2368 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2369 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2370 struct soc_bytes *params = (void *)kcontrol->private_value;
2371 unsigned int val;
2372 __be16 *data;
2373 int len;
2374 int ret;
2375
2376 len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2377
2378 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2379 if (!data)
2380 return -ENOMEM;
2381
2382 data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2383
2384 if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2385 arizona_eq_filter_unstable(true, data[4], data[5]) ||
2386 arizona_eq_filter_unstable(true, data[8], data[9]) ||
2387 arizona_eq_filter_unstable(true, data[12], data[13]) ||
2388 arizona_eq_filter_unstable(false, data[16], data[17])) {
2389 dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2390 ret = -EINVAL;
2391 goto out;
2392 }
2393
2394 ret = regmap_read(arizona->regmap, params->base, &val);
2395 if (ret != 0)
2396 goto out;
2397
2398 val &= ~ARIZONA_EQ1_B1_MODE;
2399 data[0] |= cpu_to_be16(val);
2400
2401 ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2402
2403out:
2404 kfree(data);
2405 return ret;
2406}
2407EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2408
5f8e671a
CK
2409int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2410 struct snd_ctl_elem_value *ucontrol)
2411{
2412 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2413 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2414 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2415 s16 val = be16_to_cpu(*data);
2416
2417 if (abs(val) >= 4096) {
2418 dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2419 return -EINVAL;
2420 }
2421
2422 return snd_soc_bytes_put(kcontrol, ucontrol);
2423}
2424EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2425
07ed873e
MB
2426MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2427MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2428MODULE_LICENSE("GPL");
This page took 0.395791 seconds and 5 git commands to generate.