19 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/device.h>
39 unsigned int reg,
unsigned int val);
45 static const u16 wm9713_reg[] = {
46 0x6174, 0x8080, 0x8080, 0x8080,
47 0xc880, 0xe808, 0xe808, 0x0808,
48 0x00da, 0x8000, 0xd600, 0xaaa0,
49 0xaaa0, 0xaaa0, 0x0000, 0x0000,
50 0x0f0f, 0x0040, 0x0000, 0x7f00,
51 0x0405, 0x0410, 0xbb80, 0xbb80,
52 0x0000, 0xbb80, 0x0000, 0x4523,
53 0x0000, 0x2000, 0x7eff, 0xffff,
54 0x0000, 0x0000, 0x0080, 0x0000,
55 0x0000, 0x0000, 0xfffe, 0xffff,
56 0x0000, 0x0000, 0x0000, 0xfffe,
57 0x4000, 0x0000, 0x0000, 0x0000,
58 0xb032, 0x3e00, 0x0000, 0x0000,
59 0x0000, 0x0000, 0x0000, 0x0000,
60 0x0000, 0x0000, 0x0000, 0x0006,
61 0x0001, 0x0000, 0x574d, 0x4c13,
62 0x0000, 0x0000, 0x0000
66 #define HPL_MIXER 0x80
67 #define HPR_MIXER 0x82
70 static const char *wm9713_mic_mixer[] = {
"Stereo",
"Mic 1",
"Mic 2",
"Mute"};
71 static const char *wm9713_rec_mux[] = {
"Stereo",
"Left",
"Right",
"Mute"};
72 static const char *wm9713_rec_src[] =
73 {
"Mic 1",
"Mic 2",
"Line",
"Mono In",
"Headphone",
"Speaker",
75 static const char *wm9713_rec_gain[] = {
"+1.5dB Steps",
"+0.75dB Steps"};
76 static const char *wm9713_alc_select[] = {
"None",
"Left",
"Right",
"Stereo"};
77 static const char *wm9713_mono_pga[] = {
"Vmid",
"Zh",
"Mono",
"Inv",
78 "Mono Vmid",
"Inv Vmid"};
79 static const char *wm9713_spk_pga[] =
80 {
"Vmid",
"Zh",
"Headphone",
"Speaker",
"Inv",
"Headphone Vmid",
81 "Speaker Vmid",
"Inv Vmid"};
82 static const char *wm9713_hp_pga[] = {
"Vmid",
"Zh",
"Headphone",
84 static const char *wm9713_out3_pga[] = {
"Vmid",
"Zh",
"Inv 1",
"Inv 1 Vmid"};
85 static const char *wm9713_out4_pga[] = {
"Vmid",
"Zh",
"Inv 2",
"Inv 2 Vmid"};
86 static const char *wm9713_dac_inv[] =
87 {
"Off",
"Mono",
"Speaker",
"Left Headphone",
"Right Headphone",
88 "Headphone Mono",
"NC",
"Vmid"};
89 static const char *wm9713_bass[] = {
"Linear Control",
"Adaptive Boost"};
90 static const char *wm9713_ng_type[] = {
"Constant Gain",
"Mute"};
91 static const char *wm9713_mic_select[] = {
"Mic 1",
"Mic 2 A",
"Mic 2 B"};
92 static const char *wm9713_micb_select[] = {
"MPB",
"MPA"};
94 static const struct soc_enum wm9713_enum[] = {
120 static unsigned int mic_tlv[] = {
143 SOC_ENUM(
"Capture Volume Steps", wm9713_enum[5]),
155 SOC_ENUM(
"ALC Function", wm9713_enum[6]),
160 SOC_ENUM(
"ALC NG Type", wm9713_enum[17]),
206 SOC_ENUM(
"Bass Control", wm9713_enum[16]),
260 if ((l & 0x1) || (r & 0x1))
265 if ((l & 0x2) || (r & 0x2))
270 if ((l & 0x4) || (r & 0x4))
275 if ((l & 0x8) || (r & 0x8))
280 if ((l & 0x10) || (r & 0x10))
285 if ((l & 0x20) || (r & 0x20))
401 &wm9713_hp_rec_mux_controls),
403 &wm9713_hp_mic_mux_controls),
405 &wm9713_mono_mic_mux_controls),
407 &wm9713_mono_mux_controls),
409 &wm9713_hp_spkl_mux_controls),
411 &wm9713_hp_spkr_mux_controls),
413 &wm9713_hpl_out_mux_controls),
415 &wm9713_hpr_out_mux_controls),
417 &wm9713_out3_mux_controls),
419 &wm9713_out4_mux_controls),
421 &wm9713_dac_inv1_mux_controls),
423 &wm9713_dac_inv2_mux_controls),
425 &wm9713_rec_srcl_mux_controls),
427 &wm9713_rec_srcr_mux_controls),
429 &wm9713_mic_sel_mux_controls),
431 &wm9713_micb_sel_mux_controls),
433 &wm9713_hpl_mixer_controls[0],
ARRAY_SIZE(wm9713_hpl_mixer_controls),
436 &wm9713_hpr_mixer_controls[0],
ARRAY_SIZE(wm9713_hpr_mixer_controls),
439 &wm9713_mono_mixer_controls[0],
ARRAY_SIZE(wm9713_mono_mixer_controls)),
441 &wm9713_speaker_mixer_controls[0],
492 {
"Left HP Mixer",
"Beep Playback Switch",
"PCBEEP"},
493 {
"Left HP Mixer",
"Voice Playback Switch",
"Voice DAC"},
494 {
"Left HP Mixer",
"Aux Playback Switch",
"Aux DAC"},
495 {
"Left HP Mixer",
"Bypass Playback Switch",
"Left Line In"},
496 {
"Left HP Mixer",
"PCM Playback Switch",
"Left DAC"},
497 {
"Left HP Mixer",
"MonoIn Playback Switch",
"Mono In"},
498 {
"Left HP Mixer",
NULL,
"Capture Headphone Mux"},
501 {
"Right HP Mixer",
"Beep Playback Switch",
"PCBEEP"},
502 {
"Right HP Mixer",
"Voice Playback Switch",
"Voice DAC"},
503 {
"Right HP Mixer",
"Aux Playback Switch",
"Aux DAC"},
504 {
"Right HP Mixer",
"Bypass Playback Switch",
"Right Line In"},
505 {
"Right HP Mixer",
"PCM Playback Switch",
"Right DAC"},
506 {
"Right HP Mixer",
"MonoIn Playback Switch",
"Mono In"},
507 {
"Right HP Mixer",
NULL,
"Capture Headphone Mux"},
510 {
"AC97 Mixer",
NULL,
"Left DAC"},
511 {
"AC97 Mixer",
NULL,
"Right DAC"},
512 {
"Line Mixer",
NULL,
"Right Line In"},
513 {
"Line Mixer",
NULL,
"Left Line In"},
514 {
"HP Mixer",
NULL,
"Left HP Mixer"},
515 {
"HP Mixer",
NULL,
"Right HP Mixer"},
516 {
"Capture Mixer",
NULL,
"Left Capture Source"},
517 {
"Capture Mixer",
NULL,
"Right Capture Source"},
520 {
"Speaker Mixer",
"Beep Playback Switch",
"PCBEEP"},
521 {
"Speaker Mixer",
"Voice Playback Switch",
"Voice DAC"},
522 {
"Speaker Mixer",
"Aux Playback Switch",
"Aux DAC"},
523 {
"Speaker Mixer",
"Bypass Playback Switch",
"Line Mixer"},
524 {
"Speaker Mixer",
"PCM Playback Switch",
"AC97 Mixer"},
525 {
"Speaker Mixer",
"MonoIn Playback Switch",
"Mono In"},
528 {
"Mono Mixer",
"Beep Playback Switch",
"PCBEEP"},
529 {
"Mono Mixer",
"Voice Playback Switch",
"Voice DAC"},
530 {
"Mono Mixer",
"Aux Playback Switch",
"Aux DAC"},
531 {
"Mono Mixer",
"Bypass Playback Switch",
"Line Mixer"},
532 {
"Mono Mixer",
"PCM Playback Switch",
"AC97 Mixer"},
533 {
"Mono Mixer",
"Mic 1 Sidetone Switch",
"Mic A PGA"},
534 {
"Mono Mixer",
"Mic 2 Sidetone Switch",
"Mic B PGA"},
535 {
"Mono Mixer",
NULL,
"Capture Mono Mux"},
538 {
"DAC Inv Mux 1",
"Mono",
"Mono Mixer"},
539 {
"DAC Inv Mux 1",
"Speaker",
"Speaker Mixer"},
540 {
"DAC Inv Mux 1",
"Left Headphone",
"Left HP Mixer"},
541 {
"DAC Inv Mux 1",
"Right Headphone",
"Right HP Mixer"},
542 {
"DAC Inv Mux 1",
"Headphone Mono",
"HP Mixer"},
545 {
"DAC Inv Mux 2",
"Mono",
"Mono Mixer"},
546 {
"DAC Inv Mux 2",
"Speaker",
"Speaker Mixer"},
547 {
"DAC Inv Mux 2",
"Left Headphone",
"Left HP Mixer"},
548 {
"DAC Inv Mux 2",
"Right Headphone",
"Right HP Mixer"},
549 {
"DAC Inv Mux 2",
"Headphone Mono",
"HP Mixer"},
552 {
"Left Headphone Out Mux",
"Headphone",
"Left HP Mixer"},
555 {
"Right Headphone Out Mux",
"Headphone",
"Right HP Mixer"},
558 {
"Left Speaker Out Mux",
"Headphone",
"Left HP Mixer"},
559 {
"Left Speaker Out Mux",
"Speaker",
"Speaker Mixer"},
560 {
"Left Speaker Out Mux",
"Inv",
"DAC Inv Mux 1"},
563 {
"Right Speaker Out Mux",
"Headphone",
"Right HP Mixer"},
564 {
"Right Speaker Out Mux",
"Speaker",
"Speaker Mixer"},
565 {
"Right Speaker Out Mux",
"Inv",
"DAC Inv Mux 2"},
568 {
"Mono Out Mux",
"Mono",
"Mono Mixer"},
569 {
"Mono Out Mux",
"Inv",
"DAC Inv Mux 1"},
572 {
"Out 3 Mux",
"Inv 1",
"DAC Inv Mux 1"},
575 {
"Out 4 Mux",
"Inv 2",
"DAC Inv Mux 2"},
578 {
"HPL",
NULL,
"Left Headphone"},
579 {
"Left Headphone",
NULL,
"Left Headphone Out Mux"},
580 {
"HPR",
NULL,
"Right Headphone"},
581 {
"Right Headphone",
NULL,
"Right Headphone Out Mux"},
582 {
"OUT3",
NULL,
"Out 3"},
583 {
"Out 3",
NULL,
"Out 3 Mux"},
584 {
"OUT4",
NULL,
"Out 4"},
585 {
"Out 4",
NULL,
"Out 4 Mux"},
586 {
"SPKL",
NULL,
"Left Speaker"},
587 {
"Left Speaker",
NULL,
"Left Speaker Out Mux"},
588 {
"SPKR",
NULL,
"Right Speaker"},
589 {
"Right Speaker",
NULL,
"Right Speaker Out Mux"},
590 {
"MONO",
NULL,
"Mono Out"},
591 {
"Mono Out",
NULL,
"Mono Out Mux"},
594 {
"Left Line In",
NULL,
"LINEL"},
595 {
"Right Line In",
NULL,
"LINER"},
596 {
"Mono In",
NULL,
"MONOIN"},
597 {
"Mic A PGA",
NULL,
"Mic A Pre Amp"},
598 {
"Mic B PGA",
NULL,
"Mic B Pre Amp"},
601 {
"Left Capture Source",
"Mic 1",
"Mic A Pre Amp"},
602 {
"Left Capture Source",
"Mic 2",
"Mic B Pre Amp"},
603 {
"Left Capture Source",
"Line",
"LINEL"},
604 {
"Left Capture Source",
"Mono In",
"MONOIN"},
605 {
"Left Capture Source",
"Headphone",
"Left HP Mixer"},
606 {
"Left Capture Source",
"Speaker",
"Speaker Mixer"},
607 {
"Left Capture Source",
"Mono Out",
"Mono Mixer"},
610 {
"Right Capture Source",
"Mic 1",
"Mic A Pre Amp"},
611 {
"Right Capture Source",
"Mic 2",
"Mic B Pre Amp"},
612 {
"Right Capture Source",
"Line",
"LINER"},
613 {
"Right Capture Source",
"Mono In",
"MONOIN"},
614 {
"Right Capture Source",
"Headphone",
"Right HP Mixer"},
615 {
"Right Capture Source",
"Speaker",
"Speaker Mixer"},
616 {
"Right Capture Source",
"Mono Out",
"Mono Mixer"},
619 {
"Left ADC",
NULL,
"Left Capture Source"},
620 {
"Left Voice ADC",
NULL,
"Left ADC"},
621 {
"Left HiFi ADC",
NULL,
"Left ADC"},
624 {
"Right ADC",
NULL,
"Right Capture Source"},
625 {
"Right Voice ADC",
NULL,
"Right ADC"},
626 {
"Right HiFi ADC",
NULL,
"Right ADC"},
629 {
"Mic A Pre Amp",
NULL,
"Mic A Source"},
630 {
"Mic A Source",
"Mic 1",
"MIC1"},
631 {
"Mic A Source",
"Mic 2 A",
"MIC2A"},
632 {
"Mic A Source",
"Mic 2 B",
"Mic B Source"},
633 {
"Mic B Pre Amp",
"MPB",
"Mic B Source"},
634 {
"Mic B Source",
NULL,
"MIC2B"},
637 {
"Capture Headphone Mux",
"Stereo",
"Capture Mixer"},
638 {
"Capture Headphone Mux",
"Left",
"Left Capture Source"},
639 {
"Capture Headphone Mux",
"Right",
"Right Capture Source"},
642 {
"Capture Mono Mux",
"Stereo",
"Capture Mixer"},
643 {
"Capture Mono Mux",
"Left",
"Left Capture Source"},
644 {
"Capture Mono Mux",
"Right",
"Right Capture Source"},
666 static int ac97_write(
struct snd_soc_codec *codec,
unsigned int reg,
690 #define FIXED_PLL_SIZE ((1 << 22) * 10)
695 unsigned int K, Ndiv, Nmod,
target;
701 if (source > 14400000) {
705 if (source > 14400000) {
719 if (source < 8192000) {
726 if ((Ndiv < 5) || (Ndiv > 12))
728 "WM9713 PLL N value %u out of recommended range!\n",
737 K = Kpart & 0xFFFFFFFF;
754 int pll_id,
unsigned int freq_in,
unsigned int freq_out)
756 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
783 reg = reg2 | (0x5 << 4) | (
pll_div.
k >> 20);
787 reg = reg2 | (0x4 << 4) | ((
pll_div.
k >> 16) & 0xf);
791 reg = reg2 | (0x3 << 4) | ((
pll_div.
k >> 12) & 0xf);
795 reg = reg2 | (0x2 << 4) | ((
pll_div.
k >> 8) & 0xf);
799 reg = reg2 | (0x1 << 4) | ((
pll_div.
k >> 4) & 0xf);
802 reg = reg2 | (0x0 << 4) | (
pll_div.
k & 0xf);
818 static int wm9713_set_dai_pll(
struct snd_soc_dai *codec_dai,
int pll_id,
819 int source,
unsigned int freq_in,
unsigned int freq_out)
822 return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
829 static int wm9713_set_dai_tristate(
struct snd_soc_dai *codec_dai,
845 static int wm9713_set_dai_clkdiv(
struct snd_soc_dai *codec_dai,
887 static int wm9713_set_dai_fmt(
struct snd_soc_dai *codec_dai,
991 return ac97_write(codec, reg, runtime->
rate);
1012 #define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
1013 SNDRV_PCM_RATE_11025 | \
1014 SNDRV_PCM_RATE_22050 | \
1015 SNDRV_PCM_RATE_44100 | \
1016 SNDRV_PCM_RATE_48000)
1018 #define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \
1019 SNDRV_PCM_RATE_11025 | \
1020 SNDRV_PCM_RATE_16000 | \
1021 SNDRV_PCM_RATE_22050 | \
1022 SNDRV_PCM_RATE_44100 | \
1023 SNDRV_PCM_RATE_48000)
1025 #define WM9713_PCM_FORMATS \
1026 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1027 SNDRV_PCM_FORMAT_S24_LE)
1030 .prepare = ac97_hifi_prepare,
1031 .set_clkdiv = wm9713_set_dai_clkdiv,
1032 .set_pll = wm9713_set_dai_pll,
1036 .prepare = ac97_aux_prepare,
1037 .set_clkdiv = wm9713_set_dai_clkdiv,
1038 .set_pll = wm9713_set_dai_pll,
1042 .hw_params = wm9713_pcm_hw_params,
1043 .set_clkdiv = wm9713_set_dai_clkdiv,
1044 .set_pll = wm9713_set_dai_pll,
1045 .set_fmt = wm9713_set_dai_fmt,
1046 .set_tristate = wm9713_set_dai_tristate,
1051 .name =
"wm9713-hifi",
1054 .stream_name =
"HiFi Playback",
1060 .stream_name =
"HiFi Capture",
1065 .ops = &wm9713_dai_ops_hifi,
1068 .name =
"wm9713-aux",
1070 .stream_name =
"Aux Playback",
1075 .ops = &wm9713_dai_ops_aux,
1078 .name =
"wm9713-voice",
1080 .stream_name =
"Voice Playback",
1086 .stream_name =
"Voice Capture",
1091 .ops = &wm9713_dai_ops_voice,
1092 .symmetric_rates = 1,
1100 if (ac97_read(codec, 0) == wm9713_reg[0])
1107 if (ac97_read(codec, 0) != wm9713_reg[0])
1113 static int wm9713_set_bias_level(
struct snd_soc_codec *codec,
1161 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1175 wm9713_set_pll(codec, 0, wm9713->
pll_in, 0);
1179 for (i = 2; i <
ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
1198 snd_soc_codec_set_drvdata(codec, wm9713);
1216 reg = ac97_read(codec,
AC97_CD) & 0x7fff;
1217 ac97_write(codec,
AC97_CD, reg);
1233 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1240 .probe = wm9713_soc_probe,
1241 .remove = wm9713_soc_remove,
1242 .suspend = wm9713_soc_suspend,
1243 .resume = wm9713_soc_resume,
1245 .write = ac97_write,
1246 .set_bias_level = wm9713_set_bias_level,
1248 .reg_word_size =
sizeof(
u16),
1253 .dapm_routes = wm9713_audio_map,
1254 .num_dapm_routes =
ARRAY_SIZE(wm9713_audio_map),
1260 &soc_codec_dev_wm9713, wm9713_dai,
ARRAY_SIZE(wm9713_dai));
1271 .name =
"wm9713-codec",
1275 .probe = wm9713_probe,