2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 * Universal interface for Audio Codec '97
5 * For more details look to AC '97 component specification revision 2.2
6 * by Intel Corporation (http://developer.intel.com) and to datasheets
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "ac97_local.h"
27 #include "ac97_patch.h"
30 * Chip specific initialization
33 static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count)
37 for (idx = 0; idx < count; idx++)
38 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97))) < 0)
43 /* replace with a new TLV */
44 static void reset_tlv(struct snd_ac97 *ac97, const char *name,
45 const unsigned int *tlv)
47 struct snd_ctl_elem_id sid;
48 struct snd_kcontrol *kctl;
49 memset(&sid, 0, sizeof(sid));
50 strcpy(sid.name, name);
51 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
52 kctl = snd_ctl_find_id(ac97->bus->card, &sid);
53 if (kctl && kctl->tlv.p)
57 /* set to the page, update bits and restore the page */
58 static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
60 unsigned short page_save;
63 mutex_lock(&ac97->page_mutex);
64 page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
65 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
66 ret = snd_ac97_update_bits(ac97, reg, mask, value);
67 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
68 mutex_unlock(&ac97->page_mutex); /* unlock paging */
73 * shared line-in/mic controls
75 static int ac97_enum_text_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo,
76 const char **texts, unsigned int nums)
78 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
80 uinfo->value.enumerated.items = nums;
81 if (uinfo->value.enumerated.item > nums - 1)
82 uinfo->value.enumerated.item = nums - 1;
83 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
87 static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
89 static const char *texts[] = { "Shared", "Independent" };
90 return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
93 static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
95 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
97 ucontrol->value.enumerated.item[0] = ac97->indep_surround;
101 static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
103 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
104 unsigned char indep = !!ucontrol->value.enumerated.item[0];
106 if (indep != ac97->indep_surround) {
107 ac97->indep_surround = indep;
108 if (ac97->build_ops->update_jacks)
109 ac97->build_ops->update_jacks(ac97);
115 static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
117 static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
118 return ac97_enum_text_info(kcontrol, uinfo, texts,
119 kcontrol->private_value);
122 static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
124 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
126 ucontrol->value.enumerated.item[0] = ac97->channel_mode;
130 static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
132 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
133 unsigned char mode = ucontrol->value.enumerated.item[0];
135 if (mode >= kcontrol->private_value)
138 if (mode != ac97->channel_mode) {
139 ac97->channel_mode = mode;
140 if (ac97->build_ops->update_jacks)
141 ac97->build_ops->update_jacks(ac97);
147 #define AC97_SURROUND_JACK_MODE_CTL \
149 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
150 .name = "Surround Jack Mode", \
151 .info = ac97_surround_jack_mode_info, \
152 .get = ac97_surround_jack_mode_get, \
153 .put = ac97_surround_jack_mode_put, \
156 #define AC97_CHANNEL_MODE_CTL \
158 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
159 .name = "Channel Mode", \
160 .info = ac97_channel_mode_info, \
161 .get = ac97_channel_mode_get, \
162 .put = ac97_channel_mode_put, \
163 .private_value = 3, \
166 #define AC97_CHANNEL_MODE_4CH_CTL \
168 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
169 .name = "Channel Mode", \
170 .info = ac97_channel_mode_info, \
171 .get = ac97_channel_mode_get, \
172 .put = ac97_channel_mode_put, \
173 .private_value = 2, \
176 #define AC97_CHANNEL_MODE_8CH_CTL \
178 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
179 .name = "Channel Mode", \
180 .info = ac97_channel_mode_info, \
181 .get = ac97_channel_mode_get, \
182 .put = ac97_channel_mode_put, \
183 .private_value = 4, \
186 static inline int is_surround_on(struct snd_ac97 *ac97)
188 return ac97->channel_mode >= 1;
191 static inline int is_clfe_on(struct snd_ac97 *ac97)
193 return ac97->channel_mode >= 2;
196 /* system has shared jacks with surround out enabled */
197 static inline int is_shared_surrout(struct snd_ac97 *ac97)
199 return !ac97->indep_surround && is_surround_on(ac97);
202 /* system has shared jacks with center/lfe out enabled */
203 static inline int is_shared_clfeout(struct snd_ac97 *ac97)
205 return !ac97->indep_surround && is_clfe_on(ac97);
208 /* system has shared jacks with line in enabled */
209 static inline int is_shared_linein(struct snd_ac97 *ac97)
211 return !ac97->indep_surround && !is_surround_on(ac97);
214 /* system has shared jacks with mic in enabled */
215 static inline int is_shared_micin(struct snd_ac97 *ac97)
217 return !ac97->indep_surround && !is_clfe_on(ac97);
220 static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
222 return is_surround_on(ac97);
225 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
226 /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
228 /* It is possible to indicate to the Yamaha YMF7x3 the type of
229 speakers being used. */
231 static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
232 struct snd_ctl_elem_info *uinfo)
234 static char *texts[3] = {
235 "Standard", "Small", "Smaller"
238 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
240 uinfo->value.enumerated.items = 3;
241 if (uinfo->value.enumerated.item > 2)
242 uinfo->value.enumerated.item = 2;
243 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
247 static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
248 struct snd_ctl_elem_value *ucontrol)
250 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
253 val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
254 val = (val >> 10) & 3;
255 if (val > 0) /* 0 = invalid */
257 ucontrol->value.enumerated.item[0] = val;
261 static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_value *ucontrol)
264 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
267 if (ucontrol->value.enumerated.item[0] > 2)
269 val = (ucontrol->value.enumerated.item[0] + 1) << 10;
270 return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
273 static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
276 .name = "3D Control - Speaker",
277 .info = snd_ac97_ymf7x3_info_speaker,
278 .get = snd_ac97_ymf7x3_get_speaker,
279 .put = snd_ac97_ymf7x3_put_speaker,
282 /* It is possible to indicate to the Yamaha YMF7x3 the source to
283 direct to the S/PDIF output. */
284 static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_info *uinfo)
287 static char *texts[2] = { "AC-Link", "A/D Converter" };
289 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
291 uinfo->value.enumerated.items = 2;
292 if (uinfo->value.enumerated.item > 1)
293 uinfo->value.enumerated.item = 1;
294 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
298 static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
301 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
304 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
305 ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
309 static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_value *ucontrol)
312 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
315 if (ucontrol->value.enumerated.item[0] > 1)
317 val = ucontrol->value.enumerated.item[0] << 1;
318 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
321 static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
323 struct snd_kcontrol *kctl;
326 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
327 err = snd_ctl_add(ac97->bus->card, kctl);
330 strcpy(kctl->id.name, "3D Control - Wide");
331 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
332 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
333 err = snd_ctl_add(ac97->bus->card,
334 snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
338 snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
342 static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
344 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
345 AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
347 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
348 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
349 .info = snd_ac97_ymf7x3_spdif_source_info,
350 .get = snd_ac97_ymf7x3_spdif_source_get,
351 .put = snd_ac97_ymf7x3_spdif_source_put,
353 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
354 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
357 static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
361 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
364 err = patch_build_controls(ac97,
365 snd_ac97_yamaha_ymf743_controls_spdif, 3);
368 /* set default PCM S/PDIF params */
369 /* PCM audio,no copyright,no preemphasis,PCM coder,original */
370 snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
374 static struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
375 .build_spdif = patch_yamaha_ymf743_build_spdif,
376 .build_3d = patch_yamaha_ymf7x3_3d,
379 static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
381 ac97->build_ops = &patch_yamaha_ymf743_ops;
382 ac97->caps |= AC97_BC_BASS_TREBLE;
383 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
384 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
385 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
389 /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
390 The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
391 By default, no output pin is selected, and the S/PDIF signal is not output.
392 There is also a bit to mute S/PDIF output in a vendor-specific register. */
393 static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
395 static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
397 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
399 uinfo->value.enumerated.items = 3;
400 if (uinfo->value.enumerated.item > 2)
401 uinfo->value.enumerated.item = 2;
402 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
406 static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
408 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
411 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
412 ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
416 static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
418 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
421 if (ucontrol->value.enumerated.item[0] > 2)
423 val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
424 (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
425 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
426 /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
427 snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
430 static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
432 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
433 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
434 .info = snd_ac97_ymf7x3_spdif_source_info,
435 .get = snd_ac97_ymf7x3_spdif_source_get,
436 .put = snd_ac97_ymf7x3_spdif_source_put,
439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
440 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
441 .info = snd_ac97_ymf753_spdif_output_pin_info,
442 .get = snd_ac97_ymf753_spdif_output_pin_get,
443 .put = snd_ac97_ymf753_spdif_output_pin_put,
445 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
446 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
449 static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
453 if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
458 static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
459 .build_3d = patch_yamaha_ymf7x3_3d,
460 .build_post_spdif = patch_yamaha_ymf753_post_spdif
463 static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
465 /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
466 This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
467 The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
468 The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
469 By default, no output pin is selected, and the S/PDIF signal is not output.
470 There is also a bit to mute S/PDIF output in a vendor-specific register.
472 ac97->build_ops = &patch_yamaha_ymf753_ops;
473 ac97->caps |= AC97_BC_BASS_TREBLE;
474 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
479 * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
480 * removed broken wolfson00 patch.
481 * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
484 static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = {
485 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
486 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
489 static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
491 /* This is known to work for the ViewSonic ViewPad 1000
492 * Randolph Bentson <bentson@holmsjoen.com>
493 * WM9703/9707/9708/9717
497 for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
498 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
501 snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
505 static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
506 .build_specific = patch_wolfson_wm9703_specific,
509 static int patch_wolfson03(struct snd_ac97 * ac97)
511 ac97->build_ops = &patch_wolfson_wm9703_ops;
515 static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = {
516 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
517 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
518 AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
519 AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
520 AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
521 AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
524 static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
527 for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
528 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0)
531 /* patch for DVD noise */
532 snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
536 static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
537 .build_specific = patch_wolfson_wm9704_specific,
540 static int patch_wolfson04(struct snd_ac97 * ac97)
543 ac97->build_ops = &patch_wolfson_wm9704_ops;
547 static int patch_wolfson_wm9705_specific(struct snd_ac97 * ac97)
550 for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
551 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
554 snd_ac97_write_cache(ac97, 0x72, 0x0808);
558 static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = {
559 .build_specific = patch_wolfson_wm9705_specific,
562 static int patch_wolfson05(struct snd_ac97 * ac97)
565 ac97->build_ops = &patch_wolfson_wm9705_ops;
566 #ifdef CONFIG_TOUCHSCREEN_WM9705
567 /* WM9705 touchscreen uses AUX and VIDEO for touch */
568 ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
573 static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
574 static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
575 static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
576 static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
577 static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
578 static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
579 static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
580 static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
581 static const char* wm9711_rec_sel[] =
582 {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
583 static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
585 static const struct ac97_enum wm9711_enum[] = {
586 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
587 AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
588 AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
589 AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
590 AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
591 AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
592 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
593 AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
594 AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
595 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
598 static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = {
599 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
600 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
601 AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
602 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
603 AC97_ENUM("ALC Function", wm9711_enum[0]),
604 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
605 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
606 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
607 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
608 AC97_ENUM("ALC NG Type", wm9711_enum[9]),
609 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
611 AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
612 AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
613 AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
614 AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
616 AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
617 AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
618 AC97_ENUM("Out3 Mux", wm9711_enum[2]),
619 AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
620 AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
622 AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
623 AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
624 AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
625 AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
626 AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
627 AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
629 AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
630 AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
631 AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
632 AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
633 AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
634 AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
636 AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
637 AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
639 AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
640 AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
641 AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
643 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
644 AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
645 AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
647 AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
648 AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
649 AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
650 AC97_ENUM("Capture Select", wm9711_enum[8]),
652 AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
653 AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
655 AC97_ENUM("Bass Control", wm9711_enum[5]),
656 AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
657 AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
658 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
660 AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
661 AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
662 AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
663 AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
665 AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
666 AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
667 AC97_ENUM("Mic Select Source", wm9711_enum[7]),
668 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
669 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
670 AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
672 AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
673 AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
674 AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
675 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
678 static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
682 for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
683 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0)
686 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808);
687 snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808);
688 snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808);
689 snd_ac97_write_cache(ac97, AC97_AUX, 0x0808);
690 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
691 snd_ac97_write_cache(ac97, AC97_CD, 0x0000);
695 static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
696 .build_specific = patch_wolfson_wm9711_specific,
699 static int patch_wolfson11(struct snd_ac97 * ac97)
702 ac97->build_ops = &patch_wolfson_wm9711_ops;
704 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
705 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
710 static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
711 static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
712 static const char* wm9713_rec_src[] =
713 {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix",
715 static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
716 static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
717 static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
718 static const char* wm9713_spk_pga[] =
719 {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
720 static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
721 static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
722 static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
723 static const char* wm9713_dac_inv[] =
724 {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R",
725 "Headphone Mix Mono", "NC", "Vmid"};
726 static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
727 static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
729 static const struct ac97_enum wm9713_enum[] = {
730 AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
731 AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
732 AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
733 AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
734 AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
735 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
736 AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
737 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
738 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
739 AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
740 AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
741 AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
742 AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
743 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
746 static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
747 AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
748 AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
749 AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
750 AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
752 AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
753 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
754 AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
755 AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
757 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
758 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
759 AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
760 AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
761 AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
762 AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
763 AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
765 AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
766 AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
767 AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
768 AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
770 AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
771 AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
772 AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
773 AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
774 AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
775 AC97_ENUM("Capture Select", wm9713_enum[3]),
777 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
778 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
779 AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
780 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
781 AC97_ENUM("ALC Function", wm9713_enum[5]),
782 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
783 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
784 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
785 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
786 AC97_ENUM("ALC NG Type", wm9713_enum[13]),
787 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
789 AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
790 AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
791 AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
792 AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
793 AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
794 AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
796 AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
797 AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
798 AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
799 AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
800 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
801 AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
803 AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
804 AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
805 AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
806 AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
807 AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
808 AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
810 AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
811 AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
812 AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
813 AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
814 AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
815 AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
817 AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
818 AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
819 AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
820 AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
821 AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
822 AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
824 AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
825 AC97_ENUM("Master Input Mux", wm9713_enum[7]),
826 AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
827 AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
828 AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
830 AC97_ENUM("Bass Control", wm9713_enum[12]),
831 AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
832 AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
833 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
834 AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
835 AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
838 static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {
839 AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
840 AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
841 AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
842 AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
845 static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
849 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
850 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0)
856 static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
860 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
861 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0)
864 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
865 snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
866 snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
867 snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
868 snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
869 snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
870 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
875 static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
877 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
878 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
881 static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
883 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
884 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
885 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
889 static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
890 .build_specific = patch_wolfson_wm9713_specific,
891 .build_3d = patch_wolfson_wm9713_3d,
893 .suspend = patch_wolfson_wm9713_suspend,
894 .resume = patch_wolfson_wm9713_resume
898 static int patch_wolfson13(struct snd_ac97 * ac97)
901 ac97->build_ops = &patch_wolfson_wm9713_ops;
903 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
904 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
906 ac97->scaps &= ~AC97_SCAP_MODEM;
908 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
909 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
910 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
918 static int patch_tritech_tr28028(struct snd_ac97 * ac97)
920 snd_ac97_write_cache(ac97, 0x26, 0x0300);
921 snd_ac97_write_cache(ac97, 0x26, 0x0000);
922 snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
923 snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
928 * Sigmatel STAC97xx codecs
930 static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
932 struct snd_kcontrol *kctl;
935 if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
937 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
938 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
939 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
943 static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
945 struct snd_kcontrol *kctl;
948 if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
950 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
951 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
952 if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
954 strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
955 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
956 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
960 static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
961 AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch",
962 AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
964 /* "Sigmatel " removed due to excessive name length: */
965 static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
966 AC97_SINGLE("Surround Phase Inversion Playback Switch",
967 AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
969 static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
970 AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
971 AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
974 static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
978 snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
979 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
980 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0)
982 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
983 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0)
985 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
986 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0)
988 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
989 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0)
994 static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
995 .build_3d = patch_sigmatel_stac9700_3d,
996 .build_specific = patch_sigmatel_stac97xx_specific
999 static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
1001 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1005 static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1007 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1010 mutex_lock(&ac97->page_mutex);
1011 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1012 err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
1013 (ucontrol->value.integer.value[0] & 1) << 4);
1014 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
1015 mutex_unlock(&ac97->page_mutex);
1019 static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
1020 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1021 .name = "Sigmatel Output Bias Switch",
1022 .info = snd_ac97_info_volsw,
1023 .get = snd_ac97_get_volsw,
1024 .put = snd_ac97_stac9708_put_bias,
1025 .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
1028 static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
1032 /* the register bit is writable, but the function is not implemented: */
1033 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
1035 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
1036 if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
1038 return patch_sigmatel_stac97xx_specific(ac97);
1041 static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
1042 .build_3d = patch_sigmatel_stac9708_3d,
1043 .build_specific = patch_sigmatel_stac9708_specific
1046 static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
1048 unsigned int codec72, codec6c;
1050 ac97->build_ops = &patch_sigmatel_stac9708_ops;
1051 ac97->caps |= 0x10; /* HP (sigmatel surround) support */
1053 codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
1054 codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
1056 if ((codec72==0) && (codec6c==0)) {
1057 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1058 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
1059 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1060 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
1061 } else if ((codec72==0x8000) && (codec6c==0)) {
1062 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1063 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
1064 snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
1065 } else if ((codec72==0x8000) && (codec6c==0x0080)) {
1068 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1072 static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
1074 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1075 if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
1076 // patch for SigmaTel
1077 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1078 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
1079 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1080 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1082 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1086 static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
1088 // patch for SigmaTel
1089 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1090 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1091 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1092 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1093 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1094 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1098 static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
1100 // patch for SigmaTel
1101 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1102 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1103 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1104 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1105 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1106 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1110 static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1112 static char *texts[5] = { "Input/Disabled", "Front Output",
1113 "Rear Output", "Center/LFE Output", "Mixer Output" };
1115 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1117 uinfo->value.enumerated.items = 5;
1118 if (uinfo->value.enumerated.item > 4)
1119 uinfo->value.enumerated.item = 4;
1120 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1124 static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1126 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1127 int shift = kcontrol->private_value;
1130 val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
1132 ucontrol->value.enumerated.item[0] = 0;
1134 ucontrol->value.enumerated.item[0] = 1 + (val & 3);
1138 static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1140 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1141 int shift = kcontrol->private_value;
1144 if (ucontrol->value.enumerated.item[0] > 4)
1146 if (ucontrol->value.enumerated.item[0] == 0)
1149 val = 4 | (ucontrol->value.enumerated.item[0] - 1);
1150 return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
1151 7 << shift, val << shift, 0);
1154 static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1156 static char *texts[7] = { "Mic2 Jack", "Mic1 Jack", "Line In Jack",
1157 "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
1159 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1161 uinfo->value.enumerated.items = 7;
1162 if (uinfo->value.enumerated.item > 6)
1163 uinfo->value.enumerated.item = 6;
1164 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1168 static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1170 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1171 int shift = kcontrol->private_value;
1174 val = ac97->regs[AC97_SIGMATEL_INSEL];
1175 ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
1179 static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1181 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1182 int shift = kcontrol->private_value;
1184 return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
1185 ucontrol->value.enumerated.item[0] << shift, 0);
1188 static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1190 static char *texts[3] = { "None", "Front Jack", "Rear Jack" };
1192 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1194 uinfo->value.enumerated.items = 3;
1195 if (uinfo->value.enumerated.item > 2)
1196 uinfo->value.enumerated.item = 2;
1197 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1201 static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1203 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1205 ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
1209 static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1211 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1213 return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
1214 ucontrol->value.enumerated.item[0], 0);
1217 #define STAC9758_OUTPUT_JACK(xname, shift) \
1218 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1219 .info = snd_ac97_stac9758_output_jack_info, \
1220 .get = snd_ac97_stac9758_output_jack_get, \
1221 .put = snd_ac97_stac9758_output_jack_put, \
1222 .private_value = shift }
1223 #define STAC9758_INPUT_JACK(xname, shift) \
1224 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1225 .info = snd_ac97_stac9758_input_jack_info, \
1226 .get = snd_ac97_stac9758_input_jack_get, \
1227 .put = snd_ac97_stac9758_input_jack_put, \
1228 .private_value = shift }
1229 static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
1230 STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
1231 STAC9758_OUTPUT_JACK("LineIn Jack", 4),
1232 STAC9758_OUTPUT_JACK("Front Jack", 7),
1233 STAC9758_OUTPUT_JACK("Rear Jack", 10),
1234 STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
1235 STAC9758_INPUT_JACK("Mic Input Source", 0),
1236 STAC9758_INPUT_JACK("Line Input Source", 8),
1238 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1239 .name = "Headphone Amp",
1240 .info = snd_ac97_stac9758_phonesel_info,
1241 .get = snd_ac97_stac9758_phonesel_get,
1242 .put = snd_ac97_stac9758_phonesel_put
1244 AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
1245 AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
1248 static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
1252 err = patch_sigmatel_stac97xx_specific(ac97);
1255 err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
1256 ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
1260 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
1261 /* DAC-A to Mix = PCM */
1262 /* DAC-B direct = Surround */
1264 snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
1265 /* DAC-C direct = Center/LFE */
1270 static struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
1271 .build_3d = patch_sigmatel_stac9700_3d,
1272 .build_specific = patch_sigmatel_stac9758_specific
1275 static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
1277 static unsigned short regs[4] = {
1278 AC97_SIGMATEL_OUTSEL,
1279 AC97_SIGMATEL_IOMISC,
1280 AC97_SIGMATEL_INSEL,
1281 AC97_SIGMATEL_VARIOUS
1283 static unsigned short def_regs[4] = {
1284 /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
1285 /* IOMISC */ 0x2001,
1286 /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
1287 /* VARIOUS */ 0x0040
1289 static unsigned short m675_regs[4] = {
1290 /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
1291 /* IOMISC */ 0x2102, /* HP amp on */
1292 /* INSEL */ 0x0203, /* LI:LI, MI:FR */
1293 /* VARIOUS */ 0x0041 /* stereo mic */
1295 unsigned short *pregs = def_regs;
1298 /* Gateway M675 notebook */
1300 ac97->subsystem_vendor == 0x107b &&
1301 ac97->subsystem_device == 0x0601)
1304 // patch for SigmaTel
1305 ac97->build_ops = &patch_sigmatel_stac9758_ops;
1306 /* FIXME: assume only page 0 for writing cache */
1307 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
1308 for (i = 0; i < 4; i++)
1309 snd_ac97_write_cache(ac97, regs[i], pregs[i]);
1311 ac97->flags |= AC97_STEREO_MUTES;
1316 * Cirrus Logic CS42xx codecs
1318 static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
1319 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
1320 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
1323 static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
1327 /* con mask, pro mask, default */
1328 if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
1331 if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
1333 switch (ac97->id & AC97_ID_CS_MASK) {
1334 case AC97_ID_CS4205:
1335 if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
1339 /* set default PCM S/PDIF params */
1340 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1341 snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
1345 static struct snd_ac97_build_ops patch_cirrus_ops = {
1346 .build_spdif = patch_cirrus_build_spdif
1349 static int patch_cirrus_spdif(struct snd_ac97 * ac97)
1351 /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
1352 WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh*
1353 - sp/dif EA ID is not set, but sp/dif is always present.
1354 - enable/disable is spdif register bit 15.
1355 - sp/dif control register is 0x68. differs from AC97:
1356 - valid is bit 14 (vs 15)
1358 - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48)
1359 - sp/dif ssource select is in 0x5e bits 0,1.
1362 ac97->build_ops = &patch_cirrus_ops;
1363 ac97->flags |= AC97_CS_SPDIF;
1364 ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
1365 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1366 snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
1370 static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
1372 /* force the detection of PC Beep */
1373 ac97->flags |= AC97_HAS_PC_BEEP;
1375 return patch_cirrus_spdif(ac97);
1381 static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
1382 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
1385 static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
1389 /* con mask, pro mask, default */
1390 if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
1393 if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
1395 /* set default PCM S/PDIF params */
1396 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1397 snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
1398 snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
1402 static struct snd_ac97_build_ops patch_conexant_ops = {
1403 .build_spdif = patch_conexant_build_spdif
1406 static int patch_conexant(struct snd_ac97 * ac97)
1408 ac97->build_ops = &patch_conexant_ops;
1409 ac97->flags |= AC97_CX_SPDIF;
1410 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1411 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
1415 static int patch_cx20551(struct snd_ac97 *ac97)
1417 snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
1422 * Analog Device AD18xx, AD19xx codecs
1425 static void ad18xx_resume(struct snd_ac97 *ac97)
1427 static unsigned short setup_regs[] = {
1428 AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
1432 for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
1433 unsigned short reg = setup_regs[i];
1434 if (test_bit(reg, ac97->reg_accessed)) {
1435 snd_ac97_write(ac97, reg, ac97->regs[reg]);
1436 snd_ac97_read(ac97, reg);
1440 if (! (ac97->flags & AC97_AD_MULTI))
1441 /* normal restore */
1442 snd_ac97_restore_status(ac97);
1444 /* restore the AD18xx codec configurations */
1445 for (codec = 0; codec < 3; codec++) {
1446 if (! ac97->spec.ad18xx.id[codec])
1448 /* select single codec */
1449 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1450 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1451 ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
1453 /* select all codecs */
1454 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1456 /* restore status */
1457 for (i = 2; i < 0x7c ; i += 2) {
1458 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
1460 if (test_bit(i, ac97->reg_accessed)) {
1461 /* handle multi codecs for AD18xx */
1462 if (i == AC97_PCM) {
1463 for (codec = 0; codec < 3; codec++) {
1464 if (! ac97->spec.ad18xx.id[codec])
1466 /* select single codec */
1467 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1468 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1469 /* update PCM bits */
1470 ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
1472 /* select all codecs */
1473 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1475 } else if (i == AC97_AD_TEST ||
1476 i == AC97_AD_CODEC_CFG ||
1477 i == AC97_AD_SERIAL_CFG)
1478 continue; /* ignore */
1480 snd_ac97_write(ac97, i, ac97->regs[i]);
1481 snd_ac97_read(ac97, i);
1485 snd_ac97_restore_iec958(ac97);
1488 static void ad1888_resume(struct snd_ac97 *ac97)
1490 ad18xx_resume(ac97);
1491 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
1496 static const struct snd_ac97_res_table ad1819_restbl[] = {
1497 { AC97_PHONE, 0x9f1f },
1498 { AC97_MIC, 0x9f1f },
1499 { AC97_LINE, 0x9f1f },
1500 { AC97_CD, 0x9f1f },
1501 { AC97_VIDEO, 0x9f1f },
1502 { AC97_AUX, 0x9f1f },
1503 { AC97_PCM, 0x9f1f },
1504 { } /* terminator */
1507 static int patch_ad1819(struct snd_ac97 * ac97)
1509 unsigned short scfg;
1511 // patch for Analog Devices
1512 scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1513 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
1514 ac97->res_table = ad1819_restbl;
1518 static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
1522 // test for unchained codec
1523 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
1524 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */
1525 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1526 if ((val & 0xff40) != 0x5340)
1528 ac97->spec.ad18xx.unchained[idx] = mask;
1529 ac97->spec.ad18xx.id[idx] = val;
1530 ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
1534 static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
1536 static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
1539 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
1540 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE
1541 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1542 if ((val & 0xff40) != 0x5340)
1545 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
1546 ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
1547 ac97->spec.ad18xx.id[idx] = val;
1548 ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
1552 static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
1554 // already detected?
1555 if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
1557 if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
1559 if (cidx1 < 0 && cidx2 < 0)
1561 // test for chained codecs
1562 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1563 ac97->spec.ad18xx.unchained[unchained_idx]);
1564 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
1565 ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
1568 patch_ad1881_chained1(ac97, cidx1, 0);
1569 else if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
1570 patch_ad1881_chained1(ac97, cidx2, 0);
1571 else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C
1572 patch_ad1881_chained1(ac97, cidx1, 0);
1573 } else if (cidx2 >= 0) {
1574 patch_ad1881_chained1(ac97, cidx2, 0);
1578 static struct snd_ac97_build_ops patch_ad1881_build_ops = {
1580 .resume = ad18xx_resume
1584 static int patch_ad1881(struct snd_ac97 * ac97)
1586 static const char cfg_idxs[3][2] = {
1592 // patch for Analog Devices
1593 unsigned short codecs[3];
1597 val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1598 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
1599 codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
1600 codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
1601 codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
1603 if (! (codecs[0] || codecs[1] || codecs[2]))
1606 for (idx = 0; idx < 3; idx++)
1607 if (ac97->spec.ad18xx.unchained[idx])
1608 patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
1610 if (ac97->spec.ad18xx.id[1]) {
1611 ac97->flags |= AC97_AD_MULTI;
1612 ac97->scaps |= AC97_SCAP_SURROUND_DAC;
1614 if (ac97->spec.ad18xx.id[2]) {
1615 ac97->flags |= AC97_AD_MULTI;
1616 ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
1620 /* select all codecs */
1621 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1622 /* check if only one codec is present */
1623 for (idx = num = 0; idx < 3; idx++)
1624 if (ac97->spec.ad18xx.id[idx])
1627 /* ok, deselect all ID bits */
1628 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
1629 ac97->spec.ad18xx.codec_cfg[0] =
1630 ac97->spec.ad18xx.codec_cfg[1] =
1631 ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
1633 /* required for AD1886/AD1885 combination */
1634 ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
1635 if (ac97->spec.ad18xx.id[0]) {
1636 ac97->id &= 0xffff0000;
1637 ac97->id |= ac97->spec.ad18xx.id[0];
1639 ac97->build_ops = &patch_ad1881_build_ops;
1643 static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1644 AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
1645 /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
1646 AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
1647 AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
1648 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
1649 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1652 static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1654 static int patch_ad1885_specific(struct snd_ac97 * ac97)
1658 if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
1660 reset_tlv(ac97, "Headphone Playback Volume",
1661 db_scale_6bit_6db_max);
1665 static struct snd_ac97_build_ops patch_ad1885_build_ops = {
1666 .build_specific = &patch_ad1885_specific,
1668 .resume = ad18xx_resume
1672 static int patch_ad1885(struct snd_ac97 * ac97)
1675 /* This is required to deal with the Intel D815EEAL2 */
1676 /* i.e. Line out is actually headphone out from codec */
1679 snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
1681 ac97->build_ops = &patch_ad1885_build_ops;
1685 static int patch_ad1886_specific(struct snd_ac97 * ac97)
1687 reset_tlv(ac97, "Headphone Playback Volume",
1688 db_scale_6bit_6db_max);
1692 static struct snd_ac97_build_ops patch_ad1886_build_ops = {
1693 .build_specific = &patch_ad1886_specific,
1695 .resume = ad18xx_resume
1699 static int patch_ad1886(struct snd_ac97 * ac97)
1702 /* Presario700 workaround */
1703 /* for Jack Sense/SPDIF Register misetting causing */
1704 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
1705 ac97->build_ops = &patch_ad1886_build_ops;
1709 /* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
1710 #define AC97_AD198X_MBC 0x0003 /* mic boost */
1711 #define AC97_AD198X_MBC_20 0x0000 /* +20dB */
1712 #define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1713 #define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1714 #define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1715 #define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1716 #define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */
1717 #define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1718 #define AC97_AD198X_VREF_SHIFT 2
1719 #define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1720 #define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1721 #define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1722 #define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1723 #define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */
1724 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1725 #define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1726 #define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1727 #define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
1728 #define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */
1729 #define AC97_AD198X_MSPLT 0x2000 /* mute split */
1730 #define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
1731 #define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
1733 /* MISC 1 bits (AD1986 register 0x76) */
1734 #define AC97_AD1986_MBC 0x0003 /* mic boost */
1735 #define AC97_AD1986_MBC_20 0x0000 /* +20dB */
1736 #define AC97_AD1986_MBC_10 0x0001 /* +10dB */
1737 #define AC97_AD1986_MBC_30 0x0002 /* +30dB */
1738 #define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */
1739 #define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */
1740 #define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1741 #define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */
1742 #define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */
1743 #define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */
1744 #define AC97_AD1986_SRU 0x0010 /* sample rate unlock */
1745 #define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */
1746 #define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */
1747 #define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */
1748 #define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */
1749 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1750 #define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1751 #define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */
1752 #define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */
1753 #define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */
1754 #define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */
1755 #define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */
1757 /* MISC 2 bits (AD1986 register 0x70) */
1758 #define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */
1760 #define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */
1761 #define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */
1762 #define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */
1763 #define AC97_AD1986_CVREF_MASK \
1764 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1765 #define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */
1766 #define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */
1767 #define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */
1768 #define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */
1769 #define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */
1770 #define AC97_AD1986_MVREF_MASK \
1771 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1773 /* MISC 3 bits (AD1986 register 0x7a) */
1774 #define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */
1776 #define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */
1777 #define AC97_AD1986_GPO 0x0008 /* General Purpose Out */
1778 #define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */
1779 #define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */
1780 #define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */
1781 #define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */
1782 #define AC97_AD1986_LVREF_MASK \
1783 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1784 #define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */
1785 #define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */
1786 #define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */
1787 /* input select Surround DACs */
1788 #define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */
1789 /* select C/LFE DACs */
1790 #define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */
1792 /* Serial Config bits (AD1986 register 0x74) (incomplete) */
1793 #define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */
1794 #define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */
1795 #define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */
1796 #define AC97_AD1986_OMS_MASK \
1797 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1798 #define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */
1799 #define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */
1800 #define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */
1801 #define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */
1802 /* are MIC sources */
1803 #define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */
1804 /* are MIC sources */
1805 #define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */
1806 /* are MIC sources */
1807 #define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */
1808 /* are MIC sources */
1811 static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1813 static char *texts[2] = { "AC-Link", "A/D Converter" };
1815 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1817 uinfo->value.enumerated.items = 2;
1818 if (uinfo->value.enumerated.item > 1)
1819 uinfo->value.enumerated.item = 1;
1820 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1824 static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1826 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1829 val = ac97->regs[AC97_AD_SERIAL_CFG];
1830 ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
1834 static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1836 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1839 if (ucontrol->value.enumerated.item[0] > 1)
1841 val = ucontrol->value.enumerated.item[0] << 2;
1842 return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
1845 static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
1846 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1847 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1848 .info = snd_ac97_ad198x_spdif_source_info,
1849 .get = snd_ac97_ad198x_spdif_source_get,
1850 .put = snd_ac97_ad198x_spdif_source_put,
1853 static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
1855 return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
1858 static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
1859 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
1860 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1863 /* black list to avoid HP/Line jack-sense controls
1864 * (SS vendor << 16 | device)
1866 static unsigned int ad1981_jacks_blacklist[] = {
1867 0x10140523, /* Thinkpad R40 */
1868 0x10140534, /* Thinkpad X31 */
1869 0x10140537, /* Thinkpad T41p */
1870 0x10140554, /* Thinkpad T42p/R50p */
1871 0x10140567, /* Thinkpad T43p 2668-G7U */
1872 0x10140581, /* Thinkpad X41-2527 */
1873 0x10280160, /* Dell Dimension 2400 */
1874 0x104380b0, /* Asus A7V8X-MX */
1875 0x11790241, /* Toshiba Satellite A-15 S127 */
1876 0x144dc01a, /* Samsung NP-X20C004/SEG */
1880 static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
1882 u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
1883 for (; *list; list++)
1889 static int patch_ad1981a_specific(struct snd_ac97 * ac97)
1891 if (check_list(ac97, ad1981_jacks_blacklist))
1893 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1894 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1897 static struct snd_ac97_build_ops patch_ad1981a_build_ops = {
1898 .build_post_spdif = patch_ad198x_post_spdif,
1899 .build_specific = patch_ad1981a_specific,
1901 .resume = ad18xx_resume
1905 /* white list to enable HP jack-sense bits
1906 * (SS vendor << 16 | device)
1908 static unsigned int ad1981_jacks_whitelist[] = {
1909 0x0e11005a, /* HP nc4000/4010 */
1910 0x103c0890, /* HP nc6000 */
1911 0x103c0938, /* HP nc4220 */
1912 0x103c099c, /* HP nx6110 */
1913 0x103c0944, /* HP nc6220 */
1914 0x103c0934, /* HP nc8220 */
1915 0x103c006d, /* HP nx9105 */
1916 0x17340088, /* FSC Scenic-W */
1920 static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
1922 if (check_list(ac97, ad1981_jacks_whitelist))
1923 /* enable headphone jack sense */
1924 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
1927 static int patch_ad1981a(struct snd_ac97 *ac97)
1930 ac97->build_ops = &patch_ad1981a_build_ops;
1931 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1932 ac97->flags |= AC97_STEREO_MUTES;
1933 check_ad1981_hp_jack_sense(ac97);
1937 static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
1938 AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
1940 static int patch_ad1981b_specific(struct snd_ac97 *ac97)
1944 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
1946 if (check_list(ac97, ad1981_jacks_blacklist))
1948 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1949 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1952 static struct snd_ac97_build_ops patch_ad1981b_build_ops = {
1953 .build_post_spdif = patch_ad198x_post_spdif,
1954 .build_specific = patch_ad1981b_specific,
1956 .resume = ad18xx_resume
1960 static int patch_ad1981b(struct snd_ac97 *ac97)
1963 ac97->build_ops = &patch_ad1981b_build_ops;
1964 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1965 ac97->flags |= AC97_STEREO_MUTES;
1966 check_ad1981_hp_jack_sense(ac97);
1970 #define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
1972 static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1974 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1977 val = ac97->regs[AC97_AD_MISC];
1978 ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
1979 if (ac97->spec.ad18xx.lo_as_master)
1980 ucontrol->value.integer.value[0] =
1981 !ucontrol->value.integer.value[0];
1985 static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1987 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1990 val = !ucontrol->value.integer.value[0];
1991 if (ac97->spec.ad18xx.lo_as_master)
1993 val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
1994 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1995 AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
1998 static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2000 static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
2002 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2004 uinfo->value.enumerated.items = 3;
2005 if (uinfo->value.enumerated.item > 2)
2006 uinfo->value.enumerated.item = 2;
2007 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2011 static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2013 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2016 val = ac97->regs[AC97_AD_MISC];
2017 if (!(val & AC97_AD198X_DMIX1))
2018 ucontrol->value.enumerated.item[0] = 0;
2020 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
2024 static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2026 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2029 if (ucontrol->value.enumerated.item[0] > 2)
2031 if (ucontrol->value.enumerated.item[0] == 0)
2034 val = AC97_AD198X_DMIX1 |
2035 ((ucontrol->value.enumerated.item[0] - 1) << 8);
2036 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2037 AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
2040 static void ad1888_update_jacks(struct snd_ac97 *ac97)
2042 unsigned short val = 0;
2043 /* clear LODIS if shared jack is to be used for Surround out */
2044 if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
2046 /* clear CLDIS if shared jack is to be used for C/LFE out */
2047 if (is_shared_micin(ac97))
2049 /* shared Line-In */
2050 snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
2053 static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
2055 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2056 .name = "Exchange Front/Surround",
2057 .info = snd_ac97_ad1888_lohpsel_info,
2058 .get = snd_ac97_ad1888_lohpsel_get,
2059 .put = snd_ac97_ad1888_lohpsel_put
2061 AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
2062 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
2063 AC97_AD_HPFD_SHIFT, 1, 1),
2064 AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
2066 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2068 .info = snd_ac97_ad1888_downmix_info,
2069 .get = snd_ac97_ad1888_downmix_get,
2070 .put = snd_ac97_ad1888_downmix_put
2072 AC97_SURROUND_JACK_MODE_CTL,
2073 AC97_CHANNEL_MODE_CTL,
2075 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2076 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2079 static int patch_ad1888_specific(struct snd_ac97 *ac97)
2081 if (!ac97->spec.ad18xx.lo_as_master) {
2082 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2083 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2084 "Master Surround Playback");
2085 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
2088 return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
2091 static struct snd_ac97_build_ops patch_ad1888_build_ops = {
2092 .build_post_spdif = patch_ad198x_post_spdif,
2093 .build_specific = patch_ad1888_specific,
2095 .resume = ad1888_resume,
2097 .update_jacks = ad1888_update_jacks,
2100 static int patch_ad1888(struct snd_ac97 * ac97)
2102 unsigned short misc;
2105 ac97->build_ops = &patch_ad1888_build_ops;
2108 * LO can be used as a real line-out on some devices,
2109 * and we need to revert the front/surround mixer switches
2111 if (ac97->subsystem_vendor == 0x1043 &&
2112 ac97->subsystem_device == 0x1193) /* ASUS A9T laptop */
2113 ac97->spec.ad18xx.lo_as_master = 1;
2115 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2116 /* AD-compatible mode */
2117 /* Stereo mutes enabled */
2118 misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
2119 if (!ac97->spec.ad18xx.lo_as_master)
2120 /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
2121 /* it seems that most vendors connect line-out connector to
2122 * headphone out of AC'97
2124 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
2126 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
2127 ac97->flags |= AC97_STEREO_MUTES;
2131 static int patch_ad1980_specific(struct snd_ac97 *ac97)
2135 if ((err = patch_ad1888_specific(ac97)) < 0)
2137 return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2140 static struct snd_ac97_build_ops patch_ad1980_build_ops = {
2141 .build_post_spdif = patch_ad198x_post_spdif,
2142 .build_specific = patch_ad1980_specific,
2144 .resume = ad18xx_resume,
2146 .update_jacks = ad1888_update_jacks,
2149 static int patch_ad1980(struct snd_ac97 * ac97)
2152 ac97->build_ops = &patch_ad1980_build_ops;
2156 static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2157 struct snd_ctl_elem_info *uinfo)
2159 static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
2161 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2163 uinfo->value.enumerated.items = 4;
2164 if (uinfo->value.enumerated.item > 3)
2165 uinfo->value.enumerated.item = 3;
2166 strcpy(uinfo->value.enumerated.name,
2167 texts[uinfo->value.enumerated.item]);
2171 static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2172 struct snd_ctl_elem_value *ucontrol)
2174 static const int reg2ctrl[4] = {2, 0, 1, 3};
2175 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2177 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2178 >> AC97_AD198X_VREF_SHIFT;
2179 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2183 static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2184 struct snd_ctl_elem_value *ucontrol)
2186 static const int ctrl2reg[4] = {1, 2, 0, 3};
2187 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2190 if (ucontrol->value.enumerated.item[0] > 3)
2192 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2193 << AC97_AD198X_VREF_SHIFT;
2194 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2195 AC97_AD198X_VREF_MASK, val);
2198 static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
2199 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2201 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2202 .name = "Exchange Front/Surround",
2203 .info = snd_ac97_ad1888_lohpsel_info,
2204 .get = snd_ac97_ad1888_lohpsel_get,
2205 .put = snd_ac97_ad1888_lohpsel_put
2207 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2208 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2209 AC97_AD_MISC, 7, 1, 0),
2211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2213 .info = snd_ac97_ad1888_downmix_info,
2214 .get = snd_ac97_ad1888_downmix_get,
2215 .put = snd_ac97_ad1888_downmix_put
2218 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2220 .info = snd_ac97_ad1985_vrefout_info,
2221 .get = snd_ac97_ad1985_vrefout_get,
2222 .put = snd_ac97_ad1985_vrefout_put
2224 AC97_SURROUND_JACK_MODE_CTL,
2225 AC97_CHANNEL_MODE_CTL,
2227 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2228 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2231 static void ad1985_update_jacks(struct snd_ac97 *ac97)
2233 ad1888_update_jacks(ac97);
2234 /* clear OMS if shared jack is to be used for C/LFE out */
2235 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
2236 is_shared_micin(ac97) ? 1 << 9 : 0);
2239 static int patch_ad1985_specific(struct snd_ac97 *ac97)
2243 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2244 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2245 "Master Surround Playback");
2246 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2248 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2251 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2252 ARRAY_SIZE(snd_ac97_ad1985_controls));
2255 static struct snd_ac97_build_ops patch_ad1985_build_ops = {
2256 .build_post_spdif = patch_ad198x_post_spdif,
2257 .build_specific = patch_ad1985_specific,
2259 .resume = ad18xx_resume,
2261 .update_jacks = ad1985_update_jacks,
2264 static int patch_ad1985(struct snd_ac97 * ac97)
2266 unsigned short misc;
2269 ac97->build_ops = &patch_ad1985_build_ops;
2270 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2271 /* switch front/surround line-out/hp-out */
2272 /* AD-compatible mode */
2273 /* Stereo mutes enabled */
2274 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2278 AC97_AD198X_AC97NC);
2279 ac97->flags |= AC97_STEREO_MUTES;
2281 /* update current jack configuration */
2282 ad1985_update_jacks(ac97);
2284 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2285 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2289 #define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
2291 static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2292 struct snd_ctl_elem_value *ucontrol)
2294 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2297 val = ac97->regs[AC97_AD_MISC3];
2298 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2302 static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2303 struct snd_ctl_elem_value *ucontrol)
2305 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2308 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2310 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2311 ucontrol->value.integer.value[0] != 0
2312 ? AC97_AD1986_LOSEL : 0);
2316 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2317 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2318 (ucontrol->value.integer.value[0] != 0
2320 ? AC97_AD1986_SOSEL : 0);
2324 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2327 static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2328 struct snd_ctl_elem_value *ucontrol)
2330 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2333 val = ac97->regs[AC97_AD_MISC];
2334 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2338 static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2339 struct snd_ctl_elem_value *ucontrol)
2341 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2344 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2346 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2347 ucontrol->value.integer.value[0] != 0
2348 ? AC97_AD1986_SPRD : 0);
2352 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2353 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2354 (ucontrol->value.integer.value[0] != 0
2356 ? AC97_AD1986_SOSEL : 0);
2360 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2363 static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2364 struct snd_ctl_elem_value *ucontrol)
2366 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2368 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2372 static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2373 struct snd_ctl_elem_value *ucontrol)
2375 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2376 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2378 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2379 ac97->spec.ad18xx.swap_mic_linein = swap;
2380 if (ac97->build_ops->update_jacks)
2381 ac97->build_ops->update_jacks(ac97);
2387 static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2388 struct snd_ctl_elem_value *ucontrol)
2390 /* Use MIC_1/2 V_REFOUT as the "get" value */
2391 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2393 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2394 if ((reg & AC97_AD1986_MVREF0) != 0)
2396 else if ((reg & AC97_AD1986_MVREF1) != 0)
2398 else if ((reg & AC97_AD1986_MVREF2) != 0)
2402 ucontrol->value.enumerated.item[0] = val;
2406 static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2407 struct snd_ctl_elem_value *ucontrol)
2409 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2410 unsigned short cval;
2411 unsigned short lval;
2412 unsigned short mval;
2417 switch (ucontrol->value.enumerated.item[0])
2419 case 0: /* High-Z */
2425 cval = AC97_AD1986_CVREF2;
2426 lval = AC97_AD1986_LVREF2;
2427 mval = AC97_AD1986_MVREF2;
2429 case 2: /* 2.25 V */
2430 cval = AC97_AD1986_CVREF0;
2431 lval = AC97_AD1986_LVREF0;
2432 mval = AC97_AD1986_MVREF0;
2435 cval = AC97_AD1986_CVREF1;
2436 lval = AC97_AD1986_LVREF1;
2437 mval = AC97_AD1986_MVREF1;
2443 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2444 AC97_AD1986_CVREF_MASK, cval);
2447 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2448 AC97_AD1986_LVREF_MASK, lval);
2451 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2452 AC97_AD1986_MVREF_MASK, mval);
2456 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2459 static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2460 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2462 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2463 .name = "Exchange Front/Surround",
2464 .info = snd_ac97_ad1986_bool_info,
2465 .get = snd_ac97_ad1986_lososel_get,
2466 .put = snd_ac97_ad1986_lososel_put
2469 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2470 .name = "Exchange Mic/Line In",
2471 .info = snd_ac97_ad1986_bool_info,
2472 .get = snd_ac97_ad1986_miclisel_get,
2473 .put = snd_ac97_ad1986_miclisel_put
2476 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2477 .name = "Spread Front to Surround and Center/LFE",
2478 .info = snd_ac97_ad1986_bool_info,
2479 .get = snd_ac97_ad1986_spread_get,
2480 .put = snd_ac97_ad1986_spread_put
2483 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2485 .info = snd_ac97_ad1888_downmix_info,
2486 .get = snd_ac97_ad1888_downmix_get,
2487 .put = snd_ac97_ad1888_downmix_put
2490 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2492 .info = snd_ac97_ad1985_vrefout_info,
2493 .get = snd_ac97_ad1986_vrefout_get,
2494 .put = snd_ac97_ad1986_vrefout_put
2496 AC97_SURROUND_JACK_MODE_CTL,
2497 AC97_CHANNEL_MODE_CTL,
2499 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2500 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2503 static void ad1986_update_jacks(struct snd_ac97 *ac97)
2505 unsigned short misc_val = 0;
2506 unsigned short ser_val;
2508 /* disable SURROUND and CENTER/LFE if not surround mode */
2509 if (!is_surround_on(ac97))
2510 misc_val |= AC97_AD1986_SODIS;
2511 if (!is_clfe_on(ac97))
2512 misc_val |= AC97_AD1986_CLDIS;
2514 /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
2515 if (is_shared_linein(ac97))
2516 misc_val |= AC97_AD1986_LISEL_SURR;
2517 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2518 misc_val |= AC97_AD1986_LISEL_MIC;
2519 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2520 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2521 AC97_AD1986_LISEL_MASK,
2524 /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
2525 if (is_shared_micin(ac97))
2526 ser_val = AC97_AD1986_OMS_C;
2527 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2528 ser_val = AC97_AD1986_OMS_L;
2530 ser_val = AC97_AD1986_OMS_M;
2531 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2532 AC97_AD1986_OMS_MASK,
2536 static int patch_ad1986_specific(struct snd_ac97 *ac97)
2540 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2543 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2544 ARRAY_SIZE(snd_ac97_ad1985_controls));
2547 static struct snd_ac97_build_ops patch_ad1986_build_ops = {
2548 .build_post_spdif = patch_ad198x_post_spdif,
2549 .build_specific = patch_ad1986_specific,
2551 .resume = ad18xx_resume,
2553 .update_jacks = ad1986_update_jacks,
2556 static int patch_ad1986(struct snd_ac97 * ac97)
2559 ac97->build_ops = &patch_ad1986_build_ops;
2560 ac97->flags |= AC97_STEREO_MUTES;
2562 /* update current jack configuration */
2563 ad1986_update_jacks(ac97);
2569 * realtek ALC203: use mono-out for pin 37
2571 static int patch_alc203(struct snd_ac97 *ac97)
2573 snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
2578 * realtek ALC65x/850 codecs
2580 static void alc650_update_jacks(struct snd_ac97 *ac97)
2584 /* shared Line-In / Surround Out */
2585 shared = is_shared_surrout(ac97);
2586 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2587 shared ? (1 << 9) : 0);
2588 /* update shared Mic In / Center/LFE Out */
2589 shared = is_shared_clfeout(ac97);
2590 /* disable/enable vref */
2591 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2592 shared ? (1 << 12) : 0);
2593 /* turn on/off center-on-mic */
2594 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
2595 shared ? (1 << 10) : 0);
2596 /* GPIO0 high for mic */
2597 snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
2598 shared ? 0 : 0x100);
2601 static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2602 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2603 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
2604 AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
2605 AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
2606 /* 4: Analog Input To Surround */
2607 /* 5: Analog Input To Center/LFE */
2608 /* 6: Independent Master Volume Right */
2609 /* 7: Independent Master Volume Left */
2611 /* 9: Line-In/Surround share */
2612 /* 10: Mic/CLFE share */
2613 /* 11-13: in IEC958 controls */
2614 AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
2615 #if 0 /* always set in patch_alc650 */
2616 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2617 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
2618 AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
2619 AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
2620 AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
2621 AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
2623 AC97_SURROUND_JACK_MODE_CTL,
2624 AC97_CHANNEL_MODE_CTL,
2627 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2628 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
2629 AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
2630 /* disable this controls since it doesn't work as expected */
2631 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2634 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2636 static int patch_alc650_specific(struct snd_ac97 * ac97)
2640 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
2642 if (ac97->ext_id & AC97_EI_SPDIF) {
2643 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
2646 if (ac97->id != AC97_ID_ALC650F)
2647 reset_tlv(ac97, "Master Playback Volume",
2648 db_scale_5bit_3db_max);
2652 static struct snd_ac97_build_ops patch_alc650_ops = {
2653 .build_specific = patch_alc650_specific,
2654 .update_jacks = alc650_update_jacks
2657 static int patch_alc650(struct snd_ac97 * ac97)
2661 ac97->build_ops = &patch_alc650_ops;
2663 /* determine the revision */
2664 val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
2666 ac97->id = 0x414c4720; /* Old version */
2667 else if (val < 0x10)
2668 ac97->id = 0x414c4721; /* D version */
2669 else if (val < 0x20)
2670 ac97->id = 0x414c4722; /* E version */
2671 else if (val < 0x30)
2672 ac97->id = 0x414c4723; /* F version */
2674 /* revision E or F */
2675 /* FIXME: what about revision D ? */
2676 ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
2677 ac97->id == 0x414c4723);
2679 /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
2680 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2681 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
2683 /* Enable SPDIF-IN only on Rev.E and above */
2684 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2685 /* SPDIF IN with pin 47 */
2686 if (ac97->spec.dev_flags &&
2687 /* ASUS A6KM requires EAPD */
2688 ! (ac97->subsystem_vendor == 0x1043 &&
2689 ac97->subsystem_device == 0x1103))
2690 val |= 0x03; /* enable */
2692 val &= ~0x03; /* disable */
2693 snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
2695 /* set default: slot 3,4,7,8,6,9
2696 spdif-in monitor off, analog-spdif off, spdif-in off
2697 center on mic off, surround on line-in off
2698 downmix off, duplicate front off
2700 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
2702 /* set GPIO0 for mic bias */
2703 /* GPIO0 pin output, no interrupt, high */
2704 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
2705 snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
2706 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2707 (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
2709 /* full DAC volume */
2710 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2711 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2715 static void alc655_update_jacks(struct snd_ac97 *ac97)
2719 /* shared Line-In / Surround Out */
2720 shared = is_shared_surrout(ac97);
2721 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2722 shared ? (1 << 9) : 0, 0);
2723 /* update shared Mic In / Center/LFE Out */
2724 shared = is_shared_clfeout(ac97);
2725 /* misc control; vrefout disable */
2726 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2727 shared ? (1 << 12) : 0);
2728 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
2729 shared ? (1 << 10) : 0, 0);
2732 static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
2733 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2734 AC97_SURROUND_JACK_MODE_CTL,
2735 AC97_CHANNEL_MODE_CTL,
2738 static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2740 static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" };
2741 static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" };
2742 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2744 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2746 uinfo->value.enumerated.items = ac97->spec.dev_flags ? 4 : 3;
2747 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2748 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2749 strcpy(uinfo->value.enumerated.name,
2750 ac97->spec.dev_flags ?
2751 texts_658[uinfo->value.enumerated.item] :
2752 texts_655[uinfo->value.enumerated.item]);
2756 static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2758 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2761 val = ac97->regs[AC97_ALC650_MULTICH];
2762 val = (val >> 12) & 3;
2763 if (ac97->spec.dev_flags && val == 3)
2765 ucontrol->value.enumerated.item[0] = val;
2769 static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2771 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2773 return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
2774 (unsigned short)ucontrol->value.enumerated.item[0] << 12,
2778 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
2779 AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
2780 /* disable this controls since it doesn't work as expected */
2781 /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
2783 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2784 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2785 .info = alc655_iec958_route_info,
2786 .get = alc655_iec958_route_get,
2787 .put = alc655_iec958_route_put,
2791 static int patch_alc655_specific(struct snd_ac97 * ac97)
2795 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0)
2797 if (ac97->ext_id & AC97_EI_SPDIF) {
2798 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
2804 static struct snd_ac97_build_ops patch_alc655_ops = {
2805 .build_specific = patch_alc655_specific,
2806 .update_jacks = alc655_update_jacks
2809 static int patch_alc655(struct snd_ac97 * ac97)
2813 if (ac97->id == AC97_ID_ALC658) {
2814 ac97->spec.dev_flags = 1; /* ALC658 */
2815 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
2816 ac97->id = AC97_ID_ALC658D;
2817 ac97->spec.dev_flags = 2;
2821 ac97->build_ops = &patch_alc655_ops;
2823 /* assume only page 0 for writing cache */
2824 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2826 /* adjust default values */
2827 val = snd_ac97_read(ac97, 0x7a); /* misc control */
2828 if (ac97->spec.dev_flags) /* ALC658 */
2829 val &= ~(1 << 1); /* Pin 47 is spdif input pin */
2831 if (ac97->subsystem_vendor == 0x1462 &&
2832 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
2833 ac97->subsystem_device == 0x0161 || /* LG K1 Express */
2834 ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
2835 ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */
2836 ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */
2837 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
2839 val |= (1 << 1); /* Pin 47 is spdif input pin */
2840 /* this seems missing on some hardwares */
2841 ac97->ext_id |= AC97_EI_SPDIF;
2843 val &= ~(1 << 12); /* vref enable */
2844 snd_ac97_write_cache(ac97, 0x7a, val);
2845 /* set default: spdif-in enabled,
2846 spdif-in monitor off, spdif-in PCM off
2847 center on mic off, surround on line-in off
2850 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2852 /* full DAC volume */
2853 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2854 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2856 /* update undocumented bit... */
2857 if (ac97->id == AC97_ID_ALC658D)
2858 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2864 #define AC97_ALC850_JACK_SELECT 0x76
2865 #define AC97_ALC850_MISC1 0x7a
2866 #define AC97_ALC850_MULTICH 0x6a
2868 static void alc850_update_jacks(struct snd_ac97 *ac97)
2871 int aux_is_back_surround;
2873 /* shared Line-In / Surround Out */
2874 shared = is_shared_surrout(ac97);
2875 /* SURR 1kOhm (bit4), Amp (bit5) */
2876 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2877 shared ? (1<<5) : (1<<4));
2878 /* LINE-IN = 0, SURROUND = 2 */
2879 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2880 shared ? (2<<12) : (0<<12));
2881 /* update shared Mic In / Center/LFE Out */
2882 shared = is_shared_clfeout(ac97);
2883 /* Vref disable (bit12), 1kOhm (bit13) */
2884 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2885 shared ? (1<<12) : (1<<13));
2886 /* MIC-IN = 1, CENTER-LFE = 5 */
2887 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
2888 shared ? (5<<4) : (1<<4));
2890 aux_is_back_surround = alc850_is_aux_back_surround(ac97);
2891 /* Aux is Back Surround */
2892 snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
2893 aux_is_back_surround ? (1<<10) : (0<<10));
2896 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
2897 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2898 AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
2899 AC97_SURROUND_JACK_MODE_CTL,
2900 AC97_CHANNEL_MODE_8CH_CTL,
2903 static int patch_alc850_specific(struct snd_ac97 *ac97)
2907 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
2909 if (ac97->ext_id & AC97_EI_SPDIF) {
2910 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
2916 static struct snd_ac97_build_ops patch_alc850_ops = {
2917 .build_specific = patch_alc850_specific,
2918 .update_jacks = alc850_update_jacks
2921 static int patch_alc850(struct snd_ac97 *ac97)
2923 ac97->build_ops = &patch_alc850_ops;
2925 ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
2926 ac97->flags |= AC97_HAS_8CH;
2928 /* assume only page 0 for writing cache */
2929 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2931 /* adjust default values */
2932 /* set default: spdif-in enabled,
2933 spdif-in monitor off, spdif-in PCM off
2934 center on mic off, surround on line-in off
2936 NB default bit 10=0 = Aux is Capture, not Back Surround
2938 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2939 /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
2940 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
2942 snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
2943 (1<<7)|(0<<12)|(1<<13)|(0<<14));
2944 /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
2945 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
2947 snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
2948 (1<<11)|(0<<12)|(1<<15));
2950 /* full DAC volume */
2951 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2952 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2958 * C-Media CM97xx codecs
2960 static void cm9738_update_jacks(struct snd_ac97 *ac97)
2962 /* shared Line-In / Surround Out */
2963 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2964 is_shared_surrout(ac97) ? (1 << 10) : 0);
2967 static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
2968 AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
2969 AC97_SURROUND_JACK_MODE_CTL,
2970 AC97_CHANNEL_MODE_4CH_CTL,
2973 static int patch_cm9738_specific(struct snd_ac97 * ac97)
2975 return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
2978 static struct snd_ac97_build_ops patch_cm9738_ops = {
2979 .build_specific = patch_cm9738_specific,
2980 .update_jacks = cm9738_update_jacks
2983 static int patch_cm9738(struct snd_ac97 * ac97)
2985 ac97->build_ops = &patch_cm9738_ops;
2986 /* FIXME: can anyone confirm below? */
2987 /* CM9738 has no PCM volume although the register reacts */
2988 ac97->flags |= AC97_HAS_NO_PCM_VOL;
2989 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
2994 static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2996 static char *texts[] = { "Analog", "Digital" };
2998 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3000 uinfo->value.enumerated.items = 2;
3001 if (uinfo->value.enumerated.item > 1)
3002 uinfo->value.enumerated.item = 1;
3003 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3007 static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3009 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3012 val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
3013 ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
3017 static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3019 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3021 return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
3023 (ucontrol->value.enumerated.item[0] & 0x01) << 1);
3026 static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
3027 /* BIT 0: SPDI_EN - always true */
3028 { /* BIT 1: SPDIFS */
3029 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3030 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3031 .info = snd_ac97_cmedia_spdif_playback_source_info,
3032 .get = snd_ac97_cmedia_spdif_playback_source_get,
3033 .put = snd_ac97_cmedia_spdif_playback_source_put,
3035 /* BIT 2: IG_SPIV */
3036 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
3038 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
3039 /* BIT 4: SPI2SDI */
3040 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
3041 /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
3044 static void cm9739_update_jacks(struct snd_ac97 *ac97)
3046 /* shared Line-In / Surround Out */
3047 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
3048 is_shared_surrout(ac97) ? (1 << 10) : 0);
3049 /* shared Mic In / Center/LFE Out **/
3050 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
3051 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
3054 static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
3055 AC97_SURROUND_JACK_MODE_CTL,
3056 AC97_CHANNEL_MODE_CTL,
3059 static int patch_cm9739_specific(struct snd_ac97 * ac97)
3061 return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
3064 static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
3066 return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
3069 static struct snd_ac97_build_ops patch_cm9739_ops = {
3070 .build_specific = patch_cm9739_specific,
3071 .build_post_spdif = patch_cm9739_post_spdif,
3072 .update_jacks = cm9739_update_jacks
3075 static int patch_cm9739(struct snd_ac97 * ac97)
3079 ac97->build_ops = &patch_cm9739_ops;
3081 /* CM9739/A has no Master and PCM volume although the register reacts */
3082 ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
3083 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
3084 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3087 val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
3088 if (val & AC97_EA_SPCV) {
3089 /* enable spdif in */
3090 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3091 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
3092 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3094 ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
3095 ac97->rates[AC97_RATES_SPDIF] = 0;
3098 /* set-up multi channel */
3099 /* bit 14: 0 = SPDIF, 1 = EAPD */
3100 /* bit 13: enable internal vref output for mic */
3101 /* bit 12: disable center/lfe (swithable) */
3102 /* bit 10: disable surround/line (switchable) */
3103 /* bit 9: mix 2 surround off */
3104 /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */
3105 /* bit 3: undocumented; surround? */
3107 val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
3110 if (! (ac97->ext_id & AC97_EI_SPDIF))
3112 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
3114 /* FIXME: set up GPIO */
3115 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3116 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3117 /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */
3119 ac97->subsystem_vendor == 0x1043 &&
3120 ac97->subsystem_device == 0x1843) {
3121 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3122 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
3123 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
3124 snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
3130 #define AC97_CM9761_MULTI_CHAN 0x64
3131 #define AC97_CM9761_FUNC 0x66
3132 #define AC97_CM9761_SPDIF_CTRL 0x6c
3134 static void cm9761_update_jacks(struct snd_ac97 *ac97)
3136 /* FIXME: check the bits for each model
3137 * model 83 is confirmed to work
3139 static unsigned short surr_on[3][2] = {
3140 { 0x0008, 0x0000 }, /* 9761-78 & 82 */
3141 { 0x0000, 0x0008 }, /* 9761-82 rev.B */
3142 { 0x0000, 0x0008 }, /* 9761-83 */
3144 static unsigned short clfe_on[3][2] = {
3145 { 0x0000, 0x1000 }, /* 9761-78 & 82 */
3146 { 0x1000, 0x0000 }, /* 9761-82 rev.B */
3147 { 0x0000, 0x1000 }, /* 9761-83 */
3149 static unsigned short surr_shared[3][2] = {
3150 { 0x0000, 0x0400 }, /* 9761-78 & 82 */
3151 { 0x0000, 0x0400 }, /* 9761-82 rev.B */
3152 { 0x0000, 0x0400 }, /* 9761-83 */
3154 static unsigned short clfe_shared[3][2] = {
3155 { 0x2000, 0x0880 }, /* 9761-78 & 82 */
3156 { 0x0000, 0x2880 }, /* 9761-82 rev.B */
3157 { 0x2000, 0x0800 }, /* 9761-83 */
3159 unsigned short val = 0;
3161 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
3162 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
3163 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
3164 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
3166 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
3169 static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
3170 AC97_SURROUND_JACK_MODE_CTL,
3171 AC97_CHANNEL_MODE_CTL,
3174 static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3176 static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
3178 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3180 uinfo->value.enumerated.items = 3;
3181 if (uinfo->value.enumerated.item > 2)
3182 uinfo->value.enumerated.item = 2;
3183 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3187 static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3189 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3191 if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
3192 ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
3193 else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
3194 ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
3196 ucontrol->value.enumerated.item[0] = 0; /* AC-link */
3200 static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3202 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3204 if (ucontrol->value.enumerated.item[0] == 2)
3205 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
3206 snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
3207 return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
3208 ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
3211 static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
3212 static const struct ac97_enum cm9761_dac_clock_enum =
3213 AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
3215 static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
3216 { /* BIT 1: SPDIFS */
3217 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3218 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3219 .info = cm9761_spdif_out_source_info,
3220 .get = cm9761_spdif_out_source_get,
3221 .put = cm9761_spdif_out_source_put,
3223 /* BIT 2: IG_SPIV */
3224 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
3226 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
3227 /* BIT 4: SPI2SDI */
3228 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
3229 /* BIT 9-10: DAC_CTL */
3230 AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
3233 static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
3235 return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
3238 static int patch_cm9761_specific(struct snd_ac97 * ac97)
3240 return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
3243 static struct snd_ac97_build_ops patch_cm9761_ops = {
3244 .build_specific = patch_cm9761_specific,
3245 .build_post_spdif = patch_cm9761_post_spdif,
3246 .update_jacks = cm9761_update_jacks
3249 static int patch_cm9761(struct snd_ac97 *ac97)
3253 /* CM9761 has no PCM volume although the register reacts */
3254 /* Master volume seems to have _some_ influence on the analog
3257 ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
3258 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
3259 snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
3261 ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */
3262 if (ac97->id == AC97_ID_CM9761_82) {
3264 /* check page 1, reg 0x60 */
3265 val = snd_ac97_read(ac97, AC97_INT_PAGING);
3266 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
3267 tmp = snd_ac97_read(ac97, 0x60);
3268 ac97->spec.dev_flags = tmp & 1; /* revision B? */
3269 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
3270 } else if (ac97->id == AC97_ID_CM9761_83)
3271 ac97->spec.dev_flags = 2;
3273 ac97->build_ops = &patch_cm9761_ops;
3276 /* force the SPDIF bit in ext_id - codec doesn't set this bit! */
3277 ac97->ext_id |= AC97_EI_SPDIF;
3278 /* to be sure: we overwrite the ext status bits */
3279 snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
3280 /* Don't set 0x0200 here. This results in the silent analog output */
3281 snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
3282 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3284 /* set-up multi channel */
3285 /* bit 15: pc master beep off
3286 * bit 14: pin47 = EAPD/SPDIF
3287 * bit 13: vref ctl [= cm9739]
3288 * bit 12: CLFE control (reverted on rev B)
3289 * bit 11: Mic/center share (reverted on rev B)
3290 * bit 10: suddound/line share
3291 * bit 9: Analog-in mix -> surround
3292 * bit 8: Analog-in mix -> CLFE
3293 * bit 7: Mic/LFE share (mic/center/lfe)
3294 * bit 5: vref select (9761A)
3295 * bit 4: front control
3296 * bit 3: surround control (revereted with rev B)
3299 * bit 0: mic boost level (0=20dB, 1=30dB)
3303 if (ac97->spec.dev_flags)
3308 val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
3309 val |= (1 << 4); /* front on */
3310 snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
3312 /* FIXME: set up GPIO */
3313 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3314 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3319 #define AC97_CM9780_SIDE 0x60
3320 #define AC97_CM9780_JACK 0x62
3321 #define AC97_CM9780_MIXER 0x64
3322 #define AC97_CM9780_MULTI_CHAN 0x66
3323 #define AC97_CM9780_SPDIF 0x6c
3325 static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
3326 static const struct ac97_enum cm9780_ch_select_enum =
3327 AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
3328 static const struct snd_kcontrol_new cm9780_controls[] = {
3329 AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
3330 AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
3331 AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
3334 static int patch_cm9780_specific(struct snd_ac97 *ac97)
3336 return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
3339 static struct snd_ac97_build_ops patch_cm9780_ops = {
3340 .build_specific = patch_cm9780_specific,
3341 .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
3344 static int patch_cm9780(struct snd_ac97 *ac97)
3348 ac97->build_ops = &patch_cm9780_ops;
3351 if (ac97->ext_id & AC97_EI_SPDIF) {
3352 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3353 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
3354 val |= 0x1; /* SPDI_EN */
3355 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
3364 static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
3365 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3366 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
3367 AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
3368 AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
3371 static const char *slave_vols_vt1616[] = {
3372 "Front Playback Volume",
3373 "Surround Playback Volume",
3374 "Center Playback Volume",
3375 "LFE Playback Volume",
3379 static const char *slave_sws_vt1616[] = {
3380 "Front Playback Switch",
3381 "Surround Playback Switch",
3382 "Center Playback Switch",
3383 "LFE Playback Switch",
3387 /* find a mixer control element with the given name */
3388 static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
3391 struct snd_ctl_elem_id id;
3392 memset(&id, 0, sizeof(id));
3393 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
3394 strcpy(id.name, name);
3395 return snd_ctl_find_id(ac97->bus->card, &id);
3398 /* create a virtual master control and add slaves */
3399 static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
3400 const unsigned int *tlv, const char **slaves)
3402 struct snd_kcontrol *kctl;
3406 kctl = snd_ctl_make_virtual_master(name, tlv);
3409 err = snd_ctl_add(ac97->bus->card, kctl);
3413 for (s = slaves; *s; s++) {
3414 struct snd_kcontrol *sctl;
3416 sctl = snd_ac97_find_mixer_ctl(ac97, *s);
3418 snd_printdd("Cannot find slave %s, skipped\n", *s);
3421 err = snd_ctl_add_slave(kctl, sctl);
3428 static int patch_vt1616_specific(struct snd_ac97 * ac97)
3430 struct snd_kcontrol *kctl;
3433 if (snd_ac97_try_bit(ac97, 0x5a, 9))
3434 if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
3436 if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
3439 /* There is already a misnamed master switch. Rename it. */
3440 kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
3444 snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
3446 err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
3447 kctl->tlv.p, slave_vols_vt1616);
3451 err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
3452 NULL, slave_sws_vt1616);
3459 static struct snd_ac97_build_ops patch_vt1616_ops = {
3460 .build_specific = patch_vt1616_specific
3463 static int patch_vt1616(struct snd_ac97 * ac97)
3465 ac97->build_ops = &patch_vt1616_ops;
3474 * unfortunately, the vt1617a stashes the twiddlers required for
3475 * noodling the i/o jacks on 2 different regs. that means that we can't
3476 * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
3479 * NB: this is absolutely and utterly different from the vt1618. dunno
3483 /* copied from ac97_surround_jack_mode_info() */
3484 static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
3485 struct snd_ctl_elem_info *uinfo)
3487 /* ordering in this list reflects vt1617a docs for Reg 20 and
3488 * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
3489 * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
3490 * counter-intuitive */
3492 static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3",
3493 "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
3494 "LineIn Mic2", "LineIn Mic2 Mic1",
3495 "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
3496 return ac97_enum_text_info(kcontrol, uinfo, texts, 8);
3499 static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
3500 struct snd_ctl_elem_value *ucontrol)
3502 ushort usSM51, usMS;
3504 struct snd_ac97 *pac97;
3506 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3508 /* grab our desired bits, then mash them together in a manner
3509 * consistent with Table 6 on page 17 in the 1617a docs */
3511 usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
3512 usMS = snd_ac97_read(pac97, 0x20) >> 8;
3514 ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
3519 static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
3520 struct snd_ctl_elem_value *ucontrol)
3522 ushort usSM51, usMS, usReg;
3524 struct snd_ac97 *pac97;
3526 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3528 usSM51 = ucontrol->value.enumerated.item[0] >> 1;
3529 usMS = ucontrol->value.enumerated.item[0] & 1;
3531 /* push our values into the register - consider that things will be left
3532 * in a funky state if the write fails */
3534 usReg = snd_ac97_read(pac97, 0x7a);
3535 snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
3536 usReg = snd_ac97_read(pac97, 0x20);
3537 snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8));
3542 static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
3544 AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
3546 * These are used to enable/disable surround sound on motherboards
3547 * that have 3 bidirectional analog jacks
3550 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3551 .name = "Smart 5.1 Select",
3552 .info = snd_ac97_vt1617a_smart51_info,
3553 .get = snd_ac97_vt1617a_smart51_get,
3554 .put = snd_ac97_vt1617a_smart51_put,
3558 static int patch_vt1617a(struct snd_ac97 * ac97)
3563 /* we choose to not fail out at this point, but we tell the
3564 caller when we return */
3566 err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
3567 ARRAY_SIZE(snd_ac97_controls_vt1617a));
3569 /* bring analog power consumption to normal by turning off the
3570 * headphone amplifier, like WinXP driver for EPIA SP
3572 /* We need to check the bit before writing it.
3573 * On some (many?) hardwares, setting bit actually clears it!
3575 val = snd_ac97_read(ac97, 0x5c);
3577 snd_ac97_write_cache(ac97, 0x5c, 0x20);
3579 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
3580 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3581 ac97->build_ops = &patch_vt1616_ops;
3586 /* VIA VT1618 8 CHANNEL AC97 CODEC
3588 * VIA implements 'Smart 5.1' completely differently on the 1618 than
3589 * it does on the 1617a. awesome! They seem to have sourced this
3590 * particular revision of the technology from somebody else, it's
3591 * called Universal Audio Jack and it shows up on some other folk's chips
3594 * ordering in this list reflects vt1618 docs for Reg 60h and
3595 * the block diagram, DACs are as follows:
3598 * OUT_1 -> Surround,
3601 * Unlike the 1617a, each OUT has a consistent set of mappings
3602 * for all bitpatterns other than 00:
3608 * Special Case of 00:
3610 * OUT_0 Mixed Output
3614 * I have no idea what the hell Reserved does, but on an MSI
3615 * CN700T, i have to set it to get 5.1 output - YMMV, bad
3618 * If other chips use Universal Audio Jack, then this code might be applicable
3622 struct vt1618_uaj_item {
3623 unsigned short mask;
3624 unsigned short shift;
3625 const char *items[4];
3628 /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */
3630 static struct vt1618_uaj_item vt1618_uaj[3] = {
3636 "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
3644 "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
3652 "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
3657 static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
3658 struct snd_ctl_elem_info *uinfo)
3660 return ac97_enum_text_info(kcontrol, uinfo,
3661 vt1618_uaj[kcontrol->private_value].items,
3665 /* All of the vt1618 Universal Audio Jack twiddlers are on
3666 * Vendor Defined Register 0x60, page 0. The bits, and thus
3667 * the mask, are the only thing that changes
3669 static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
3670 struct snd_ctl_elem_value *ucontrol)
3672 unsigned short datpag, uaj;
3673 struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
3675 mutex_lock(&pac97->page_mutex);
3677 datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
3678 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
3680 uaj = snd_ac97_read(pac97, 0x60) &
3681 vt1618_uaj[kcontrol->private_value].mask;
3683 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
3684 mutex_unlock(&pac97->page_mutex);
3686 ucontrol->value.enumerated.item[0] = uaj >>
3687 vt1618_uaj[kcontrol->private_value].shift;
3692 static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
3693 struct snd_ctl_elem_value *ucontrol)
3695 return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
3696 vt1618_uaj[kcontrol->private_value].mask,
3697 ucontrol->value.enumerated.item[0]<<
3698 vt1618_uaj[kcontrol->private_value].shift,
3702 /* config aux in jack - not found on 3 jack motherboards or soundcards */
3704 static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
3705 struct snd_ctl_elem_info *uinfo)
3707 static const char *txt_aux[] = {"Aux In", "Back Surr Out"};
3709 return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2);
3712 static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
3713 struct snd_ctl_elem_value *ucontrol)
3715 ucontrol->value.enumerated.item[0] =
3716 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
3720 static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
3721 struct snd_ctl_elem_value *ucontrol)
3723 /* toggle surround rear dac power */
3725 snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
3726 ucontrol->value.enumerated.item[0] << 3);
3728 /* toggle aux in surround rear out jack */
3730 return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
3731 ucontrol->value.enumerated.item[0] << 3);
3734 static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
3735 AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
3736 AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
3737 AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
3738 AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
3739 AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
3740 AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
3742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3743 .name = "Speaker Jack Mode",
3744 .info = snd_ac97_vt1618_UAJ_info,
3745 .get = snd_ac97_vt1618_UAJ_get,
3746 .put = snd_ac97_vt1618_UAJ_put,
3750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3751 .name = "Line Jack Mode",
3752 .info = snd_ac97_vt1618_UAJ_info,
3753 .get = snd_ac97_vt1618_UAJ_get,
3754 .put = snd_ac97_vt1618_UAJ_put,
3758 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3759 .name = "Mic Jack Mode",
3760 .info = snd_ac97_vt1618_UAJ_info,
3761 .get = snd_ac97_vt1618_UAJ_get,
3762 .put = snd_ac97_vt1618_UAJ_put,
3766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3767 .name = "Aux Jack Mode",
3768 .info = snd_ac97_vt1618_aux_info,
3769 .get = snd_ac97_vt1618_aux_get,
3770 .put = snd_ac97_vt1618_aux_put,
3774 static int patch_vt1618(struct snd_ac97 *ac97)
3776 return patch_build_controls(ac97, snd_ac97_controls_vt1618,
3777 ARRAY_SIZE(snd_ac97_controls_vt1618));
3782 static void it2646_update_jacks(struct snd_ac97 *ac97)
3784 /* shared Line-In / Surround Out */
3785 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
3786 is_shared_surrout(ac97) ? (1<<9) : 0);
3787 /* shared Mic / Center/LFE Out */
3788 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
3789 is_shared_clfeout(ac97) ? (1<<10) : 0);
3792 static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
3793 AC97_SURROUND_JACK_MODE_CTL,
3794 AC97_CHANNEL_MODE_CTL,
3797 static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
3798 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
3799 AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
3800 AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
3803 static int patch_it2646_specific(struct snd_ac97 * ac97)
3806 if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0)
3808 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0)
3813 static struct snd_ac97_build_ops patch_it2646_ops = {
3814 .build_specific = patch_it2646_specific,
3815 .update_jacks = it2646_update_jacks
3818 static int patch_it2646(struct snd_ac97 * ac97)
3820 ac97->build_ops = &patch_it2646_ops;
3821 /* full DAC volume */
3822 snd_ac97_write_cache(ac97, 0x5E, 0x0808);
3823 snd_ac97_write_cache(ac97, 0x7A, 0x0808);
3831 #define AC97_SI3036_CHIP_ID 0x5a
3832 #define AC97_SI3036_LINE_CFG 0x5c
3834 static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
3835 AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
3838 static int patch_si3036_specific(struct snd_ac97 * ac97)
3841 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++)
3842 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0)
3847 static struct snd_ac97_build_ops patch_si3036_ops = {
3848 .build_specific = patch_si3036_specific,
3851 static int mpatch_si3036(struct snd_ac97 * ac97)
3853 ac97->build_ops = &patch_si3036_ops;
3854 snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
3855 snd_ac97_write_cache(ac97, 0x68, 0);
3862 * We use a static resolution table since LM4550 codec cannot be
3863 * properly autoprobed to determine the resolution via
3864 * check_volume_resolution().
3867 static struct snd_ac97_res_table lm4550_restbl[] = {
3868 { AC97_MASTER, 0x1f1f },
3869 { AC97_HEADPHONE, 0x1f1f },
3870 { AC97_MASTER_MONO, 0x001f },
3871 { AC97_PC_BEEP, 0x001f }, /* LSB is ignored */
3872 { AC97_PHONE, 0x001f },
3873 { AC97_MIC, 0x001f },
3874 { AC97_LINE, 0x1f1f },
3875 { AC97_CD, 0x1f1f },
3876 { AC97_VIDEO, 0x1f1f },
3877 { AC97_AUX, 0x1f1f },
3878 { AC97_PCM, 0x1f1f },
3879 { AC97_REC_GAIN, 0x0f0f },
3880 { } /* terminator */
3883 static int patch_lm4550(struct snd_ac97 *ac97)
3885 ac97->res_table = lm4550_restbl;
3890 * UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf)
3892 static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = {
3893 /* enable/disable headphone driver which allows direct connection to
3894 stereo headphone without the use of external DC blocking
3896 AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0),
3897 /* Filter used to compensate the DC offset is added in the ADC to remove idle
3898 tones from the audio band. */
3899 AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0),
3900 /* Control smart-low-power mode feature. Allows automatic power down
3901 of unused blocks in the ADC analog front end and the PLL. */
3902 AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0),
3905 static int patch_ucb1400_specific(struct snd_ac97 * ac97)
3908 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++)
3909 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0)
3914 static struct snd_ac97_build_ops patch_ucb1400_ops = {
3915 .build_specific = patch_ucb1400_specific,
3918 static int patch_ucb1400(struct snd_ac97 * ac97)
3920 ac97->build_ops = &patch_ucb1400_ops;
3921 /* enable headphone driver and smart low power mode by default */
3922 snd_ac97_write_cache(ac97, 0x6a, 0x0050);
3923 snd_ac97_write_cache(ac97, 0x6c, 0x0030);