2 * wm9713.c -- ALSA Soc WM9713 codec support
4 * Copyright 2006-10 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
14 * o Support for AC97 Codec, Voice DAC and Aux DAC
18 #include <linux/init.h>
19 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/device.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/ac97_codec.h>
25 #include <sound/initval.h>
26 #include <sound/pcm_params.h>
27 #include <sound/tlv.h>
28 #include <sound/soc.h>
33 u32 pll_in
; /* PLL input frequency */
34 unsigned int hp_mixer
[2];
38 static unsigned int ac97_read(struct snd_soc_codec
*codec
,
40 static int ac97_write(struct snd_soc_codec
*codec
,
41 unsigned int reg
, unsigned int val
);
44 * WM9713 register cache
45 * Reg 0x3c bit 15 is used by touch driver.
47 static const u16 wm9713_reg
[] = {
48 0x6174, 0x8080, 0x8080, 0x8080,
49 0xc880, 0xe808, 0xe808, 0x0808,
50 0x00da, 0x8000, 0xd600, 0xaaa0,
51 0xaaa0, 0xaaa0, 0x0000, 0x0000,
52 0x0f0f, 0x0040, 0x0000, 0x7f00,
53 0x0405, 0x0410, 0xbb80, 0xbb80,
54 0x0000, 0xbb80, 0x0000, 0x4523,
55 0x0000, 0x2000, 0x7eff, 0xffff,
56 0x0000, 0x0000, 0x0080, 0x0000,
57 0x0000, 0x0000, 0xfffe, 0xffff,
58 0x0000, 0x0000, 0x0000, 0xfffe,
59 0x4000, 0x0000, 0x0000, 0x0000,
60 0xb032, 0x3e00, 0x0000, 0x0000,
61 0x0000, 0x0000, 0x0000, 0x0000,
62 0x0000, 0x0000, 0x0000, 0x0006,
63 0x0001, 0x0000, 0x574d, 0x4c13,
69 static const char *wm9713_mic_mixer
[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
70 static const char *wm9713_rec_mux
[] = {"Stereo", "Left", "Right", "Mute"};
71 static const char *wm9713_rec_src
[] =
72 {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
74 static const char *wm9713_rec_gain
[] = {"+1.5dB Steps", "+0.75dB Steps"};
75 static const char *wm9713_alc_select
[] = {"None", "Left", "Right", "Stereo"};
76 static const char *wm9713_mono_pga
[] = {"Vmid", "Zh", "Mono", "Inv"};
77 static const char *wm9713_spk_pga
[] =
78 {"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
79 "Speaker Vmid", "Inv Vmid"};
80 static const char *wm9713_hp_pga
[] = {"Vmid", "Zh", "Headphone",
82 static const char *wm9713_out3_pga
[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
83 static const char *wm9713_out4_pga
[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
84 static const char *wm9713_dac_inv
[] =
85 {"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
86 "Headphone Mono", "NC", "Vmid"};
87 static const char *wm9713_bass
[] = {"Linear Control", "Adaptive Boost"};
88 static const char *wm9713_ng_type
[] = {"Constant Gain", "Mute"};
89 static const char *wm9713_mic_select
[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
90 static const char *wm9713_micb_select
[] = {"MPB", "MPA"};
92 static const struct soc_enum wm9713_enum
[] = {
93 SOC_ENUM_SINGLE(AC97_LINE
, 3, 4, wm9713_mic_mixer
), /* record mic mixer 0 */
94 SOC_ENUM_SINGLE(AC97_VIDEO
, 14, 4, wm9713_rec_mux
), /* record mux hp 1 */
95 SOC_ENUM_SINGLE(AC97_VIDEO
, 9, 4, wm9713_rec_mux
), /* record mux mono 2 */
96 SOC_ENUM_SINGLE(AC97_VIDEO
, 3, 8, wm9713_rec_src
), /* record mux left 3 */
97 SOC_ENUM_SINGLE(AC97_VIDEO
, 0, 8, wm9713_rec_src
), /* record mux right 4*/
98 SOC_ENUM_DOUBLE(AC97_CD
, 14, 6, 2, wm9713_rec_gain
), /* record step size 5 */
99 SOC_ENUM_SINGLE(AC97_PCI_SVID
, 14, 4, wm9713_alc_select
), /* alc source select 6*/
100 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 14, 4, wm9713_mono_pga
), /* mono input select 7 */
101 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 11, 8, wm9713_spk_pga
), /* speaker left input select 8 */
102 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 8, 8, wm9713_spk_pga
), /* speaker right input select 9 */
103 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 6, 3, wm9713_hp_pga
), /* headphone left input 10 */
104 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 4, 3, wm9713_hp_pga
), /* headphone right input 11 */
105 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 2, 4, wm9713_out3_pga
), /* out 3 source 12 */
106 SOC_ENUM_SINGLE(AC97_REC_GAIN
, 0, 4, wm9713_out4_pga
), /* out 4 source 13 */
107 SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC
, 13, 8, wm9713_dac_inv
), /* dac invert 1 14 */
108 SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC
, 10, 8, wm9713_dac_inv
), /* dac invert 2 15 */
109 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE
, 15, 2, wm9713_bass
), /* bass control 16 */
110 SOC_ENUM_SINGLE(AC97_PCI_SVID
, 5, 2, wm9713_ng_type
), /* noise gate type 17 */
111 SOC_ENUM_SINGLE(AC97_3D_CONTROL
, 12, 3, wm9713_mic_select
), /* mic selection 18 */
112 SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select
), /* mic selection 19 */
115 static const DECLARE_TLV_DB_SCALE(out_tlv
, -4650, 150, 0);
116 static const DECLARE_TLV_DB_SCALE(main_tlv
, -3450, 150, 0);
117 static const DECLARE_TLV_DB_SCALE(misc_tlv
, -1500, 300, 0);
118 static unsigned int mic_tlv
[] = {
119 TLV_DB_RANGE_HEAD(2),
120 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
121 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0),
124 static const struct snd_kcontrol_new wm9713_snd_ac97_controls
[] = {
125 SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER
, 8, 0, 31, 1, out_tlv
),
126 SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER
, 15, 7, 1, 1),
127 SOC_DOUBLE_TLV("Headphone Playback Volume", AC97_HEADPHONE
, 8, 0, 31, 1,
129 SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE
, 15, 7, 1, 1),
130 SOC_DOUBLE_TLV("Line In Volume", AC97_PC_BEEP
, 8, 0, 31, 1, main_tlv
),
131 SOC_DOUBLE_TLV("PCM Playback Volume", AC97_PHONE
, 8, 0, 31, 1, main_tlv
),
132 SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC
, 8, 31, 1, main_tlv
),
133 SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC
, 0, 31, 1, main_tlv
),
134 SOC_SINGLE_TLV("Mic 1 Preamp Volume", AC97_3D_CONTROL
, 10, 3, 0, mic_tlv
),
135 SOC_SINGLE_TLV("Mic 2 Preamp Volume", AC97_3D_CONTROL
, 12, 3, 0, mic_tlv
),
137 SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE
, 5, 1, 0),
138 SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE
, 0, 7, 1),
140 SOC_SINGLE("Capture Switch", AC97_CD
, 15, 1, 1),
141 SOC_ENUM("Capture Volume Steps", wm9713_enum
[5]),
142 SOC_DOUBLE("Capture Volume", AC97_CD
, 8, 0, 31, 0),
143 SOC_SINGLE("Capture ZC Switch", AC97_CD
, 7, 1, 0),
145 SOC_SINGLE_TLV("Capture to Headphone Volume", AC97_VIDEO
, 11, 7, 1, misc_tlv
),
146 SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO
, 8, 1, 0),
147 SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO
, 6, 1, 0),
149 SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV
, 12, 15, 0),
150 SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV
, 8, 15, 0),
151 SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV
, 4, 15, 0),
152 SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV
, 0, 15, 0),
153 SOC_ENUM("ALC Function", wm9713_enum
[6]),
154 SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID
, 11, 7, 0),
155 SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID
, 9, 3, 0),
156 SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID
, 8, 1, 0),
157 SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID
, 7, 1, 0),
158 SOC_ENUM("ALC NG Type", wm9713_enum
[17]),
159 SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID
, 0, 31, 0),
161 SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER
, 14, 6, 1, 0),
162 SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE
, 14, 6, 1, 0),
164 SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO
, 15, 1, 1),
165 SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO
, 14, 1, 0),
166 SOC_SINGLE_TLV("Out4 Playback Volume", AC97_MASTER_MONO
, 8, 31, 1, out_tlv
),
168 SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO
, 7, 1, 1),
169 SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO
, 6, 1, 0),
170 SOC_SINGLE_TLV("Out3 Playback Volume", AC97_MASTER_MONO
, 0, 31, 1, out_tlv
),
172 SOC_SINGLE_TLV("Mono Capture Volume", AC97_MASTER_TONE
, 8, 31, 1, main_tlv
),
173 SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE
, 7, 1, 1),
174 SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE
, 6, 1, 0),
175 SOC_SINGLE_TLV("Mono Playback Volume", AC97_MASTER_TONE
, 0, 31, 1, out_tlv
),
177 SOC_SINGLE_TLV("Headphone Mixer Beep Playback Volume", AC97_AUX
, 12, 7, 1,
179 SOC_SINGLE_TLV("Speaker Mixer Beep Playback Volume", AC97_AUX
, 8, 7, 1,
181 SOC_SINGLE_TLV("Mono Mixer Beep Playback Volume", AC97_AUX
, 4, 7, 1, misc_tlv
),
183 SOC_SINGLE_TLV("Voice Playback Headphone Volume", AC97_PCM
, 12, 7, 1,
185 SOC_SINGLE("Voice Playback Master Volume", AC97_PCM
, 8, 7, 1),
186 SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM
, 4, 7, 1),
188 SOC_SINGLE_TLV("Headphone Mixer Aux Playback Volume", AC97_REC_SEL
, 12, 7, 1,
191 SOC_SINGLE_TLV("Speaker Mixer Voice Playback Volume", AC97_PCM
, 8, 7, 1,
193 SOC_SINGLE_TLV("Speaker Mixer Aux Playback Volume", AC97_REC_SEL
, 8, 7, 1,
196 SOC_SINGLE_TLV("Mono Mixer Voice Playback Volume", AC97_PCM
, 4, 7, 1,
198 SOC_SINGLE_TLV("Mono Mixer Aux Playback Volume", AC97_REC_SEL
, 4, 7, 1,
201 SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL
, 12, 7, 1),
202 SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL
, 8, 7, 1),
204 SOC_ENUM("Bass Control", wm9713_enum
[16]),
205 SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE
, 12, 1, 1),
206 SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE
, 4, 1, 1),
207 SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE
, 6, 1, 0),
208 SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE
, 8, 15, 1),
209 SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE
, 0, 15, 1),
211 SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC
, 5, 1, 0),
212 SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC
, 4, 1, 0),
213 SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC
, 0, 15, 1),
216 static int wm9713_voice_shutdown(struct snd_soc_dapm_widget
*w
,
217 struct snd_kcontrol
*kcontrol
, int event
)
219 struct snd_soc_codec
*codec
= w
->codec
;
222 if (WARN_ON(event
!= SND_SOC_DAPM_PRE_PMD
))
225 /* Gracefully shut down the voice interface. */
226 status
= ac97_read(codec
, AC97_EXTENDED_MID
) | 0x1000;
227 rate
= ac97_read(codec
, AC97_HANDSET_RATE
) & 0xF0FF;
228 ac97_write(codec
, AC97_HANDSET_RATE
, rate
| 0x0200);
229 schedule_timeout_interruptible(msecs_to_jiffies(1));
230 ac97_write(codec
, AC97_HANDSET_RATE
, rate
| 0x0F00);
231 ac97_write(codec
, AC97_EXTENDED_MID
, status
);
236 static const unsigned int wm9713_mixer_mute_regs
[] = {
245 /* We have to create a fake left and right HP mixers because
246 * the codec only has a single control that is shared by both channels.
247 * This makes it impossible to determine the audio path using the current
248 * register map, thus we add a new (virtual) register to help determine the
249 * audio route within the device.
251 static int wm9713_hp_mixer_put(struct snd_kcontrol
*kcontrol
,
252 struct snd_ctl_elem_value
*ucontrol
)
254 struct snd_soc_dapm_context
*dapm
= snd_soc_dapm_kcontrol_dapm(kcontrol
);
255 struct snd_soc_codec
*codec
= snd_soc_dapm_to_codec(dapm
);
256 struct wm9713_priv
*wm9713
= snd_soc_codec_get_drvdata(codec
);
257 unsigned int val
= ucontrol
->value
.enumerated
.item
[0];
258 struct soc_mixer_control
*mc
=
259 (struct soc_mixer_control
*)kcontrol
->private_value
;
260 unsigned int mixer
, mask
, shift
, old
;
261 struct snd_soc_dapm_update update
;
264 mixer
= mc
->shift
>> 8;
265 shift
= mc
->shift
& 0xff;
268 mutex_lock(&wm9713
->lock
);
269 old
= wm9713
->hp_mixer
[mixer
];
270 if (ucontrol
->value
.enumerated
.item
[0])
271 wm9713
->hp_mixer
[mixer
] |= mask
;
273 wm9713
->hp_mixer
[mixer
] &= ~mask
;
275 change
= old
!= wm9713
->hp_mixer
[mixer
];
277 update
.kcontrol
= kcontrol
;
278 update
.reg
= wm9713_mixer_mute_regs
[shift
];
279 update
.mask
= 0x8000;
280 if ((wm9713
->hp_mixer
[0] & mask
) ||
281 (wm9713
->hp_mixer
[1] & mask
))
286 snd_soc_dapm_mixer_update_power(dapm
, kcontrol
, val
,
290 mutex_unlock(&wm9713
->lock
);
295 static int wm9713_hp_mixer_get(struct snd_kcontrol
*kcontrol
,
296 struct snd_ctl_elem_value
*ucontrol
)
298 struct snd_soc_dapm_context
*dapm
= snd_soc_dapm_kcontrol_dapm(kcontrol
);
299 struct snd_soc_codec
*codec
= snd_soc_dapm_to_codec(dapm
);
300 struct wm9713_priv
*wm9713
= snd_soc_codec_get_drvdata(codec
);
301 struct soc_mixer_control
*mc
=
302 (struct soc_mixer_control
*)kcontrol
->private_value
;
303 unsigned int mixer
, shift
;
305 mixer
= mc
->shift
>> 8;
306 shift
= mc
->shift
& 0xff;
308 ucontrol
->value
.enumerated
.item
[0] =
309 (wm9713
->hp_mixer
[mixer
] >> shift
) & 1;
314 #define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \
315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
316 .info = snd_soc_info_volsw, \
317 .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \
318 .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \
319 xshift, xmixer, 1, 0, 0) \
322 /* Left Headphone Mixers */
323 static const struct snd_kcontrol_new wm9713_hpl_mixer_controls
[] = {
324 WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER
, 5),
325 WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER
, 4),
326 WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER
, 3),
327 WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER
, 2),
328 WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER
, 1),
329 WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER
, 0),
332 /* Right Headphone Mixers */
333 static const struct snd_kcontrol_new wm9713_hpr_mixer_controls
[] = {
334 WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER
, 5),
335 WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER
, 4),
336 WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER
, 3),
337 WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER
, 2),
338 WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER
, 1),
339 WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER
, 0),
342 /* headphone capture mux */
343 static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls
=
344 SOC_DAPM_ENUM("Route", wm9713_enum
[1]);
346 /* headphone mic mux */
347 static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls
=
348 SOC_DAPM_ENUM("Route", wm9713_enum
[0]);
351 static const struct snd_kcontrol_new wm9713_speaker_mixer_controls
[] = {
352 SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX
, 11, 1, 1),
353 SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM
, 11, 1, 1),
354 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL
, 11, 1, 1),
355 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE
, 14, 1, 1),
356 SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE
, 14, 1, 1),
357 SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP
, 14, 1, 1),
361 static const struct snd_kcontrol_new wm9713_mono_mixer_controls
[] = {
362 SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX
, 7, 1, 1),
363 SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM
, 7, 1, 1),
364 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL
, 7, 1, 1),
365 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE
, 13, 1, 1),
366 SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE
, 13, 1, 1),
367 SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP
, 13, 1, 1),
368 SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE
, 7, 1, 1),
369 SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE
, 6, 1, 1),
373 static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls
=
374 SOC_DAPM_ENUM("Route", wm9713_enum
[2]);
376 /* mono output mux */
377 static const struct snd_kcontrol_new wm9713_mono_mux_controls
=
378 SOC_DAPM_ENUM("Route", wm9713_enum
[7]);
380 /* speaker left output mux */
381 static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls
=
382 SOC_DAPM_ENUM("Route", wm9713_enum
[8]);
384 /* speaker right output mux */
385 static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls
=
386 SOC_DAPM_ENUM("Route", wm9713_enum
[9]);
388 /* headphone left output mux */
389 static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls
=
390 SOC_DAPM_ENUM("Route", wm9713_enum
[10]);
392 /* headphone right output mux */
393 static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls
=
394 SOC_DAPM_ENUM("Route", wm9713_enum
[11]);
397 static const struct snd_kcontrol_new wm9713_out3_mux_controls
=
398 SOC_DAPM_ENUM("Route", wm9713_enum
[12]);
401 static const struct snd_kcontrol_new wm9713_out4_mux_controls
=
402 SOC_DAPM_ENUM("Route", wm9713_enum
[13]);
405 static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls
=
406 SOC_DAPM_ENUM("Route", wm9713_enum
[14]);
409 static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls
=
410 SOC_DAPM_ENUM("Route", wm9713_enum
[15]);
412 /* Capture source left */
413 static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls
=
414 SOC_DAPM_ENUM("Route", wm9713_enum
[3]);
416 /* Capture source right */
417 static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls
=
418 SOC_DAPM_ENUM("Route", wm9713_enum
[4]);
421 static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls
=
422 SOC_DAPM_ENUM("Route", wm9713_enum
[18]);
424 /* mic source B virtual control */
425 static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls
=
426 SOC_DAPM_ENUM("Route", wm9713_enum
[19]);
428 static const struct snd_soc_dapm_widget wm9713_dapm_widgets
[] = {
429 SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM
, 0, 0,
430 &wm9713_hp_rec_mux_controls
),
431 SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM
, 0, 0,
432 &wm9713_hp_mic_mux_controls
),
433 SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM
, 0, 0,
434 &wm9713_mono_mic_mux_controls
),
435 SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM
, 0, 0,
436 &wm9713_mono_mux_controls
),
437 SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM
, 0, 0,
438 &wm9713_hp_spkl_mux_controls
),
439 SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM
, 0, 0,
440 &wm9713_hp_spkr_mux_controls
),
441 SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM
, 0, 0,
442 &wm9713_hpl_out_mux_controls
),
443 SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM
, 0, 0,
444 &wm9713_hpr_out_mux_controls
),
445 SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM
, 0, 0,
446 &wm9713_out3_mux_controls
),
447 SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM
, 0, 0,
448 &wm9713_out4_mux_controls
),
449 SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM
, 0, 0,
450 &wm9713_dac_inv1_mux_controls
),
451 SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM
, 0, 0,
452 &wm9713_dac_inv2_mux_controls
),
453 SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM
, 0, 0,
454 &wm9713_rec_srcl_mux_controls
),
455 SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM
, 0, 0,
456 &wm9713_rec_srcr_mux_controls
),
457 SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM
, 0, 0,
458 &wm9713_mic_sel_mux_controls
),
459 SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM
, 0, 0,
460 &wm9713_micb_sel_mux_controls
),
461 SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID
, 3, 1,
462 &wm9713_hpl_mixer_controls
[0], ARRAY_SIZE(wm9713_hpl_mixer_controls
)),
463 SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID
, 2, 1,
464 &wm9713_hpr_mixer_controls
[0], ARRAY_SIZE(wm9713_hpr_mixer_controls
)),
465 SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID
, 0, 1,
466 &wm9713_mono_mixer_controls
[0], ARRAY_SIZE(wm9713_mono_mixer_controls
)),
467 SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID
, 1, 1,
468 &wm9713_speaker_mixer_controls
[0],
469 ARRAY_SIZE(wm9713_speaker_mixer_controls
)),
470 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID
, 7, 1),
471 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID
, 6, 1),
472 SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM
, 0, 0, NULL
, 0),
473 SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM
, 0, 0, NULL
, 0),
474 SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM
, 0, 0, NULL
, 0),
475 SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM
, 0, 0, NULL
, 0),
476 SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID
, 12, 1,
477 wm9713_voice_shutdown
, SND_SOC_DAPM_PRE_PMD
),
478 SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID
, 11, 1),
479 SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID
, 5, 1, NULL
, 0),
480 SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID
, 4, 1, NULL
, 0),
481 SND_SOC_DAPM_ADC("Left HiFi ADC", "Left HiFi Capture", SND_SOC_NOPM
, 0, 0),
482 SND_SOC_DAPM_ADC("Right HiFi ADC", "Right HiFi Capture", SND_SOC_NOPM
, 0, 0),
483 SND_SOC_DAPM_ADC("Left Voice ADC", "Left Voice Capture", SND_SOC_NOPM
, 0, 0),
484 SND_SOC_DAPM_ADC("Right Voice ADC", "Right Voice Capture", SND_SOC_NOPM
, 0, 0),
485 SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS
, 10, 1, NULL
, 0),
486 SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS
, 9, 1, NULL
, 0),
487 SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS
, 8, 1, NULL
, 0),
488 SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS
, 7, 1, NULL
, 0),
489 SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS
, 11, 1, NULL
, 0),
490 SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS
, 12, 1, NULL
, 0),
491 SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS
, 13, 1, NULL
, 0),
492 SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS
, 6, 1, NULL
, 0),
493 SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS
, 5, 1, NULL
, 0),
494 SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS
, 4, 1, NULL
, 0),
495 SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS
, 3, 1, NULL
, 0),
496 SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS
, 2, 1, NULL
, 0),
497 SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS
, 1, 1, NULL
, 0),
498 SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS
, 0, 1, NULL
, 0),
499 SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS
, 14, 1),
500 SND_SOC_DAPM_OUTPUT("MONO"),
501 SND_SOC_DAPM_OUTPUT("HPL"),
502 SND_SOC_DAPM_OUTPUT("HPR"),
503 SND_SOC_DAPM_OUTPUT("SPKL"),
504 SND_SOC_DAPM_OUTPUT("SPKR"),
505 SND_SOC_DAPM_OUTPUT("OUT3"),
506 SND_SOC_DAPM_OUTPUT("OUT4"),
507 SND_SOC_DAPM_INPUT("LINEL"),
508 SND_SOC_DAPM_INPUT("LINER"),
509 SND_SOC_DAPM_INPUT("MONOIN"),
510 SND_SOC_DAPM_INPUT("PCBEEP"),
511 SND_SOC_DAPM_INPUT("MIC1"),
512 SND_SOC_DAPM_INPUT("MIC2A"),
513 SND_SOC_DAPM_INPUT("MIC2B"),
514 SND_SOC_DAPM_VMID("VMID"),
517 static const struct snd_soc_dapm_route wm9713_audio_map
[] = {
519 {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"},
520 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
521 {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
522 {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"},
523 {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
524 {"Left HP Mixer", "MonoIn Playback Switch", "Mono In"},
525 {"Left HP Mixer", NULL
, "Capture Headphone Mux"},
528 {"Right HP Mixer", "Beep Playback Switch", "PCBEEP"},
529 {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"},
530 {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
531 {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"},
532 {"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
533 {"Right HP Mixer", "MonoIn Playback Switch", "Mono In"},
534 {"Right HP Mixer", NULL
, "Capture Headphone Mux"},
536 /* virtual mixer - mixes left & right channels for spk and mono */
537 {"AC97 Mixer", NULL
, "Left DAC"},
538 {"AC97 Mixer", NULL
, "Right DAC"},
539 {"Line Mixer", NULL
, "Right Line In"},
540 {"Line Mixer", NULL
, "Left Line In"},
541 {"HP Mixer", NULL
, "Left HP Mixer"},
542 {"HP Mixer", NULL
, "Right HP Mixer"},
543 {"Capture Mixer", NULL
, "Left Capture Source"},
544 {"Capture Mixer", NULL
, "Right Capture Source"},
547 {"Speaker Mixer", "Beep Playback Switch", "PCBEEP"},
548 {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"},
549 {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
550 {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"},
551 {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
552 {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"},
555 {"Mono Mixer", "Beep Playback Switch", "PCBEEP"},
556 {"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
557 {"Mono Mixer", "Aux Playback Switch", "Aux DAC"},
558 {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"},
559 {"Mono Mixer", "PCM Playback Switch", "AC97 Mixer"},
560 {"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
561 {"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
562 {"Mono Mixer", NULL
, "Capture Mono Mux"},
565 {"DAC Inv Mux 1", "Mono", "Mono Mixer"},
566 {"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
567 {"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
568 {"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
569 {"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
572 {"DAC Inv Mux 2", "Mono", "Mono Mixer"},
573 {"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
574 {"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
575 {"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
576 {"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
578 /* headphone left mux */
579 {"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
581 /* headphone right mux */
582 {"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
584 /* speaker left mux */
585 {"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
586 {"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
587 {"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
589 /* speaker right mux */
590 {"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
591 {"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
592 {"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
595 {"Mono Out Mux", "Mono", "Mono Mixer"},
596 {"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
599 {"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
602 {"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
605 {"HPL", NULL
, "Left Headphone"},
606 {"Left Headphone", NULL
, "Left Headphone Out Mux"},
607 {"HPR", NULL
, "Right Headphone"},
608 {"Right Headphone", NULL
, "Right Headphone Out Mux"},
609 {"OUT3", NULL
, "Out 3"},
610 {"Out 3", NULL
, "Out 3 Mux"},
611 {"OUT4", NULL
, "Out 4"},
612 {"Out 4", NULL
, "Out 4 Mux"},
613 {"SPKL", NULL
, "Left Speaker"},
614 {"Left Speaker", NULL
, "Left Speaker Out Mux"},
615 {"SPKR", NULL
, "Right Speaker"},
616 {"Right Speaker", NULL
, "Right Speaker Out Mux"},
617 {"MONO", NULL
, "Mono Out"},
618 {"Mono Out", NULL
, "Mono Out Mux"},
621 {"Left Line In", NULL
, "LINEL"},
622 {"Right Line In", NULL
, "LINER"},
623 {"Mono In", NULL
, "MONOIN"},
624 {"Mic A PGA", NULL
, "Mic A Pre Amp"},
625 {"Mic B PGA", NULL
, "Mic B Pre Amp"},
627 /* left capture select */
628 {"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
629 {"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
630 {"Left Capture Source", "Line", "LINEL"},
631 {"Left Capture Source", "Mono In", "MONOIN"},
632 {"Left Capture Source", "Headphone", "Left HP Mixer"},
633 {"Left Capture Source", "Speaker", "Speaker Mixer"},
634 {"Left Capture Source", "Mono Out", "Mono Mixer"},
636 /* right capture select */
637 {"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
638 {"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
639 {"Right Capture Source", "Line", "LINER"},
640 {"Right Capture Source", "Mono In", "MONOIN"},
641 {"Right Capture Source", "Headphone", "Right HP Mixer"},
642 {"Right Capture Source", "Speaker", "Speaker Mixer"},
643 {"Right Capture Source", "Mono Out", "Mono Mixer"},
646 {"Left ADC", NULL
, "Left Capture Source"},
647 {"Left Voice ADC", NULL
, "Left ADC"},
648 {"Left HiFi ADC", NULL
, "Left ADC"},
651 {"Right ADC", NULL
, "Right Capture Source"},
652 {"Right Voice ADC", NULL
, "Right ADC"},
653 {"Right HiFi ADC", NULL
, "Right ADC"},
656 {"Mic A Pre Amp", NULL
, "Mic A Source"},
657 {"Mic A Source", "Mic 1", "MIC1"},
658 {"Mic A Source", "Mic 2 A", "MIC2A"},
659 {"Mic A Source", "Mic 2 B", "Mic B Source"},
660 {"Mic B Pre Amp", "MPB", "Mic B Source"},
661 {"Mic B Source", NULL
, "MIC2B"},
663 /* headphone capture */
664 {"Capture Headphone Mux", "Stereo", "Capture Mixer"},
665 {"Capture Headphone Mux", "Left", "Left Capture Source"},
666 {"Capture Headphone Mux", "Right", "Right Capture Source"},
669 {"Capture Mono Mux", "Stereo", "Capture Mixer"},
670 {"Capture Mono Mux", "Left", "Left Capture Source"},
671 {"Capture Mono Mux", "Right", "Right Capture Source"},
674 static unsigned int ac97_read(struct snd_soc_codec
*codec
,
677 u16
*cache
= codec
->reg_cache
;
679 if (reg
== AC97_RESET
|| reg
== AC97_GPIO_STATUS
||
680 reg
== AC97_VENDOR_ID1
|| reg
== AC97_VENDOR_ID2
||
682 return soc_ac97_ops
->read(codec
->ac97
, reg
);
686 if (reg
>= (ARRAY_SIZE(wm9713_reg
)))
693 static int ac97_write(struct snd_soc_codec
*codec
, unsigned int reg
,
696 u16
*cache
= codec
->reg_cache
;
697 soc_ac97_ops
->write(codec
->ac97
, reg
, val
);
699 if (reg
< (ARRAY_SIZE(wm9713_reg
)))
714 /* The size in bits of the PLL divide multiplied by 10
715 * to allow rounding later */
716 #define FIXED_PLL_SIZE ((1 << 22) * 10)
718 static void pll_factors(struct snd_soc_codec
*codec
,
719 struct _pll_div
*pll_div
, unsigned int source
)
722 unsigned int K
, Ndiv
, Nmod
, target
;
724 /* The the PLL output is always 98.304MHz. */
727 /* If the input frequency is over 14.4MHz then scale it down. */
728 if (source
> 14400000) {
732 if (source
> 14400000) {
743 /* Low frequency sources require an additional divide in the
746 if (source
< 8192000) {
752 Ndiv
= target
/ source
;
753 if ((Ndiv
< 5) || (Ndiv
> 12))
755 "WM9713 PLL N value %u out of recommended range!\n",
759 Nmod
= target
% source
;
760 Kpart
= FIXED_PLL_SIZE
* (long long)Nmod
;
762 do_div(Kpart
, source
);
764 K
= Kpart
& 0xFFFFFFFF;
766 /* Check if we need to round */
770 /* Move down to proper range now rounding is done */
777 * Please note that changing the PLL input frequency may require
778 * resynchronisation with the AC97 controller.
780 static int wm9713_set_pll(struct snd_soc_codec
*codec
,
781 int pll_id
, unsigned int freq_in
, unsigned int freq_out
)
783 struct wm9713_priv
*wm9713
= snd_soc_codec_get_drvdata(codec
);
785 struct _pll_div pll_div
;
789 /* disable PLL power and select ext source */
790 reg
= ac97_read(codec
, AC97_HANDSET_RATE
);
791 ac97_write(codec
, AC97_HANDSET_RATE
, reg
| 0x0080);
792 reg
= ac97_read(codec
, AC97_EXTENDED_MID
);
793 ac97_write(codec
, AC97_EXTENDED_MID
, reg
| 0x0200);
798 pll_factors(codec
, &pll_div
, freq_in
);
800 if (pll_div
.k
== 0) {
801 reg
= (pll_div
.n
<< 12) | (pll_div
.lf
<< 11) |
802 (pll_div
.divsel
<< 9) | (pll_div
.divctl
<< 8);
803 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
805 /* write the fractional k to the reg 0x46 pages */
806 reg2
= (pll_div
.n
<< 12) | (pll_div
.lf
<< 11) | (1 << 10) |
807 (pll_div
.divsel
<< 9) | (pll_div
.divctl
<< 8);
810 reg
= reg2
| (0x5 << 4) | (pll_div
.k
>> 20);
811 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
814 reg
= reg2
| (0x4 << 4) | ((pll_div
.k
>> 16) & 0xf);
815 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
818 reg
= reg2
| (0x3 << 4) | ((pll_div
.k
>> 12) & 0xf);
819 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
822 reg
= reg2
| (0x2 << 4) | ((pll_div
.k
>> 8) & 0xf);
823 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
826 reg
= reg2
| (0x1 << 4) | ((pll_div
.k
>> 4) & 0xf);
827 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
829 reg
= reg2
| (0x0 << 4) | (pll_div
.k
& 0xf); /* K [3:0] */
830 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
);
833 /* turn PLL on and select as source */
834 reg
= ac97_read(codec
, AC97_EXTENDED_MID
);
835 ac97_write(codec
, AC97_EXTENDED_MID
, reg
& 0xfdff);
836 reg
= ac97_read(codec
, AC97_HANDSET_RATE
);
837 ac97_write(codec
, AC97_HANDSET_RATE
, reg
& 0xff7f);
838 wm9713
->pll_in
= freq_in
;
840 /* wait 10ms AC97 link frames for the link to stabilise */
841 schedule_timeout_interruptible(msecs_to_jiffies(10));
845 static int wm9713_set_dai_pll(struct snd_soc_dai
*codec_dai
, int pll_id
,
846 int source
, unsigned int freq_in
, unsigned int freq_out
)
848 struct snd_soc_codec
*codec
= codec_dai
->codec
;
849 return wm9713_set_pll(codec
, pll_id
, freq_in
, freq_out
);
853 * Tristate the PCM DAI lines, tristate can be disabled by calling
854 * wm9713_set_dai_fmt()
856 static int wm9713_set_dai_tristate(struct snd_soc_dai
*codec_dai
,
859 struct snd_soc_codec
*codec
= codec_dai
->codec
;
860 u16 reg
= ac97_read(codec
, AC97_CENTER_LFE_MASTER
) & 0x9fff;
863 ac97_write(codec
, AC97_CENTER_LFE_MASTER
, reg
);
869 * Configure WM9713 clock dividers.
870 * Voice DAC needs 256 FS
872 static int wm9713_set_dai_clkdiv(struct snd_soc_dai
*codec_dai
,
875 struct snd_soc_codec
*codec
= codec_dai
->codec
;
879 case WM9713_PCMCLK_DIV
:
880 reg
= ac97_read(codec
, AC97_HANDSET_RATE
) & 0xf0ff;
881 ac97_write(codec
, AC97_HANDSET_RATE
, reg
| div
);
883 case WM9713_CLKA_MULT
:
884 reg
= ac97_read(codec
, AC97_HANDSET_RATE
) & 0xfffd;
885 ac97_write(codec
, AC97_HANDSET_RATE
, reg
| div
);
887 case WM9713_CLKB_MULT
:
888 reg
= ac97_read(codec
, AC97_HANDSET_RATE
) & 0xfffb;
889 ac97_write(codec
, AC97_HANDSET_RATE
, reg
| div
);
891 case WM9713_HIFI_DIV
:
892 reg
= ac97_read(codec
, AC97_HANDSET_RATE
) & 0x8fff;
893 ac97_write(codec
, AC97_HANDSET_RATE
, reg
| div
);
895 case WM9713_PCMBCLK_DIV
:
896 reg
= ac97_read(codec
, AC97_CENTER_LFE_MASTER
) & 0xf1ff;
897 ac97_write(codec
, AC97_CENTER_LFE_MASTER
, reg
| div
);
899 case WM9713_PCMCLK_PLL_DIV
:
900 reg
= ac97_read(codec
, AC97_LINE1_LEVEL
) & 0xff80;
901 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
| 0x60 | div
);
903 case WM9713_HIFI_PLL_DIV
:
904 reg
= ac97_read(codec
, AC97_LINE1_LEVEL
) & 0xff80;
905 ac97_write(codec
, AC97_LINE1_LEVEL
, reg
| 0x70 | div
);
914 static int wm9713_set_dai_fmt(struct snd_soc_dai
*codec_dai
,
917 struct snd_soc_codec
*codec
= codec_dai
->codec
;
918 u16 gpio
= ac97_read(codec
, AC97_GPIO_CFG
) & 0xffc5;
922 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
923 case SND_SOC_DAIFMT_CBM_CFM
:
927 case SND_SOC_DAIFMT_CBM_CFS
:
931 case SND_SOC_DAIFMT_CBS_CFS
:
935 case SND_SOC_DAIFMT_CBS_CFM
:
940 /* clock inversion */
941 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
942 case SND_SOC_DAIFMT_IB_IF
:
945 case SND_SOC_DAIFMT_IB_NF
:
948 case SND_SOC_DAIFMT_NB_IF
:
954 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
955 case SND_SOC_DAIFMT_I2S
:
958 case SND_SOC_DAIFMT_RIGHT_J
:
960 case SND_SOC_DAIFMT_LEFT_J
:
963 case SND_SOC_DAIFMT_DSP_A
:
966 case SND_SOC_DAIFMT_DSP_B
:
971 ac97_write(codec
, AC97_GPIO_CFG
, gpio
);
972 ac97_write(codec
, AC97_CENTER_LFE_MASTER
, reg
);
976 static int wm9713_pcm_hw_params(struct snd_pcm_substream
*substream
,
977 struct snd_pcm_hw_params
*params
,
978 struct snd_soc_dai
*dai
)
980 struct snd_soc_codec
*codec
= dai
->codec
;
981 u16 reg
= ac97_read(codec
, AC97_CENTER_LFE_MASTER
) & 0xfff3;
983 switch (params_width(params
)) {
997 /* enable PCM interface in master mode */
998 ac97_write(codec
, AC97_CENTER_LFE_MASTER
, reg
);
1002 static int ac97_hifi_prepare(struct snd_pcm_substream
*substream
,
1003 struct snd_soc_dai
*dai
)
1005 struct snd_soc_codec
*codec
= dai
->codec
;
1006 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1010 vra
= ac97_read(codec
, AC97_EXTENDED_STATUS
);
1011 ac97_write(codec
, AC97_EXTENDED_STATUS
, vra
| 0x1);
1013 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
1014 reg
= AC97_PCM_FRONT_DAC_RATE
;
1016 reg
= AC97_PCM_LR_ADC_RATE
;
1018 return ac97_write(codec
, reg
, runtime
->rate
);
1021 static int ac97_aux_prepare(struct snd_pcm_substream
*substream
,
1022 struct snd_soc_dai
*dai
)
1024 struct snd_soc_codec
*codec
= dai
->codec
;
1025 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1028 vra
= ac97_read(codec
, AC97_EXTENDED_STATUS
);
1029 ac97_write(codec
, AC97_EXTENDED_STATUS
, vra
| 0x1);
1030 xsle
= ac97_read(codec
, AC97_PCI_SID
);
1031 ac97_write(codec
, AC97_PCI_SID
, xsle
| 0x8000);
1033 if (substream
->stream
!= SNDRV_PCM_STREAM_PLAYBACK
)
1036 return ac97_write(codec
, AC97_PCM_SURR_DAC_RATE
, runtime
->rate
);
1039 #define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
1040 SNDRV_PCM_RATE_11025 | \
1041 SNDRV_PCM_RATE_22050 | \
1042 SNDRV_PCM_RATE_44100 | \
1043 SNDRV_PCM_RATE_48000)
1045 #define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \
1046 SNDRV_PCM_RATE_11025 | \
1047 SNDRV_PCM_RATE_16000 | \
1048 SNDRV_PCM_RATE_22050 | \
1049 SNDRV_PCM_RATE_44100 | \
1050 SNDRV_PCM_RATE_48000)
1052 #define WM9713_PCM_FORMATS \
1053 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1054 SNDRV_PCM_FORMAT_S24_LE)
1056 static const struct snd_soc_dai_ops wm9713_dai_ops_hifi
= {
1057 .prepare
= ac97_hifi_prepare
,
1058 .set_clkdiv
= wm9713_set_dai_clkdiv
,
1059 .set_pll
= wm9713_set_dai_pll
,
1062 static const struct snd_soc_dai_ops wm9713_dai_ops_aux
= {
1063 .prepare
= ac97_aux_prepare
,
1064 .set_clkdiv
= wm9713_set_dai_clkdiv
,
1065 .set_pll
= wm9713_set_dai_pll
,
1068 static const struct snd_soc_dai_ops wm9713_dai_ops_voice
= {
1069 .hw_params
= wm9713_pcm_hw_params
,
1070 .set_clkdiv
= wm9713_set_dai_clkdiv
,
1071 .set_pll
= wm9713_set_dai_pll
,
1072 .set_fmt
= wm9713_set_dai_fmt
,
1073 .set_tristate
= wm9713_set_dai_tristate
,
1076 static struct snd_soc_dai_driver wm9713_dai
[] = {
1078 .name
= "wm9713-hifi",
1080 .stream_name
= "HiFi Playback",
1083 .rates
= WM9713_RATES
,
1084 .formats
= SND_SOC_STD_AC97_FMTS
,},
1086 .stream_name
= "HiFi Capture",
1089 .rates
= WM9713_RATES
,
1090 .formats
= SND_SOC_STD_AC97_FMTS
,},
1091 .ops
= &wm9713_dai_ops_hifi
,
1094 .name
= "wm9713-aux",
1096 .stream_name
= "Aux Playback",
1099 .rates
= WM9713_RATES
,
1100 .formats
= SND_SOC_STD_AC97_FMTS
,},
1101 .ops
= &wm9713_dai_ops_aux
,
1104 .name
= "wm9713-voice",
1106 .stream_name
= "Voice Playback",
1109 .rates
= WM9713_PCM_RATES
,
1110 .formats
= WM9713_PCM_FORMATS
,},
1112 .stream_name
= "Voice Capture",
1115 .rates
= WM9713_PCM_RATES
,
1116 .formats
= WM9713_PCM_FORMATS
,},
1117 .ops
= &wm9713_dai_ops_voice
,
1118 .symmetric_rates
= 1,
1122 int wm9713_reset(struct snd_soc_codec
*codec
, int try_warm
)
1124 if (try_warm
&& soc_ac97_ops
->warm_reset
) {
1125 soc_ac97_ops
->warm_reset(codec
->ac97
);
1126 if (ac97_read(codec
, 0) == wm9713_reg
[0])
1130 soc_ac97_ops
->reset(codec
->ac97
);
1131 if (soc_ac97_ops
->warm_reset
)
1132 soc_ac97_ops
->warm_reset(codec
->ac97
);
1133 if (ac97_read(codec
, 0) != wm9713_reg
[0]) {
1134 dev_err(codec
->dev
, "Failed to reset: AC97 link error\n");
1140 EXPORT_SYMBOL_GPL(wm9713_reset
);
1142 static int wm9713_set_bias_level(struct snd_soc_codec
*codec
,
1143 enum snd_soc_bias_level level
)
1148 case SND_SOC_BIAS_ON
:
1149 /* enable thermal shutdown */
1150 reg
= ac97_read(codec
, AC97_EXTENDED_MID
) & 0x1bff;
1151 ac97_write(codec
, AC97_EXTENDED_MID
, reg
);
1153 case SND_SOC_BIAS_PREPARE
:
1155 case SND_SOC_BIAS_STANDBY
:
1156 /* enable master bias and vmid */
1157 reg
= ac97_read(codec
, AC97_EXTENDED_MID
) & 0x3bff;
1158 ac97_write(codec
, AC97_EXTENDED_MID
, reg
);
1159 ac97_write(codec
, AC97_POWERDOWN
, 0x0000);
1161 case SND_SOC_BIAS_OFF
:
1162 /* disable everything including AC link */
1163 ac97_write(codec
, AC97_EXTENDED_MID
, 0xffff);
1164 ac97_write(codec
, AC97_EXTENDED_MSTATUS
, 0xffff);
1165 ac97_write(codec
, AC97_POWERDOWN
, 0xffff);
1168 codec
->dapm
.bias_level
= level
;
1172 static int wm9713_soc_suspend(struct snd_soc_codec
*codec
)
1176 /* Disable everything except touchpanel - that will be handled
1177 * by the touch driver and left disabled if touch is not in
1179 reg
= ac97_read(codec
, AC97_EXTENDED_MID
);
1180 ac97_write(codec
, AC97_EXTENDED_MID
, reg
| 0x7fff);
1181 ac97_write(codec
, AC97_EXTENDED_MSTATUS
, 0xffff);
1182 ac97_write(codec
, AC97_POWERDOWN
, 0x6f00);
1183 ac97_write(codec
, AC97_POWERDOWN
, 0xffff);
1188 static int wm9713_soc_resume(struct snd_soc_codec
*codec
)
1190 struct wm9713_priv
*wm9713
= snd_soc_codec_get_drvdata(codec
);
1192 u16
*cache
= codec
->reg_cache
;
1194 ret
= wm9713_reset(codec
, 1);
1198 wm9713_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
1200 /* do we need to re-start the PLL ? */
1202 wm9713_set_pll(codec
, 0, wm9713
->pll_in
, 0);
1204 /* only synchronise the codec if warm reset failed */
1206 for (i
= 2; i
< ARRAY_SIZE(wm9713_reg
) << 1; i
+= 2) {
1207 if (i
== AC97_POWERDOWN
|| i
== AC97_EXTENDED_MID
||
1208 i
== AC97_EXTENDED_MSTATUS
|| i
> 0x66)
1210 soc_ac97_ops
->write(codec
->ac97
, i
, cache
[i
>>1]);
1217 static int wm9713_soc_probe(struct snd_soc_codec
*codec
)
1221 ret
= snd_soc_new_ac97_codec(codec
);
1225 /* do a cold reset for the controller and then try
1226 * a warm reset followed by an optional cold reset for codec */
1227 wm9713_reset(codec
, 0);
1228 ret
= wm9713_reset(codec
, 1);
1232 wm9713_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
1234 /* unmute the adc - move to kcontrol */
1235 reg
= ac97_read(codec
, AC97_CD
) & 0x7fff;
1236 ac97_write(codec
, AC97_CD
, reg
);
1241 snd_soc_free_ac97_codec(codec
);
1245 static int wm9713_soc_remove(struct snd_soc_codec
*codec
)
1247 snd_soc_free_ac97_codec(codec
);
1251 static struct snd_soc_codec_driver soc_codec_dev_wm9713
= {
1252 .probe
= wm9713_soc_probe
,
1253 .remove
= wm9713_soc_remove
,
1254 .suspend
= wm9713_soc_suspend
,
1255 .resume
= wm9713_soc_resume
,
1257 .write
= ac97_write
,
1258 .set_bias_level
= wm9713_set_bias_level
,
1259 .reg_cache_size
= ARRAY_SIZE(wm9713_reg
),
1260 .reg_word_size
= sizeof(u16
),
1261 .reg_cache_step
= 2,
1262 .reg_cache_default
= wm9713_reg
,
1264 .controls
= wm9713_snd_ac97_controls
,
1265 .num_controls
= ARRAY_SIZE(wm9713_snd_ac97_controls
),
1266 .dapm_widgets
= wm9713_dapm_widgets
,
1267 .num_dapm_widgets
= ARRAY_SIZE(wm9713_dapm_widgets
),
1268 .dapm_routes
= wm9713_audio_map
,
1269 .num_dapm_routes
= ARRAY_SIZE(wm9713_audio_map
),
1272 static int wm9713_probe(struct platform_device
*pdev
)
1274 struct wm9713_priv
*wm9713
;
1276 wm9713
= devm_kzalloc(&pdev
->dev
, sizeof(*wm9713
), GFP_KERNEL
);
1280 mutex_init(&wm9713
->lock
);
1282 platform_set_drvdata(pdev
, wm9713
);
1284 return snd_soc_register_codec(&pdev
->dev
,
1285 &soc_codec_dev_wm9713
, wm9713_dai
, ARRAY_SIZE(wm9713_dai
));
1288 static int wm9713_remove(struct platform_device
*pdev
)
1290 snd_soc_unregister_codec(&pdev
->dev
);
1294 static struct platform_driver wm9713_codec_driver
= {
1296 .name
= "wm9713-codec",
1297 .owner
= THIS_MODULE
,
1300 .probe
= wm9713_probe
,
1301 .remove
= wm9713_remove
,
1304 module_platform_driver(wm9713_codec_driver
);
1306 MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
1307 MODULE_AUTHOR("Liam Girdwood");
1308 MODULE_LICENSE("GPL");