13 #include <linux/module.h>
15 #include <linux/kernel.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
31 0x0000, 0x0000, 0x0000, 0x0000,
32 0x0050, 0x0000, 0x0140, 0x0000,
33 0x0000, 0x0000, 0x0000, 0x00ff,
34 0x0000, 0x0000, 0x0100, 0x00ff,
35 0x0000, 0x0000, 0x012c, 0x002c,
36 0x002c, 0x002c, 0x002c, 0x0000,
37 0x0032, 0x0000, 0x0000, 0x0000,
38 0x0000, 0x0000, 0x0000, 0x0000,
39 0x0038, 0x000b, 0x0032, 0x0000,
40 0x0008, 0x000c, 0x0093, 0x00e9,
41 0x0000, 0x0000, 0x0000, 0x0000,
42 0x0003, 0x0010, 0x0000, 0x0000,
43 0x0000, 0x0002, 0x0000, 0x0000,
44 0x0000, 0x0000, 0x0039, 0x0000,
48 #define WM8974_POWER1_BIASEN 0x08
49 #define WM8974_POWER1_BUFIOEN 0x04
51 #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
53 static const char *wm8974_companding[] = {
"Off",
"NC",
"u-law",
"A-law" };
54 static const char *wm8974_deemp[] = {
"None",
"32kHz",
"44.1kHz",
"48kHz" };
55 static const char *wm8974_eqmode[] = {
"Capture",
"Playback" };
56 static const char *wm8974_bw[] = {
"Narrow",
"Wide" };
57 static const char *wm8974_eq1[] = {
"80Hz",
"105Hz",
"135Hz",
"175Hz" };
58 static const char *wm8974_eq2[] = {
"230Hz",
"300Hz",
"385Hz",
"500Hz" };
59 static const char *wm8974_eq3[] = {
"650Hz",
"850Hz",
"1.1kHz",
"1.4kHz" };
60 static const char *wm8974_eq4[] = {
"1.8kHz",
"2.4kHz",
"3.2kHz",
"4.1kHz" };
61 static const char *wm8974_eq5[] = {
"5.3kHz",
"6.9kHz",
"9kHz",
"11.7kHz" };
62 static const char *wm8974_alc[] = {
"ALC",
"Limiter" };
64 static const struct soc_enum wm8974_enum[] = {
84 static const char *wm8974_auxmode_text[] = {
"Buffer",
"Mixer" };
86 static const struct soc_enum wm8974_auxmode =
98 SOC_ENUM(
"DAC Companding", wm8974_enum[1]),
99 SOC_ENUM(
"ADC Companding", wm8974_enum[0]),
101 SOC_ENUM(
"Playback De-emphasis", wm8974_enum[2]),
112 SOC_ENUM(
"Equaliser Function", wm8974_enum[3]),
113 SOC_ENUM(
"EQ1 Cut Off", wm8974_enum[4]),
116 SOC_ENUM(
"Equaliser EQ2 Bandwith", wm8974_enum[5]),
117 SOC_ENUM(
"EQ2 Cut Off", wm8974_enum[6]),
120 SOC_ENUM(
"Equaliser EQ3 Bandwith", wm8974_enum[7]),
121 SOC_ENUM(
"EQ3 Cut Off", wm8974_enum[8]),
124 SOC_ENUM(
"Equaliser EQ4 Bandwith", wm8974_enum[9]),
125 SOC_ENUM(
"EQ4 Cut Off", wm8974_enum[10]),
128 SOC_ENUM(
"Equaliser EQ5 Bandwith", wm8974_enum[11]),
129 SOC_ENUM(
"EQ5 Cut Off", wm8974_enum[12]),
147 SOC_ENUM(
"ALC Capture Mode", wm8974_enum[13]),
161 SOC_ENUM(
"Aux Mode", wm8974_auxmode),
207 &wm8974_speaker_mixer_controls[0],
210 &wm8974_mono_mixer_controls[0],
222 wm8974_boost_mixer,
ARRAY_SIZE(wm8974_boost_mixer)),
236 {
"Mono Mixer",
"PCM Playback Switch",
"DAC"},
237 {
"Mono Mixer",
"Aux Playback Switch",
"Aux Input"},
238 {
"Mono Mixer",
"Line Bypass Switch",
"Boost Mixer"},
241 {
"Speaker Mixer",
"PCM Playback Switch",
"DAC"},
242 {
"Speaker Mixer",
"Aux Playback Switch",
"Aux Input"},
243 {
"Speaker Mixer",
"Line Bypass Switch",
"Boost Mixer"},
246 {
"Mono Out",
NULL,
"Mono Mixer"},
247 {
"MONOOUT",
NULL,
"Mono Out"},
248 {
"SpkN Out",
NULL,
"Speaker Mixer"},
249 {
"SpkP Out",
NULL,
"Speaker Mixer"},
250 {
"SPKOUTN",
NULL,
"SpkN Out"},
251 {
"SPKOUTP",
NULL,
"SpkP Out"},
254 {
"ADC",
NULL,
"Boost Mixer"},
255 {
"Boost Mixer",
"Aux Switch",
"Aux Input"},
256 {
"Boost Mixer",
NULL,
"Input PGA"},
257 {
"Boost Mixer",
NULL,
"MICP"},
260 {
"Input PGA",
"Aux Switch",
"Aux Input"},
261 {
"Input PGA",
"MicN Switch",
"MICN"},
262 {
"Input PGA",
"MicP Switch",
"MICP"},
265 {
"Aux Input",
NULL,
"AUX"},
276 #define FIXED_PLL_SIZE ((1 << 24) * 10)
281 unsigned long long Kpart;
282 unsigned int K, Ndiv, Nmod;
295 if ((Ndiv < 6) || (Ndiv > 12))
297 "WM8974 N value %u outwith recommended range!\n",
306 K = Kpart & 0xFFFFFFFF;
318 static int wm8974_set_dai_pll(
struct snd_soc_dai *codec_dai,
int pll_id,
319 int source,
unsigned int freq_in,
unsigned int freq_out)
325 if (freq_in == 0 || freq_out == 0) {
355 static int wm8974_set_dai_clkdiv(
struct snd_soc_dai *codec_dai,
381 static int wm8974_set_dai_fmt(
struct snd_soc_dai *codec_dai,
501 static int wm8974_set_bias_level(
struct snd_soc_codec *codec,
539 #define WM8974_RATES (SNDRV_PCM_RATE_8000_48000)
541 #define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
542 SNDRV_PCM_FMTBIT_S24_LE)
545 .hw_params = wm8974_pcm_hw_params,
546 .digital_mute = wm8974_mute,
547 .set_fmt = wm8974_set_dai_fmt,
548 .set_clkdiv = wm8974_set_dai_clkdiv,
549 .set_pll = wm8974_set_dai_pll,
553 .name =
"wm8974-hifi",
555 .stream_name =
"Playback",
561 .stream_name =
"Capture",
567 .symmetric_rates = 1,
588 dev_err(codec->
dev,
"Failed to set cache I/O: %d\n", ret);
594 dev_err(codec->
dev,
"Failed to issue reset\n");
611 .probe = wm8974_probe,
612 .remove = wm8974_remove,
613 .suspend = wm8974_suspend,
614 .resume = wm8974_resume,
615 .set_bias_level = wm8974_set_bias_level,
617 .reg_word_size =
sizeof(
u16),
622 .dapm_widgets = wm8974_dapm_widgets,
623 .num_dapm_widgets =
ARRAY_SIZE(wm8974_dapm_widgets),
624 .dapm_routes = wm8974_dapm_routes,
625 .num_dapm_routes =
ARRAY_SIZE(wm8974_dapm_routes),
634 &soc_codec_dev_wm8974, &wm8974_dai, 1);
652 static struct i2c_driver wm8974_i2c_driver = {
657 .probe = wm8974_i2c_probe,
659 .id_table = wm8974_i2c_id,