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