Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm5110.c
Go to the documentation of this file.
1 /*
2  * wm5110.c -- WM5110 ALSA SoC Audio driver
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/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/pm.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/slab.h>
21 #include <sound/core.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
25 #include <sound/jack.h>
26 #include <sound/initval.h>
27 #include <sound/tlv.h>
28 
29 #include <linux/mfd/arizona/core.h>
31 
32 #include "arizona.h"
33 #include "wm5110.h"
34 
35 struct wm5110_priv {
37  struct arizona_fll fll[2];
38 };
39 
40 static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
41 static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
42 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
43 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
44 
45 static const struct snd_kcontrol_new wm5110_snd_controls[] = {
46 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
47  ARIZONA_IN1_OSR_SHIFT, 1, 0),
48 SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
49  ARIZONA_IN2_OSR_SHIFT, 1, 0),
50 SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
51  ARIZONA_IN3_OSR_SHIFT, 1, 0),
52 SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL,
53  ARIZONA_IN4_OSR_SHIFT, 1, 0),
54 
57  ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
60  ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
63  ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
64 
65 SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L,
67 SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L,
69 SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L,
71 SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L,
73 
76  0xbf, 0, digital_tlv),
79  0xbf, 0, digital_tlv),
82  0xbf, 0, digital_tlv),
85  0xbf, 0, digital_tlv),
86 
91 
93  24, 0, eq_tlv),
95  24, 0, eq_tlv),
97  24, 0, eq_tlv),
99  24, 0, eq_tlv),
101  24, 0, eq_tlv),
102 
104  24, 0, eq_tlv),
106  24, 0, eq_tlv),
108  24, 0, eq_tlv),
110  24, 0, eq_tlv),
112  24, 0, eq_tlv),
113 
115  24, 0, eq_tlv),
117  24, 0, eq_tlv),
119  24, 0, eq_tlv),
121  24, 0, eq_tlv),
123  24, 0, eq_tlv),
124 
126  24, 0, eq_tlv),
128  24, 0, eq_tlv),
130  24, 0, eq_tlv),
132  24, 0, eq_tlv),
134  24, 0, eq_tlv),
135 
140 
145 
150 
151 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
152 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
153 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
154 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
155 
164 
167 
168 SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
169  ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
170 
183 
184 SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
185  ARIZONA_OUT1_OSR_SHIFT, 1, 0),
186 SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
187  ARIZONA_OUT2_OSR_SHIFT, 1, 0),
188 SOC_SINGLE("OUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
189  ARIZONA_OUT3_OSR_SHIFT, 1, 0),
190 SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
191  ARIZONA_OUT4_OSR_SHIFT, 1, 0),
192 SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
193  ARIZONA_OUT5_OSR_SHIFT, 1, 0),
194 SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
195  ARIZONA_OUT6_OSR_SHIFT, 1, 0),
196 
197 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
199 SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
201 SOC_DOUBLE_R("OUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
203 SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
205 SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
207 SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L,
209 
210 SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
212  0xbf, 0, digital_tlv),
213 SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
215  0xbf, 0, digital_tlv),
216 SOC_DOUBLE_R_TLV("OUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
218  0xbf, 0, digital_tlv),
219 SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
221  0xbf, 0, digital_tlv),
222 SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
224  0xbf, 0, digital_tlv),
225 SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
227  0xbf, 0, digital_tlv),
228 
232  0x34, 0x40, 0, ana_tlv),
236  0x34, 0x40, 0, ana_tlv),
239  ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
240 
245 
254 
257 
260 };
261 
266 
271 
276 
279 
282 
295 
304 
307 
310 
315 
316 static const char *wm5110_aec_loopback_texts[] = {
317  "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
318  "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R",
319 };
320 
321 static const unsigned int wm5110_aec_loopback_values[] = {
322  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
323 };
324 
325 static const struct soc_enum wm5110_aec_loopback =
329  ARRAY_SIZE(wm5110_aec_loopback_texts),
330  wm5110_aec_loopback_texts,
331  wm5110_aec_loopback_values);
332 
333 static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
334  SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback);
335 
336 static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
338  0, NULL, 0),
345 
346 SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
347 SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0),
348 SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
350 SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0),
351 SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
352 
353 SND_SOC_DAPM_SIGGEN("TONE"),
354 SND_SOC_DAPM_SIGGEN("NOISE"),
355 
356 SND_SOC_DAPM_INPUT("IN1L"),
357 SND_SOC_DAPM_INPUT("IN1R"),
358 SND_SOC_DAPM_INPUT("IN2L"),
359 SND_SOC_DAPM_INPUT("IN2R"),
360 SND_SOC_DAPM_INPUT("IN3L"),
361 SND_SOC_DAPM_INPUT("IN3R"),
362 SND_SOC_DAPM_INPUT("IN4L"),
363 SND_SOC_DAPM_INPUT("IN4R"),
364 
366  0, NULL, 0, arizona_in_ev,
369  0, NULL, 0, arizona_in_ev,
372  0, NULL, 0, arizona_in_ev,
375  0, NULL, 0, arizona_in_ev,
378  0, NULL, 0, arizona_in_ev,
381  0, NULL, 0, arizona_in_ev,
384  0, NULL, 0, arizona_in_ev,
387  0, NULL, 0, arizona_in_ev,
389 
396 
399 
400 SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
402 SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
404 
407 
412 
414  NULL, 0),
416  NULL, 0),
418  NULL, 0),
420  NULL, 0),
421 
423  NULL, 0),
425  NULL, 0),
427  NULL, 0),
429  NULL, 0),
430 
432  0, NULL, 0),
434  0, NULL, 0),
435 
437  NULL, 0),
439  NULL, 0),
441  NULL, 0),
443  NULL, 0),
444 
446  ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5110_aec_loopback_mux),
447 
448 SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
450 SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
452 SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
454 SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
456 SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
458 SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
460 SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
462 SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
464 
465 SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
467 SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
469 SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
471 SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
473 SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
475 SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
477 SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
479 SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
481 
482 SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
484 SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
486 
487 SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
489 SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
491 
492 SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
494 SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
496 
497 SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
499 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
501 
538 
539 ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
540 ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
541 ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
542 ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
543 
544 ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
545 ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
546 ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
547 ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
548 
549 ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
550 ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
551 ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
552 ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
553 
554 ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
555 ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
556 
557 ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
558 ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
559 
560 ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
561 ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
562 ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
563 ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
564 ARIZONA_MIXER_WIDGETS(OUT3L, "HPOUT3L"),
565 ARIZONA_MIXER_WIDGETS(OUT3R, "HPOUT3R"),
566 ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
567 ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
568 ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
569 ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
570 ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
571 ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
572 
573 ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
574 ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
575 ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
576 ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
577 ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
578 ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
579 ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
580 ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
581 
582 ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
583 ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
584 
585 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
586 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
587 
588 ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
589 ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
590 ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
591 ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
592 
593 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
594 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
595 SND_SOC_DAPM_OUTPUT("HPOUT2L"),
596 SND_SOC_DAPM_OUTPUT("HPOUT2R"),
597 SND_SOC_DAPM_OUTPUT("HPOUT3L"),
598 SND_SOC_DAPM_OUTPUT("HPOUT3R"),
599 SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
600 SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
601 SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
602 SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
603 SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
604 SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
605 SND_SOC_DAPM_OUTPUT("SPKDAT2L"),
606 SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
607 };
608 
609 #define ARIZONA_MIXER_INPUT_ROUTES(name) \
610  { name, "Noise Generator", "Noise Generator" }, \
611  { name, "Tone Generator 1", "Tone Generator 1" }, \
612  { name, "Tone Generator 2", "Tone Generator 2" }, \
613  { name, "AEC", "AEC Loopback" }, \
614  { name, "IN1L", "IN1L PGA" }, \
615  { name, "IN1R", "IN1R PGA" }, \
616  { name, "IN2L", "IN2L PGA" }, \
617  { name, "IN2R", "IN2R PGA" }, \
618  { name, "IN3L", "IN3L PGA" }, \
619  { name, "IN3R", "IN3R PGA" }, \
620  { name, "IN4L", "IN4L PGA" }, \
621  { name, "IN4R", "IN4R PGA" }, \
622  { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
623  { name, "AIF1RX1", "AIF1RX1" }, \
624  { name, "AIF1RX2", "AIF1RX2" }, \
625  { name, "AIF1RX3", "AIF1RX3" }, \
626  { name, "AIF1RX4", "AIF1RX4" }, \
627  { name, "AIF1RX5", "AIF1RX5" }, \
628  { name, "AIF1RX6", "AIF1RX6" }, \
629  { name, "AIF1RX7", "AIF1RX7" }, \
630  { name, "AIF1RX8", "AIF1RX8" }, \
631  { name, "AIF2RX1", "AIF2RX1" }, \
632  { name, "AIF2RX2", "AIF2RX2" }, \
633  { name, "AIF3RX1", "AIF3RX1" }, \
634  { name, "AIF3RX2", "AIF3RX2" }, \
635  { name, "EQ1", "EQ1" }, \
636  { name, "EQ2", "EQ2" }, \
637  { name, "EQ3", "EQ3" }, \
638  { name, "EQ4", "EQ4" }, \
639  { name, "DRC1L", "DRC1L" }, \
640  { name, "DRC1R", "DRC1R" }, \
641  { name, "DRC2L", "DRC2L" }, \
642  { name, "DRC2R", "DRC2R" }, \
643  { name, "LHPF1", "LHPF1" }, \
644  { name, "LHPF2", "LHPF2" }, \
645  { name, "LHPF3", "LHPF3" }, \
646  { name, "LHPF4", "LHPF4" }, \
647  { name, "ASRC1L", "ASRC1L" }, \
648  { name, "ASRC1R", "ASRC1R" }, \
649  { name, "ASRC2L", "ASRC2L" }, \
650  { name, "ASRC2R", "ASRC2R" }
651 
652 static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
653  { "AIF2 Capture", NULL, "DBVDD2" },
654  { "AIF2 Playback", NULL, "DBVDD2" },
655 
656  { "AIF3 Capture", NULL, "DBVDD3" },
657  { "AIF3 Playback", NULL, "DBVDD3" },
658 
659  { "OUT1L", NULL, "CPVDD" },
660  { "OUT1R", NULL, "CPVDD" },
661  { "OUT2L", NULL, "CPVDD" },
662  { "OUT2R", NULL, "CPVDD" },
663  { "OUT3L", NULL, "CPVDD" },
664  { "OUT3R", NULL, "CPVDD" },
665 
666  { "OUT4L", NULL, "SPKVDDL" },
667  { "OUT4R", NULL, "SPKVDDR" },
668 
669  { "OUT1L", NULL, "SYSCLK" },
670  { "OUT1R", NULL, "SYSCLK" },
671  { "OUT2L", NULL, "SYSCLK" },
672  { "OUT2R", NULL, "SYSCLK" },
673  { "OUT3L", NULL, "SYSCLK" },
674  { "OUT4L", NULL, "SYSCLK" },
675  { "OUT4R", NULL, "SYSCLK" },
676  { "OUT5L", NULL, "SYSCLK" },
677  { "OUT5R", NULL, "SYSCLK" },
678  { "OUT6L", NULL, "SYSCLK" },
679  { "OUT6R", NULL, "SYSCLK" },
680 
681  { "MICBIAS1", NULL, "MICVDD" },
682  { "MICBIAS2", NULL, "MICVDD" },
683  { "MICBIAS3", NULL, "MICVDD" },
684 
685  { "Noise Generator", NULL, "NOISE" },
686  { "Tone Generator 1", NULL, "TONE" },
687  { "Tone Generator 2", NULL, "TONE" },
688 
689  { "Mic Mute Mixer", NULL, "Noise Mixer" },
690  { "Mic Mute Mixer", NULL, "Mic Mixer" },
691 
692  { "AIF1 Capture", NULL, "AIF1TX1" },
693  { "AIF1 Capture", NULL, "AIF1TX2" },
694  { "AIF1 Capture", NULL, "AIF1TX3" },
695  { "AIF1 Capture", NULL, "AIF1TX4" },
696  { "AIF1 Capture", NULL, "AIF1TX5" },
697  { "AIF1 Capture", NULL, "AIF1TX6" },
698  { "AIF1 Capture", NULL, "AIF1TX7" },
699  { "AIF1 Capture", NULL, "AIF1TX8" },
700 
701  { "AIF1RX1", NULL, "AIF1 Playback" },
702  { "AIF1RX2", NULL, "AIF1 Playback" },
703  { "AIF1RX3", NULL, "AIF1 Playback" },
704  { "AIF1RX4", NULL, "AIF1 Playback" },
705  { "AIF1RX5", NULL, "AIF1 Playback" },
706  { "AIF1RX6", NULL, "AIF1 Playback" },
707  { "AIF1RX7", NULL, "AIF1 Playback" },
708  { "AIF1RX8", NULL, "AIF1 Playback" },
709 
710  { "AIF2 Capture", NULL, "AIF2TX1" },
711  { "AIF2 Capture", NULL, "AIF2TX2" },
712 
713  { "AIF2RX1", NULL, "AIF2 Playback" },
714  { "AIF2RX2", NULL, "AIF2 Playback" },
715 
716  { "AIF3 Capture", NULL, "AIF3TX1" },
717  { "AIF3 Capture", NULL, "AIF3TX2" },
718 
719  { "AIF3RX1", NULL, "AIF3 Playback" },
720  { "AIF3RX2", NULL, "AIF3 Playback" },
721 
722  { "AIF1 Playback", NULL, "SYSCLK" },
723  { "AIF2 Playback", NULL, "SYSCLK" },
724  { "AIF3 Playback", NULL, "SYSCLK" },
725 
726  { "AIF1 Capture", NULL, "SYSCLK" },
727  { "AIF2 Capture", NULL, "SYSCLK" },
728  { "AIF3 Capture", NULL, "SYSCLK" },
729 
730  { "IN1L PGA", NULL, "IN1L" },
731  { "IN1R PGA", NULL, "IN1R" },
732 
733  { "IN2L PGA", NULL, "IN2L" },
734  { "IN2R PGA", NULL, "IN2R" },
735 
736  { "IN3L PGA", NULL, "IN3L" },
737  { "IN3R PGA", NULL, "IN3R" },
738 
739  { "IN4L PGA", NULL, "IN4L" },
740  { "IN4R PGA", NULL, "IN4R" },
741 
742  ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
743  ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
744  ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
745  ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
746  ARIZONA_MIXER_ROUTES("OUT3L", "HPOUT3L"),
747  ARIZONA_MIXER_ROUTES("OUT3R", "HPOUT3R"),
748 
749  ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
750  ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
751  ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
752  ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
753  ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
754  ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
755 
756  ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
757  ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
758 
759  ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
760  ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
761  ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
762  ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
763  ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
764  ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
765  ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
766  ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
767 
768  ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
769  ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
770 
771  ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
772  ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
773 
774  ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
775  ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
776  ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
777  ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
778 
779  ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
780  ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
781  ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
782  ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
783 
784  ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
785  ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
786  ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
787  ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
788 
789  ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
790  ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
791  ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
792  ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
793 
794  { "HPOUT1L", NULL, "OUT1L" },
795  { "HPOUT1R", NULL, "OUT1R" },
796 
797  { "HPOUT2L", NULL, "OUT2L" },
798  { "HPOUT2R", NULL, "OUT2R" },
799 
800  { "HPOUT3L", NULL, "OUT3L" },
801  { "HPOUT3R", NULL, "OUT3L" },
802 
803  { "SPKOUTLN", NULL, "OUT4L" },
804  { "SPKOUTLP", NULL, "OUT4L" },
805 
806  { "SPKOUTRN", NULL, "OUT4R" },
807  { "SPKOUTRP", NULL, "OUT4R" },
808 
809  { "SPKDAT1L", NULL, "OUT5L" },
810  { "SPKDAT1R", NULL, "OUT5R" },
811 
812  { "SPKDAT2L", NULL, "OUT6L" },
813  { "SPKDAT2R", NULL, "OUT6R" },
814 };
815 
816 static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
817  unsigned int Fref, unsigned int Fout)
818 {
819  struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec);
820 
821  switch (fll_id) {
822  case WM5110_FLL1:
823  return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
824  case WM5110_FLL2:
825  return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
826  default:
827  return -EINVAL;
828  }
829 }
830 
831 #define WM5110_RATES SNDRV_PCM_RATE_8000_192000
832 
833 #define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
834  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
835 
836 static struct snd_soc_dai_driver wm5110_dai[] = {
837  {
838  .name = "wm5110-aif1",
839  .id = 1,
840  .base = ARIZONA_AIF1_BCLK_CTRL,
841  .playback = {
842  .stream_name = "AIF1 Playback",
843  .channels_min = 1,
844  .channels_max = 8,
845  .rates = WM5110_RATES,
846  .formats = WM5110_FORMATS,
847  },
848  .capture = {
849  .stream_name = "AIF1 Capture",
850  .channels_min = 1,
851  .channels_max = 8,
852  .rates = WM5110_RATES,
853  .formats = WM5110_FORMATS,
854  },
855  .ops = &arizona_dai_ops,
856  .symmetric_rates = 1,
857  },
858  {
859  .name = "wm5110-aif2",
860  .id = 2,
861  .base = ARIZONA_AIF2_BCLK_CTRL,
862  .playback = {
863  .stream_name = "AIF2 Playback",
864  .channels_min = 1,
865  .channels_max = 2,
866  .rates = WM5110_RATES,
867  .formats = WM5110_FORMATS,
868  },
869  .capture = {
870  .stream_name = "AIF2 Capture",
871  .channels_min = 1,
872  .channels_max = 2,
873  .rates = WM5110_RATES,
874  .formats = WM5110_FORMATS,
875  },
876  .ops = &arizona_dai_ops,
877  .symmetric_rates = 1,
878  },
879  {
880  .name = "wm5110-aif3",
881  .id = 3,
882  .base = ARIZONA_AIF3_BCLK_CTRL,
883  .playback = {
884  .stream_name = "AIF3 Playback",
885  .channels_min = 1,
886  .channels_max = 2,
887  .rates = WM5110_RATES,
888  .formats = WM5110_FORMATS,
889  },
890  .capture = {
891  .stream_name = "AIF3 Capture",
892  .channels_min = 1,
893  .channels_max = 2,
894  .rates = WM5110_RATES,
895  .formats = WM5110_FORMATS,
896  },
897  .ops = &arizona_dai_ops,
898  .symmetric_rates = 1,
899  },
900 };
901 
902 static int wm5110_codec_probe(struct snd_soc_codec *codec)
903 {
904  struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
905 
906  codec->control_data = priv->core.arizona->regmap;
907  return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
908 }
909 
910 #define WM5110_DIG_VU 0x0200
911 
912 static unsigned int wm5110_digital_vu[] = {
921 
934 };
935 
936 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
937  .probe = wm5110_codec_probe,
938 
939  .idle_bias_off = true,
940 
941  .set_sysclk = arizona_set_sysclk,
942  .set_pll = wm5110_set_fll,
943 
944  .controls = wm5110_snd_controls,
945  .num_controls = ARRAY_SIZE(wm5110_snd_controls),
946  .dapm_widgets = wm5110_dapm_widgets,
947  .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets),
948  .dapm_routes = wm5110_dapm_routes,
949  .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
950 };
951 
952 static int __devinit wm5110_probe(struct platform_device *pdev)
953 {
954  struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
955  struct wm5110_priv *wm5110;
956  int i;
957 
958  wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv),
959  GFP_KERNEL);
960  if (wm5110 == NULL)
961  return -ENOMEM;
962  platform_set_drvdata(pdev, wm5110);
963 
964  wm5110->core.arizona = arizona;
965 
966  for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
967  wm5110->fll[i].vco_mult = 3;
968 
971  &wm5110->fll[0]);
974  &wm5110->fll[1]);
975 
976  for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++)
977  arizona_init_dai(&wm5110->core, i);
978 
979  /* Latch volume update bits */
980  for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++)
981  regmap_update_bits(arizona->regmap, wm5110_digital_vu[i],
983 
984  pm_runtime_enable(&pdev->dev);
985  pm_runtime_idle(&pdev->dev);
986 
987  return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
988  wm5110_dai, ARRAY_SIZE(wm5110_dai));
989 }
990 
991 static int __devexit wm5110_remove(struct platform_device *pdev)
992 {
994  pm_runtime_disable(&pdev->dev);
995 
996  return 0;
997 }
998 
999 static struct platform_driver wm5110_codec_driver = {
1000  .driver = {
1001  .name = "wm5110-codec",
1002  .owner = THIS_MODULE,
1003  },
1004  .probe = wm5110_probe,
1005  .remove = __devexit_p(wm5110_remove),
1006 };
1007 
1008 module_platform_driver(wm5110_codec_driver);
1009 
1010 MODULE_DESCRIPTION("ASoC WM5110 driver");
1011 MODULE_AUTHOR("Mark Brown <[email protected]>");
1012 MODULE_LICENSE("GPL");
1013 MODULE_ALIAS("platform:wm5110-codec");