Diff markup
1 /* 1 /*
2 * wm9712.c -- ALSA Soc WM9712 codec support 2 * wm9712.c -- ALSA Soc WM9712 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or l 6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 7 *
8 * This program is free software; you can red 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Publ 9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history 13 * Revision history
14 * 4th Feb 2006 Initial version. 14 * 4th Feb 2006 Initial version.
15 */ 15 */
16 16
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/module.h> 18 #include <linux/module.h>
19 #include <linux/version.h> 19 #include <linux/version.h>
20 #include <linux/kernel.h> 20 #include <linux/kernel.h>
21 #include <linux/device.h> 21 #include <linux/device.h>
22 #include <sound/core.h> 22 #include <sound/core.h>
23 #include <sound/pcm.h> 23 #include <sound/pcm.h>
24 #include <sound/ac97_codec.h> 24 #include <sound/ac97_codec.h>
25 #include <sound/initval.h> 25 #include <sound/initval.h>
26 #include <sound/soc.h> 26 #include <sound/soc.h>
27 #include <sound/soc-dapm.h> 27 #include <sound/soc-dapm.h>
28 28
29 #define WM9712_VERSION "0.4" 29 #define WM9712_VERSION "0.4"
30 30
31 static unsigned int ac97_read(struct snd_soc_c 31 static unsigned int ac97_read(struct snd_soc_codec *codec,
32 unsigned int reg); 32 unsigned int reg);
33 static int ac97_write(struct snd_soc_codec *co 33 static int ac97_write(struct snd_soc_codec *codec,
34 unsigned int reg, unsigned int val); 34 unsigned int reg, unsigned int val);
35 35
36 /* 36 /*
37 * WM9712 register cache 37 * WM9712 register cache
38 */ 38 */
39 static const u16 wm9712_reg[] = { 39 static const u16 wm9712_reg[] = {
40 0x6174, 0x8000, 0x8000, 0x8000, // 6 40 0x6174, 0x8000, 0x8000, 0x8000, // 6
41 0x0f0f, 0xaaa0, 0xc008, 0x6808, // e 41 0x0f0f, 0xaaa0, 0xc008, 0x6808, // e
42 0xe808, 0xaaa0, 0xad00, 0x8000, // 16 42 0xe808, 0xaaa0, 0xad00, 0x8000, // 16
43 0xe808, 0x3000, 0x8000, 0x0000, // 1e 43 0xe808, 0x3000, 0x8000, 0x0000, // 1e
44 0x0000, 0x0000, 0x0000, 0x000f, // 26 44 0x0000, 0x0000, 0x0000, 0x000f, // 26
45 0x0405, 0x0410, 0xbb80, 0xbb80, // 2e 45 0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
46 0x0000, 0xbb80, 0x0000, 0x0000, // 36 46 0x0000, 0xbb80, 0x0000, 0x0000, // 36
47 0x0000, 0x2000, 0x0000, 0x0000, // 3e 47 0x0000, 0x2000, 0x0000, 0x0000, // 3e
48 0x0000, 0x0000, 0x0000, 0x0000, // 46 48 0x0000, 0x0000, 0x0000, 0x0000, // 46
49 0x0000, 0x0000, 0xf83e, 0xffff, // 4e 49 0x0000, 0x0000, 0xf83e, 0xffff, // 4e
50 0x0000, 0x0000, 0x0000, 0xf83e, // 56 50 0x0000, 0x0000, 0x0000, 0xf83e, // 56
51 0x0008, 0x0000, 0x0000, 0x0000, // 5e 51 0x0008, 0x0000, 0x0000, 0x0000, // 5e
52 0xb032, 0x3e00, 0x0000, 0x0000, // 66 52 0xb032, 0x3e00, 0x0000, 0x0000, // 66
53 0x0000, 0x0000, 0x0000, 0x0000, // 6e 53 0x0000, 0x0000, 0x0000, 0x0000, // 6e
54 0x0000, 0x0000, 0x0000, 0x0006, // 76 54 0x0000, 0x0000, 0x0000, 0x0006, // 76
55 0x0001, 0x0000, 0x574d, 0x4c12, // 7e 55 0x0001, 0x0000, 0x574d, 0x4c12, // 7e
56 0x0000, 0x0000 // virtual hp mixers 56 0x0000, 0x0000 // virtual hp mixers
57 }; 57 };
58 58
59 /* virtual HP mixers regs */ 59 /* virtual HP mixers regs */
60 #define HPL_MIXER 0x80 60 #define HPL_MIXER 0x80
61 #define HPR_MIXER 0x82 61 #define HPR_MIXER 0x82
62 62
63 static const char *wm9712_alc_select[] = {"Non 63 static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"};
64 static const char *wm9712_alc_mux[] = {"Stereo 64 static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"};
65 static const char *wm9712_out3_src[] = {"Left" 65 static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right",
66 "Mono"}; 66 "Mono"};
67 static const char *wm9712_spk_src[] = {"Speake 67 static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"};
68 static const char *wm9712_rec_adc[] = {"Stereo 68 static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
69 static const char *wm9712_base[] = {"Linear Co 69 static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"};
70 static const char *wm9712_rec_gain[] = {"+1.5d 70 static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
71 static const char *wm9712_mic[] = {"Mic 1", "D 71 static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2",
72 "Stereo"}; 72 "Stereo"};
73 static const char *wm9712_rec_sel[] = {"Mic", 73 static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
74 "Line", "Headphone Mixer", "Phone Mixe 74 "Line", "Headphone Mixer", "Phone Mixer", "Phone"};
75 static const char *wm9712_ng_type[] = {"Consta 75 static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
76 static const char *wm9712_diff_sel[] = {"Mic", 76 static const char *wm9712_diff_sel[] = {"Mic", "Line"};
77 77
78 static const struct soc_enum wm9712_enum[] = { 78 static const struct soc_enum wm9712_enum[] = {
79 SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_a 79 SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
80 SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_ 80 SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
81 SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_sr 81 SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src),
82 SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src 82 SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src),
83 SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_re 83 SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc),
84 SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm971 84 SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base),
85 SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm971 85 SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain),
86 SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic), 86 SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic),
87 SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec 87 SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel),
88 SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec 88 SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel),
89 SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng 89 SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type),
90 SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel), 90 SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel),
91 }; 91 };
92 92
93 static const struct snd_kcontrol_new wm9712_sn 93 static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
94 SOC_DOUBLE("Speaker Playback Volume", AC97_MAS 94 SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
95 SOC_SINGLE("Speaker Playback Switch", AC97_MAS 95 SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
96 SOC_DOUBLE("Headphone Playback Volume", AC97_H 96 SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
97 SOC_SINGLE("Headphone Playback Switch", AC97_H 97 SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
98 SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 98 SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
99 99
100 SOC_SINGLE("Speaker Playback ZC Switch", AC97_ 100 SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
101 SOC_SINGLE("Speaker Playback Invert Switch", A 101 SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),
102 SOC_SINGLE("Headphone Playback ZC Switch", AC9 102 SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0),
103 SOC_SINGLE("Mono Playback ZC Switch", AC97_MAS 103 SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
104 SOC_SINGLE("Mono Playback Volume", AC97_MASTER 104 SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1),
105 SOC_SINGLE("Mono Playback Switch", AC97_MASTER 105 SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
106 106
107 SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLA 107 SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
108 SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_R 108 SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
109 SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_ 109 SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
110 SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS 110 SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
111 SOC_ENUM("ALC Function", wm9712_enum[0]), 111 SOC_ENUM("ALC Function", wm9712_enum[0]),
112 SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11 112 SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
113 SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 113 SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
114 SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 114 SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
115 SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 115 SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
116 SOC_ENUM("ALC NG Type", wm9712_enum[10]), 116 SOC_ENUM("ALC NG Type", wm9712_enum[10]),
117 SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 117 SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
118 118
119 SOC_SINGLE("Mic Headphone Volume", AC97_VIDEO 119 SOC_SINGLE("Mic Headphone Volume", AC97_VIDEO, 12, 7, 1),
120 SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 120 SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
121 121
122 SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1), 122 SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
123 SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1 123 SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
124 SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1), 124 SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
125 125
126 SOC_SINGLE("PCBeep Bypass Headphone Volume", A 126 SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
127 SOC_SINGLE("PCBeep Bypass Speaker Volume", AC9 127 SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1),
128 SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_ 128 SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1),
129 129
130 SOC_SINGLE("Aux Playback Headphone Volume", AC 130 SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1),
131 SOC_SINGLE("Aux Playback Speaker Volume", AC97 131 SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1),
132 SOC_SINGLE("Aux Playback Phone Volume", AC97_C 132 SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1),
133 133
134 SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 134 SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1),
135 SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8 135 SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1),
136 136
137 SOC_SINGLE("Capture 20dB Boost Switch", AC97_R 137 SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
138 SOC_SINGLE("Capture to Phone 20dB Boost Switch 138 SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
139 139
140 SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_ 140 SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
141 SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_ 141 SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
142 SOC_SINGLE("3D Playback Volume", AC97_3D_CONTR 142 SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0),
143 143
144 SOC_ENUM("Bass Control", wm9712_enum[5]), 144 SOC_ENUM("Bass Control", wm9712_enum[5]),
145 SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_ 145 SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
146 SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_ 146 SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
147 SOC_SINGLE("Playback Attenuate (-6dB) Switch", 147 SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
148 SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 148 SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1),
149 SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 149 SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1),
150 150
151 SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN 151 SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
152 SOC_ENUM("Capture Volume Steps", wm9712_enum[6 152 SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
153 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 153 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
154 SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 154 SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
155 155
156 SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1) 156 SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
157 SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1) 157 SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
158 SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 158 SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
159 }; 159 };
160 160
161 /* add non dapm controls */ 161 /* add non dapm controls */
162 static int wm9712_add_controls(struct snd_soc_ 162 static int wm9712_add_controls(struct snd_soc_codec *codec)
163 { 163 {
164 int err, i; 164 int err, i;
165 165
166 for (i = 0; i < ARRAY_SIZE(wm9712_snd_ 166 for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
167 err = snd_ctl_add(codec->card, 167 err = snd_ctl_add(codec->card,
168 snd_soc_cnew(& 168 snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
169 if (err < 0) 169 if (err < 0)
170 return err; 170 return err;
171 } 171 }
172 return 0; 172 return 0;
173 } 173 }
174 174
175 /* We have to create a fake left and right HP 175 /* We have to create a fake left and right HP mixers because
176 * the codec only has a single control that is 176 * the codec only has a single control that is shared by both channels.
177 * This makes it impossible to determine the a 177 * This makes it impossible to determine the audio path.
178 */ 178 */
179 static int mixer_event(struct snd_soc_dapm_wid 179 static int mixer_event(struct snd_soc_dapm_widget *w,
180 struct snd_kcontrol *k, int event) 180 struct snd_kcontrol *k, int event)
181 { 181 {
182 u16 l, r, beep, line, phone, mic, pcm, 182 u16 l, r, beep, line, phone, mic, pcm, aux;
183 183
184 l = ac97_read(w->codec, HPL_MIXER); 184 l = ac97_read(w->codec, HPL_MIXER);
185 r = ac97_read(w->codec, HPR_MIXER); 185 r = ac97_read(w->codec, HPR_MIXER);
186 beep = ac97_read(w->codec, AC97_PC_BEE 186 beep = ac97_read(w->codec, AC97_PC_BEEP);
187 mic = ac97_read(w->codec, AC97_VIDEO); 187 mic = ac97_read(w->codec, AC97_VIDEO);
188 phone = ac97_read(w->codec, AC97_PHONE 188 phone = ac97_read(w->codec, AC97_PHONE);
189 line = ac97_read(w->codec, AC97_LINE); 189 line = ac97_read(w->codec, AC97_LINE);
190 pcm = ac97_read(w->codec, AC97_PCM); 190 pcm = ac97_read(w->codec, AC97_PCM);
191 aux = ac97_read(w->codec, AC97_CD); 191 aux = ac97_read(w->codec, AC97_CD);
192 192
193 if (l & 0x1 || r & 0x1) 193 if (l & 0x1 || r & 0x1)
194 ac97_write(w->codec, AC97_VIDE 194 ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff);
195 else 195 else
196 ac97_write(w->codec, AC97_VIDE 196 ac97_write(w->codec, AC97_VIDEO, mic | 0x8000);
197 197
198 if (l & 0x2 || r & 0x2) 198 if (l & 0x2 || r & 0x2)
199 ac97_write(w->codec, AC97_PCM, 199 ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
200 else 200 else
201 ac97_write(w->codec, AC97_PCM, 201 ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
202 202
203 if (l & 0x4 || r & 0x4) 203 if (l & 0x4 || r & 0x4)
204 ac97_write(w->codec, AC97_LINE 204 ac97_write(w->codec, AC97_LINE, line & 0x7fff);
205 else 205 else
206 ac97_write(w->codec, AC97_LINE 206 ac97_write(w->codec, AC97_LINE, line | 0x8000);
207 207
208 if (l & 0x8 || r & 0x8) 208 if (l & 0x8 || r & 0x8)
209 ac97_write(w->codec, AC97_PHON 209 ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
210 else 210 else
211 ac97_write(w->codec, AC97_PHON 211 ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
212 212
213 if (l & 0x10 || r & 0x10) 213 if (l & 0x10 || r & 0x10)
214 ac97_write(w->codec, AC97_CD, 214 ac97_write(w->codec, AC97_CD, aux & 0x7fff);
215 else 215 else
216 ac97_write(w->codec, AC97_CD, 216 ac97_write(w->codec, AC97_CD, aux | 0x8000);
217 217
218 if (l & 0x20 || r & 0x20) 218 if (l & 0x20 || r & 0x20)
219 ac97_write(w->codec, AC97_PC_B 219 ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
220 else 220 else
221 ac97_write(w->codec, AC97_PC_B 221 ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
222 222
223 return 0; 223 return 0;
224 } 224 }
225 225
226 /* Left Headphone Mixers */ 226 /* Left Headphone Mixers */
227 static const struct snd_kcontrol_new wm9712_hp 227 static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = {
228 SOC_DAPM_SINGLE("PCBeep Bypass Switch" 228 SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0),
229 SOC_DAPM_SINGLE("Aux Playback Switch", 229 SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0),
230 SOC_DAPM_SINGLE("Phone Bypass Switch", 230 SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0),
231 SOC_DAPM_SINGLE("Line Bypass Switch", 231 SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0),
232 SOC_DAPM_SINGLE("PCM Playback Switch", 232 SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0),
233 SOC_DAPM_SINGLE("Mic Sidetone Switch", 233 SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0),
234 }; 234 };
235 235
236 /* Right Headphone Mixers */ 236 /* Right Headphone Mixers */
237 static const struct snd_kcontrol_new wm9712_hp 237 static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = {
238 SOC_DAPM_SINGLE("PCBeep Bypass Switch" 238 SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0),
239 SOC_DAPM_SINGLE("Aux Playback Switch", 239 SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0),
240 SOC_DAPM_SINGLE("Phone Bypass Switch", 240 SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0),
241 SOC_DAPM_SINGLE("Line Bypass Switch", 241 SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0),
242 SOC_DAPM_SINGLE("PCM Playback Switch", 242 SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0),
243 SOC_DAPM_SINGLE("Mic Sidetone Switch", 243 SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0),
244 }; 244 };
245 245
246 /* Speaker Mixer */ 246 /* Speaker Mixer */
247 static const struct snd_kcontrol_new wm9712_sp 247 static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = {
248 SOC_DAPM_SINGLE("PCBeep Bypass Switch" 248 SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1),
249 SOC_DAPM_SINGLE("Aux Playback Switch", 249 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1),
250 SOC_DAPM_SINGLE("Phone Bypass Switch", 250 SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1),
251 SOC_DAPM_SINGLE("Line Bypass Switch", 251 SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1),
252 SOC_DAPM_SINGLE("PCM Playback Switch", 252 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1),
253 }; 253 };
254 254
255 /* Phone Mixer */ 255 /* Phone Mixer */
256 static const struct snd_kcontrol_new wm9712_ph 256 static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = {
257 SOC_DAPM_SINGLE("PCBeep Bypass Switch" 257 SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1),
258 SOC_DAPM_SINGLE("Aux Playback Switch", 258 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1),
259 SOC_DAPM_SINGLE("Line Bypass Switch", 259 SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1),
260 SOC_DAPM_SINGLE("PCM Playback Switch", 260 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1),
261 SOC_DAPM_SINGLE("Mic 1 Sidetone Switch 261 SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1),
262 SOC_DAPM_SINGLE("Mic 2 Sidetone Switch 262 SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1),
263 }; 263 };
264 264
265 /* ALC headphone mux */ 265 /* ALC headphone mux */
266 static const struct snd_kcontrol_new wm9712_al 266 static const struct snd_kcontrol_new wm9712_alc_mux_controls =
267 SOC_DAPM_ENUM("Route", wm9712_enum[1]); 267 SOC_DAPM_ENUM("Route", wm9712_enum[1]);
268 268
269 /* out 3 mux */ 269 /* out 3 mux */
270 static const struct snd_kcontrol_new wm9712_ou 270 static const struct snd_kcontrol_new wm9712_out3_mux_controls =
271 SOC_DAPM_ENUM("Route", wm9712_enum[2]); 271 SOC_DAPM_ENUM("Route", wm9712_enum[2]);
272 272
273 /* spk mux */ 273 /* spk mux */
274 static const struct snd_kcontrol_new wm9712_sp 274 static const struct snd_kcontrol_new wm9712_spk_mux_controls =
275 SOC_DAPM_ENUM("Route", wm9712_enum[3]); 275 SOC_DAPM_ENUM("Route", wm9712_enum[3]);
276 276
277 /* Capture to Phone mux */ 277 /* Capture to Phone mux */
278 static const struct snd_kcontrol_new wm9712_ca 278 static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls =
279 SOC_DAPM_ENUM("Route", wm9712_enum[4]); 279 SOC_DAPM_ENUM("Route", wm9712_enum[4]);
280 280
281 /* Capture left select */ 281 /* Capture left select */
282 static const struct snd_kcontrol_new wm9712_ca 282 static const struct snd_kcontrol_new wm9712_capture_selectl_controls =
283 SOC_DAPM_ENUM("Route", wm9712_enum[8]); 283 SOC_DAPM_ENUM("Route", wm9712_enum[8]);
284 284
285 /* Capture right select */ 285 /* Capture right select */
286 static const struct snd_kcontrol_new wm9712_ca 286 static const struct snd_kcontrol_new wm9712_capture_selectr_controls =
287 SOC_DAPM_ENUM("Route", wm9712_enum[9]); 287 SOC_DAPM_ENUM("Route", wm9712_enum[9]);
288 288
289 /* Mic select */ 289 /* Mic select */
290 static const struct snd_kcontrol_new wm9712_mi 290 static const struct snd_kcontrol_new wm9712_mic_src_controls =
291 SOC_DAPM_ENUM("Route", wm9712_enum[7]); 291 SOC_DAPM_ENUM("Route", wm9712_enum[7]);
292 292
293 /* diff select */ 293 /* diff select */
294 static const struct snd_kcontrol_new wm9712_di 294 static const struct snd_kcontrol_new wm9712_diff_sel_controls =
295 SOC_DAPM_ENUM("Route", wm9712_enum[11]); 295 SOC_DAPM_ENUM("Route", wm9712_enum[11]);
296 296
297 static const struct snd_soc_dapm_widget wm9712 297 static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = {
298 SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_N 298 SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0,
299 &wm9712_alc_mux_controls), 299 &wm9712_alc_mux_controls),
300 SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 300 SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0,
301 &wm9712_out3_mux_controls), 301 &wm9712_out3_mux_controls),
302 SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 302 SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0,
303 &wm9712_spk_mux_controls), 303 &wm9712_spk_mux_controls),
304 SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_ 304 SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0,
305 &wm9712_capture_phone_mux_controls), 305 &wm9712_capture_phone_mux_controls),
306 SND_SOC_DAPM_MUX("Left Capture Select", SND_SO 306 SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
307 &wm9712_capture_selectl_controls), 307 &wm9712_capture_selectl_controls),
308 SND_SOC_DAPM_MUX("Right Capture Select", SND_S 308 SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
309 &wm9712_capture_selectr_controls), 309 &wm9712_capture_selectr_controls),
310 SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_ 310 SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
311 &wm9712_mic_src_controls), 311 &wm9712_mic_src_controls),
312 SND_SOC_DAPM_MUX("Differential Source", SND_SO 312 SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
313 &wm9712_diff_sel_controls), 313 &wm9712_diff_sel_controls),
314 SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 314 SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
315 SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT 315 SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1,
316 &wm9712_hpl_mixer_controls[0], ARRAY_S 316 &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls),
317 mixer_event, SND_SOC_DAPM_POST_REG), 317 mixer_event, SND_SOC_DAPM_POST_REG),
318 SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_IN 318 SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1,
319 &wm9712_hpr_mixer_controls[0], ARRAY_S 319 &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls),
320 mixer_event, SND_SOC_DAPM_POST_REG), 320 mixer_event, SND_SOC_DAPM_POST_REG),
321 SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAG 321 SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1,
322 &wm9712_phone_mixer_controls[0], ARRAY 322 &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)),
323 SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_P 323 SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1,
324 &wm9712_speaker_mixer_controls[0], 324 &wm9712_speaker_mixer_controls[0],
325 ARRAY_SIZE(wm9712_speaker_mixer_contro 325 ARRAY_SIZE(wm9712_speaker_mixer_controls)),
326 SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 326 SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
327 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playba 327 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1),
328 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Play 328 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1),
329 SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SN 329 SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0),
330 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Captur 330 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1),
331 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capt 331 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1),
332 SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAG 332 SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0),
333 SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGIN 333 SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0),
334 SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 334 SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
335 SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 335 SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
336 SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 336 SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
337 SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0 337 SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
338 SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGI 338 SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
339 SND_SOC_DAPM_OUTPUT("MONOOUT"), 339 SND_SOC_DAPM_OUTPUT("MONOOUT"),
340 SND_SOC_DAPM_OUTPUT("HPOUTL"), 340 SND_SOC_DAPM_OUTPUT("HPOUTL"),
341 SND_SOC_DAPM_OUTPUT("HPOUTR"), 341 SND_SOC_DAPM_OUTPUT("HPOUTR"),
342 SND_SOC_DAPM_OUTPUT("LOUT2"), 342 SND_SOC_DAPM_OUTPUT("LOUT2"),
343 SND_SOC_DAPM_OUTPUT("ROUT2"), 343 SND_SOC_DAPM_OUTPUT("ROUT2"),
344 SND_SOC_DAPM_OUTPUT("OUT3"), 344 SND_SOC_DAPM_OUTPUT("OUT3"),
345 SND_SOC_DAPM_INPUT("LINEINL"), 345 SND_SOC_DAPM_INPUT("LINEINL"),
346 SND_SOC_DAPM_INPUT("LINEINR"), 346 SND_SOC_DAPM_INPUT("LINEINR"),
347 SND_SOC_DAPM_INPUT("PHONE"), 347 SND_SOC_DAPM_INPUT("PHONE"),
348 SND_SOC_DAPM_INPUT("PCBEEP"), 348 SND_SOC_DAPM_INPUT("PCBEEP"),
349 SND_SOC_DAPM_INPUT("MIC1"), 349 SND_SOC_DAPM_INPUT("MIC1"),
350 SND_SOC_DAPM_INPUT("MIC2"), 350 SND_SOC_DAPM_INPUT("MIC2"),
351 }; 351 };
352 352
353 static const char *audio_map[][3] = { 353 static const char *audio_map[][3] = {
354 /* virtual mixer - mixes left & right 354 /* virtual mixer - mixes left & right channels for spk and mono */
355 {"AC97 Mixer", NULL, "Left DAC"}, 355 {"AC97 Mixer", NULL, "Left DAC"},
356 {"AC97 Mixer", NULL, "Right DAC"}, 356 {"AC97 Mixer", NULL, "Right DAC"},
357 357
358 /* Left HP mixer */ 358 /* Left HP mixer */
359 {"Left HP Mixer", "PCBeep Bypass Switc 359 {"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
360 {"Left HP Mixer", "Aux Playback Switch 360 {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
361 {"Left HP Mixer", "Phone Bypass Switch 361 {"Left HP Mixer", "Phone Bypass Switch", "Phone PGA"},
362 {"Left HP Mixer", "Line Bypass Switch" 362 {"Left HP Mixer", "Line Bypass Switch", "Line PGA"},
363 {"Left HP Mixer", "PCM Playback Switch 363 {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
364 {"Left HP Mixer", "Mic Sidetone Switch 364 {"Left HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
365 {"Left HP Mixer", NULL, "ALC Sidetone 365 {"Left HP Mixer", NULL, "ALC Sidetone Mux"},
366 //{"Right HP Mixer", NULL, "HP Mixer"} 366 //{"Right HP Mixer", NULL, "HP Mixer"},
367 367
368 /* Right HP mixer */ 368 /* Right HP mixer */
369 {"Right HP Mixer", "PCBeep Bypass Swit 369 {"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
370 {"Right HP Mixer", "Aux Playback Switc 370 {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
371 {"Right HP Mixer", "Phone Bypass Switc 371 {"Right HP Mixer", "Phone Bypass Switch", "Phone PGA"},
372 {"Right HP Mixer", "Line Bypass Switch 372 {"Right HP Mixer", "Line Bypass Switch", "Line PGA"},
373 {"Right HP Mixer", "PCM Playback Switc 373 {"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
374 {"Right HP Mixer", "Mic Sidetone Switc 374 {"Right HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
375 {"Right HP Mixer", NULL, "ALC Sideton 375 {"Right HP Mixer", NULL, "ALC Sidetone Mux"},
376 376
377 /* speaker mixer */ 377 /* speaker mixer */
378 {"Speaker Mixer", "PCBeep Bypass Switc 378 {"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"},
379 {"Speaker Mixer", "Line Bypass Switch" 379 {"Speaker Mixer", "Line Bypass Switch", "Line PGA"},
380 {"Speaker Mixer", "PCM Playback Switch 380 {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
381 {"Speaker Mixer", "Phone Bypass Switch 381 {"Speaker Mixer", "Phone Bypass Switch", "Phone PGA"},
382 {"Speaker Mixer", "Aux Playback Switch 382 {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
383 383
384 /* Phone mixer */ 384 /* Phone mixer */
385 {"Phone Mixer", "PCBeep Bypass Switch" 385 {"Phone Mixer", "PCBeep Bypass Switch", "PCBEEP"},
386 {"Phone Mixer", "Line Bypass Switch", 386 {"Phone Mixer", "Line Bypass Switch", "Line PGA"},
387 {"Phone Mixer", "Aux Playback Switch", 387 {"Phone Mixer", "Aux Playback Switch", "Aux DAC"},
388 {"Phone Mixer", "PCM Playback Switch", 388 {"Phone Mixer", "PCM Playback Switch", "AC97 Mixer"},
389 {"Phone Mixer", "Mic 1 Sidetone Switch 389 {"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"},
390 {"Phone Mixer", "Mic 2 Sidetone Switch 390 {"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"},
391 391
392 /* inputs */ 392 /* inputs */
393 {"Line PGA", NULL, "LINEINL"}, 393 {"Line PGA", NULL, "LINEINL"},
394 {"Line PGA", NULL, "LINEINR"}, 394 {"Line PGA", NULL, "LINEINR"},
395 {"Phone PGA", NULL, "PHONE"}, 395 {"Phone PGA", NULL, "PHONE"},
396 {"Mic PGA", NULL, "MIC1"}, 396 {"Mic PGA", NULL, "MIC1"},
397 {"Mic PGA", NULL, "MIC2"}, 397 {"Mic PGA", NULL, "MIC2"},
398 398
399 /* left capture selector */ 399 /* left capture selector */
400 {"Left Capture Select", "Mic", "MIC1"} 400 {"Left Capture Select", "Mic", "MIC1"},
401 {"Left Capture Select", "Speaker Mixer 401 {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
402 {"Left Capture Select", "Line", "LINEI 402 {"Left Capture Select", "Line", "LINEINL"},
403 {"Left Capture Select", "Headphone Mix 403 {"Left Capture Select", "Headphone Mixer", "Left HP Mixer"},
404 {"Left Capture Select", "Phone Mixer", 404 {"Left Capture Select", "Phone Mixer", "Phone Mixer"},
405 {"Left Capture Select", "Phone", "PHON 405 {"Left Capture Select", "Phone", "PHONE"},
406 406
407 /* right capture selector */ 407 /* right capture selector */
408 {"Right Capture Select", "Mic", "MIC2" 408 {"Right Capture Select", "Mic", "MIC2"},
409 {"Right Capture Select", "Speaker Mixe 409 {"Right Capture Select", "Speaker Mixer", "Speaker Mixer"},
410 {"Right Capture Select", "Line", "LINE 410 {"Right Capture Select", "Line", "LINEINR"},
411 {"Right Capture Select", "Headphone Mi 411 {"Right Capture Select", "Headphone Mixer", "Right HP Mixer"},
412 {"Right Capture Select", "Phone Mixer" 412 {"Right Capture Select", "Phone Mixer", "Phone Mixer"},
413 {"Right Capture Select", "Phone", "PHO 413 {"Right Capture Select", "Phone", "PHONE"},
414 414
415 /* ALC Sidetone */ 415 /* ALC Sidetone */
416 {"ALC Sidetone Mux", "Stereo", "Left C 416 {"ALC Sidetone Mux", "Stereo", "Left Capture Select"},
417 {"ALC Sidetone Mux", "Stereo", "Right 417 {"ALC Sidetone Mux", "Stereo", "Right Capture Select"},
418 {"ALC Sidetone Mux", "Left", "Left Cap 418 {"ALC Sidetone Mux", "Left", "Left Capture Select"},
419 {"ALC Sidetone Mux", "Right", "Right C 419 {"ALC Sidetone Mux", "Right", "Right Capture Select"},
420 420
421 /* ADC's */ 421 /* ADC's */
422 {"Left ADC", NULL, "Left Capture Selec 422 {"Left ADC", NULL, "Left Capture Select"},
423 {"Right ADC", NULL, "Right Capture Sel 423 {"Right ADC", NULL, "Right Capture Select"},
424 424
425 /* outputs */ 425 /* outputs */
426 {"MONOOUT", NULL, "Phone Mixer"}, 426 {"MONOOUT", NULL, "Phone Mixer"},
427 {"HPOUTL", NULL, "Headphone PGA"}, 427 {"HPOUTL", NULL, "Headphone PGA"},
428 {"Headphone PGA", NULL, "Left HP Mixer 428 {"Headphone PGA", NULL, "Left HP Mixer"},
429 {"HPOUTR", NULL, "Headphone PGA"}, 429 {"HPOUTR", NULL, "Headphone PGA"},
430 {"Headphone PGA", NULL, "Right HP Mixe 430 {"Headphone PGA", NULL, "Right HP Mixer"},
431 431
432 /* mono hp mixer */ 432 /* mono hp mixer */
433 {"Mono HP Mixer", NULL, "Left HP Mixer 433 {"Mono HP Mixer", NULL, "Left HP Mixer"},
434 {"Mono HP Mixer", NULL, "Right HP Mixe 434 {"Mono HP Mixer", NULL, "Right HP Mixer"},
435 435
436 /* Out3 Mux */ 436 /* Out3 Mux */
437 {"Out3 Mux", "Left", "Left HP Mixer"}, 437 {"Out3 Mux", "Left", "Left HP Mixer"},
438 {"Out3 Mux", "Mono", "Phone Mixer"}, 438 {"Out3 Mux", "Mono", "Phone Mixer"},
439 {"Out3 Mux", "Left + Right", "Mono HP 439 {"Out3 Mux", "Left + Right", "Mono HP Mixer"},
440 {"Out 3 PGA", NULL, "Out3 Mux"}, 440 {"Out 3 PGA", NULL, "Out3 Mux"},
441 {"OUT3", NULL, "Out 3 PGA"}, 441 {"OUT3", NULL, "Out 3 PGA"},
442 442
443 /* speaker Mux */ 443 /* speaker Mux */
444 {"Speaker Mux", "Speaker Mix", "Speake 444 {"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
445 {"Speaker Mux", "Headphone Mix", "Mono 445 {"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
446 {"Speaker PGA", NULL, "Speaker Mux"}, 446 {"Speaker PGA", NULL, "Speaker Mux"},
447 {"LOUT2", NULL, "Speaker PGA"}, 447 {"LOUT2", NULL, "Speaker PGA"},
448 {"ROUT2", NULL, "Speaker PGA"}, 448 {"ROUT2", NULL, "Speaker PGA"},
449 449
450 {NULL, NULL, NULL}, 450 {NULL, NULL, NULL},
451 }; 451 };
452 452
453 static int wm9712_add_widgets(struct snd_soc_c 453 static int wm9712_add_widgets(struct snd_soc_codec *codec)
454 { 454 {
455 int i; 455 int i;
456 456
457 for(i = 0; i < ARRAY_SIZE(wm9712_dapm_ 457 for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
458 snd_soc_dapm_new_control(codec 458 snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
459 } 459 }
460 460
461 /* set up audio path audio_mapnects */ 461 /* set up audio path audio_mapnects */
462 for(i = 0; audio_map[i][0] != NULL; i+ 462 for(i = 0; audio_map[i][0] != NULL; i++) {
463 snd_soc_dapm_connect_input(cod 463 snd_soc_dapm_connect_input(codec, audio_map[i][0],
464 audio_map[i][1], audio 464 audio_map[i][1], audio_map[i][2]);
465 } 465 }
466 466
467 snd_soc_dapm_new_widgets(codec); 467 snd_soc_dapm_new_widgets(codec);
468 return 0; 468 return 0;
469 } 469 }
470 470
471 static unsigned int ac97_read(struct snd_soc_c 471 static unsigned int ac97_read(struct snd_soc_codec *codec,
472 unsigned int reg) 472 unsigned int reg)
473 { 473 {
474 u16 *cache = codec->reg_cache; 474 u16 *cache = codec->reg_cache;
475 475
476 if (reg == AC97_RESET || reg == AC97_G 476 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
477 reg == AC97_VENDOR_ID1 || reg 477 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
478 reg == AC97_REC_GAIN) 478 reg == AC97_REC_GAIN)
479 return soc_ac97_ops.read(codec 479 return soc_ac97_ops.read(codec->ac97, reg);
480 else { 480 else {
481 reg = reg >> 1; 481 reg = reg >> 1;
482 482
483 if (reg > (ARRAY_SIZE(wm9712_r 483 if (reg > (ARRAY_SIZE(wm9712_reg)))
484 return -EIO; 484 return -EIO;
485 485
486 return cache[reg]; 486 return cache[reg];
487 } 487 }
488 } 488 }
489 489
490 static int ac97_write(struct snd_soc_codec *co 490 static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
491 unsigned int val) 491 unsigned int val)
492 { 492 {
493 u16 *cache = codec->reg_cache; 493 u16 *cache = codec->reg_cache;
494 494
495 soc_ac97_ops.write(codec->ac97, reg, v 495 soc_ac97_ops.write(codec->ac97, reg, val);
496 reg = reg >> 1; 496 reg = reg >> 1;
497 if (reg <= (ARRAY_SIZE(wm9712_reg))) 497 if (reg <= (ARRAY_SIZE(wm9712_reg)))
498 cache[reg] = val; 498 cache[reg] = val;
499 499
500 return 0; 500 return 0;
501 } 501 }
502 502
503 static int ac97_prepare(struct snd_pcm_substre 503 static int ac97_prepare(struct snd_pcm_substream *substream)
504 { 504 {
505 struct snd_pcm_runtime *runtime = subs 505 struct snd_pcm_runtime *runtime = substream->runtime;
506 struct snd_soc_pcm_runtime *rtd = subs 506 struct snd_soc_pcm_runtime *rtd = substream->private_data;
507 struct snd_soc_device *socdev = rtd->s 507 struct snd_soc_device *socdev = rtd->socdev;
508 struct snd_soc_codec *codec = socdev-> 508 struct snd_soc_codec *codec = socdev->codec;
509 int reg; 509 int reg;
510 u16 vra; 510 u16 vra;
511 511
512 vra = ac97_read(codec, AC97_EXTENDED_S 512 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
513 ac97_write(codec, AC97_EXTENDED_STATUS 513 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
514 514
515 if (substream->stream == SNDRV_PCM_STR 515 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
516 reg = AC97_PCM_FRONT_DAC_RATE; 516 reg = AC97_PCM_FRONT_DAC_RATE;
517 else 517 else
518 reg = AC97_PCM_LR_ADC_RATE; 518 reg = AC97_PCM_LR_ADC_RATE;
519 519
520 return ac97_write(codec, reg, runtime- 520 return ac97_write(codec, reg, runtime->rate);
521 } 521 }
522 522
523 static int ac97_aux_prepare(struct snd_pcm_sub 523 static int ac97_aux_prepare(struct snd_pcm_substream *substream)
524 { 524 {
525 struct snd_pcm_runtime *runtime = subs 525 struct snd_pcm_runtime *runtime = substream->runtime;
526 struct snd_soc_pcm_runtime *rtd = subs 526 struct snd_soc_pcm_runtime *rtd = substream->private_data;
527 struct snd_soc_device *socdev = rtd->s 527 struct snd_soc_device *socdev = rtd->socdev;
528 struct snd_soc_codec *codec = socdev-> 528 struct snd_soc_codec *codec = socdev->codec;
529 u16 vra, xsle; 529 u16 vra, xsle;
530 530
531 vra = ac97_read(codec, AC97_EXTENDED_S 531 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
532 ac97_write(codec, AC97_EXTENDED_STATUS 532 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
533 xsle = ac97_read(codec, AC97_PCI_SID); 533 xsle = ac97_read(codec, AC97_PCI_SID);
534 ac97_write(codec, AC97_PCI_SID, xsle | 534 ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
535 535
536 if (substream->stream != SNDRV_PCM_STR 536 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
537 return -ENODEV; 537 return -ENODEV;
538 538
539 return ac97_write(codec, AC97_PCM_SURR 539 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
540 } 540 }
541 541
542 #define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 542 #define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
543 SNDRV_PCM_RATE_22050 | SNDRV_P 543 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
544 544
545 struct snd_soc_codec_dai wm9712_dai[] = { 545 struct snd_soc_codec_dai wm9712_dai[] = {
546 { 546 {
547 .name = "AC97 HiFi", 547 .name = "AC97 HiFi",
548 .type = SND_SOC_DAI_AC97_BUS, 548 .type = SND_SOC_DAI_AC97_BUS,
549 .playback = { 549 .playback = {
550 .stream_name = "HiFi Playback" 550 .stream_name = "HiFi Playback",
551 .channels_min = 1, 551 .channels_min = 1,
552 .channels_max = 2, 552 .channels_max = 2,
553 .rates = WM9712_AC97_RATES, 553 .rates = WM9712_AC97_RATES,
554 .formats = SNDRV_PCM_FMTBIT_S1 554 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
555 .capture = { 555 .capture = {
556 .stream_name = "HiFi Capture", 556 .stream_name = "HiFi Capture",
557 .channels_min = 1, 557 .channels_min = 1,
558 .channels_max = 2, 558 .channels_max = 2,
559 .rates = WM9712_AC97_RATES, 559 .rates = WM9712_AC97_RATES,
560 .formats = SNDRV_PCM_FMTBIT_S1 560 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
561 .ops = { 561 .ops = {
562 .prepare = ac97_prepare,}, 562 .prepare = ac97_prepare,},
563 }, 563 },
564 { 564 {
565 .name = "AC97 Aux", 565 .name = "AC97 Aux",
566 .playback = { 566 .playback = {
567 .stream_name = "Aux Playback", 567 .stream_name = "Aux Playback",
568 .channels_min = 1, 568 .channels_min = 1,
569 .channels_max = 1, 569 .channels_max = 1,
570 .rates = WM9712_AC97_RATES, 570 .rates = WM9712_AC97_RATES,
571 .formats = SNDRV_PCM_FMTBIT_S1 571 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
572 .ops = { 572 .ops = {
573 .prepare = ac97_aux_prepare,}, 573 .prepare = ac97_aux_prepare,},
574 } 574 }
575 }; 575 };
576 EXPORT_SYMBOL_GPL(wm9712_dai); 576 EXPORT_SYMBOL_GPL(wm9712_dai);
577 577
578 static int wm9712_dapm_event(struct snd_soc_co 578 static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
579 { 579 {
580 u16 reg; 580 u16 reg;
581 581
582 switch (event) { 582 switch (event) {
583 case SNDRV_CTL_POWER_D0: /* full On */ 583 case SNDRV_CTL_POWER_D0: /* full On */
584 /* liam - maybe enable thermal 584 /* liam - maybe enable thermal shutdown */
585 reg = ac97_read(codec, AC97_EX 585 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
586 ac97_write(codec, AC97_EXTENDE 586 ac97_write(codec, AC97_EXTENDED_MID, reg);
587 break; 587 break;
588 case SNDRV_CTL_POWER_D1: /* partial On 588 case SNDRV_CTL_POWER_D1: /* partial On */
589 case SNDRV_CTL_POWER_D2: /* partial On 589 case SNDRV_CTL_POWER_D2: /* partial On */
590 break; 590 break;
591 case SNDRV_CTL_POWER_D3hot: /* Off, wi 591 case SNDRV_CTL_POWER_D3hot: /* Off, with power */
592 /* enable master bias and vmid 592 /* enable master bias and vmid */
593 reg = ac97_read(codec, AC97_EX 593 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
594 ac97_write(codec, AC97_EXTENDE 594 ac97_write(codec, AC97_EXTENDED_MID, reg);
595 ac97_write(codec, AC97_POWERDO 595 ac97_write(codec, AC97_POWERDOWN, 0x0000);
596 break; 596 break;
597 case SNDRV_CTL_POWER_D3cold: /* Off, w 597 case SNDRV_CTL_POWER_D3cold: /* Off, without power */
598 /* disable everything includin 598 /* disable everything including AC link */
599 ac97_write(codec, AC97_EXTENDE 599 ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
600 ac97_write(codec, AC97_EXTENDE 600 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
601 ac97_write(codec, AC97_POWERDO 601 ac97_write(codec, AC97_POWERDOWN, 0xffff);
602 break; 602 break;
603 } 603 }
604 codec->dapm_state = event; 604 codec->dapm_state = event;
605 return 0; 605 return 0;
606 } 606 }
607 607
608 static int wm9712_reset(struct snd_soc_codec * 608 static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
609 { 609 {
610 if (try_warm && soc_ac97_ops.warm_rese 610 if (try_warm && soc_ac97_ops.warm_reset) {
611 soc_ac97_ops.warm_reset(codec- 611 soc_ac97_ops.warm_reset(codec->ac97);
612 if (!(ac97_read(codec, 0) & 0x 612 if (!(ac97_read(codec, 0) & 0x8000))
613 return 1; 613 return 1;
614 } 614 }
615 615
616 soc_ac97_ops.reset(codec->ac97); 616 soc_ac97_ops.reset(codec->ac97);
617 if (ac97_read(codec, 0) & 0x8000) 617 if (ac97_read(codec, 0) & 0x8000)
618 goto err; 618 goto err;
619 return 0; 619 return 0;
620 620
621 err: 621 err:
622 printk(KERN_ERR "WM9712 AC97 reset fai 622 printk(KERN_ERR "WM9712 AC97 reset failed\n");
623 return -EIO; 623 return -EIO;
624 } 624 }
625 625
626 static int wm9712_soc_suspend(struct platform_ 626 static int wm9712_soc_suspend(struct platform_device *pdev,
627 pm_message_t state) 627 pm_message_t state)
628 { 628 {
629 struct snd_soc_device *socdev = platfo 629 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
630 struct snd_soc_codec *codec = socdev-> 630 struct snd_soc_codec *codec = socdev->codec;
631 631
632 wm9712_dapm_event(codec, SNDRV_CTL_POW 632 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
633 return 0; 633 return 0;
634 } 634 }
635 635
636 static int wm9712_soc_resume(struct platform_d 636 static int wm9712_soc_resume(struct platform_device *pdev)
637 { 637 {
638 struct snd_soc_device *socdev = platfo 638 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
639 struct snd_soc_codec *codec = socdev-> 639 struct snd_soc_codec *codec = socdev->codec;
640 int i, ret; 640 int i, ret;
641 u16 *cache = codec->reg_cache; 641 u16 *cache = codec->reg_cache;
642 642
643 ret = wm9712_reset(codec, 1); 643 ret = wm9712_reset(codec, 1);
644 if (ret < 0){ 644 if (ret < 0){
645 printk(KERN_ERR "could not res 645 printk(KERN_ERR "could not reset AC97 codec\n");
646 return ret; 646 return ret;
647 } 647 }
648 648
649 wm9712_dapm_event(codec, SNDRV_CTL_POW 649 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
650 650
651 if (ret == 0) { 651 if (ret == 0) {
652 /* Sync reg_cache with the har 652 /* Sync reg_cache with the hardware after cold reset */
653 for (i = 2; i < ARRAY_SIZE(wm9 653 for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
654 if (i == AC97_INT_PAGI 654 if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
655 (i > 0x58 && i 655 (i > 0x58 && i != 0x5c))
656 continue; 656 continue;
657 soc_ac97_ops.write(cod 657 soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
658 } 658 }
659 } 659 }
660 660
661 if (codec->suspend_dapm_state == SNDRV 661 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
662 wm9712_dapm_event(codec, SNDRV 662 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
663 663
664 return ret; 664 return ret;
665 } 665 }
666 666
667 static int wm9712_soc_probe(struct platform_de 667 static int wm9712_soc_probe(struct platform_device *pdev)
668 { 668 {
669 struct snd_soc_device *socdev = platfo 669 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
670 struct snd_soc_codec *codec; 670 struct snd_soc_codec *codec;
671 int ret = 0; 671 int ret = 0;
672 672
673 printk(KERN_INFO "WM9711/WM9712 SoC Au 673 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
674 674
675 socdev->codec = kzalloc(sizeof(struct 675 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
676 if (socdev->codec == NULL) 676 if (socdev->codec == NULL)
677 return -ENOMEM; 677 return -ENOMEM;
678 codec = socdev->codec; 678 codec = socdev->codec;
679 mutex_init(&codec->mutex); 679 mutex_init(&codec->mutex);
680 680
681 codec->reg_cache = kmemdup(wm9712_reg, 681 codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
682 682
683 if (codec->reg_cache == NULL) { 683 if (codec->reg_cache == NULL) {
684 ret = -ENOMEM; 684 ret = -ENOMEM;
685 goto cache_err; 685 goto cache_err;
686 } 686 }
687 codec->reg_cache_size = sizeof(wm9712_ 687 codec->reg_cache_size = sizeof(wm9712_reg);
688 codec->reg_cache_step = 2; 688 codec->reg_cache_step = 2;
689 689
690 codec->name = "WM9712"; 690 codec->name = "WM9712";
691 codec->owner = THIS_MODULE; 691 codec->owner = THIS_MODULE;
692 codec->dai = wm9712_dai; 692 codec->dai = wm9712_dai;
693 codec->num_dai = ARRAY_SIZE(wm9712_dai 693 codec->num_dai = ARRAY_SIZE(wm9712_dai);
694 codec->write = ac97_write; 694 codec->write = ac97_write;
695 codec->read = ac97_read; 695 codec->read = ac97_read;
696 codec->dapm_event = wm9712_dapm_event; 696 codec->dapm_event = wm9712_dapm_event;
697 INIT_LIST_HEAD(&codec->dapm_widgets); 697 INIT_LIST_HEAD(&codec->dapm_widgets);
698 INIT_LIST_HEAD(&codec->dapm_paths); 698 INIT_LIST_HEAD(&codec->dapm_paths);
699 699
700 ret = snd_soc_new_ac97_codec(codec, &s 700 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
701 if (ret < 0) { 701 if (ret < 0) {
702 printk(KERN_ERR "wm9712: faile 702 printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
703 goto codec_err; 703 goto codec_err;
704 } 704 }
705 705
706 /* register pcms */ 706 /* register pcms */
707 ret = snd_soc_new_pcms(socdev, SNDRV_D 707 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
708 if (ret < 0) 708 if (ret < 0)
709 goto pcm_err; 709 goto pcm_err;
710 710
711 ret = wm9712_reset(codec, 0); 711 ret = wm9712_reset(codec, 0);
712 if (ret < 0) { 712 if (ret < 0) {
713 printk(KERN_ERR "AC97 link err 713 printk(KERN_ERR "AC97 link error\n");
714 goto reset_err; 714 goto reset_err;
715 } 715 }
716 716
717 /* set alc mux to none */ 717 /* set alc mux to none */
718 ac97_write(codec, AC97_VIDEO, ac97_rea 718 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
719 719
720 wm9712_dapm_event(codec, SNDRV_CTL_POW 720 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
721 wm9712_add_controls(codec); 721 wm9712_add_controls(codec);
722 wm9712_add_widgets(codec); 722 wm9712_add_widgets(codec);
723 ret = snd_soc_register_card(socdev); 723 ret = snd_soc_register_card(socdev);
724 if (ret < 0) { 724 if (ret < 0) {
725 printk(KERN_ERR "wm9712: faile 725 printk(KERN_ERR "wm9712: failed to register card\n");
726 goto reset_err; 726 goto reset_err;
727 } 727 }
728 728
729 return 0; 729 return 0;
730 730
731 reset_err: 731 reset_err:
732 snd_soc_free_pcms(socdev); 732 snd_soc_free_pcms(socdev);
733 733
734 pcm_err: 734 pcm_err:
735 snd_soc_free_ac97_codec(codec); 735 snd_soc_free_ac97_codec(codec);
736 736
737 codec_err: 737 codec_err:
738 kfree(codec->reg_cache); 738 kfree(codec->reg_cache);
739 739
740 cache_err: 740 cache_err:
741 kfree(socdev->codec); 741 kfree(socdev->codec);
742 socdev->codec = NULL; 742 socdev->codec = NULL;
743 return ret; 743 return ret;
744 } 744 }
745 745
746 static int wm9712_soc_remove(struct platform_d 746 static int wm9712_soc_remove(struct platform_device *pdev)
747 { 747 {
748 struct snd_soc_device *socdev = platfo 748 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
749 struct snd_soc_codec *codec = socdev-> 749 struct snd_soc_codec *codec = socdev->codec;
750 750
751 if (codec == NULL) 751 if (codec == NULL)
752 return 0; 752 return 0;
753 753
754 snd_soc_dapm_free(socdev); 754 snd_soc_dapm_free(socdev);
755 snd_soc_free_pcms(socdev); 755 snd_soc_free_pcms(socdev);
756 snd_soc_free_ac97_codec(codec); 756 snd_soc_free_ac97_codec(codec);
757 kfree(codec->reg_cache); 757 kfree(codec->reg_cache);
758 kfree(codec); 758 kfree(codec);
759 return 0; 759 return 0;
760 } 760 }
761 761
762 struct snd_soc_codec_device soc_codec_dev_wm97 762 struct snd_soc_codec_device soc_codec_dev_wm9712 = {
763 .probe = wm9712_soc_probe, 763 .probe = wm9712_soc_probe,
764 .remove = wm9712_soc_remove, 764 .remove = wm9712_soc_remove,
765 .suspend = wm9712_soc_suspend, 765 .suspend = wm9712_soc_suspend,
766 .resume = wm9712_soc_resume, 766 .resume = wm9712_soc_resume,
767 }; 767 };
768 768
769 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); 769 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
770 770
771 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver" 771 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
772 MODULE_AUTHOR("Liam Girdwood"); 772 MODULE_AUTHOR("Liam Girdwood");
773 MODULE_LICENSE("GPL"); 773 MODULE_LICENSE("GPL");
774 774
|
This page was automatically generated by the
LXR engine.
|