]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - sound/soc/codecs/arizona.c
c167c896eaeeab152984838d99671b4f62d92ab9
[~shefty/rdma-dev.git] / sound / soc / codecs / arizona.c
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/gcd.h>
14 #include <linux/module.h>
15 #include <linux/pm_runtime.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/tlv.h>
19
20 #include <linux/mfd/arizona/core.h>
21 #include <linux/mfd/arizona/registers.h>
22
23 #include "arizona.h"
24
25 #define ARIZONA_AIF_BCLK_CTRL                   0x00
26 #define ARIZONA_AIF_TX_PIN_CTRL                 0x01
27 #define ARIZONA_AIF_RX_PIN_CTRL                 0x02
28 #define ARIZONA_AIF_RATE_CTRL                   0x03
29 #define ARIZONA_AIF_FORMAT                      0x04
30 #define ARIZONA_AIF_TX_BCLK_RATE                0x05
31 #define ARIZONA_AIF_RX_BCLK_RATE                0x06
32 #define ARIZONA_AIF_FRAME_CTRL_1                0x07
33 #define ARIZONA_AIF_FRAME_CTRL_2                0x08
34 #define ARIZONA_AIF_FRAME_CTRL_3                0x09
35 #define ARIZONA_AIF_FRAME_CTRL_4                0x0A
36 #define ARIZONA_AIF_FRAME_CTRL_5                0x0B
37 #define ARIZONA_AIF_FRAME_CTRL_6                0x0C
38 #define ARIZONA_AIF_FRAME_CTRL_7                0x0D
39 #define ARIZONA_AIF_FRAME_CTRL_8                0x0E
40 #define ARIZONA_AIF_FRAME_CTRL_9                0x0F
41 #define ARIZONA_AIF_FRAME_CTRL_10               0x10
42 #define ARIZONA_AIF_FRAME_CTRL_11               0x11
43 #define ARIZONA_AIF_FRAME_CTRL_12               0x12
44 #define ARIZONA_AIF_FRAME_CTRL_13               0x13
45 #define ARIZONA_AIF_FRAME_CTRL_14               0x14
46 #define ARIZONA_AIF_FRAME_CTRL_15               0x15
47 #define ARIZONA_AIF_FRAME_CTRL_16               0x16
48 #define ARIZONA_AIF_FRAME_CTRL_17               0x17
49 #define ARIZONA_AIF_FRAME_CTRL_18               0x18
50 #define ARIZONA_AIF_TX_ENABLES                  0x19
51 #define ARIZONA_AIF_RX_ENABLES                  0x1A
52 #define ARIZONA_AIF_FORCE_WRITE                 0x1B
53
54 #define arizona_fll_err(_fll, fmt, ...) \
55         dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
56 #define arizona_fll_warn(_fll, fmt, ...) \
57         dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58 #define arizona_fll_dbg(_fll, fmt, ...) \
59         dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
60
61 #define arizona_aif_err(_dai, fmt, ...) \
62         dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
63 #define arizona_aif_warn(_dai, fmt, ...) \
64         dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65 #define arizona_aif_dbg(_dai, fmt, ...) \
66         dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67
68 const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69         "None",
70         "Tone Generator 1",
71         "Tone Generator 2",
72         "Haptics",
73         "AEC",
74         "Mic Mute Mixer",
75         "Noise Generator",
76         "IN1L",
77         "IN1R",
78         "IN2L",
79         "IN2R",
80         "IN3L",
81         "IN3R",
82         "IN4L",
83         "IN4R",
84         "AIF1RX1",
85         "AIF1RX2",
86         "AIF1RX3",
87         "AIF1RX4",
88         "AIF1RX5",
89         "AIF1RX6",
90         "AIF1RX7",
91         "AIF1RX8",
92         "AIF2RX1",
93         "AIF2RX2",
94         "AIF3RX1",
95         "AIF3RX2",
96         "SLIMRX1",
97         "SLIMRX2",
98         "SLIMRX3",
99         "SLIMRX4",
100         "SLIMRX5",
101         "SLIMRX6",
102         "SLIMRX7",
103         "SLIMRX8",
104         "EQ1",
105         "EQ2",
106         "EQ3",
107         "EQ4",
108         "DRC1L",
109         "DRC1R",
110         "DRC2L",
111         "DRC2R",
112         "LHPF1",
113         "LHPF2",
114         "LHPF3",
115         "LHPF4",
116         "DSP1.1",
117         "DSP1.2",
118         "DSP1.3",
119         "DSP1.4",
120         "DSP1.5",
121         "DSP1.6",
122         "ASRC1L",
123         "ASRC1R",
124         "ASRC2L",
125         "ASRC2R",
126 };
127 EXPORT_SYMBOL_GPL(arizona_mixer_texts);
128
129 int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
130         0x00,  /* None */
131         0x04,  /* Tone */
132         0x05,
133         0x06,  /* Haptics */
134         0x08,  /* AEC */
135         0x0c,  /* Noise mixer */
136         0x0d,  /* Comfort noise */
137         0x10,  /* IN1L */
138         0x11,
139         0x12,
140         0x13,
141         0x14,
142         0x15,
143         0x16,
144         0x17,
145         0x20,  /* AIF1RX1 */
146         0x21,
147         0x22,
148         0x23,
149         0x24,
150         0x25,
151         0x26,
152         0x27,
153         0x28,  /* AIF2RX1 */
154         0x29,
155         0x30,  /* AIF3RX1 */
156         0x31,
157         0x38,  /* SLIMRX1 */
158         0x39,
159         0x3a,
160         0x3b,
161         0x3c,
162         0x3d,
163         0x3e,
164         0x3f,
165         0x50,  /* EQ1 */
166         0x51,
167         0x52,
168         0x53,
169         0x58,  /* DRC1L */
170         0x59,
171         0x5a,
172         0x5b,
173         0x60,  /* LHPF1 */
174         0x61,
175         0x62,
176         0x63,
177         0x68,  /* DSP1.1 */
178         0x69,
179         0x6a,
180         0x6b,
181         0x6c,
182         0x6d,
183         0x90,  /* ASRC1L */
184         0x91,
185         0x92,
186         0x93,
187 };
188 EXPORT_SYMBOL_GPL(arizona_mixer_values);
189
190 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
191 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
192
193 static const char *arizona_lhpf_mode_text[] = {
194         "Low-pass", "High-pass"
195 };
196
197 const struct soc_enum arizona_lhpf1_mode =
198         SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
199                         arizona_lhpf_mode_text);
200 EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
201
202 const struct soc_enum arizona_lhpf2_mode =
203         SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
204                         arizona_lhpf_mode_text);
205 EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
206
207 const struct soc_enum arizona_lhpf3_mode =
208         SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
209                         arizona_lhpf_mode_text);
210 EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
211
212 const struct soc_enum arizona_lhpf4_mode =
213         SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
214                         arizona_lhpf_mode_text);
215 EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
216
217 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
218                   int event)
219 {
220         return 0;
221 }
222 EXPORT_SYMBOL_GPL(arizona_in_ev);
223
224 int arizona_out_ev(struct snd_soc_dapm_widget *w,
225                    struct snd_kcontrol *kcontrol,
226                    int event)
227 {
228         return 0;
229 }
230 EXPORT_SYMBOL_GPL(arizona_out_ev);
231
232 static unsigned int arizona_sysclk_48k_rates[] = {
233         6144000,
234         12288000,
235         22579200,
236         49152000,
237 };
238
239 static unsigned int arizona_sysclk_44k1_rates[] = {
240         5644800,
241         11289600,
242         24576000,
243         45158400,
244 };
245
246 static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
247                              unsigned int freq)
248 {
249         struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
250         unsigned int reg;
251         unsigned int *rates;
252         int ref, div, refclk;
253
254         switch (clk) {
255         case ARIZONA_CLK_OPCLK:
256                 reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
257                 refclk = priv->sysclk;
258                 break;
259         case ARIZONA_CLK_ASYNC_OPCLK:
260                 reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
261                 refclk = priv->asyncclk;
262                 break;
263         default:
264                 return -EINVAL;
265         }
266
267         if (refclk % 8000)
268                 rates = arizona_sysclk_44k1_rates;
269         else
270                 rates = arizona_sysclk_48k_rates;
271
272         for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
273                      rates[ref] <= refclk; ref++) {
274                 div = 1;
275                 while (rates[ref] / div >= freq && div < 32) {
276                         if (rates[ref] / div == freq) {
277                                 dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
278                                         freq);
279                                 snd_soc_update_bits(codec, reg,
280                                                     ARIZONA_OPCLK_DIV_MASK |
281                                                     ARIZONA_OPCLK_SEL_MASK,
282                                                     (div <<
283                                                      ARIZONA_OPCLK_DIV_SHIFT) |
284                                                     ref);
285                                 return 0;
286                         }
287                         div++;
288                 }
289         }
290
291         dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
292         return -EINVAL;
293 }
294
295 int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
296                        int source, unsigned int freq, int dir)
297 {
298         struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
299         struct arizona *arizona = priv->arizona;
300         char *name;
301         unsigned int reg;
302         unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
303         unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
304         unsigned int *clk;
305
306         switch (clk_id) {
307         case ARIZONA_CLK_SYSCLK:
308                 name = "SYSCLK";
309                 reg = ARIZONA_SYSTEM_CLOCK_1;
310                 clk = &priv->sysclk;
311                 mask |= ARIZONA_SYSCLK_FRAC;
312                 break;
313         case ARIZONA_CLK_ASYNCCLK:
314                 name = "ASYNCCLK";
315                 reg = ARIZONA_ASYNC_CLOCK_1;
316                 clk = &priv->asyncclk;
317                 break;
318         case ARIZONA_CLK_OPCLK:
319         case ARIZONA_CLK_ASYNC_OPCLK:
320                 return arizona_set_opclk(codec, clk_id, freq);
321         default:
322                 return -EINVAL;
323         }
324
325         switch (freq) {
326         case  5644800:
327         case  6144000:
328                 break;
329         case 11289600:
330         case 12288000:
331                 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
332                 break;
333         case 22579200:
334         case 24576000:
335                 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
336                 break;
337         case 45158400:
338         case 49152000:
339                 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
340                 break;
341         default:
342                 return -EINVAL;
343         }
344
345         *clk = freq;
346
347         if (freq % 6144000)
348                 val |= ARIZONA_SYSCLK_FRAC;
349
350         dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
351
352         return regmap_update_bits(arizona->regmap, reg, mask, val);
353 }
354 EXPORT_SYMBOL_GPL(arizona_set_sysclk);
355
356 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
357 {
358         struct snd_soc_codec *codec = dai->codec;
359         int lrclk, bclk, mode, base;
360
361         base = dai->driver->base;
362
363         lrclk = 0;
364         bclk = 0;
365
366         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
367         case SND_SOC_DAIFMT_DSP_A:
368                 mode = 0;
369                 break;
370         case SND_SOC_DAIFMT_DSP_B:
371                 mode = 1;
372                 break;
373         case SND_SOC_DAIFMT_I2S:
374                 mode = 2;
375                 break;
376         case SND_SOC_DAIFMT_LEFT_J:
377                 mode = 3;
378                 break;
379         default:
380                 arizona_aif_err(dai, "Unsupported DAI format %d\n",
381                                 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
382                 return -EINVAL;
383         }
384
385         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
386         case SND_SOC_DAIFMT_CBS_CFS:
387                 break;
388         case SND_SOC_DAIFMT_CBS_CFM:
389                 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
390                 break;
391         case SND_SOC_DAIFMT_CBM_CFS:
392                 bclk |= ARIZONA_AIF1_BCLK_MSTR;
393                 break;
394         case SND_SOC_DAIFMT_CBM_CFM:
395                 bclk |= ARIZONA_AIF1_BCLK_MSTR;
396                 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
397                 break;
398         default:
399                 arizona_aif_err(dai, "Unsupported master mode %d\n",
400                                 fmt & SND_SOC_DAIFMT_MASTER_MASK);
401                 return -EINVAL;
402         }
403
404         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
405         case SND_SOC_DAIFMT_NB_NF:
406                 break;
407         case SND_SOC_DAIFMT_IB_IF:
408                 bclk |= ARIZONA_AIF1_BCLK_INV;
409                 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
410                 break;
411         case SND_SOC_DAIFMT_IB_NF:
412                 bclk |= ARIZONA_AIF1_BCLK_INV;
413                 break;
414         case SND_SOC_DAIFMT_NB_IF:
415                 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
416                 break;
417         default:
418                 return -EINVAL;
419         }
420
421         snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
422                             ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
423                             bclk);
424         snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
425                             ARIZONA_AIF1TX_LRCLK_INV |
426                             ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
427         snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
428                             ARIZONA_AIF1RX_LRCLK_INV |
429                             ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
430         snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
431                             ARIZONA_AIF1_FMT_MASK, mode);
432
433         return 0;
434 }
435
436 static const int arizona_48k_bclk_rates[] = {
437         -1,
438         48000,
439         64000,
440         96000,
441         128000,
442         192000,
443         256000,
444         384000,
445         512000,
446         768000,
447         1024000,
448         1536000,
449         2048000,
450         3072000,
451         4096000,
452         6144000,
453         8192000,
454         12288000,
455         24576000,
456 };
457
458 static const unsigned int arizona_48k_rates[] = {
459         12000,
460         24000,
461         48000,
462         96000,
463         192000,
464         384000,
465         768000,
466         4000,
467         8000,
468         16000,
469         32000,
470         64000,
471         128000,
472         256000,
473         512000,
474 };
475
476 static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
477         .count  = ARRAY_SIZE(arizona_48k_rates),
478         .list   = arizona_48k_rates,
479 };
480
481 static const int arizona_44k1_bclk_rates[] = {
482         -1,
483         44100,
484         58800,
485         88200,
486         117600,
487         177640,
488         235200,
489         352800,
490         470400,
491         705600,
492         940800,
493         1411200,
494         1881600,
495         2822400,
496         3763200,
497         5644800,
498         7526400,
499         11289600,
500         22579200,
501 };
502
503 static const unsigned int arizona_44k1_rates[] = {
504         11025,
505         22050,
506         44100,
507         88200,
508         176400,
509         352800,
510         705600,
511 };
512
513 static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
514         .count  = ARRAY_SIZE(arizona_44k1_rates),
515         .list   = arizona_44k1_rates,
516 };
517
518 static int arizona_sr_vals[] = {
519         0,
520         12000,
521         24000,
522         48000,
523         96000,
524         192000,
525         384000,
526         768000,
527         0,
528         11025,
529         22050,
530         44100,
531         88200,
532         176400,
533         352800,
534         705600,
535         4000,
536         8000,
537         16000,
538         32000,
539         64000,
540         128000,
541         256000,
542         512000,
543 };
544
545 static int arizona_startup(struct snd_pcm_substream *substream,
546                            struct snd_soc_dai *dai)
547 {
548         struct snd_soc_codec *codec = dai->codec;
549         struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
550         struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
551         const struct snd_pcm_hw_constraint_list *constraint;
552         unsigned int base_rate;
553
554         switch (dai_priv->clk) {
555         case ARIZONA_CLK_SYSCLK:
556                 base_rate = priv->sysclk;
557                 break;
558         case ARIZONA_CLK_ASYNCCLK:
559                 base_rate = priv->asyncclk;
560                 break;
561         default:
562                 return 0;
563         }
564
565         if (base_rate % 8000)
566                 constraint = &arizona_44k1_constraint;
567         else
568                 constraint = &arizona_48k_constraint;
569
570         return snd_pcm_hw_constraint_list(substream->runtime, 0,
571                                           SNDRV_PCM_HW_PARAM_RATE,
572                                           constraint);
573 }
574
575 static int arizona_hw_params(struct snd_pcm_substream *substream,
576                              struct snd_pcm_hw_params *params,
577                              struct snd_soc_dai *dai)
578 {
579         struct snd_soc_codec *codec = dai->codec;
580         struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
581         struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
582         int base = dai->driver->base;
583         const int *rates;
584         int i;
585         int bclk, lrclk, wl, frame, sr_val;
586
587         if (params_rate(params) % 8000)
588                 rates = &arizona_44k1_bclk_rates[0];
589         else
590                 rates = &arizona_48k_bclk_rates[0];
591
592         for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
593                 if (rates[i] >= snd_soc_params_to_bclk(params) &&
594                     rates[i] % params_rate(params) == 0) {
595                         bclk = i;
596                         break;
597                 }
598         }
599         if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
600                 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
601                                 params_rate(params));
602                 return -EINVAL;
603         }
604
605         for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
606                 if (arizona_sr_vals[i] == params_rate(params))
607                         break;
608         if (i == ARRAY_SIZE(arizona_sr_vals)) {
609                 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
610                                 params_rate(params));
611                 return -EINVAL;
612         }
613         sr_val = i;
614
615         lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
616
617         arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
618                         rates[bclk], rates[bclk] / lrclk);
619
620         wl = snd_pcm_format_width(params_format(params));
621         frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
622
623         /*
624          * We will need to be more flexible than this in future,
625          * currently we use a single sample rate for SYSCLK.
626          */
627         switch (dai_priv->clk) {
628         case ARIZONA_CLK_SYSCLK:
629                 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
630                                     ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
631                 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
632                                     ARIZONA_AIF1_RATE_MASK, 0);
633                 break;
634         case ARIZONA_CLK_ASYNCCLK:
635                 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
636                                     ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
637                 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
638                                     ARIZONA_AIF1_RATE_MASK, 8);
639                 break;
640         default:
641                 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
642                 return -EINVAL;
643         }
644
645         snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
646                             ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
647         snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
648                             ARIZONA_AIF1TX_BCPF_MASK, lrclk);
649         snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
650                             ARIZONA_AIF1RX_BCPF_MASK, lrclk);
651         snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
652                             ARIZONA_AIF1TX_WL_MASK |
653                             ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
654         snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
655                             ARIZONA_AIF1RX_WL_MASK |
656                             ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
657
658         return 0;
659 }
660
661 static const char *arizona_dai_clk_str(int clk_id)
662 {
663         switch (clk_id) {
664         case ARIZONA_CLK_SYSCLK:
665                 return "SYSCLK";
666         case ARIZONA_CLK_ASYNCCLK:
667                 return "ASYNCCLK";
668         default:
669                 return "Unknown clock";
670         }
671 }
672
673 static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
674                                   int clk_id, unsigned int freq, int dir)
675 {
676         struct snd_soc_codec *codec = dai->codec;
677         struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
678         struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
679         struct snd_soc_dapm_route routes[2];
680
681         switch (clk_id) {
682         case ARIZONA_CLK_SYSCLK:
683         case ARIZONA_CLK_ASYNCCLK:
684                 break;
685         default:
686                 return -EINVAL;
687         }
688
689         if (clk_id == dai_priv->clk)
690                 return 0;
691
692         if (dai->active) {
693                 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
694                         dai->id);
695                 return -EBUSY;
696         }
697
698         memset(&routes, 0, sizeof(routes));
699         routes[0].sink = dai->driver->capture.stream_name;
700         routes[1].sink = dai->driver->playback.stream_name;
701
702         routes[0].source = arizona_dai_clk_str(dai_priv->clk);
703         routes[1].source = arizona_dai_clk_str(dai_priv->clk);
704         snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
705
706         routes[0].source = arizona_dai_clk_str(clk_id);
707         routes[1].source = arizona_dai_clk_str(clk_id);
708         snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
709
710         return snd_soc_dapm_sync(&codec->dapm);
711 }
712
713 const struct snd_soc_dai_ops arizona_dai_ops = {
714         .startup = arizona_startup,
715         .set_fmt = arizona_set_fmt,
716         .hw_params = arizona_hw_params,
717         .set_sysclk = arizona_dai_set_sysclk,
718 };
719 EXPORT_SYMBOL_GPL(arizona_dai_ops);
720
721 int arizona_init_dai(struct arizona_priv *priv, int id)
722 {
723         struct arizona_dai_priv *dai_priv = &priv->dai[id];
724
725         dai_priv->clk = ARIZONA_CLK_SYSCLK;
726
727         return 0;
728 }
729 EXPORT_SYMBOL_GPL(arizona_init_dai);
730
731 static irqreturn_t arizona_fll_lock(int irq, void *data)
732 {
733         struct arizona_fll *fll = data;
734
735         arizona_fll_dbg(fll, "Lock status changed\n");
736
737         complete(&fll->lock);
738
739         return IRQ_HANDLED;
740 }
741
742 static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
743 {
744         struct arizona_fll *fll = data;
745
746         arizona_fll_dbg(fll, "clock OK\n");
747
748         complete(&fll->ok);
749
750         return IRQ_HANDLED;
751 }
752
753 static struct {
754         unsigned int min;
755         unsigned int max;
756         u16 fratio;
757         int ratio;
758 } fll_fratios[] = {
759         {       0,    64000, 4, 16 },
760         {   64000,   128000, 3,  8 },
761         {  128000,   256000, 2,  4 },
762         {  256000,  1000000, 1,  2 },
763         { 1000000, 13500000, 0,  1 },
764 };
765
766 struct arizona_fll_cfg {
767         int n;
768         int theta;
769         int lambda;
770         int refdiv;
771         int outdiv;
772         int fratio;
773 };
774
775 static int arizona_calc_fll(struct arizona_fll *fll,
776                             struct arizona_fll_cfg *cfg,
777                             unsigned int Fref,
778                             unsigned int Fout)
779 {
780         unsigned int target, div, gcd_fll;
781         int i, ratio;
782
783         arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
784
785         /* Fref must be <=13.5MHz */
786         div = 1;
787         cfg->refdiv = 0;
788         while ((Fref / div) > 13500000) {
789                 div *= 2;
790                 cfg->refdiv++;
791
792                 if (div > 8) {
793                         arizona_fll_err(fll,
794                                         "Can't scale %dMHz in to <=13.5MHz\n",
795                                         Fref);
796                         return -EINVAL;
797                 }
798         }
799
800         /* Apply the division for our remaining calculations */
801         Fref /= div;
802
803         /* Fvco should be over the targt; don't check the upper bound */
804         div = 1;
805         while (Fout * div < 90000000 * fll->vco_mult) {
806                 div++;
807                 if (div > 7) {
808                         arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
809                                         Fout);
810                         return -EINVAL;
811                 }
812         }
813         target = Fout * div / fll->vco_mult;
814         cfg->outdiv = div;
815
816         arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
817
818         /* Find an appropraite FLL_FRATIO and factor it out of the target */
819         for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
820                 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
821                         cfg->fratio = fll_fratios[i].fratio;
822                         ratio = fll_fratios[i].ratio;
823                         break;
824                 }
825         }
826         if (i == ARRAY_SIZE(fll_fratios)) {
827                 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
828                                 Fref);
829                 return -EINVAL;
830         }
831
832         cfg->n = target / (ratio * Fref);
833
834         if (target % Fref) {
835                 gcd_fll = gcd(target, ratio * Fref);
836                 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
837
838                 cfg->theta = (target - (cfg->n * ratio * Fref))
839                         / gcd_fll;
840                 cfg->lambda = (ratio * Fref) / gcd_fll;
841         } else {
842                 cfg->theta = 0;
843                 cfg->lambda = 0;
844         }
845
846         arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
847                         cfg->n, cfg->theta, cfg->lambda);
848         arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
849                         cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
850
851         return 0;
852
853 }
854
855 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
856                               struct arizona_fll_cfg *cfg, int source)
857 {
858         regmap_update_bits(arizona->regmap, base + 3,
859                            ARIZONA_FLL1_THETA_MASK, cfg->theta);
860         regmap_update_bits(arizona->regmap, base + 4,
861                            ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
862         regmap_update_bits(arizona->regmap, base + 5,
863                            ARIZONA_FLL1_FRATIO_MASK,
864                            cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
865         regmap_update_bits(arizona->regmap, base + 6,
866                            ARIZONA_FLL1_CLK_REF_DIV_MASK |
867                            ARIZONA_FLL1_CLK_REF_SRC_MASK,
868                            cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
869                            source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
870
871         regmap_update_bits(arizona->regmap, base + 2,
872                            ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
873                            ARIZONA_FLL1_CTRL_UPD | cfg->n);
874 }
875
876 int arizona_set_fll(struct arizona_fll *fll, int source,
877                     unsigned int Fref, unsigned int Fout)
878 {
879         struct arizona *arizona = fll->arizona;
880         struct arizona_fll_cfg cfg, sync;
881         unsigned int reg, val;
882         int syncsrc;
883         bool ena;
884         int ret;
885
886         ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
887         if (ret != 0) {
888                 arizona_fll_err(fll, "Failed to read current state: %d\n",
889                                 ret);
890                 return ret;
891         }
892         ena = reg & ARIZONA_FLL1_ENA;
893
894         if (Fout) {
895                 /* Do we have a 32kHz reference? */
896                 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
897                 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
898                 case ARIZONA_CLK_SRC_MCLK1:
899                 case ARIZONA_CLK_SRC_MCLK2:
900                         syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
901                         break;
902                 default:
903                         syncsrc = -1;
904                 }
905
906                 if (source == syncsrc)
907                         syncsrc = -1;
908
909                 if (syncsrc >= 0) {
910                         ret = arizona_calc_fll(fll, &sync, Fref, Fout);
911                         if (ret != 0)
912                                 return ret;
913
914                         ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
915                         if (ret != 0)
916                                 return ret;
917                 } else {
918                         ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
919                         if (ret != 0)
920                                 return ret;
921                 }
922         } else {
923                 regmap_update_bits(arizona->regmap, fll->base + 1,
924                                    ARIZONA_FLL1_ENA, 0);
925                 regmap_update_bits(arizona->regmap, fll->base + 0x11,
926                                    ARIZONA_FLL1_SYNC_ENA, 0);
927
928                 if (ena)
929                         pm_runtime_put_autosuspend(arizona->dev);
930
931                 return 0;
932         }
933
934         regmap_update_bits(arizona->regmap, fll->base + 5,
935                            ARIZONA_FLL1_OUTDIV_MASK,
936                            cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
937
938         if (syncsrc >= 0) {
939                 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
940                 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
941         } else {
942                 arizona_apply_fll(arizona, fll->base, &cfg, source);
943         }
944
945         if (!ena)
946                 pm_runtime_get(arizona->dev);
947
948         /* Clear any pending completions */
949         try_wait_for_completion(&fll->ok);
950
951         regmap_update_bits(arizona->regmap, fll->base + 1,
952                            ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
953         if (syncsrc >= 0)
954                 regmap_update_bits(arizona->regmap, fll->base + 0x11,
955                                    ARIZONA_FLL1_SYNC_ENA,
956                                    ARIZONA_FLL1_SYNC_ENA);
957
958         ret = wait_for_completion_timeout(&fll->ok,
959                                           msecs_to_jiffies(25));
960         if (ret == 0)
961                 arizona_fll_warn(fll, "Timed out waiting for lock\n");
962
963         return 0;
964 }
965 EXPORT_SYMBOL_GPL(arizona_set_fll);
966
967 int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
968                      int ok_irq, struct arizona_fll *fll)
969 {
970         int ret;
971
972         init_completion(&fll->lock);
973         init_completion(&fll->ok);
974
975         fll->id = id;
976         fll->base = base;
977         fll->arizona = arizona;
978
979         snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
980         snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
981                  "FLL%d clock OK", id);
982
983         ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
984                                   arizona_fll_lock, fll);
985         if (ret != 0) {
986                 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
987                         id, ret);
988         }
989
990         ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
991                                   arizona_fll_clock_ok, fll);
992         if (ret != 0) {
993                 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
994                         id, ret);
995         }
996
997         return 0;
998 }
999 EXPORT_SYMBOL_GPL(arizona_init_fll);
1000
1001 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1002 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1003 MODULE_LICENSE("GPL");