~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/arizona.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.15 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.73 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.144 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.193 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.193 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp