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