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

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

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

~ [ 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