Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
arizona.c
Go to the documentation of this file.
1 /*
2  * arizona.c - Wolfson Arizona class device shared support
3  *
4  * Copyright 2012 Wolfson Microelectronics plc
5  *
6  * Author: Mark Brown <[email protected]>
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>
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 
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  "DSP2.1",
123  "DSP2.2",
124  "DSP2.3",
125  "DSP2.4",
126  "DSP2.5",
127  "DSP2.6",
128  "DSP3.1",
129  "DSP3.2",
130  "DSP3.3",
131  "DSP3.4",
132  "DSP3.5",
133  "DSP3.6",
134  "DSP4.1",
135  "DSP4.2",
136  "DSP4.3",
137  "DSP4.4",
138  "DSP4.5",
139  "DSP4.6",
140  "ASRC1L",
141  "ASRC1R",
142  "ASRC2L",
143  "ASRC2R",
144 };
146 
148  0x00, /* None */
149  0x04, /* Tone */
150  0x05,
151  0x06, /* Haptics */
152  0x08, /* AEC */
153  0x0c, /* Noise mixer */
154  0x0d, /* Comfort noise */
155  0x10, /* IN1L */
156  0x11,
157  0x12,
158  0x13,
159  0x14,
160  0x15,
161  0x16,
162  0x17,
163  0x20, /* AIF1RX1 */
164  0x21,
165  0x22,
166  0x23,
167  0x24,
168  0x25,
169  0x26,
170  0x27,
171  0x28, /* AIF2RX1 */
172  0x29,
173  0x30, /* AIF3RX1 */
174  0x31,
175  0x38, /* SLIMRX1 */
176  0x39,
177  0x3a,
178  0x3b,
179  0x3c,
180  0x3d,
181  0x3e,
182  0x3f,
183  0x50, /* EQ1 */
184  0x51,
185  0x52,
186  0x53,
187  0x58, /* DRC1L */
188  0x59,
189  0x5a,
190  0x5b,
191  0x60, /* LHPF1 */
192  0x61,
193  0x62,
194  0x63,
195  0x68, /* DSP1.1 */
196  0x69,
197  0x6a,
198  0x6b,
199  0x6c,
200  0x6d,
201  0x70, /* DSP2.1 */
202  0x71,
203  0x72,
204  0x73,
205  0x74,
206  0x75,
207  0x78, /* DSP3.1 */
208  0x79,
209  0x7a,
210  0x7b,
211  0x7c,
212  0x7d,
213  0x80, /* DSP4.1 */
214  0x81,
215  0x82,
216  0x83,
217  0x84,
218  0x85,
219  0x90, /* ASRC1L */
220  0x91,
221  0x92,
222  0x93,
223 };
225 
226 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
227 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
228 
229 static const char *arizona_lhpf_mode_text[] = {
230  "Low-pass", "High-pass"
231 };
232 
235  arizona_lhpf_mode_text);
236 EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
237 
240  arizona_lhpf_mode_text);
241 EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
242 
245  arizona_lhpf_mode_text);
246 EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
247 
250  arizona_lhpf_mode_text);
251 EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
252 
253 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
254  int event)
255 {
256  return 0;
257 }
259 
261  struct snd_kcontrol *kcontrol,
262  int event)
263 {
264  return 0;
265 }
267 
268 static unsigned int arizona_sysclk_48k_rates[] = {
269  6144000,
270  12288000,
271  24576000,
272  49152000,
273  73728000,
274  98304000,
275  147456000,
276 };
277 
278 static unsigned int arizona_sysclk_44k1_rates[] = {
279  5644800,
280  11289600,
281  22579200,
282  45158400,
283  67737600,
284  90316800,
285  135475200,
286 };
287 
288 static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
289  unsigned int freq)
290 {
291  struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
292  unsigned int reg;
293  unsigned int *rates;
294  int ref, div, refclk;
295 
296  switch (clk) {
297  case ARIZONA_CLK_OPCLK:
299  refclk = priv->sysclk;
300  break;
303  refclk = priv->asyncclk;
304  break;
305  default:
306  return -EINVAL;
307  }
308 
309  if (refclk % 8000)
310  rates = arizona_sysclk_44k1_rates;
311  else
312  rates = arizona_sysclk_48k_rates;
313 
314  for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
315  rates[ref] <= refclk; ref++) {
316  div = 1;
317  while (rates[ref] / div >= freq && div < 32) {
318  if (rates[ref] / div == freq) {
319  dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
320  freq);
321  snd_soc_update_bits(codec, reg,
324  (div <<
326  ref);
327  return 0;
328  }
329  div++;
330  }
331  }
332 
333  dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
334  return -EINVAL;
335 }
336 
337 int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
338  int source, unsigned int freq, int dir)
339 {
340  struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
341  struct arizona *arizona = priv->arizona;
342  char *name;
343  unsigned int reg;
345  unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
346  unsigned int *clk;
347 
348  switch (clk_id) {
349  case ARIZONA_CLK_SYSCLK:
350  name = "SYSCLK";
352  clk = &priv->sysclk;
353  mask |= ARIZONA_SYSCLK_FRAC;
354  break;
356  name = "ASYNCCLK";
357  reg = ARIZONA_ASYNC_CLOCK_1;
358  clk = &priv->asyncclk;
359  break;
360  case ARIZONA_CLK_OPCLK:
362  return arizona_set_opclk(codec, clk_id, freq);
363  default:
364  return -EINVAL;
365  }
366 
367  switch (freq) {
368  case 5644800:
369  case 6144000:
370  break;
371  case 11289600:
372  case 12288000:
373  val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
374  break;
375  case 22579200:
376  case 24576000:
377  val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
378  break;
379  case 45158400:
380  case 49152000:
381  val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
382  break;
383  default:
384  return -EINVAL;
385  }
386 
387  *clk = freq;
388 
389  if (freq % 6144000)
390  val |= ARIZONA_SYSCLK_FRAC;
391 
392  dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
393 
394  return regmap_update_bits(arizona->regmap, reg, mask, val);
395 }
397 
398 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
399 {
400  struct snd_soc_codec *codec = dai->codec;
401  int lrclk, bclk, mode, base;
402 
403  base = dai->driver->base;
404 
405  lrclk = 0;
406  bclk = 0;
407 
408  switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
410  mode = 0;
411  break;
413  mode = 1;
414  break;
415  case SND_SOC_DAIFMT_I2S:
416  mode = 2;
417  break;
419  mode = 3;
420  break;
421  default:
422  arizona_aif_err(dai, "Unsupported DAI format %d\n",
423  fmt & SND_SOC_DAIFMT_FORMAT_MASK);
424  return -EINVAL;
425  }
426 
427  switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
429  break;
431  lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
432  break;
434  bclk |= ARIZONA_AIF1_BCLK_MSTR;
435  break;
437  bclk |= ARIZONA_AIF1_BCLK_MSTR;
438  lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
439  break;
440  default:
441  arizona_aif_err(dai, "Unsupported master mode %d\n",
442  fmt & SND_SOC_DAIFMT_MASTER_MASK);
443  return -EINVAL;
444  }
445 
446  switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
448  break;
450  bclk |= ARIZONA_AIF1_BCLK_INV;
451  lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
452  break;
454  bclk |= ARIZONA_AIF1_BCLK_INV;
455  break;
457  lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
458  break;
459  default:
460  return -EINVAL;
461  }
462 
465  bclk);
473  ARIZONA_AIF1_FMT_MASK, mode);
474 
475  return 0;
476 }
477 
478 static const int arizona_48k_bclk_rates[] = {
479  -1,
480  48000,
481  64000,
482  96000,
483  128000,
484  192000,
485  256000,
486  384000,
487  512000,
488  768000,
489  1024000,
490  1536000,
491  2048000,
492  3072000,
493  4096000,
494  6144000,
495  8192000,
496  12288000,
497  24576000,
498 };
499 
500 static const unsigned int arizona_48k_rates[] = {
501  12000,
502  24000,
503  48000,
504  96000,
505  192000,
506  384000,
507  768000,
508  4000,
509  8000,
510  16000,
511  32000,
512  64000,
513  128000,
514  256000,
515  512000,
516 };
517 
518 static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
519  .count = ARRAY_SIZE(arizona_48k_rates),
520  .list = arizona_48k_rates,
521 };
522 
523 static const int arizona_44k1_bclk_rates[] = {
524  -1,
525  44100,
526  58800,
527  88200,
528  117600,
529  177640,
530  235200,
531  352800,
532  470400,
533  705600,
534  940800,
535  1411200,
536  1881600,
537  2822400,
538  3763200,
539  5644800,
540  7526400,
541  11289600,
542  22579200,
543 };
544 
545 static const unsigned int arizona_44k1_rates[] = {
546  11025,
547  22050,
548  44100,
549  88200,
550  176400,
551  352800,
552  705600,
553 };
554 
555 static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
556  .count = ARRAY_SIZE(arizona_44k1_rates),
557  .list = arizona_44k1_rates,
558 };
559 
560 static int arizona_sr_vals[] = {
561  0,
562  12000,
563  24000,
564  48000,
565  96000,
566  192000,
567  384000,
568  768000,
569  0,
570  11025,
571  22050,
572  44100,
573  88200,
574  176400,
575  352800,
576  705600,
577  4000,
578  8000,
579  16000,
580  32000,
581  64000,
582  128000,
583  256000,
584  512000,
585 };
586 
587 static int arizona_startup(struct snd_pcm_substream *substream,
588  struct snd_soc_dai *dai)
589 {
590  struct snd_soc_codec *codec = dai->codec;
591  struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
592  struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
593  const struct snd_pcm_hw_constraint_list *constraint;
594  unsigned int base_rate;
595 
596  switch (dai_priv->clk) {
597  case ARIZONA_CLK_SYSCLK:
598  base_rate = priv->sysclk;
599  break;
601  base_rate = priv->asyncclk;
602  break;
603  default:
604  return 0;
605  }
606 
607  if (base_rate % 8000)
608  constraint = &arizona_44k1_constraint;
609  else
610  constraint = &arizona_48k_constraint;
611 
612  return snd_pcm_hw_constraint_list(substream->runtime, 0,
614  constraint);
615 }
616 
617 static int arizona_hw_params(struct snd_pcm_substream *substream,
618  struct snd_pcm_hw_params *params,
619  struct snd_soc_dai *dai)
620 {
621  struct snd_soc_codec *codec = dai->codec;
622  struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
623  struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
624  int base = dai->driver->base;
625  const int *rates;
626  int i;
627  int bclk, lrclk, wl, frame, sr_val;
628 
629  if (params_rate(params) % 8000)
630  rates = &arizona_44k1_bclk_rates[0];
631  else
632  rates = &arizona_48k_bclk_rates[0];
633 
634  for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
635  if (rates[i] >= snd_soc_params_to_bclk(params) &&
636  rates[i] % params_rate(params) == 0) {
637  bclk = i;
638  break;
639  }
640  }
641  if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
642  arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
643  params_rate(params));
644  return -EINVAL;
645  }
646 
647  for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
648  if (arizona_sr_vals[i] == params_rate(params))
649  break;
650  if (i == ARRAY_SIZE(arizona_sr_vals)) {
651  arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
652  params_rate(params));
653  return -EINVAL;
654  }
655  sr_val = i;
656 
657  lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
658 
659  arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
660  rates[bclk], rates[bclk] / lrclk);
661 
662  wl = snd_pcm_format_width(params_format(params));
663  frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
664 
665  /*
666  * We will need to be more flexible than this in future,
667  * currently we use a single sample rate for SYSCLK.
668  */
669  switch (dai_priv->clk) {
670  case ARIZONA_CLK_SYSCLK:
675  break;
681  break;
682  default:
683  arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
684  return -EINVAL;
685  }
686 
690  ARIZONA_AIF1TX_BCPF_MASK, lrclk);
692  ARIZONA_AIF1RX_BCPF_MASK, lrclk);
699 
700  return 0;
701 }
702 
703 static const char *arizona_dai_clk_str(int clk_id)
704 {
705  switch (clk_id) {
706  case ARIZONA_CLK_SYSCLK:
707  return "SYSCLK";
709  return "ASYNCCLK";
710  default:
711  return "Unknown clock";
712  }
713 }
714 
715 static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
716  int clk_id, unsigned int freq, int dir)
717 {
718  struct snd_soc_codec *codec = dai->codec;
719  struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
720  struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
721  struct snd_soc_dapm_route routes[2];
722 
723  switch (clk_id) {
724  case ARIZONA_CLK_SYSCLK:
726  break;
727  default:
728  return -EINVAL;
729  }
730 
731  if (clk_id == dai_priv->clk)
732  return 0;
733 
734  if (dai->active) {
735  dev_err(codec->dev, "Can't change clock on active DAI %d\n",
736  dai->id);
737  return -EBUSY;
738  }
739 
740  memset(&routes, 0, sizeof(routes));
741  routes[0].sink = dai->driver->capture.stream_name;
742  routes[1].sink = dai->driver->playback.stream_name;
743 
744  routes[0].source = arizona_dai_clk_str(dai_priv->clk);
745  routes[1].source = arizona_dai_clk_str(dai_priv->clk);
746  snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
747 
748  routes[0].source = arizona_dai_clk_str(clk_id);
749  routes[1].source = arizona_dai_clk_str(clk_id);
750  snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
751 
752  return snd_soc_dapm_sync(&codec->dapm);
753 }
754 
756  .startup = arizona_startup,
757  .set_fmt = arizona_set_fmt,
758  .hw_params = arizona_hw_params,
759  .set_sysclk = arizona_dai_set_sysclk,
760 };
761 EXPORT_SYMBOL_GPL(arizona_dai_ops);
762 
763 int arizona_init_dai(struct arizona_priv *priv, int id)
764 {
765  struct arizona_dai_priv *dai_priv = &priv->dai[id];
766 
767  dai_priv->clk = ARIZONA_CLK_SYSCLK;
768 
769  return 0;
770 }
772 
773 static irqreturn_t arizona_fll_lock(int irq, void *data)
774 {
775  struct arizona_fll *fll = data;
776 
777  arizona_fll_dbg(fll, "Lock status changed\n");
778 
779  complete(&fll->lock);
780 
781  return IRQ_HANDLED;
782 }
783 
784 static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
785 {
786  struct arizona_fll *fll = data;
787 
788  arizona_fll_dbg(fll, "clock OK\n");
789 
790  complete(&fll->ok);
791 
792  return IRQ_HANDLED;
793 }
794 
795 static struct {
796  unsigned int min;
797  unsigned int max;
799  int ratio;
800 } fll_fratios[] = {
801  { 0, 64000, 4, 16 },
802  { 64000, 128000, 3, 8 },
803  { 128000, 256000, 2, 4 },
804  { 256000, 1000000, 1, 2 },
805  { 1000000, 13500000, 0, 1 },
806 };
807 
809  int n;
810  int theta;
811  int lambda;
812  int refdiv;
813  int outdiv;
814  int fratio;
815 };
816 
817 static int arizona_calc_fll(struct arizona_fll *fll,
818  struct arizona_fll_cfg *cfg,
819  unsigned int Fref,
820  unsigned int Fout)
821 {
822  unsigned int target, div, gcd_fll;
823  int i, ratio;
824 
825  arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
826 
827  /* Fref must be <=13.5MHz */
828  div = 1;
829  cfg->refdiv = 0;
830  while ((Fref / div) > 13500000) {
831  div *= 2;
832  cfg->refdiv++;
833 
834  if (div > 8) {
835  arizona_fll_err(fll,
836  "Can't scale %dMHz in to <=13.5MHz\n",
837  Fref);
838  return -EINVAL;
839  }
840  }
841 
842  /* Apply the division for our remaining calculations */
843  Fref /= div;
844 
845  /* Fvco should be over the targt; don't check the upper bound */
846  div = 1;
847  while (Fout * div < 90000000 * fll->vco_mult) {
848  div++;
849  if (div > 7) {
850  arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
851  Fout);
852  return -EINVAL;
853  }
854  }
855  target = Fout * div / fll->vco_mult;
856  cfg->outdiv = div;
857 
858  arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
859 
860  /* Find an appropraite FLL_FRATIO and factor it out of the target */
861  for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
862  if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
863  cfg->fratio = fll_fratios[i].fratio;
864  ratio = fll_fratios[i].ratio;
865  break;
866  }
867  }
868  if (i == ARRAY_SIZE(fll_fratios)) {
869  arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
870  Fref);
871  return -EINVAL;
872  }
873 
874  cfg->n = target / (ratio * Fref);
875 
876  if (target % Fref) {
877  gcd_fll = gcd(target, ratio * Fref);
878  arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
879 
880  cfg->theta = (target - (cfg->n * ratio * Fref))
881  / gcd_fll;
882  cfg->lambda = (ratio * Fref) / gcd_fll;
883  } else {
884  cfg->theta = 0;
885  cfg->lambda = 0;
886  }
887 
888  arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
889  cfg->n, cfg->theta, cfg->lambda);
890  arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
891  cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
892 
893  return 0;
894 
895 }
896 
897 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
898  struct arizona_fll_cfg *cfg, int source)
899 {
900  regmap_update_bits(arizona->regmap, base + 3,
902  regmap_update_bits(arizona->regmap, base + 4,
904  regmap_update_bits(arizona->regmap, base + 5,
907  regmap_update_bits(arizona->regmap, base + 6,
912 
913  regmap_update_bits(arizona->regmap, base + 2,
915  ARIZONA_FLL1_CTRL_UPD | cfg->n);
916 }
917 
918 int arizona_set_fll(struct arizona_fll *fll, int source,
919  unsigned int Fref, unsigned int Fout)
920 {
921  struct arizona *arizona = fll->arizona;
922  struct arizona_fll_cfg cfg, sync;
923  unsigned int reg, val;
924  int syncsrc;
925  bool ena;
926  int ret;
927 
928  ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
929  if (ret != 0) {
930  arizona_fll_err(fll, "Failed to read current state: %d\n",
931  ret);
932  return ret;
933  }
934  ena = reg & ARIZONA_FLL1_ENA;
935 
936  if (Fout) {
937  /* Do we have a 32kHz reference? */
938  regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
939  switch (val & ARIZONA_CLK_32K_SRC_MASK) {
942  syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
943  break;
944  default:
945  syncsrc = -1;
946  }
947 
948  if (source == syncsrc)
949  syncsrc = -1;
950 
951  if (syncsrc >= 0) {
952  ret = arizona_calc_fll(fll, &sync, Fref, Fout);
953  if (ret != 0)
954  return ret;
955 
956  ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
957  if (ret != 0)
958  return ret;
959  } else {
960  ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
961  if (ret != 0)
962  return ret;
963  }
964  } else {
965  regmap_update_bits(arizona->regmap, fll->base + 1,
966  ARIZONA_FLL1_ENA, 0);
967  regmap_update_bits(arizona->regmap, fll->base + 0x11,
969 
970  if (ena)
971  pm_runtime_put_autosuspend(arizona->dev);
972 
973  return 0;
974  }
975 
976  regmap_update_bits(arizona->regmap, fll->base + 5,
979 
980  if (syncsrc >= 0) {
981  arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
982  arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
983  } else {
984  arizona_apply_fll(arizona, fll->base, &cfg, source);
985  }
986 
987  if (!ena)
988  pm_runtime_get(arizona->dev);
989 
990  /* Clear any pending completions */
992 
993  regmap_update_bits(arizona->regmap, fll->base + 1,
994  ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
995  if (syncsrc >= 0)
996  regmap_update_bits(arizona->regmap, fll->base + 0x11,
999 
1000  ret = wait_for_completion_timeout(&fll->ok,
1001  msecs_to_jiffies(25));
1002  if (ret == 0)
1003  arizona_fll_warn(fll, "Timed out waiting for lock\n");
1004 
1005  return 0;
1006 }
1008 
1009 int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1010  int ok_irq, struct arizona_fll *fll)
1011 {
1012  int ret;
1013 
1014  init_completion(&fll->lock);
1015  init_completion(&fll->ok);
1016 
1017  fll->id = id;
1018  fll->base = base;
1019  fll->arizona = arizona;
1020 
1021  snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1022  snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1023  "FLL%d clock OK", id);
1024 
1025  ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
1026  arizona_fll_lock, fll);
1027  if (ret != 0) {
1028  dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
1029  id, ret);
1030  }
1031 
1032  ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1033  arizona_fll_clock_ok, fll);
1034  if (ret != 0) {
1035  dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
1036  id, ret);
1037  }
1038 
1039  return 0;
1040 }
1042 
1043 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1044 MODULE_AUTHOR("Mark Brown <[email protected]>");
1045 MODULE_LICENSE("GPL");