ASoC: arizona: Calculate OUTDIV first
[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>
b63144e6 22#include <linux/mfd/arizona/gpio.h>
07ed873e
MB
23#include <linux/mfd/arizona/registers.h>
24
25#include "arizona.h"
26
27#define ARIZONA_AIF_BCLK_CTRL 0x00
28#define ARIZONA_AIF_TX_PIN_CTRL 0x01
29#define ARIZONA_AIF_RX_PIN_CTRL 0x02
30#define ARIZONA_AIF_RATE_CTRL 0x03
31#define ARIZONA_AIF_FORMAT 0x04
32#define ARIZONA_AIF_TX_BCLK_RATE 0x05
33#define ARIZONA_AIF_RX_BCLK_RATE 0x06
34#define ARIZONA_AIF_FRAME_CTRL_1 0x07
35#define ARIZONA_AIF_FRAME_CTRL_2 0x08
36#define ARIZONA_AIF_FRAME_CTRL_3 0x09
37#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
38#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
39#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
40#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
41#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
42#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
43#define ARIZONA_AIF_FRAME_CTRL_10 0x10
44#define ARIZONA_AIF_FRAME_CTRL_11 0x11
45#define ARIZONA_AIF_FRAME_CTRL_12 0x12
46#define ARIZONA_AIF_FRAME_CTRL_13 0x13
47#define ARIZONA_AIF_FRAME_CTRL_14 0x14
48#define ARIZONA_AIF_FRAME_CTRL_15 0x15
49#define ARIZONA_AIF_FRAME_CTRL_16 0x16
50#define ARIZONA_AIF_FRAME_CTRL_17 0x17
51#define ARIZONA_AIF_FRAME_CTRL_18 0x18
52#define ARIZONA_AIF_TX_ENABLES 0x19
53#define ARIZONA_AIF_RX_ENABLES 0x1A
54#define ARIZONA_AIF_FORCE_WRITE 0x1B
55
87383ac5
CK
56#define ARIZONA_FLL_MAX_FREF 13500000
57#define ARIZONA_FLL_MIN_FVCO 90000000
58#define ARIZONA_FLL_MAX_REFDIV 8
59#define ARIZONA_FLL_MIN_OUTDIV 2
60#define ARIZONA_FLL_MAX_OUTDIV 7
61
07ed873e
MB
62#define arizona_fll_err(_fll, fmt, ...) \
63 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
64#define arizona_fll_warn(_fll, fmt, ...) \
65 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
66#define arizona_fll_dbg(_fll, fmt, ...) \
9092a6ea 67 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
07ed873e
MB
68
69#define arizona_aif_err(_dai, fmt, ...) \
70 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
71#define arizona_aif_warn(_dai, fmt, ...) \
72 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
73#define arizona_aif_dbg(_dai, fmt, ...) \
9092a6ea 74 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
07ed873e 75
56447e13
MB
76static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
77 struct snd_kcontrol *kcontrol,
78 int event)
79{
80 struct snd_soc_codec *codec = w->codec;
81 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
82 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
83 bool manual_ena = false;
f4a76e7c 84 int val;
56447e13
MB
85
86 switch (arizona->type) {
87 case WM5102:
88 switch (arizona->rev) {
89 case 0:
90 break;
91 default:
92 manual_ena = true;
93 break;
94 }
95 default:
96 break;
97 }
98
99 switch (event) {
100 case SND_SOC_DAPM_PRE_PMU:
101 if (!priv->spk_ena && manual_ena) {
3c43c695 102 regmap_write_async(arizona->regmap, 0x4f5, 0x25a);
56447e13
MB
103 priv->spk_ena_pending = true;
104 }
105 break;
106 case SND_SOC_DAPM_POST_PMU:
f4a76e7c
MB
107 val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
108 if (val & ARIZONA_SPK_SHUTDOWN_STS) {
109 dev_crit(arizona->dev,
110 "Speaker not enabled due to temperature\n");
111 return -EBUSY;
112 }
113
3c43c695
MB
114 regmap_update_bits_async(arizona->regmap,
115 ARIZONA_OUTPUT_ENABLES_1,
116 1 << w->shift, 1 << w->shift);
f4a76e7c 117
56447e13
MB
118 if (priv->spk_ena_pending) {
119 msleep(75);
3c43c695 120 regmap_write_async(arizona->regmap, 0x4f5, 0xda);
56447e13
MB
121 priv->spk_ena_pending = false;
122 priv->spk_ena++;
123 }
124 break;
125 case SND_SOC_DAPM_PRE_PMD:
126 if (manual_ena) {
127 priv->spk_ena--;
128 if (!priv->spk_ena)
3c43c695
MB
129 regmap_write_async(arizona->regmap,
130 0x4f5, 0x25a);
56447e13 131 }
f4a76e7c 132
3c43c695
MB
133 regmap_update_bits_async(arizona->regmap,
134 ARIZONA_OUTPUT_ENABLES_1,
135 1 << w->shift, 0);
56447e13
MB
136 break;
137 case SND_SOC_DAPM_POST_PMD:
138 if (manual_ena) {
139 if (!priv->spk_ena)
3c43c695
MB
140 regmap_write_async(arizona->regmap,
141 0x4f5, 0x0da);
56447e13
MB
142 }
143 break;
144 }
145
146 return 0;
147}
148
899817e2
MB
149static irqreturn_t arizona_thermal_warn(int irq, void *data)
150{
151 struct arizona *arizona = data;
152 unsigned int val;
153 int ret;
154
155 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
156 &val);
157 if (ret != 0) {
158 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
159 ret);
160 } else if (val & ARIZONA_SPK_SHUTDOWN_WARN_STS) {
161 dev_crit(arizona->dev, "Thermal warning\n");
162 }
163
164 return IRQ_HANDLED;
165}
166
167static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
168{
169 struct arizona *arizona = data;
170 unsigned int val;
171 int ret;
172
173 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
174 &val);
175 if (ret != 0) {
176 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
177 ret);
178 } else if (val & ARIZONA_SPK_SHUTDOWN_STS) {
179 dev_crit(arizona->dev, "Thermal shutdown\n");
f4a76e7c
MB
180 ret = regmap_update_bits(arizona->regmap,
181 ARIZONA_OUTPUT_ENABLES_1,
182 ARIZONA_OUT4L_ENA |
183 ARIZONA_OUT4R_ENA, 0);
184 if (ret != 0)
185 dev_crit(arizona->dev,
186 "Failed to disable speaker outputs: %d\n",
187 ret);
899817e2
MB
188 }
189
190 return IRQ_HANDLED;
191}
192
56447e13 193static const struct snd_soc_dapm_widget arizona_spkl =
f4a76e7c 194 SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
56447e13
MB
195 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
196 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
197
198static const struct snd_soc_dapm_widget arizona_spkr =
f4a76e7c 199 SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
56447e13
MB
200 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
201 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
202
203int arizona_init_spk(struct snd_soc_codec *codec)
204{
899817e2
MB
205 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
206 struct arizona *arizona = priv->arizona;
56447e13
MB
207 int ret;
208
209 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
210 if (ret != 0)
211 return ret;
212
40843aea
CK
213 switch (arizona->type) {
214 case WM8997:
215 break;
216 default:
217 ret = snd_soc_dapm_new_controls(&codec->dapm,
218 &arizona_spkr, 1);
219 if (ret != 0)
220 return ret;
221 break;
222 }
56447e13 223
899817e2
MB
224 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
225 "Thermal warning", arizona_thermal_warn,
226 arizona);
227 if (ret != 0)
228 dev_err(arizona->dev,
229 "Failed to get thermal warning IRQ: %d\n",
230 ret);
231
232 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN,
233 "Thermal shutdown", arizona_thermal_shutdown,
234 arizona);
235 if (ret != 0)
236 dev_err(arizona->dev,
237 "Failed to get thermal shutdown IRQ: %d\n",
238 ret);
239
56447e13
MB
240 return 0;
241}
242EXPORT_SYMBOL_GPL(arizona_init_spk);
243
b63144e6
CK
244int arizona_init_gpio(struct snd_soc_codec *codec)
245{
246 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
247 struct arizona *arizona = priv->arizona;
248 int i;
249
250 switch (arizona->type) {
251 case WM5110:
252 snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
b79fae60
CK
253 break;
254 default:
255 break;
b63144e6
CK
256 }
257
258 snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity");
259
260 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
261 switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
262 case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
263 snd_soc_dapm_enable_pin(&codec->dapm,
264 "DRC1 Signal Activity");
265 break;
266 case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
267 snd_soc_dapm_enable_pin(&codec->dapm,
268 "DRC2 Signal Activity");
269 break;
270 default:
271 break;
272 }
273 }
274
275 return 0;
276}
277EXPORT_SYMBOL_GPL(arizona_init_gpio);
278
07ed873e
MB
279const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
280 "None",
281 "Tone Generator 1",
282 "Tone Generator 2",
283 "Haptics",
284 "AEC",
285 "Mic Mute Mixer",
286 "Noise Generator",
287 "IN1L",
288 "IN1R",
289 "IN2L",
290 "IN2R",
291 "IN3L",
292 "IN3R",
c9c56fd0
MB
293 "IN4L",
294 "IN4R",
07ed873e
MB
295 "AIF1RX1",
296 "AIF1RX2",
297 "AIF1RX3",
298 "AIF1RX4",
299 "AIF1RX5",
300 "AIF1RX6",
301 "AIF1RX7",
302 "AIF1RX8",
303 "AIF2RX1",
304 "AIF2RX2",
e64001e8
RF
305 "AIF2RX3",
306 "AIF2RX4",
307 "AIF2RX5",
308 "AIF2RX6",
07ed873e
MB
309 "AIF3RX1",
310 "AIF3RX2",
311 "SLIMRX1",
312 "SLIMRX2",
313 "SLIMRX3",
314 "SLIMRX4",
315 "SLIMRX5",
316 "SLIMRX6",
317 "SLIMRX7",
318 "SLIMRX8",
319 "EQ1",
320 "EQ2",
321 "EQ3",
322 "EQ4",
323 "DRC1L",
324 "DRC1R",
325 "DRC2L",
326 "DRC2R",
327 "LHPF1",
328 "LHPF2",
329 "LHPF3",
330 "LHPF4",
331 "DSP1.1",
332 "DSP1.2",
333 "DSP1.3",
334 "DSP1.4",
335 "DSP1.5",
336 "DSP1.6",
c922cc4c
MB
337 "DSP2.1",
338 "DSP2.2",
339 "DSP2.3",
340 "DSP2.4",
341 "DSP2.5",
342 "DSP2.6",
343 "DSP3.1",
344 "DSP3.2",
345 "DSP3.3",
346 "DSP3.4",
347 "DSP3.5",
348 "DSP3.6",
349 "DSP4.1",
350 "DSP4.2",
351 "DSP4.3",
352 "DSP4.4",
353 "DSP4.5",
354 "DSP4.6",
07ed873e
MB
355 "ASRC1L",
356 "ASRC1R",
357 "ASRC2L",
358 "ASRC2R",
91660bd6
MB
359 "ISRC1INT1",
360 "ISRC1INT2",
361 "ISRC1INT3",
362 "ISRC1INT4",
363 "ISRC1DEC1",
364 "ISRC1DEC2",
365 "ISRC1DEC3",
366 "ISRC1DEC4",
367 "ISRC2INT1",
368 "ISRC2INT2",
369 "ISRC2INT3",
370 "ISRC2INT4",
371 "ISRC2DEC1",
372 "ISRC2DEC2",
373 "ISRC2DEC3",
374 "ISRC2DEC4",
375 "ISRC3INT1",
376 "ISRC3INT2",
377 "ISRC3INT3",
378 "ISRC3INT4",
379 "ISRC3DEC1",
380 "ISRC3DEC2",
381 "ISRC3DEC3",
382 "ISRC3DEC4",
07ed873e
MB
383};
384EXPORT_SYMBOL_GPL(arizona_mixer_texts);
385
386int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
387 0x00, /* None */
388 0x04, /* Tone */
389 0x05,
390 0x06, /* Haptics */
391 0x08, /* AEC */
392 0x0c, /* Noise mixer */
393 0x0d, /* Comfort noise */
394 0x10, /* IN1L */
395 0x11,
396 0x12,
397 0x13,
398 0x14,
399 0x15,
c9c56fd0
MB
400 0x16,
401 0x17,
07ed873e
MB
402 0x20, /* AIF1RX1 */
403 0x21,
404 0x22,
405 0x23,
406 0x24,
407 0x25,
408 0x26,
409 0x27,
410 0x28, /* AIF2RX1 */
411 0x29,
e64001e8
RF
412 0x2a,
413 0x2b,
414 0x2c,
415 0x2d,
07ed873e
MB
416 0x30, /* AIF3RX1 */
417 0x31,
418 0x38, /* SLIMRX1 */
419 0x39,
420 0x3a,
421 0x3b,
422 0x3c,
423 0x3d,
424 0x3e,
425 0x3f,
426 0x50, /* EQ1 */
427 0x51,
428 0x52,
429 0x53,
430 0x58, /* DRC1L */
431 0x59,
432 0x5a,
433 0x5b,
434 0x60, /* LHPF1 */
435 0x61,
436 0x62,
437 0x63,
438 0x68, /* DSP1.1 */
439 0x69,
440 0x6a,
441 0x6b,
442 0x6c,
443 0x6d,
c922cc4c
MB
444 0x70, /* DSP2.1 */
445 0x71,
446 0x72,
447 0x73,
448 0x74,
449 0x75,
450 0x78, /* DSP3.1 */
451 0x79,
452 0x7a,
453 0x7b,
454 0x7c,
455 0x7d,
456 0x80, /* DSP4.1 */
457 0x81,
458 0x82,
459 0x83,
460 0x84,
461 0x85,
07ed873e
MB
462 0x90, /* ASRC1L */
463 0x91,
464 0x92,
465 0x93,
91660bd6
MB
466 0xa0, /* ISRC1INT1 */
467 0xa1,
468 0xa2,
469 0xa3,
470 0xa4, /* ISRC1DEC1 */
471 0xa5,
472 0xa6,
473 0xa7,
474 0xa8, /* ISRC2DEC1 */
475 0xa9,
476 0xaa,
477 0xab,
478 0xac, /* ISRC2INT1 */
479 0xad,
480 0xae,
481 0xaf,
482 0xb0, /* ISRC3DEC1 */
483 0xb1,
484 0xb2,
485 0xb3,
486 0xb4, /* ISRC3INT1 */
487 0xb5,
488 0xb6,
489 0xb7,
07ed873e
MB
490};
491EXPORT_SYMBOL_GPL(arizona_mixer_values);
492
493const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
494EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
495
dc91428a
MB
496const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
497 "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
498};
499EXPORT_SYMBOL_GPL(arizona_rate_text);
500
501const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
502 0, 1, 2, 8,
503};
504EXPORT_SYMBOL_GPL(arizona_rate_val);
505
506
fbedc8cb
CK
507const struct soc_enum arizona_isrc_fsh[] = {
508 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1,
509 ARIZONA_ISRC1_FSH_SHIFT, 0xf,
510 ARIZONA_RATE_ENUM_SIZE,
511 arizona_rate_text, arizona_rate_val),
512 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1,
513 ARIZONA_ISRC2_FSH_SHIFT, 0xf,
514 ARIZONA_RATE_ENUM_SIZE,
515 arizona_rate_text, arizona_rate_val),
516 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1,
517 ARIZONA_ISRC3_FSH_SHIFT, 0xf,
518 ARIZONA_RATE_ENUM_SIZE,
519 arizona_rate_text, arizona_rate_val),
520};
521EXPORT_SYMBOL_GPL(arizona_isrc_fsh);
522
dc91428a
MB
523const struct soc_enum arizona_isrc_fsl[] = {
524 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
525 ARIZONA_ISRC1_FSL_SHIFT, 0xf,
526 ARIZONA_RATE_ENUM_SIZE,
527 arizona_rate_text, arizona_rate_val),
528 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
529 ARIZONA_ISRC2_FSL_SHIFT, 0xf,
530 ARIZONA_RATE_ENUM_SIZE,
531 arizona_rate_text, arizona_rate_val),
532 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
533 ARIZONA_ISRC3_FSL_SHIFT, 0xf,
534 ARIZONA_RATE_ENUM_SIZE,
535 arizona_rate_text, arizona_rate_val),
536};
537EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
538
56d37d85
CK
539const struct soc_enum arizona_asrc_rate1 =
540 SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1,
541 ARIZONA_ASRC_RATE1_SHIFT, 0xf,
542 ARIZONA_RATE_ENUM_SIZE - 1,
543 arizona_rate_text, arizona_rate_val);
544EXPORT_SYMBOL_GPL(arizona_asrc_rate1);
545
e853a00f
MB
546static const char *arizona_vol_ramp_text[] = {
547 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
548 "15ms/6dB", "30ms/6dB",
549};
550
551const struct soc_enum arizona_in_vd_ramp =
552 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
553 ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
554EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
555
556const struct soc_enum arizona_in_vi_ramp =
557 SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
558 ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
559EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
560
561const struct soc_enum arizona_out_vd_ramp =
562 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
563 ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
564EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
565
566const struct soc_enum arizona_out_vi_ramp =
567 SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
568 ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
569EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
570
07ed873e
MB
571static const char *arizona_lhpf_mode_text[] = {
572 "Low-pass", "High-pass"
573};
574
575const struct soc_enum arizona_lhpf1_mode =
576 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
577 arizona_lhpf_mode_text);
578EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
579
580const struct soc_enum arizona_lhpf2_mode =
581 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
582 arizona_lhpf_mode_text);
583EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
584
585const struct soc_enum arizona_lhpf3_mode =
586 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
587 arizona_lhpf_mode_text);
588EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
589
590const struct soc_enum arizona_lhpf4_mode =
591 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
592 arizona_lhpf_mode_text);
593EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
594
845571cc
MB
595static const char *arizona_ng_hold_text[] = {
596 "30ms", "120ms", "250ms", "500ms",
597};
598
599const struct soc_enum arizona_ng_hold =
600 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
601 4, arizona_ng_hold_text);
602EXPORT_SYMBOL_GPL(arizona_ng_hold);
603
254dc326
CK
604static const char * const arizona_in_hpf_cut_text[] = {
605 "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
606};
607
608const struct soc_enum arizona_in_hpf_cut_enum =
609 SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT,
610 ARRAY_SIZE(arizona_in_hpf_cut_text),
611 arizona_in_hpf_cut_text);
612EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
613
c7f38435
CK
614static const char * const arizona_in_dmic_osr_text[] = {
615 "1.536MHz", "3.072MHz", "6.144MHz",
616};
617
618const struct soc_enum arizona_in_dmic_osr[] = {
619 SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
620 ARRAY_SIZE(arizona_in_dmic_osr_text),
621 arizona_in_dmic_osr_text),
622 SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
623 ARRAY_SIZE(arizona_in_dmic_osr_text),
624 arizona_in_dmic_osr_text),
625 SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
626 ARRAY_SIZE(arizona_in_dmic_osr_text),
627 arizona_in_dmic_osr_text),
628 SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
629 ARRAY_SIZE(arizona_in_dmic_osr_text),
630 arizona_in_dmic_osr_text),
631};
632EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
633
ddbce97c
MB
634static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
635{
636 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
637 unsigned int val;
638 int i;
639
640 if (ena)
641 val = ARIZONA_IN_VU;
642 else
643 val = 0;
644
645 for (i = 0; i < priv->num_inputs; i++)
646 snd_soc_update_bits(codec,
647 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
648 ARIZONA_IN_VU, val);
649}
650
07ed873e
MB
651int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
652 int event)
653{
ddbce97c 654 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
43cd8bf1
MB
655 unsigned int reg;
656
657 if (w->shift % 2)
658 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
659 else
660 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
661
662 switch (event) {
ddbce97c
MB
663 case SND_SOC_DAPM_PRE_PMU:
664 priv->in_pending++;
665 break;
43cd8bf1
MB
666 case SND_SOC_DAPM_POST_PMU:
667 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
ddbce97c
MB
668
669 /* If this is the last input pending then allow VU */
670 priv->in_pending--;
671 if (priv->in_pending == 0) {
672 msleep(1);
673 arizona_in_set_vu(w->codec, 1);
674 }
43cd8bf1
MB
675 break;
676 case SND_SOC_DAPM_PRE_PMD:
ddbce97c
MB
677 snd_soc_update_bits(w->codec, reg,
678 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
679 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
43cd8bf1 680 break;
ddbce97c
MB
681 case SND_SOC_DAPM_POST_PMD:
682 /* Disable volume updates if no inputs are enabled */
683 reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
684 if (reg == 0)
685 arizona_in_set_vu(w->codec, 0);
43cd8bf1
MB
686 }
687
07ed873e
MB
688 return 0;
689}
690EXPORT_SYMBOL_GPL(arizona_in_ev);
691
692int arizona_out_ev(struct snd_soc_dapm_widget *w,
693 struct snd_kcontrol *kcontrol,
694 int event)
695{
1a2c7d56
MB
696 switch (event) {
697 case SND_SOC_DAPM_POST_PMU:
698 switch (w->shift) {
699 case ARIZONA_OUT1L_ENA_SHIFT:
700 case ARIZONA_OUT1R_ENA_SHIFT:
701 case ARIZONA_OUT2L_ENA_SHIFT:
702 case ARIZONA_OUT2R_ENA_SHIFT:
703 case ARIZONA_OUT3L_ENA_SHIFT:
704 case ARIZONA_OUT3R_ENA_SHIFT:
705 msleep(17);
706 break;
707
708 default:
709 break;
710 }
711 break;
712 }
713
07ed873e
MB
714 return 0;
715}
716EXPORT_SYMBOL_GPL(arizona_out_ev);
717
f607e31c
MB
718int arizona_hp_ev(struct snd_soc_dapm_widget *w,
719 struct snd_kcontrol *kcontrol,
720 int event)
721{
722 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
3c43c695 723 struct arizona *arizona = priv->arizona;
f607e31c
MB
724 unsigned int mask = 1 << w->shift;
725 unsigned int val;
726
727 switch (event) {
728 case SND_SOC_DAPM_POST_PMU:
729 val = mask;
730 break;
731 case SND_SOC_DAPM_PRE_PMD:
732 val = 0;
733 break;
734 default:
735 return -EINVAL;
736 }
737
738 /* Store the desired state for the HP outputs */
739 priv->arizona->hp_ena &= ~mask;
740 priv->arizona->hp_ena |= val;
741
742 /* Force off if HPDET magic is active */
743 if (priv->arizona->hpdet_magic)
744 val = 0;
745
3c43c695
MB
746 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
747 mask, val);
f607e31c
MB
748
749 return arizona_out_ev(w, kcontrol, event);
750}
751EXPORT_SYMBOL_GPL(arizona_hp_ev);
752
cbd840da
MB
753static unsigned int arizona_sysclk_48k_rates[] = {
754 6144000,
755 12288000,
96e1f18f 756 24576000,
cbd840da 757 49152000,
aeaeee1a
MB
758 73728000,
759 98304000,
760 147456000,
cbd840da
MB
761};
762
763static unsigned int arizona_sysclk_44k1_rates[] = {
764 5644800,
765 11289600,
96e1f18f 766 22579200,
cbd840da 767 45158400,
aeaeee1a
MB
768 67737600,
769 90316800,
770 135475200,
cbd840da
MB
771};
772
773static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
774 unsigned int freq)
775{
776 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
777 unsigned int reg;
778 unsigned int *rates;
779 int ref, div, refclk;
780
781 switch (clk) {
782 case ARIZONA_CLK_OPCLK:
783 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
784 refclk = priv->sysclk;
785 break;
786 case ARIZONA_CLK_ASYNC_OPCLK:
787 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
788 refclk = priv->asyncclk;
789 break;
790 default:
791 return -EINVAL;
792 }
793
794 if (refclk % 8000)
795 rates = arizona_sysclk_44k1_rates;
796 else
797 rates = arizona_sysclk_48k_rates;
798
799 for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
800 rates[ref] <= refclk; ref++) {
801 div = 1;
802 while (rates[ref] / div >= freq && div < 32) {
803 if (rates[ref] / div == freq) {
804 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
805 freq);
806 snd_soc_update_bits(codec, reg,
807 ARIZONA_OPCLK_DIV_MASK |
808 ARIZONA_OPCLK_SEL_MASK,
809 (div <<
810 ARIZONA_OPCLK_DIV_SHIFT) |
811 ref);
812 return 0;
813 }
814 div++;
815 }
816 }
817
818 dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
819 return -EINVAL;
820}
821
07ed873e
MB
822int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
823 int source, unsigned int freq, int dir)
824{
825 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
826 struct arizona *arizona = priv->arizona;
827 char *name;
828 unsigned int reg;
829 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
830 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
831 unsigned int *clk;
832
833 switch (clk_id) {
834 case ARIZONA_CLK_SYSCLK:
835 name = "SYSCLK";
836 reg = ARIZONA_SYSTEM_CLOCK_1;
837 clk = &priv->sysclk;
838 mask |= ARIZONA_SYSCLK_FRAC;
839 break;
840 case ARIZONA_CLK_ASYNCCLK:
841 name = "ASYNCCLK";
842 reg = ARIZONA_ASYNC_CLOCK_1;
843 clk = &priv->asyncclk;
844 break;
cbd840da
MB
845 case ARIZONA_CLK_OPCLK:
846 case ARIZONA_CLK_ASYNC_OPCLK:
847 return arizona_set_opclk(codec, clk_id, freq);
07ed873e
MB
848 default:
849 return -EINVAL;
850 }
851
852 switch (freq) {
853 case 5644800:
854 case 6144000:
855 break;
856 case 11289600:
857 case 12288000:
3f341f74 858 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
859 break;
860 case 22579200:
861 case 24576000:
3f341f74 862 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e
MB
863 break;
864 case 45158400:
865 case 49152000:
3f341f74 866 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
07ed873e 867 break;
38113360
MB
868 case 67737600:
869 case 73728000:
3f341f74 870 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
871 break;
872 case 90316800:
873 case 98304000:
3f341f74 874 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360
MB
875 break;
876 case 135475200:
877 case 147456000:
3f341f74 878 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
38113360 879 break;
f2c26d48
MB
880 case 0:
881 dev_dbg(arizona->dev, "%s cleared\n", name);
882 *clk = freq;
883 return 0;
07ed873e
MB
884 default:
885 return -EINVAL;
886 }
887
888 *clk = freq;
889
890 if (freq % 6144000)
891 val |= ARIZONA_SYSCLK_FRAC;
892
893 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
894
895 return regmap_update_bits(arizona->regmap, reg, mask, val);
896}
897EXPORT_SYMBOL_GPL(arizona_set_sysclk);
898
899static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
900{
901 struct snd_soc_codec *codec = dai->codec;
3c43c695
MB
902 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
903 struct arizona *arizona = priv->arizona;
07ed873e
MB
904 int lrclk, bclk, mode, base;
905
906 base = dai->driver->base;
907
908 lrclk = 0;
909 bclk = 0;
910
911 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
912 case SND_SOC_DAIFMT_DSP_A:
913 mode = 0;
914 break;
07ed873e
MB
915 case SND_SOC_DAIFMT_I2S:
916 mode = 2;
917 break;
07ed873e
MB
918 default:
919 arizona_aif_err(dai, "Unsupported DAI format %d\n",
920 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
921 return -EINVAL;
922 }
923
924 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
925 case SND_SOC_DAIFMT_CBS_CFS:
926 break;
927 case SND_SOC_DAIFMT_CBS_CFM:
928 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
929 break;
930 case SND_SOC_DAIFMT_CBM_CFS:
931 bclk |= ARIZONA_AIF1_BCLK_MSTR;
932 break;
933 case SND_SOC_DAIFMT_CBM_CFM:
934 bclk |= ARIZONA_AIF1_BCLK_MSTR;
935 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
936 break;
937 default:
938 arizona_aif_err(dai, "Unsupported master mode %d\n",
939 fmt & SND_SOC_DAIFMT_MASTER_MASK);
940 return -EINVAL;
941 }
942
943 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
944 case SND_SOC_DAIFMT_NB_NF:
945 break;
946 case SND_SOC_DAIFMT_IB_IF:
947 bclk |= ARIZONA_AIF1_BCLK_INV;
948 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
949 break;
950 case SND_SOC_DAIFMT_IB_NF:
951 bclk |= ARIZONA_AIF1_BCLK_INV;
952 break;
953 case SND_SOC_DAIFMT_NB_IF:
954 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
955 break;
956 default:
957 return -EINVAL;
958 }
959
3c43c695
MB
960 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
961 ARIZONA_AIF1_BCLK_INV |
962 ARIZONA_AIF1_BCLK_MSTR,
963 bclk);
964 regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
965 ARIZONA_AIF1TX_LRCLK_INV |
966 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
967 regmap_update_bits_async(arizona->regmap,
968 base + ARIZONA_AIF_RX_PIN_CTRL,
969 ARIZONA_AIF1RX_LRCLK_INV |
970 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
971 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
972 ARIZONA_AIF1_FMT_MASK, mode);
07ed873e
MB
973
974 return 0;
975}
976
949e6bc7 977static const int arizona_48k_bclk_rates[] = {
07ed873e
MB
978 -1,
979 48000,
980 64000,
981 96000,
982 128000,
983 192000,
984 256000,
985 384000,
986 512000,
987 768000,
988 1024000,
989 1536000,
990 2048000,
991 3072000,
992 4096000,
993 6144000,
994 8192000,
995 12288000,
996 24576000,
997};
998
5b2eec3f
MB
999static const unsigned int arizona_48k_rates[] = {
1000 12000,
1001 24000,
1002 48000,
1003 96000,
1004 192000,
1005 384000,
1006 768000,
1007 4000,
1008 8000,
1009 16000,
1010 32000,
1011 64000,
1012 128000,
1013 256000,
1014 512000,
1015};
1016
1017static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
1018 .count = ARRAY_SIZE(arizona_48k_rates),
1019 .list = arizona_48k_rates,
1020};
1021
949e6bc7 1022static const int arizona_44k1_bclk_rates[] = {
07ed873e
MB
1023 -1,
1024 44100,
1025 58800,
1026 88200,
1027 117600,
1028 177640,
1029 235200,
1030 352800,
1031 470400,
1032 705600,
1033 940800,
1034 1411200,
1035 1881600,
4758be37 1036 2822400,
07ed873e
MB
1037 3763200,
1038 5644800,
1039 7526400,
1040 11289600,
1041 22579200,
1042};
1043
5b2eec3f
MB
1044static const unsigned int arizona_44k1_rates[] = {
1045 11025,
1046 22050,
1047 44100,
1048 88200,
1049 176400,
1050 352800,
1051 705600,
1052};
1053
1054static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
1055 .count = ARRAY_SIZE(arizona_44k1_rates),
1056 .list = arizona_44k1_rates,
1057};
1058
07ed873e
MB
1059static int arizona_sr_vals[] = {
1060 0,
1061 12000,
1062 24000,
1063 48000,
1064 96000,
1065 192000,
1066 384000,
1067 768000,
1068 0,
1069 11025,
1070 22050,
1071 44100,
1072 88200,
1073 176400,
1074 352800,
1075 705600,
1076 4000,
1077 8000,
1078 16000,
1079 32000,
1080 64000,
1081 128000,
1082 256000,
1083 512000,
1084};
1085
5b2eec3f
MB
1086static int arizona_startup(struct snd_pcm_substream *substream,
1087 struct snd_soc_dai *dai)
1088{
1089 struct snd_soc_codec *codec = dai->codec;
1090 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1091 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1092 const struct snd_pcm_hw_constraint_list *constraint;
1093 unsigned int base_rate;
1094
1095 switch (dai_priv->clk) {
1096 case ARIZONA_CLK_SYSCLK:
1097 base_rate = priv->sysclk;
1098 break;
1099 case ARIZONA_CLK_ASYNCCLK:
1100 base_rate = priv->asyncclk;
1101 break;
1102 default:
1103 return 0;
1104 }
1105
f2c26d48
MB
1106 if (base_rate == 0)
1107 return 0;
1108
5b2eec3f
MB
1109 if (base_rate % 8000)
1110 constraint = &arizona_44k1_constraint;
1111 else
1112 constraint = &arizona_48k_constraint;
1113
1114 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1115 SNDRV_PCM_HW_PARAM_RATE,
1116 constraint);
1117}
1118
b272efc8
MB
1119static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1120 struct snd_pcm_hw_params *params,
1121 struct snd_soc_dai *dai)
1122{
1123 struct snd_soc_codec *codec = dai->codec;
1124 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1125 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1126 int base = dai->driver->base;
1127 int i, sr_val;
1128
1129 /*
1130 * We will need to be more flexible than this in future,
1131 * currently we use a single sample rate for SYSCLK.
1132 */
1133 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1134 if (arizona_sr_vals[i] == params_rate(params))
1135 break;
1136 if (i == ARRAY_SIZE(arizona_sr_vals)) {
1137 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1138 params_rate(params));
1139 return -EINVAL;
1140 }
1141 sr_val = i;
1142
1143 switch (dai_priv->clk) {
1144 case ARIZONA_CLK_SYSCLK:
1145 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1146 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1147 if (base)
1148 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1149 ARIZONA_AIF1_RATE_MASK, 0);
1150 break;
1151 case ARIZONA_CLK_ASYNCCLK:
1152 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
1153 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
1154 if (base)
1155 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1156 ARIZONA_AIF1_RATE_MASK,
1157 8 << ARIZONA_AIF1_RATE_SHIFT);
1158 break;
1159 default:
1160 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1161 return -EINVAL;
1162 }
1163
1164 return 0;
1165}
1166
07ed873e
MB
1167static int arizona_hw_params(struct snd_pcm_substream *substream,
1168 struct snd_pcm_hw_params *params,
1169 struct snd_soc_dai *dai)
1170{
1171 struct snd_soc_codec *codec = dai->codec;
c013b27a 1172 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
c94aa30e 1173 struct arizona *arizona = priv->arizona;
07ed873e
MB
1174 int base = dai->driver->base;
1175 const int *rates;
76bf969e 1176 int i, ret, val;
c94aa30e
MB
1177 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
1178 int bclk, lrclk, wl, frame, bclk_target;
07ed873e
MB
1179
1180 if (params_rate(params) % 8000)
949e6bc7 1181 rates = &arizona_44k1_bclk_rates[0];
07ed873e 1182 else
949e6bc7 1183 rates = &arizona_48k_bclk_rates[0];
07ed873e 1184
c94aa30e
MB
1185 bclk_target = snd_soc_params_to_bclk(params);
1186 if (chan_limit && chan_limit < params_channels(params)) {
1187 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
1188 bclk_target /= params_channels(params);
1189 bclk_target *= chan_limit;
1190 }
1191
76bf969e
MB
1192 /* Force stereo for I2S mode */
1193 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
1194 if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
1195 arizona_aif_dbg(dai, "Forcing stereo mode\n");
1196 bclk_target *= 2;
1197 }
1198
949e6bc7 1199 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
c94aa30e 1200 if (rates[i] >= bclk_target &&
5001765f 1201 rates[i] % params_rate(params) == 0) {
07ed873e
MB
1202 bclk = i;
1203 break;
1204 }
1205 }
949e6bc7 1206 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
07ed873e
MB
1207 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1208 params_rate(params));
1209 return -EINVAL;
1210 }
1211
b59e0f82 1212 lrclk = rates[bclk] / params_rate(params);
07ed873e
MB
1213
1214 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1215 rates[bclk], rates[bclk] / lrclk);
1216
1217 wl = snd_pcm_format_width(params_format(params));
1218 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
1219
b272efc8
MB
1220 ret = arizona_hw_params_rate(substream, params, dai);
1221 if (ret != 0)
1222 return ret;
c013b27a 1223
3c43c695
MB
1224 regmap_update_bits_async(arizona->regmap,
1225 base + ARIZONA_AIF_BCLK_CTRL,
1226 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1227 regmap_update_bits_async(arizona->regmap,
1228 base + ARIZONA_AIF_TX_BCLK_RATE,
1229 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1230 regmap_update_bits_async(arizona->regmap,
1231 base + ARIZONA_AIF_RX_BCLK_RATE,
1232 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1233 regmap_update_bits_async(arizona->regmap,
1234 base + ARIZONA_AIF_FRAME_CTRL_1,
1235 ARIZONA_AIF1TX_WL_MASK |
1236 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1237 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
1238 ARIZONA_AIF1RX_WL_MASK |
1239 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
07ed873e
MB
1240
1241 return 0;
1242}
1243
410837a7
MB
1244static const char *arizona_dai_clk_str(int clk_id)
1245{
1246 switch (clk_id) {
1247 case ARIZONA_CLK_SYSCLK:
1248 return "SYSCLK";
1249 case ARIZONA_CLK_ASYNCCLK:
1250 return "ASYNCCLK";
1251 default:
1252 return "Unknown clock";
1253 }
1254}
1255
5b2eec3f
MB
1256static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1257 int clk_id, unsigned int freq, int dir)
1258{
1259 struct snd_soc_codec *codec = dai->codec;
1260 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1261 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
410837a7 1262 struct snd_soc_dapm_route routes[2];
5b2eec3f
MB
1263
1264 switch (clk_id) {
1265 case ARIZONA_CLK_SYSCLK:
1266 case ARIZONA_CLK_ASYNCCLK:
1267 break;
1268 default:
1269 return -EINVAL;
1270 }
1271
410837a7
MB
1272 if (clk_id == dai_priv->clk)
1273 return 0;
1274
1275 if (dai->active) {
5b2eec3f
MB
1276 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1277 dai->id);
1278 return -EBUSY;
1279 }
1280
c8d35a6a
MB
1281 dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1282 arizona_dai_clk_str(clk_id));
1283
410837a7
MB
1284 memset(&routes, 0, sizeof(routes));
1285 routes[0].sink = dai->driver->capture.stream_name;
1286 routes[1].sink = dai->driver->playback.stream_name;
5b2eec3f 1287
410837a7
MB
1288 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1289 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1290 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
1291
1292 routes[0].source = arizona_dai_clk_str(clk_id);
1293 routes[1].source = arizona_dai_clk_str(clk_id);
1294 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
1295
0c778e86
MB
1296 dai_priv->clk = clk_id;
1297
410837a7 1298 return snd_soc_dapm_sync(&codec->dapm);
5b2eec3f
MB
1299}
1300
01df259f
MB
1301static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1302{
1303 struct snd_soc_codec *codec = dai->codec;
1304 int base = dai->driver->base;
1305 unsigned int reg;
1306
1307 if (tristate)
1308 reg = ARIZONA_AIF1_TRI;
1309 else
1310 reg = 0;
1311
1312 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1313 ARIZONA_AIF1_TRI, reg);
1314}
1315
07ed873e 1316const struct snd_soc_dai_ops arizona_dai_ops = {
5b2eec3f 1317 .startup = arizona_startup,
07ed873e
MB
1318 .set_fmt = arizona_set_fmt,
1319 .hw_params = arizona_hw_params,
5b2eec3f 1320 .set_sysclk = arizona_dai_set_sysclk,
01df259f 1321 .set_tristate = arizona_set_tristate,
07ed873e 1322};
a837987e 1323EXPORT_SYMBOL_GPL(arizona_dai_ops);
07ed873e 1324
bd1dd885
MB
1325const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1326 .startup = arizona_startup,
1327 .hw_params = arizona_hw_params_rate,
1328 .set_sysclk = arizona_dai_set_sysclk,
1329};
1330EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1331
5b2eec3f
MB
1332int arizona_init_dai(struct arizona_priv *priv, int id)
1333{
1334 struct arizona_dai_priv *dai_priv = &priv->dai[id];
1335
1336 dai_priv->clk = ARIZONA_CLK_SYSCLK;
1337
1338 return 0;
1339}
1340EXPORT_SYMBOL_GPL(arizona_init_dai);
1341
07ed873e
MB
1342static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
1343{
1344 struct arizona_fll *fll = data;
1345
1346 arizona_fll_dbg(fll, "clock OK\n");
1347
1348 complete(&fll->ok);
1349
1350 return IRQ_HANDLED;
1351}
1352
1353static struct {
1354 unsigned int min;
1355 unsigned int max;
1356 u16 fratio;
1357 int ratio;
1358} fll_fratios[] = {
1359 { 0, 64000, 4, 16 },
1360 { 64000, 128000, 3, 8 },
1361 { 128000, 256000, 2, 4 },
1362 { 256000, 1000000, 1, 2 },
1363 { 1000000, 13500000, 0, 1 },
1364};
1365
8f113d7d
MB
1366static struct {
1367 unsigned int min;
1368 unsigned int max;
1369 u16 gain;
1370} fll_gains[] = {
1371 { 0, 256000, 0 },
1372 { 256000, 1000000, 2 },
1373 { 1000000, 13500000, 4 },
1374};
1375
07ed873e
MB
1376struct arizona_fll_cfg {
1377 int n;
1378 int theta;
1379 int lambda;
1380 int refdiv;
1381 int outdiv;
1382 int fratio;
8f113d7d 1383 int gain;
07ed873e
MB
1384};
1385
23f785a8
CK
1386static int arizona_validate_fll(struct arizona_fll *fll,
1387 unsigned int Fref,
1388 unsigned int Fout)
1389{
1390 unsigned int Fvco_min;
1391
1392 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1393 arizona_fll_err(fll,
1394 "Can't scale %dMHz in to <=13.5MHz\n",
1395 Fref);
1396 return -EINVAL;
1397 }
1398
1399 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1400 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1401 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1402 Fout);
1403 return -EINVAL;
1404 }
1405
1406 return 0;
1407}
1408
07ed873e
MB
1409static int arizona_calc_fll(struct arizona_fll *fll,
1410 struct arizona_fll_cfg *cfg,
8ccefcd2 1411 unsigned int Fref)
07ed873e
MB
1412{
1413 unsigned int target, div, gcd_fll;
1414 int i, ratio;
1415
8ccefcd2 1416 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
07ed873e 1417
f641aec6
CK
1418 /* Fvco should be over the targt; don't check the upper bound */
1419 div = ARIZONA_FLL_MIN_OUTDIV;
1420 while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
1421 div++;
1422 if (div > ARIZONA_FLL_MAX_OUTDIV)
1423 return -EINVAL;
1424 }
1425 target = fll->fout * div / fll->vco_mult;
1426 cfg->outdiv = div;
1427
1428 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
1429
07ed873e
MB
1430 /* Fref must be <=13.5MHz */
1431 div = 1;
1432 cfg->refdiv = 0;
87383ac5 1433 while ((Fref / div) > ARIZONA_FLL_MAX_FREF) {
07ed873e
MB
1434 div *= 2;
1435 cfg->refdiv++;
1436
23f785a8 1437 if (div > ARIZONA_FLL_MAX_REFDIV)
07ed873e 1438 return -EINVAL;
07ed873e
MB
1439 }
1440
1441 /* Apply the division for our remaining calculations */
1442 Fref /= div;
1443
07ed873e
MB
1444 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1445 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1446 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1447 cfg->fratio = fll_fratios[i].fratio;
1448 ratio = fll_fratios[i].ratio;
1449 break;
1450 }
1451 }
1452 if (i == ARRAY_SIZE(fll_fratios)) {
1453 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
1454 Fref);
1455 return -EINVAL;
1456 }
1457
8f113d7d
MB
1458 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
1459 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
1460 cfg->gain = fll_gains[i].gain;
1461 break;
1462 }
1463 }
1464 if (i == ARRAY_SIZE(fll_gains)) {
1465 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
1466 Fref);
1467 return -EINVAL;
1468 }
1469
07ed873e
MB
1470 cfg->n = target / (ratio * Fref);
1471
01f58153 1472 if (target % (ratio * Fref)) {
07ed873e
MB
1473 gcd_fll = gcd(target, ratio * Fref);
1474 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
1475
1476 cfg->theta = (target - (cfg->n * ratio * Fref))
1477 / gcd_fll;
1478 cfg->lambda = (ratio * Fref) / gcd_fll;
1479 } else {
1480 cfg->theta = 0;
1481 cfg->lambda = 0;
1482 }
1483
01f58153
RT
1484 /* Round down to 16bit range with cost of accuracy lost.
1485 * Denominator must be bigger than numerator so we only
1486 * take care of it.
1487 */
1488 while (cfg->lambda >= (1 << 16)) {
1489 cfg->theta >>= 1;
1490 cfg->lambda >>= 1;
1491 }
1492
07ed873e
MB
1493 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
1494 cfg->n, cfg->theta, cfg->lambda);
1495 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1496 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
8f113d7d 1497 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
07ed873e
MB
1498
1499 return 0;
1500
1501}
1502
1503static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
8f113d7d
MB
1504 struct arizona_fll_cfg *cfg, int source,
1505 bool sync)
07ed873e 1506{
3c43c695
MB
1507 regmap_update_bits_async(arizona->regmap, base + 3,
1508 ARIZONA_FLL1_THETA_MASK, cfg->theta);
1509 regmap_update_bits_async(arizona->regmap, base + 4,
1510 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
1511 regmap_update_bits_async(arizona->regmap, base + 5,
1512 ARIZONA_FLL1_FRATIO_MASK,
1513 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
1514 regmap_update_bits_async(arizona->regmap, base + 6,
1515 ARIZONA_FLL1_CLK_REF_DIV_MASK |
1516 ARIZONA_FLL1_CLK_REF_SRC_MASK,
1517 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1518 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
07ed873e 1519
61719db8
CK
1520 if (sync) {
1521 regmap_update_bits(arizona->regmap, base + 0x7,
1522 ARIZONA_FLL1_GAIN_MASK,
1523 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1524 } else {
1525 regmap_update_bits(arizona->regmap, base + 0x5,
1526 ARIZONA_FLL1_OUTDIV_MASK,
1527 cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1528 regmap_update_bits(arizona->regmap, base + 0x9,
1529 ARIZONA_FLL1_GAIN_MASK,
1530 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1531 }
8f113d7d 1532
3c43c695
MB
1533 regmap_update_bits_async(arizona->regmap, base + 2,
1534 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1535 ARIZONA_FLL1_CTRL_UPD | cfg->n);
07ed873e
MB
1536}
1537
d122d6c9
CK
1538static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1539{
1540 struct arizona *arizona = fll->arizona;
1541 unsigned int reg;
1542 int ret;
1543
1544 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1545 if (ret != 0) {
1546 arizona_fll_err(fll, "Failed to read current state: %d\n",
1547 ret);
1548 return ret;
1549 }
1550
1551 return reg & ARIZONA_FLL1_ENA;
1552}
1553
23f785a8 1554static void arizona_enable_fll(struct arizona_fll *fll)
35722815
CK
1555{
1556 struct arizona *arizona = fll->arizona;
1557 int ret;
49c60547 1558 bool use_sync = false;
23f785a8 1559 struct arizona_fll_cfg cfg;
35722815 1560
ff680a17
MB
1561 /*
1562 * If we have both REFCLK and SYNCCLK then enable both,
1563 * otherwise apply the SYNCCLK settings to REFCLK.
1564 */
49c60547
CK
1565 if (fll->ref_src >= 0 && fll->ref_freq &&
1566 fll->ref_src != fll->sync_src) {
8ccefcd2 1567 arizona_calc_fll(fll, &cfg, fll->ref_freq);
23f785a8
CK
1568
1569 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
8f113d7d 1570 false);
49c60547 1571 if (fll->sync_src >= 0) {
8ccefcd2 1572 arizona_calc_fll(fll, &cfg, fll->sync_freq);
23f785a8
CK
1573
1574 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
8f113d7d 1575 fll->sync_src, true);
49c60547
CK
1576 use_sync = true;
1577 }
ff680a17 1578 } else if (fll->sync_src >= 0) {
8ccefcd2 1579 arizona_calc_fll(fll, &cfg, fll->sync_freq);
23f785a8
CK
1580
1581 arizona_apply_fll(arizona, fll->base, &cfg,
8f113d7d 1582 fll->sync_src, false);
eca2e8e2 1583
3c43c695
MB
1584 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
1585 ARIZONA_FLL1_SYNC_ENA, 0);
ff680a17
MB
1586 } else {
1587 arizona_fll_err(fll, "No clocks provided\n");
1588 return;
1589 }
35722815 1590
576411be
MB
1591 /*
1592 * Increase the bandwidth if we're not using a low frequency
1593 * sync source.
1594 */
49c60547 1595 if (use_sync && fll->sync_freq > 100000)
3c43c695
MB
1596 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
1597 ARIZONA_FLL1_SYNC_BW, 0);
576411be 1598 else
3c43c695
MB
1599 regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
1600 ARIZONA_FLL1_SYNC_BW,
1601 ARIZONA_FLL1_SYNC_BW);
576411be 1602
35722815
CK
1603 if (!arizona_is_enabled_fll(fll))
1604 pm_runtime_get(arizona->dev);
1605
1606 /* Clear any pending completions */
1607 try_wait_for_completion(&fll->ok);
1608
3c43c695
MB
1609 regmap_update_bits_async(arizona->regmap, fll->base + 1,
1610 ARIZONA_FLL1_FREERUN, 0);
1611 regmap_update_bits_async(arizona->regmap, fll->base + 1,
1612 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
49c60547 1613 if (use_sync)
3c43c695
MB
1614 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
1615 ARIZONA_FLL1_SYNC_ENA,
1616 ARIZONA_FLL1_SYNC_ENA);
35722815
CK
1617
1618 ret = wait_for_completion_timeout(&fll->ok,
1619 msecs_to_jiffies(250));
1620 if (ret == 0)
1621 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1622}
1623
7604054e
CK
1624static void arizona_disable_fll(struct arizona_fll *fll)
1625{
1626 struct arizona *arizona = fll->arizona;
1627 bool change;
1628
3c43c695
MB
1629 regmap_update_bits_async(arizona->regmap, fll->base + 1,
1630 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
7604054e
CK
1631 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1632 ARIZONA_FLL1_ENA, 0, &change);
1633 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1634 ARIZONA_FLL1_SYNC_ENA, 0);
1635
1636 if (change)
1637 pm_runtime_put_autosuspend(arizona->dev);
1638}
1639
ee929a97
CK
1640int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1641 unsigned int Fref, unsigned int Fout)
1642{
ee929a97
CK
1643 int ret;
1644
1c5617fc 1645 if (fll->ref_src == source && fll->ref_freq == Fref)
ee929a97
CK
1646 return 0;
1647
23f785a8
CK
1648 if (fll->fout && Fref > 0) {
1649 ret = arizona_validate_fll(fll, Fref, fll->fout);
1650 if (ret != 0)
1651 return ret;
ee929a97
CK
1652 }
1653
1654 fll->ref_src = source;
1655 fll->ref_freq = Fref;
ee929a97 1656
86cd684f 1657 if (fll->fout && Fref > 0) {
23f785a8 1658 arizona_enable_fll(fll);
ee929a97
CK
1659 }
1660
1661 return 0;
1662}
1663EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1664
07ed873e
MB
1665int arizona_set_fll(struct arizona_fll *fll, int source,
1666 unsigned int Fref, unsigned int Fout)
1667{
07ed873e
MB
1668 int ret;
1669
ff680a17
MB
1670 if (fll->sync_src == source &&
1671 fll->sync_freq == Fref && fll->fout == Fout)
1672 return 0;
9e359c64 1673
ff680a17
MB
1674 if (Fout) {
1675 if (fll->ref_src >= 0) {
23f785a8 1676 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
9e359c64
CK
1677 if (ret != 0)
1678 return ret;
1679 }
1680
23f785a8 1681 ret = arizona_validate_fll(fll, Fref, Fout);
ff680a17
MB
1682 if (ret != 0)
1683 return ret;
9e359c64 1684 }
ff680a17
MB
1685
1686 fll->sync_src = source;
1687 fll->sync_freq = Fref;
de1e6eed 1688 fll->fout = Fout;
9e359c64 1689
07ed873e 1690 if (Fout) {
23f785a8 1691 arizona_enable_fll(fll);
07ed873e 1692 } else {
7604054e 1693 arizona_disable_fll(fll);
07ed873e
MB
1694 }
1695
07ed873e
MB
1696 return 0;
1697}
1698EXPORT_SYMBOL_GPL(arizona_set_fll);
1699
1700int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1701 int ok_irq, struct arizona_fll *fll)
1702{
1703 int ret;
19b34bdc 1704 unsigned int val;
07ed873e 1705
07ed873e
MB
1706 init_completion(&fll->ok);
1707
1708 fll->id = id;
1709 fll->base = base;
1710 fll->arizona = arizona;
f3f1163d 1711 fll->sync_src = ARIZONA_FLL_SRC_NONE;
07ed873e 1712
19b34bdc
CK
1713 /* Configure default refclk to 32kHz if we have one */
1714 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1715 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1716 case ARIZONA_CLK_SRC_MCLK1:
1717 case ARIZONA_CLK_SRC_MCLK2:
1718 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1719 break;
1720 default:
f3f1163d 1721 fll->ref_src = ARIZONA_FLL_SRC_NONE;
19b34bdc
CK
1722 }
1723 fll->ref_freq = 32768;
1724
07ed873e
MB
1725 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1726 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1727 "FLL%d clock OK", id);
1728
07ed873e
MB
1729 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1730 arizona_fll_clock_ok, fll);
1731 if (ret != 0) {
1732 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1733 id, ret);
1734 }
1735
e31c1946
CK
1736 regmap_update_bits(arizona->regmap, fll->base + 1,
1737 ARIZONA_FLL1_FREERUN, 0);
1738
07ed873e
MB
1739 return 0;
1740}
1741EXPORT_SYMBOL_GPL(arizona_init_fll);
1742
bc9ab6d3
MB
1743/**
1744 * arizona_set_output_mode - Set the mode of the specified output
1745 *
1746 * @codec: Device to configure
1747 * @output: Output number
1748 * @diff: True to set the output to differential mode
1749 *
1750 * Some systems use external analogue switches to connect more
1751 * analogue devices to the CODEC than are supported by the device. In
1752 * some systems this requires changing the switched output from single
1753 * ended to differential mode dynamically at runtime, an operation
1754 * supported using this function.
1755 *
1756 * Most systems have a single static configuration and should use
1757 * platform data instead.
1758 */
1759int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1760{
1761 unsigned int reg, val;
1762
1763 if (output < 1 || output > 6)
1764 return -EINVAL;
1765
1766 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1767
1768 if (diff)
1769 val = ARIZONA_OUT1_MONO;
1770 else
1771 val = 0;
1772
1773 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1774}
1775EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1776
07ed873e
MB
1777MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1778MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1779MODULE_LICENSE("GPL");
This page took 0.160648 seconds and 5 git commands to generate.