1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4 * Universal interface for Audio Codec '97
6 * For more details look to AC '97 component specification revision 2.2
7 * by Intel Corporation (http://developer.intel.com) and to datasheets
11 #include "ac97_local.h"
12 #include "ac97_patch.h"
15 * Forward declarations
18 static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
20 static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
21 const unsigned int *tlv,
22 const char * const *followers);
25 * Chip specific initialization
28 static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count)
32 for (idx = 0; idx < count; idx++) {
33 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97));
40 /* replace with a new TLV */
41 static void reset_tlv(struct snd_ac97 *ac97, const char *name,
42 const unsigned int *tlv)
44 struct snd_ctl_elem_id sid;
45 struct snd_kcontrol *kctl;
46 memset(&sid, 0, sizeof(sid));
47 strcpy(sid.name, name);
48 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
49 kctl = snd_ctl_find_id(ac97->bus->card, &sid);
50 if (kctl && kctl->tlv.p)
54 /* set to the page, update bits and restore the page */
55 static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
57 unsigned short page_save;
60 mutex_lock(&ac97->page_mutex);
61 page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
62 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
63 ret = snd_ac97_update_bits(ac97, reg, mask, value);
64 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
65 mutex_unlock(&ac97->page_mutex); /* unlock paging */
70 * shared line-in/mic controls
72 static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
74 static const char * const texts[] = { "Shared", "Independent" };
76 return snd_ctl_enum_info(uinfo, 1, 2, texts);
79 static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
81 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
83 ucontrol->value.enumerated.item[0] = ac97->indep_surround;
87 static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
89 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
90 unsigned char indep = !!ucontrol->value.enumerated.item[0];
92 if (indep != ac97->indep_surround) {
93 ac97->indep_surround = indep;
94 if (ac97->build_ops->update_jacks)
95 ac97->build_ops->update_jacks(ac97);
101 static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
103 static const char * const texts[] = { "2ch", "4ch", "6ch", "8ch" };
105 return snd_ctl_enum_info(uinfo, 1, kcontrol->private_value, texts);
108 static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
112 ucontrol->value.enumerated.item[0] = ac97->channel_mode;
116 static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
118 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
119 unsigned char mode = ucontrol->value.enumerated.item[0];
121 if (mode >= kcontrol->private_value)
124 if (mode != ac97->channel_mode) {
125 ac97->channel_mode = mode;
126 if (ac97->build_ops->update_jacks)
127 ac97->build_ops->update_jacks(ac97);
133 #define AC97_SURROUND_JACK_MODE_CTL \
135 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
136 .name = "Surround Jack Mode", \
137 .info = ac97_surround_jack_mode_info, \
138 .get = ac97_surround_jack_mode_get, \
139 .put = ac97_surround_jack_mode_put, \
142 #define AC97_CHANNEL_MODE_CTL \
144 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
145 .name = "Channel Mode", \
146 .info = ac97_channel_mode_info, \
147 .get = ac97_channel_mode_get, \
148 .put = ac97_channel_mode_put, \
149 .private_value = 3, \
152 #define AC97_CHANNEL_MODE_4CH_CTL \
154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
155 .name = "Channel Mode", \
156 .info = ac97_channel_mode_info, \
157 .get = ac97_channel_mode_get, \
158 .put = ac97_channel_mode_put, \
159 .private_value = 2, \
162 #define AC97_CHANNEL_MODE_8CH_CTL \
164 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
165 .name = "Channel Mode", \
166 .info = ac97_channel_mode_info, \
167 .get = ac97_channel_mode_get, \
168 .put = ac97_channel_mode_put, \
169 .private_value = 4, \
172 static inline int is_surround_on(struct snd_ac97 *ac97)
174 return ac97->channel_mode >= 1;
177 static inline int is_clfe_on(struct snd_ac97 *ac97)
179 return ac97->channel_mode >= 2;
182 /* system has shared jacks with surround out enabled */
183 static inline int is_shared_surrout(struct snd_ac97 *ac97)
185 return !ac97->indep_surround && is_surround_on(ac97);
188 /* system has shared jacks with center/lfe out enabled */
189 static inline int is_shared_clfeout(struct snd_ac97 *ac97)
191 return !ac97->indep_surround && is_clfe_on(ac97);
194 /* system has shared jacks with line in enabled */
195 static inline int is_shared_linein(struct snd_ac97 *ac97)
197 return !ac97->indep_surround && !is_surround_on(ac97);
200 /* system has shared jacks with mic in enabled */
201 static inline int is_shared_micin(struct snd_ac97 *ac97)
203 return !ac97->indep_surround && !is_clfe_on(ac97);
206 static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
208 return is_surround_on(ac97);
211 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
212 /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
214 /* It is possible to indicate to the Yamaha YMF7x3 the type of
215 speakers being used. */
217 static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
218 struct snd_ctl_elem_info *uinfo)
220 static const char * const texts[3] = {
221 "Standard", "Small", "Smaller"
224 return snd_ctl_enum_info(uinfo, 1, 3, texts);
227 static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
228 struct snd_ctl_elem_value *ucontrol)
230 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
233 val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
234 val = (val >> 10) & 3;
235 if (val > 0) /* 0 = invalid */
237 ucontrol->value.enumerated.item[0] = val;
241 static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
244 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
247 if (ucontrol->value.enumerated.item[0] > 2)
249 val = (ucontrol->value.enumerated.item[0] + 1) << 10;
250 return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
253 static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
256 .name = "3D Control - Speaker",
257 .info = snd_ac97_ymf7x3_info_speaker,
258 .get = snd_ac97_ymf7x3_get_speaker,
259 .put = snd_ac97_ymf7x3_put_speaker,
262 /* It is possible to indicate to the Yamaha YMF7x3 the source to
263 direct to the S/PDIF output. */
264 static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_info *uinfo)
267 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
269 return snd_ctl_enum_info(uinfo, 1, 2, texts);
272 static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
275 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
278 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
279 ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
283 static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_value *ucontrol)
286 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
289 if (ucontrol->value.enumerated.item[0] > 1)
291 val = ucontrol->value.enumerated.item[0] << 1;
292 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
295 static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
297 struct snd_kcontrol *kctl;
300 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
301 err = snd_ctl_add(ac97->bus->card, kctl);
304 strcpy(kctl->id.name, "3D Control - Wide");
305 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
306 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
307 err = snd_ctl_add(ac97->bus->card,
308 snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
312 snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
316 static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
318 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
319 AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
321 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
322 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
323 .info = snd_ac97_ymf7x3_spdif_source_info,
324 .get = snd_ac97_ymf7x3_spdif_source_get,
325 .put = snd_ac97_ymf7x3_spdif_source_put,
327 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
328 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
331 static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
335 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
338 err = patch_build_controls(ac97,
339 snd_ac97_yamaha_ymf743_controls_spdif, 3);
342 /* set default PCM S/PDIF params */
343 /* PCM audio,no copyright,no preemphasis,PCM coder,original */
344 snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
348 static const struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
349 .build_spdif = patch_yamaha_ymf743_build_spdif,
350 .build_3d = patch_yamaha_ymf7x3_3d,
353 static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
355 ac97->build_ops = &patch_yamaha_ymf743_ops;
356 ac97->caps |= AC97_BC_BASS_TREBLE;
357 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
358 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
359 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
363 /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
364 The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
365 By default, no output pin is selected, and the S/PDIF signal is not output.
366 There is also a bit to mute S/PDIF output in a vendor-specific register. */
367 static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
369 static const char * const texts[3] = { "Disabled", "Pin 43", "Pin 48" };
371 return snd_ctl_enum_info(uinfo, 1, 3, texts);
374 static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
376 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
379 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
380 ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
384 static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
386 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
389 if (ucontrol->value.enumerated.item[0] > 2)
391 val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
392 (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
393 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
394 /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
395 snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
398 static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
401 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
402 .info = snd_ac97_ymf7x3_spdif_source_info,
403 .get = snd_ac97_ymf7x3_spdif_source_get,
404 .put = snd_ac97_ymf7x3_spdif_source_put,
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
409 .info = snd_ac97_ymf753_spdif_output_pin_info,
410 .get = snd_ac97_ymf753_spdif_output_pin_get,
411 .put = snd_ac97_ymf753_spdif_output_pin_put,
413 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
414 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
417 static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
421 err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif));
427 static const struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
428 .build_3d = patch_yamaha_ymf7x3_3d,
429 .build_post_spdif = patch_yamaha_ymf753_post_spdif
432 static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
434 /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
435 This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
436 The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
437 The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
438 By default, no output pin is selected, and the S/PDIF signal is not output.
439 There is also a bit to mute S/PDIF output in a vendor-specific register.
441 ac97->build_ops = &patch_yamaha_ymf753_ops;
442 ac97->caps |= AC97_BC_BASS_TREBLE;
443 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
448 * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
449 * removed broken wolfson00 patch.
450 * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
453 static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = {
454 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
455 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
458 static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
460 /* This is known to work for the ViewSonic ViewPad 1000
461 * Randolph Bentson <bentson@holmsjoen.com>
462 * WM9703/9707/9708/9717
466 for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
467 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97));
471 snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
475 static const struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
476 .build_specific = patch_wolfson_wm9703_specific,
479 static int patch_wolfson03(struct snd_ac97 * ac97)
481 ac97->build_ops = &patch_wolfson_wm9703_ops;
485 static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = {
486 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
487 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
488 AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
489 AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
490 AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
491 AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
494 static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
497 for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
498 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97));
502 /* patch for DVD noise */
503 snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
507 static const struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
508 .build_specific = patch_wolfson_wm9704_specific,
511 static int patch_wolfson04(struct snd_ac97 * ac97)
514 ac97->build_ops = &patch_wolfson_wm9704_ops;
518 static int patch_wolfson05(struct snd_ac97 * ac97)
521 ac97->build_ops = &patch_wolfson_wm9703_ops;
522 #ifdef CONFIG_TOUCHSCREEN_WM9705
523 /* WM9705 touchscreen uses AUX and VIDEO for touch */
524 ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
529 static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
530 static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
531 static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
532 static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
533 static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
534 static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
535 static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
536 static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
537 static const char* wm9711_rec_sel[] =
538 {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
539 static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
541 static const struct ac97_enum wm9711_enum[] = {
542 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
543 AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
544 AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
545 AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
546 AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
547 AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
548 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
549 AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
550 AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
551 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
554 static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = {
555 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
556 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
557 AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
558 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
559 AC97_ENUM("ALC Function", wm9711_enum[0]),
560 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
561 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
562 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
563 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
564 AC97_ENUM("ALC NG Type", wm9711_enum[9]),
565 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
567 AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
568 AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
569 AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
570 AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
572 AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
573 AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
574 AC97_ENUM("Out3 Mux", wm9711_enum[2]),
575 AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
576 AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
578 AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
579 AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
580 AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
581 AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
582 AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
583 AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
585 AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
586 AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
587 AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
588 AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
589 AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
590 AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
592 AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
593 AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
595 AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
596 AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
597 AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
599 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
600 AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
601 AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
603 AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
604 AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
605 AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
606 AC97_ENUM("Capture Select", wm9711_enum[8]),
608 AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
609 AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
611 AC97_ENUM("Bass Control", wm9711_enum[5]),
612 AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
613 AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
614 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
616 AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
617 AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
618 AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
619 AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
621 AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
622 AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
623 AC97_ENUM("Mic Select Source", wm9711_enum[7]),
624 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
625 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
626 AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
628 AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
629 AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
630 AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
631 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
634 static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
638 for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
639 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97));
643 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808);
644 snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808);
645 snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808);
646 snd_ac97_write_cache(ac97, AC97_AUX, 0x0808);
647 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
648 snd_ac97_write_cache(ac97, AC97_CD, 0x0000);
652 static const struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
653 .build_specific = patch_wolfson_wm9711_specific,
656 static int patch_wolfson11(struct snd_ac97 * ac97)
659 ac97->build_ops = &patch_wolfson_wm9711_ops;
661 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
662 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
667 static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
668 static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
669 static const char* wm9713_rec_src[] =
670 {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix",
672 static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
673 static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
674 static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
675 static const char* wm9713_spk_pga[] =
676 {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
677 static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
678 static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
679 static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
680 static const char* wm9713_dac_inv[] =
681 {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R",
682 "Headphone Mix Mono", "NC", "Vmid"};
683 static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
684 static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
686 static const struct ac97_enum wm9713_enum[] = {
687 AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
688 AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
689 AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
690 AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
691 AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
692 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
693 AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
694 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
695 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
696 AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
697 AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
698 AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
699 AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
700 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
703 static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
704 AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
705 AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
706 AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
707 AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
709 AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
710 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
711 AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
712 AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
714 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
715 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
716 AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
717 AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
718 AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
719 AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
720 AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
722 AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
723 AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
724 AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
725 AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
727 AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
728 AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
729 AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
730 AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
731 AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
732 AC97_ENUM("Capture Select", wm9713_enum[3]),
734 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
735 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
736 AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
737 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
738 AC97_ENUM("ALC Function", wm9713_enum[5]),
739 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
740 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
741 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
742 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
743 AC97_ENUM("ALC NG Type", wm9713_enum[13]),
744 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
746 AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
747 AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
748 AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
749 AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
750 AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
751 AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
753 AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
754 AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
755 AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
756 AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
757 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
758 AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
760 AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
761 AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
762 AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
763 AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
764 AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
765 AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
767 AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
768 AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
769 AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
770 AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
771 AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
772 AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
774 AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
775 AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
776 AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
777 AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
778 AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
779 AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
781 AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
782 AC97_ENUM("Master Input Mux", wm9713_enum[7]),
783 AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
784 AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
785 AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
787 AC97_ENUM("Bass Control", wm9713_enum[12]),
788 AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
789 AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
790 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
791 AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
792 AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
795 static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {
796 AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
797 AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
798 AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
799 AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
802 static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
806 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
807 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97));
814 static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
818 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
819 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97));
823 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
824 snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
825 snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
826 snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
827 snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
828 snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
829 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
834 static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
836 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
837 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
840 static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
842 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
843 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
844 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
848 static const struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
849 .build_specific = patch_wolfson_wm9713_specific,
850 .build_3d = patch_wolfson_wm9713_3d,
852 .suspend = patch_wolfson_wm9713_suspend,
853 .resume = patch_wolfson_wm9713_resume
857 static int patch_wolfson13(struct snd_ac97 * ac97)
860 ac97->build_ops = &patch_wolfson_wm9713_ops;
862 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
863 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
865 ac97->scaps &= ~AC97_SCAP_MODEM;
867 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
868 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
869 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
877 static int patch_tritech_tr28028(struct snd_ac97 * ac97)
879 snd_ac97_write_cache(ac97, 0x26, 0x0300);
880 snd_ac97_write_cache(ac97, 0x26, 0x0000);
881 snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
882 snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
887 * Sigmatel STAC97xx codecs
889 static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
891 struct snd_kcontrol *kctl;
894 err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97));
897 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
898 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
899 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
903 static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
905 struct snd_kcontrol *kctl;
908 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
909 err = snd_ctl_add(ac97->bus->card, kctl);
912 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
913 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
914 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
915 err = snd_ctl_add(ac97->bus->card, kctl);
918 strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
919 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
920 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
924 static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
925 AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch",
926 AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
928 /* "Sigmatel " removed due to excessive name length: */
929 static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
930 AC97_SINGLE("Surround Phase Inversion Playback Switch",
931 AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
933 static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
934 AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
935 AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
938 static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
942 snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
943 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) {
944 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1);
948 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) {
949 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1);
953 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) {
954 err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1);
958 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) {
959 err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1);
966 static const struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
967 .build_3d = patch_sigmatel_stac9700_3d,
968 .build_specific = patch_sigmatel_stac97xx_specific
971 static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
973 ac97->build_ops = &patch_sigmatel_stac9700_ops;
977 static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
979 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
982 mutex_lock(&ac97->page_mutex);
983 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
984 err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
985 (ucontrol->value.integer.value[0] & 1) << 4);
986 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
987 mutex_unlock(&ac97->page_mutex);
991 static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
992 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
993 .name = "Sigmatel Output Bias Switch",
994 .info = snd_ac97_info_volsw,
995 .get = snd_ac97_get_volsw,
996 .put = snd_ac97_stac9708_put_bias,
997 .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
1000 static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
1004 /* the register bit is writable, but the function is not implemented: */
1005 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
1007 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
1008 err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1);
1011 return patch_sigmatel_stac97xx_specific(ac97);
1014 static const struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
1015 .build_3d = patch_sigmatel_stac9708_3d,
1016 .build_specific = patch_sigmatel_stac9708_specific
1019 static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
1021 unsigned int codec72, codec6c;
1023 ac97->build_ops = &patch_sigmatel_stac9708_ops;
1024 ac97->caps |= 0x10; /* HP (sigmatel surround) support */
1026 codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
1027 codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
1029 if ((codec72==0) && (codec6c==0)) {
1030 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1031 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
1032 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1033 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
1034 } else if ((codec72==0x8000) && (codec6c==0)) {
1035 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1036 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
1037 snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
1038 } else if ((codec72==0x8000) && (codec6c==0x0080)) {
1041 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1045 static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
1047 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1048 if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
1049 // patch for SigmaTel
1050 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1051 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
1052 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1053 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1055 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1059 static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
1061 // patch for SigmaTel
1062 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1063 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1064 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1065 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1066 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1067 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1071 static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
1073 // patch for SigmaTel
1074 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1075 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1076 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1077 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1078 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1079 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1083 static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1085 static const char * const texts[5] = {
1086 "Input/Disabled", "Front Output",
1087 "Rear Output", "Center/LFE Output", "Mixer Output" };
1089 return snd_ctl_enum_info(uinfo, 1, 5, texts);
1092 static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1094 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1095 int shift = kcontrol->private_value;
1098 val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
1100 ucontrol->value.enumerated.item[0] = 0;
1102 ucontrol->value.enumerated.item[0] = 1 + (val & 3);
1106 static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1108 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1109 int shift = kcontrol->private_value;
1112 if (ucontrol->value.enumerated.item[0] > 4)
1114 if (ucontrol->value.enumerated.item[0] == 0)
1117 val = 4 | (ucontrol->value.enumerated.item[0] - 1);
1118 return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
1119 7 << shift, val << shift, 0);
1122 static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1124 static const char * const texts[7] = {
1125 "Mic2 Jack", "Mic1 Jack", "Line In Jack",
1126 "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
1128 return snd_ctl_enum_info(uinfo, 1, 7, texts);
1131 static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1133 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1134 int shift = kcontrol->private_value;
1137 val = ac97->regs[AC97_SIGMATEL_INSEL];
1138 ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
1142 static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1144 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1145 int shift = kcontrol->private_value;
1147 return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
1148 ucontrol->value.enumerated.item[0] << shift, 0);
1151 static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1153 static const char * const texts[3] = {
1154 "None", "Front Jack", "Rear Jack"
1157 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1160 static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1162 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1164 ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
1168 static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1170 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1172 return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
1173 ucontrol->value.enumerated.item[0], 0);
1176 #define STAC9758_OUTPUT_JACK(xname, shift) \
1177 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1178 .info = snd_ac97_stac9758_output_jack_info, \
1179 .get = snd_ac97_stac9758_output_jack_get, \
1180 .put = snd_ac97_stac9758_output_jack_put, \
1181 .private_value = shift }
1182 #define STAC9758_INPUT_JACK(xname, shift) \
1183 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1184 .info = snd_ac97_stac9758_input_jack_info, \
1185 .get = snd_ac97_stac9758_input_jack_get, \
1186 .put = snd_ac97_stac9758_input_jack_put, \
1187 .private_value = shift }
1188 static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
1189 STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
1190 STAC9758_OUTPUT_JACK("LineIn Jack", 4),
1191 STAC9758_OUTPUT_JACK("Front Jack", 7),
1192 STAC9758_OUTPUT_JACK("Rear Jack", 10),
1193 STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
1194 STAC9758_INPUT_JACK("Mic Input Source", 0),
1195 STAC9758_INPUT_JACK("Line Input Source", 8),
1197 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1198 .name = "Headphone Amp",
1199 .info = snd_ac97_stac9758_phonesel_info,
1200 .get = snd_ac97_stac9758_phonesel_get,
1201 .put = snd_ac97_stac9758_phonesel_put
1203 AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
1204 AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
1207 static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
1211 err = patch_sigmatel_stac97xx_specific(ac97);
1214 err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
1215 ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
1219 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
1220 /* DAC-A to Mix = PCM */
1221 /* DAC-B direct = Surround */
1223 snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
1224 /* DAC-C direct = Center/LFE */
1229 static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
1230 .build_3d = patch_sigmatel_stac9700_3d,
1231 .build_specific = patch_sigmatel_stac9758_specific
1234 static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
1236 static const unsigned short regs[4] = {
1237 AC97_SIGMATEL_OUTSEL,
1238 AC97_SIGMATEL_IOMISC,
1239 AC97_SIGMATEL_INSEL,
1240 AC97_SIGMATEL_VARIOUS
1242 static const unsigned short def_regs[4] = {
1243 /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
1244 /* IOMISC */ 0x2001,
1245 /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
1246 /* VARIOUS */ 0x0040
1248 static const unsigned short m675_regs[4] = {
1249 /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
1250 /* IOMISC */ 0x2102, /* HP amp on */
1251 /* INSEL */ 0x0203, /* LI:LI, MI:FR */
1252 /* VARIOUS */ 0x0041 /* stereo mic */
1254 const unsigned short *pregs = def_regs;
1257 /* Gateway M675 notebook */
1259 ac97->subsystem_vendor == 0x107b &&
1260 ac97->subsystem_device == 0x0601)
1263 // patch for SigmaTel
1264 ac97->build_ops = &patch_sigmatel_stac9758_ops;
1265 /* FIXME: assume only page 0 for writing cache */
1266 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
1267 for (i = 0; i < 4; i++)
1268 snd_ac97_write_cache(ac97, regs[i], pregs[i]);
1270 ac97->flags |= AC97_STEREO_MUTES;
1275 * Cirrus Logic CS42xx codecs
1277 static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
1278 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
1279 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
1282 static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
1286 /* con mask, pro mask, default */
1287 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1291 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1);
1294 switch (ac97->id & AC97_ID_CS_MASK) {
1295 case AC97_ID_CS4205:
1296 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1);
1301 /* set default PCM S/PDIF params */
1302 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1303 snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
1307 static const struct snd_ac97_build_ops patch_cirrus_ops = {
1308 .build_spdif = patch_cirrus_build_spdif
1311 static int patch_cirrus_spdif(struct snd_ac97 * ac97)
1313 /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
1314 WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh*
1315 - sp/dif EA ID is not set, but sp/dif is always present.
1316 - enable/disable is spdif register bit 15.
1317 - sp/dif control register is 0x68. differs from AC97:
1318 - valid is bit 14 (vs 15)
1320 - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48)
1321 - sp/dif ssource select is in 0x5e bits 0,1.
1324 ac97->build_ops = &patch_cirrus_ops;
1325 ac97->flags |= AC97_CS_SPDIF;
1326 ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
1327 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1328 snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
1332 static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
1334 /* force the detection of PC Beep */
1335 ac97->flags |= AC97_HAS_PC_BEEP;
1337 return patch_cirrus_spdif(ac97);
1343 static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
1344 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
1347 static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
1351 /* con mask, pro mask, default */
1352 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1356 err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1);
1359 /* set default PCM S/PDIF params */
1360 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1361 snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
1362 snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
1366 static const struct snd_ac97_build_ops patch_conexant_ops = {
1367 .build_spdif = patch_conexant_build_spdif
1370 static int patch_conexant(struct snd_ac97 * ac97)
1372 ac97->build_ops = &patch_conexant_ops;
1373 ac97->flags |= AC97_CX_SPDIF;
1374 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1375 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
1379 static int patch_cx20551(struct snd_ac97 *ac97)
1381 snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
1386 * Analog Devices AD18xx, AD19xx codecs
1389 static void ad18xx_resume(struct snd_ac97 *ac97)
1391 static const unsigned short setup_regs[] = {
1392 AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
1396 for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
1397 unsigned short reg = setup_regs[i];
1398 if (test_bit(reg, ac97->reg_accessed)) {
1399 snd_ac97_write(ac97, reg, ac97->regs[reg]);
1400 snd_ac97_read(ac97, reg);
1404 if (! (ac97->flags & AC97_AD_MULTI))
1405 /* normal restore */
1406 snd_ac97_restore_status(ac97);
1408 /* restore the AD18xx codec configurations */
1409 for (codec = 0; codec < 3; codec++) {
1410 if (! ac97->spec.ad18xx.id[codec])
1412 /* select single codec */
1413 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1414 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1415 ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
1417 /* select all codecs */
1418 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1420 /* restore status */
1421 for (i = 2; i < 0x7c ; i += 2) {
1422 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
1424 if (test_bit(i, ac97->reg_accessed)) {
1425 /* handle multi codecs for AD18xx */
1426 if (i == AC97_PCM) {
1427 for (codec = 0; codec < 3; codec++) {
1428 if (! ac97->spec.ad18xx.id[codec])
1430 /* select single codec */
1431 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1432 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1433 /* update PCM bits */
1434 ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
1436 /* select all codecs */
1437 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1439 } else if (i == AC97_AD_TEST ||
1440 i == AC97_AD_CODEC_CFG ||
1441 i == AC97_AD_SERIAL_CFG)
1442 continue; /* ignore */
1444 snd_ac97_write(ac97, i, ac97->regs[i]);
1445 snd_ac97_read(ac97, i);
1449 snd_ac97_restore_iec958(ac97);
1452 static void ad1888_resume(struct snd_ac97 *ac97)
1454 ad18xx_resume(ac97);
1455 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
1460 static const struct snd_ac97_res_table ad1819_restbl[] = {
1461 { AC97_PHONE, 0x9f1f },
1462 { AC97_MIC, 0x9f1f },
1463 { AC97_LINE, 0x9f1f },
1464 { AC97_CD, 0x9f1f },
1465 { AC97_VIDEO, 0x9f1f },
1466 { AC97_AUX, 0x9f1f },
1467 { AC97_PCM, 0x9f1f },
1468 { } /* terminator */
1471 static int patch_ad1819(struct snd_ac97 * ac97)
1473 unsigned short scfg;
1475 // patch for Analog Devices
1476 scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1477 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
1478 ac97->res_table = ad1819_restbl;
1482 static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
1486 // test for unchained codec
1487 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
1488 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */
1489 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1490 if ((val & 0xff40) != 0x5340)
1492 ac97->spec.ad18xx.unchained[idx] = mask;
1493 ac97->spec.ad18xx.id[idx] = val;
1494 ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
1498 static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
1500 static const int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
1503 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
1504 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE
1505 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1506 if ((val & 0xff40) != 0x5340)
1509 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
1510 ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
1511 ac97->spec.ad18xx.id[idx] = val;
1512 ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
1516 static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
1518 // already detected?
1519 if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
1521 if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
1523 if (cidx1 < 0 && cidx2 < 0)
1525 // test for chained codecs
1526 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1527 ac97->spec.ad18xx.unchained[unchained_idx]);
1528 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
1529 ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
1532 patch_ad1881_chained1(ac97, cidx1, 0);
1533 else if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
1534 patch_ad1881_chained1(ac97, cidx2, 0);
1535 else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C
1536 patch_ad1881_chained1(ac97, cidx1, 0);
1537 } else if (cidx2 >= 0) {
1538 patch_ad1881_chained1(ac97, cidx2, 0);
1542 static const struct snd_ac97_build_ops patch_ad1881_build_ops = {
1544 .resume = ad18xx_resume
1548 static int patch_ad1881(struct snd_ac97 * ac97)
1550 static const char cfg_idxs[3][2] = {
1556 // patch for Analog Devices
1557 unsigned short codecs[3];
1561 val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1562 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
1563 codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
1564 codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
1565 codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
1567 if (! (codecs[0] || codecs[1] || codecs[2]))
1570 for (idx = 0; idx < 3; idx++)
1571 if (ac97->spec.ad18xx.unchained[idx])
1572 patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
1574 if (ac97->spec.ad18xx.id[1]) {
1575 ac97->flags |= AC97_AD_MULTI;
1576 ac97->scaps |= AC97_SCAP_SURROUND_DAC;
1578 if (ac97->spec.ad18xx.id[2]) {
1579 ac97->flags |= AC97_AD_MULTI;
1580 ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
1584 /* select all codecs */
1585 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1586 /* check if only one codec is present */
1587 for (idx = num = 0; idx < 3; idx++)
1588 if (ac97->spec.ad18xx.id[idx])
1591 /* ok, deselect all ID bits */
1592 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
1593 ac97->spec.ad18xx.codec_cfg[0] =
1594 ac97->spec.ad18xx.codec_cfg[1] =
1595 ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
1597 /* required for AD1886/AD1885 combination */
1598 ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
1599 if (ac97->spec.ad18xx.id[0]) {
1600 ac97->id &= 0xffff0000;
1601 ac97->id |= ac97->spec.ad18xx.id[0];
1603 ac97->build_ops = &patch_ad1881_build_ops;
1607 static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1608 AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
1609 /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
1610 AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
1611 AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
1612 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
1613 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1616 static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1618 static int patch_ad1885_specific(struct snd_ac97 * ac97)
1622 err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885));
1625 reset_tlv(ac97, "Headphone Playback Volume",
1626 db_scale_6bit_6db_max);
1630 static const struct snd_ac97_build_ops patch_ad1885_build_ops = {
1631 .build_specific = &patch_ad1885_specific,
1633 .resume = ad18xx_resume
1637 static int patch_ad1885(struct snd_ac97 * ac97)
1640 /* This is required to deal with the Intel D815EEAL2 */
1641 /* i.e. Line out is actually headphone out from codec */
1644 snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
1646 ac97->build_ops = &patch_ad1885_build_ops;
1650 static int patch_ad1886_specific(struct snd_ac97 * ac97)
1652 reset_tlv(ac97, "Headphone Playback Volume",
1653 db_scale_6bit_6db_max);
1657 static const struct snd_ac97_build_ops patch_ad1886_build_ops = {
1658 .build_specific = &patch_ad1886_specific,
1660 .resume = ad18xx_resume
1664 static int patch_ad1886(struct snd_ac97 * ac97)
1667 /* Presario700 workaround */
1668 /* for Jack Sense/SPDIF Register misetting causing */
1669 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
1670 ac97->build_ops = &patch_ad1886_build_ops;
1674 /* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
1675 #define AC97_AD198X_MBC 0x0003 /* mic boost */
1676 #define AC97_AD198X_MBC_20 0x0000 /* +20dB */
1677 #define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1678 #define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1679 #define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1680 #define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1681 #define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */
1682 #define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1683 #define AC97_AD198X_VREF_SHIFT 2
1684 #define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1685 #define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1686 #define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1687 #define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1688 #define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */
1689 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1690 #define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1691 #define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1692 #define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
1693 #define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */
1694 #define AC97_AD198X_MSPLT 0x2000 /* mute split */
1695 #define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
1696 #define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
1698 /* MISC 1 bits (AD1986 register 0x76) */
1699 #define AC97_AD1986_MBC 0x0003 /* mic boost */
1700 #define AC97_AD1986_MBC_20 0x0000 /* +20dB */
1701 #define AC97_AD1986_MBC_10 0x0001 /* +10dB */
1702 #define AC97_AD1986_MBC_30 0x0002 /* +30dB */
1703 #define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */
1704 #define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */
1705 #define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1706 #define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */
1707 #define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */
1708 #define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */
1709 #define AC97_AD1986_SRU 0x0010 /* sample rate unlock */
1710 #define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */
1711 #define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */
1712 #define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */
1713 #define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */
1714 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1715 #define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1716 #define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */
1717 #define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */
1718 #define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */
1719 #define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */
1720 #define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */
1722 /* MISC 2 bits (AD1986 register 0x70) */
1723 #define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */
1725 #define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */
1726 #define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */
1727 #define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */
1728 #define AC97_AD1986_CVREF_MASK \
1729 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1730 #define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */
1731 #define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */
1732 #define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */
1733 #define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */
1734 #define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */
1735 #define AC97_AD1986_MVREF_MASK \
1736 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1738 /* MISC 3 bits (AD1986 register 0x7a) */
1739 #define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */
1741 #define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */
1742 #define AC97_AD1986_GPO 0x0008 /* General Purpose Out */
1743 #define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */
1744 #define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */
1745 #define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */
1746 #define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */
1747 #define AC97_AD1986_LVREF_MASK \
1748 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1749 #define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */
1750 #define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */
1751 #define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */
1752 /* input select Surround DACs */
1753 #define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */
1754 /* select C/LFE DACs */
1755 #define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */
1757 /* Serial Config bits (AD1986 register 0x74) (incomplete) */
1758 #define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */
1759 #define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */
1760 #define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */
1761 #define AC97_AD1986_OMS_MASK \
1762 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1763 #define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */
1764 #define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */
1765 #define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */
1766 #define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */
1767 /* are MIC sources */
1768 #define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */
1769 /* are MIC sources */
1770 #define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */
1771 /* are MIC sources */
1772 #define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */
1773 /* are MIC sources */
1776 static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1778 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
1780 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1783 static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1785 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1788 val = ac97->regs[AC97_AD_SERIAL_CFG];
1789 ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
1793 static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1795 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1798 if (ucontrol->value.enumerated.item[0] > 1)
1800 val = ucontrol->value.enumerated.item[0] << 2;
1801 return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
1804 static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
1805 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1806 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1807 .info = snd_ac97_ad198x_spdif_source_info,
1808 .get = snd_ac97_ad198x_spdif_source_get,
1809 .put = snd_ac97_ad198x_spdif_source_put,
1812 static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
1814 return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
1817 static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
1818 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
1819 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1822 /* deny list to avoid HP/Line jack-sense controls
1823 * (SS vendor << 16 | device)
1825 static const unsigned int ad1981_jacks_denylist[] = {
1826 0x10140523, /* Thinkpad R40 */
1827 0x10140534, /* Thinkpad X31 */
1828 0x10140537, /* Thinkpad T41p */
1829 0x1014053e, /* Thinkpad R40e */
1830 0x10140554, /* Thinkpad T42p/R50p */
1831 0x10140567, /* Thinkpad T43p 2668-G7U */
1832 0x10140581, /* Thinkpad X41-2527 */
1833 0x10280160, /* Dell Dimension 2400 */
1834 0x104380b0, /* Asus A7V8X-MX */
1835 0x11790241, /* Toshiba Satellite A-15 S127 */
1836 0x1179ff10, /* Toshiba P500 */
1837 0x144dc01a, /* Samsung NP-X20C004/SEG */
1841 static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
1843 u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
1844 for (; *list; list++)
1850 static int patch_ad1981a_specific(struct snd_ac97 * ac97)
1852 if (check_list(ac97, ad1981_jacks_denylist))
1854 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1855 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1858 static const struct snd_ac97_build_ops patch_ad1981a_build_ops = {
1859 .build_post_spdif = patch_ad198x_post_spdif,
1860 .build_specific = patch_ad1981a_specific,
1862 .resume = ad18xx_resume
1866 /* allow list to enable HP jack-sense bits
1867 * (SS vendor << 16 | device)
1869 static const unsigned int ad1981_jacks_allowlist[] = {
1870 0x0e11005a, /* HP nc4000/4010 */
1871 0x103c0890, /* HP nc6000 */
1872 0x103c0938, /* HP nc4220 */
1873 0x103c099c, /* HP nx6110 */
1874 0x103c0944, /* HP nc6220 */
1875 0x103c0934, /* HP nc8220 */
1876 0x103c006d, /* HP nx9105 */
1877 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
1878 0x17340088, /* FSC Scenic-W */
1882 static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
1884 if (check_list(ac97, ad1981_jacks_allowlist))
1885 /* enable headphone jack sense */
1886 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
1889 static int patch_ad1981a(struct snd_ac97 *ac97)
1892 ac97->build_ops = &patch_ad1981a_build_ops;
1893 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1894 ac97->flags |= AC97_STEREO_MUTES;
1895 check_ad1981_hp_jack_sense(ac97);
1899 static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
1900 AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
1902 static int patch_ad1981b_specific(struct snd_ac97 *ac97)
1906 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
1909 if (check_list(ac97, ad1981_jacks_denylist))
1911 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1912 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1915 static const struct snd_ac97_build_ops patch_ad1981b_build_ops = {
1916 .build_post_spdif = patch_ad198x_post_spdif,
1917 .build_specific = patch_ad1981b_specific,
1919 .resume = ad18xx_resume
1923 static int patch_ad1981b(struct snd_ac97 *ac97)
1926 ac97->build_ops = &patch_ad1981b_build_ops;
1927 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1928 ac97->flags |= AC97_STEREO_MUTES;
1929 check_ad1981_hp_jack_sense(ac97);
1933 #define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
1935 static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1937 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1940 val = ac97->regs[AC97_AD_MISC];
1941 ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
1942 if (ac97->spec.ad18xx.lo_as_master)
1943 ucontrol->value.integer.value[0] =
1944 !ucontrol->value.integer.value[0];
1948 static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1950 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1953 val = !ucontrol->value.integer.value[0];
1954 if (ac97->spec.ad18xx.lo_as_master)
1956 val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
1957 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1958 AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
1961 static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1963 static const char * const texts[3] = {"Off", "6 -> 4", "6 -> 2"};
1965 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1968 static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1970 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1973 val = ac97->regs[AC97_AD_MISC];
1974 if (!(val & AC97_AD198X_DMIX1))
1975 ucontrol->value.enumerated.item[0] = 0;
1977 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
1981 static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1983 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1986 if (ucontrol->value.enumerated.item[0] > 2)
1988 if (ucontrol->value.enumerated.item[0] == 0)
1991 val = AC97_AD198X_DMIX1 |
1992 ((ucontrol->value.enumerated.item[0] - 1) << 8);
1993 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1994 AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
1997 static void ad1888_update_jacks(struct snd_ac97 *ac97)
1999 unsigned short val = 0;
2000 /* clear LODIS if shared jack is to be used for Surround out */
2001 if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
2003 /* clear CLDIS if shared jack is to be used for C/LFE out */
2004 if (is_shared_micin(ac97))
2006 /* shared Line-In */
2007 snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
2010 static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
2012 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2013 .name = "Exchange Front/Surround",
2014 .info = snd_ac97_ad1888_lohpsel_info,
2015 .get = snd_ac97_ad1888_lohpsel_get,
2016 .put = snd_ac97_ad1888_lohpsel_put
2018 AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
2019 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
2020 AC97_AD_HPFD_SHIFT, 1, 1),
2021 AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
2023 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2025 .info = snd_ac97_ad1888_downmix_info,
2026 .get = snd_ac97_ad1888_downmix_get,
2027 .put = snd_ac97_ad1888_downmix_put
2029 AC97_SURROUND_JACK_MODE_CTL,
2030 AC97_CHANNEL_MODE_CTL,
2032 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2033 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2036 static int patch_ad1888_specific(struct snd_ac97 *ac97)
2038 if (!ac97->spec.ad18xx.lo_as_master) {
2039 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2040 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2041 "Master Surround Playback");
2042 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
2045 return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
2048 static const struct snd_ac97_build_ops patch_ad1888_build_ops = {
2049 .build_post_spdif = patch_ad198x_post_spdif,
2050 .build_specific = patch_ad1888_specific,
2052 .resume = ad1888_resume,
2054 .update_jacks = ad1888_update_jacks,
2057 static int patch_ad1888(struct snd_ac97 * ac97)
2059 unsigned short misc;
2062 ac97->build_ops = &patch_ad1888_build_ops;
2065 * LO can be used as a real line-out on some devices,
2066 * and we need to revert the front/surround mixer switches
2068 if (ac97->subsystem_vendor == 0x1043 &&
2069 ac97->subsystem_device == 0x1193) /* ASUS A9T laptop */
2070 ac97->spec.ad18xx.lo_as_master = 1;
2072 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2073 /* AD-compatible mode */
2074 /* Stereo mutes enabled */
2075 misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
2076 if (!ac97->spec.ad18xx.lo_as_master)
2077 /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
2078 /* it seems that most vendors connect line-out connector to
2079 * headphone out of AC'97
2081 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
2083 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
2084 ac97->flags |= AC97_STEREO_MUTES;
2088 static int patch_ad1980_specific(struct snd_ac97 *ac97)
2092 err = patch_ad1888_specific(ac97);
2095 return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2098 static const struct snd_ac97_build_ops patch_ad1980_build_ops = {
2099 .build_post_spdif = patch_ad198x_post_spdif,
2100 .build_specific = patch_ad1980_specific,
2102 .resume = ad18xx_resume,
2104 .update_jacks = ad1888_update_jacks,
2107 static int patch_ad1980(struct snd_ac97 * ac97)
2110 ac97->build_ops = &patch_ad1980_build_ops;
2114 static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2115 struct snd_ctl_elem_info *uinfo)
2117 static const char * const texts[4] = {
2118 "High-Z", "3.7 V", "2.25 V", "0 V"
2121 return snd_ctl_enum_info(uinfo, 1, 4, texts);
2124 static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2125 struct snd_ctl_elem_value *ucontrol)
2127 static const int reg2ctrl[4] = {2, 0, 1, 3};
2128 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2130 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2131 >> AC97_AD198X_VREF_SHIFT;
2132 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2136 static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2137 struct snd_ctl_elem_value *ucontrol)
2139 static const int ctrl2reg[4] = {1, 2, 0, 3};
2140 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2143 if (ucontrol->value.enumerated.item[0] > 3)
2145 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2146 << AC97_AD198X_VREF_SHIFT;
2147 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2148 AC97_AD198X_VREF_MASK, val);
2151 static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
2152 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2155 .name = "Exchange Front/Surround",
2156 .info = snd_ac97_ad1888_lohpsel_info,
2157 .get = snd_ac97_ad1888_lohpsel_get,
2158 .put = snd_ac97_ad1888_lohpsel_put
2160 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2161 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2162 AC97_AD_MISC, 7, 1, 0),
2164 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2166 .info = snd_ac97_ad1888_downmix_info,
2167 .get = snd_ac97_ad1888_downmix_get,
2168 .put = snd_ac97_ad1888_downmix_put
2171 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2173 .info = snd_ac97_ad1985_vrefout_info,
2174 .get = snd_ac97_ad1985_vrefout_get,
2175 .put = snd_ac97_ad1985_vrefout_put
2177 AC97_SURROUND_JACK_MODE_CTL,
2178 AC97_CHANNEL_MODE_CTL,
2180 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2181 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2184 static void ad1985_update_jacks(struct snd_ac97 *ac97)
2186 ad1888_update_jacks(ac97);
2187 /* clear OMS if shared jack is to be used for C/LFE out */
2188 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
2189 is_shared_micin(ac97) ? 1 << 9 : 0);
2192 static int patch_ad1985_specific(struct snd_ac97 *ac97)
2196 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2197 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2198 "Master Surround Playback");
2199 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2201 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2205 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2206 ARRAY_SIZE(snd_ac97_ad1985_controls));
2209 static const struct snd_ac97_build_ops patch_ad1985_build_ops = {
2210 .build_post_spdif = patch_ad198x_post_spdif,
2211 .build_specific = patch_ad1985_specific,
2213 .resume = ad18xx_resume,
2215 .update_jacks = ad1985_update_jacks,
2218 static int patch_ad1985(struct snd_ac97 * ac97)
2220 unsigned short misc;
2223 ac97->build_ops = &patch_ad1985_build_ops;
2224 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2225 /* switch front/surround line-out/hp-out */
2226 /* AD-compatible mode */
2227 /* Stereo mutes enabled */
2228 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2232 AC97_AD198X_AC97NC);
2233 ac97->flags |= AC97_STEREO_MUTES;
2235 /* update current jack configuration */
2236 ad1985_update_jacks(ac97);
2238 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2239 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2243 #define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
2245 static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2246 struct snd_ctl_elem_value *ucontrol)
2248 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2251 val = ac97->regs[AC97_AD_MISC3];
2252 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2256 static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2257 struct snd_ctl_elem_value *ucontrol)
2259 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2262 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2264 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2265 ucontrol->value.integer.value[0] != 0
2266 ? AC97_AD1986_LOSEL : 0);
2270 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2271 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2272 (ucontrol->value.integer.value[0] != 0
2274 ? AC97_AD1986_SOSEL : 0);
2278 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2281 static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2282 struct snd_ctl_elem_value *ucontrol)
2284 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2287 val = ac97->regs[AC97_AD_MISC];
2288 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2292 static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2293 struct snd_ctl_elem_value *ucontrol)
2295 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2298 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2300 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2301 ucontrol->value.integer.value[0] != 0
2302 ? AC97_AD1986_SPRD : 0);
2306 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2307 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2308 (ucontrol->value.integer.value[0] != 0
2310 ? AC97_AD1986_SOSEL : 0);
2314 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2317 static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2318 struct snd_ctl_elem_value *ucontrol)
2320 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2322 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2326 static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2327 struct snd_ctl_elem_value *ucontrol)
2329 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2330 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2332 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2333 ac97->spec.ad18xx.swap_mic_linein = swap;
2334 if (ac97->build_ops->update_jacks)
2335 ac97->build_ops->update_jacks(ac97);
2341 static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2342 struct snd_ctl_elem_value *ucontrol)
2344 /* Use MIC_1/2 V_REFOUT as the "get" value */
2345 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2347 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2348 if ((reg & AC97_AD1986_MVREF0) != 0)
2350 else if ((reg & AC97_AD1986_MVREF1) != 0)
2352 else if ((reg & AC97_AD1986_MVREF2) != 0)
2356 ucontrol->value.enumerated.item[0] = val;
2360 static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2361 struct snd_ctl_elem_value *ucontrol)
2363 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2364 unsigned short cval;
2365 unsigned short lval;
2366 unsigned short mval;
2371 switch (ucontrol->value.enumerated.item[0])
2373 case 0: /* High-Z */
2379 cval = AC97_AD1986_CVREF2;
2380 lval = AC97_AD1986_LVREF2;
2381 mval = AC97_AD1986_MVREF2;
2383 case 2: /* 2.25 V */
2384 cval = AC97_AD1986_CVREF0;
2385 lval = AC97_AD1986_LVREF0;
2386 mval = AC97_AD1986_MVREF0;
2389 cval = AC97_AD1986_CVREF1;
2390 lval = AC97_AD1986_LVREF1;
2391 mval = AC97_AD1986_MVREF1;
2397 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2398 AC97_AD1986_CVREF_MASK, cval);
2401 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2402 AC97_AD1986_LVREF_MASK, lval);
2405 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2406 AC97_AD1986_MVREF_MASK, mval);
2410 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2413 static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2414 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2417 .name = "Exchange Front/Surround",
2418 .info = snd_ac97_ad1986_bool_info,
2419 .get = snd_ac97_ad1986_lososel_get,
2420 .put = snd_ac97_ad1986_lososel_put
2423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2424 .name = "Exchange Mic/Line In",
2425 .info = snd_ac97_ad1986_bool_info,
2426 .get = snd_ac97_ad1986_miclisel_get,
2427 .put = snd_ac97_ad1986_miclisel_put
2430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2431 .name = "Spread Front to Surround and Center/LFE",
2432 .info = snd_ac97_ad1986_bool_info,
2433 .get = snd_ac97_ad1986_spread_get,
2434 .put = snd_ac97_ad1986_spread_put
2437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2439 .info = snd_ac97_ad1888_downmix_info,
2440 .get = snd_ac97_ad1888_downmix_get,
2441 .put = snd_ac97_ad1888_downmix_put
2444 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2446 .info = snd_ac97_ad1985_vrefout_info,
2447 .get = snd_ac97_ad1986_vrefout_get,
2448 .put = snd_ac97_ad1986_vrefout_put
2450 AC97_SURROUND_JACK_MODE_CTL,
2451 AC97_CHANNEL_MODE_CTL,
2453 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2454 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2457 static void ad1986_update_jacks(struct snd_ac97 *ac97)
2459 unsigned short misc_val = 0;
2460 unsigned short ser_val;
2462 /* disable SURROUND and CENTER/LFE if not surround mode */
2463 if (!is_surround_on(ac97))
2464 misc_val |= AC97_AD1986_SODIS;
2465 if (!is_clfe_on(ac97))
2466 misc_val |= AC97_AD1986_CLDIS;
2468 /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
2469 if (is_shared_linein(ac97))
2470 misc_val |= AC97_AD1986_LISEL_SURR;
2471 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2472 misc_val |= AC97_AD1986_LISEL_MIC;
2473 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2474 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2475 AC97_AD1986_LISEL_MASK,
2478 /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
2479 if (is_shared_micin(ac97))
2480 ser_val = AC97_AD1986_OMS_C;
2481 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2482 ser_val = AC97_AD1986_OMS_L;
2484 ser_val = AC97_AD1986_OMS_M;
2485 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2486 AC97_AD1986_OMS_MASK,
2490 static int patch_ad1986_specific(struct snd_ac97 *ac97)
2494 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2498 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2499 ARRAY_SIZE(snd_ac97_ad1985_controls));
2502 static const struct snd_ac97_build_ops patch_ad1986_build_ops = {
2503 .build_post_spdif = patch_ad198x_post_spdif,
2504 .build_specific = patch_ad1986_specific,
2506 .resume = ad18xx_resume,
2508 .update_jacks = ad1986_update_jacks,
2511 static int patch_ad1986(struct snd_ac97 * ac97)
2514 ac97->build_ops = &patch_ad1986_build_ops;
2515 ac97->flags |= AC97_STEREO_MUTES;
2517 /* update current jack configuration */
2518 ad1986_update_jacks(ac97);
2524 * realtek ALC203: use mono-out for pin 37
2526 static int patch_alc203(struct snd_ac97 *ac97)
2528 snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
2533 * realtek ALC65x/850 codecs
2535 static void alc650_update_jacks(struct snd_ac97 *ac97)
2539 /* shared Line-In / Surround Out */
2540 shared = is_shared_surrout(ac97);
2541 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2542 shared ? (1 << 9) : 0);
2543 /* update shared Mic In / Center/LFE Out */
2544 shared = is_shared_clfeout(ac97);
2545 /* disable/enable vref */
2546 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2547 shared ? (1 << 12) : 0);
2548 /* turn on/off center-on-mic */
2549 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
2550 shared ? (1 << 10) : 0);
2551 /* GPIO0 high for mic */
2552 snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
2553 shared ? 0 : 0x100);
2556 static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
2557 struct snd_ctl_elem_value *ucontrol)
2559 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2560 struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
2563 if (ucontrol->value.integer.value[0])
2564 map->chmap = snd_pcm_std_chmaps;
2566 map->chmap = snd_pcm_alt_chmaps;
2568 return snd_ac97_put_volsw(kcontrol, ucontrol);
2571 static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2572 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2573 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
2574 AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
2575 AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
2576 /* 4: Analog Input To Surround */
2577 /* 5: Analog Input To Center/LFE */
2578 /* 6: Independent Master Volume Right */
2579 /* 7: Independent Master Volume Left */
2581 /* 9: Line-In/Surround share */
2582 /* 10: Mic/CLFE share */
2583 /* 11-13: in IEC958 controls */
2585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2586 .name = "Swap Surround Slot",
2587 .info = snd_ac97_info_volsw,
2588 .get = snd_ac97_get_volsw,
2589 .put = alc650_swap_surround_put,
2590 .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
2592 #if 0 /* always set in patch_alc650 */
2593 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2594 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
2595 AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
2596 AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
2597 AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
2598 AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
2600 AC97_SURROUND_JACK_MODE_CTL,
2601 AC97_CHANNEL_MODE_CTL,
2604 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2605 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
2606 AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
2607 /* disable this controls since it doesn't work as expected */
2608 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2611 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2613 static int patch_alc650_specific(struct snd_ac97 * ac97)
2617 err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650));
2620 if (ac97->ext_id & AC97_EI_SPDIF) {
2621 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650));
2625 if (ac97->id != AC97_ID_ALC650F)
2626 reset_tlv(ac97, "Master Playback Volume",
2627 db_scale_5bit_3db_max);
2631 static const struct snd_ac97_build_ops patch_alc650_ops = {
2632 .build_specific = patch_alc650_specific,
2633 .update_jacks = alc650_update_jacks
2636 static int patch_alc650(struct snd_ac97 * ac97)
2640 ac97->build_ops = &patch_alc650_ops;
2642 /* determine the revision */
2643 val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
2645 ac97->id = 0x414c4720; /* Old version */
2646 else if (val < 0x10)
2647 ac97->id = 0x414c4721; /* D version */
2648 else if (val < 0x20)
2649 ac97->id = 0x414c4722; /* E version */
2650 else if (val < 0x30)
2651 ac97->id = 0x414c4723; /* F version */
2653 /* revision E or F */
2654 /* FIXME: what about revision D ? */
2655 ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
2656 ac97->id == 0x414c4723);
2658 /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
2659 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2660 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
2662 /* Enable SPDIF-IN only on Rev.E and above */
2663 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2664 /* SPDIF IN with pin 47 */
2665 if (ac97->spec.dev_flags &&
2666 /* ASUS A6KM requires EAPD */
2667 ! (ac97->subsystem_vendor == 0x1043 &&
2668 ac97->subsystem_device == 0x1103))
2669 val |= 0x03; /* enable */
2671 val &= ~0x03; /* disable */
2672 snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
2674 /* set default: slot 3,4,7,8,6,9
2675 spdif-in monitor off, analog-spdif off, spdif-in off
2676 center on mic off, surround on line-in off
2677 downmix off, duplicate front off
2679 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
2681 /* set GPIO0 for mic bias */
2682 /* GPIO0 pin output, no interrupt, high */
2683 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
2684 snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
2685 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2686 (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
2688 /* full DAC volume */
2689 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2690 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2694 static void alc655_update_jacks(struct snd_ac97 *ac97)
2698 /* shared Line-In / Surround Out */
2699 shared = is_shared_surrout(ac97);
2700 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2701 shared ? (1 << 9) : 0, 0);
2702 /* update shared Mic In / Center/LFE Out */
2703 shared = is_shared_clfeout(ac97);
2704 /* misc control; vrefout disable */
2705 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2706 shared ? (1 << 12) : 0);
2707 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
2708 shared ? (1 << 10) : 0, 0);
2711 static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
2712 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2713 AC97_SURROUND_JACK_MODE_CTL,
2714 AC97_CHANNEL_MODE_CTL,
2717 static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2719 static const char * const texts_655[3] = {
2720 "PCM", "Analog In", "IEC958 In"
2722 static const char * const texts_658[4] = {
2723 "PCM", "Analog1 In", "Analog2 In", "IEC958 In"
2725 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2727 if (ac97->spec.dev_flags)
2728 return snd_ctl_enum_info(uinfo, 1, 4, texts_658);
2730 return snd_ctl_enum_info(uinfo, 1, 3, texts_655);
2733 static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2735 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2738 val = ac97->regs[AC97_ALC650_MULTICH];
2739 val = (val >> 12) & 3;
2740 if (ac97->spec.dev_flags && val == 3)
2742 ucontrol->value.enumerated.item[0] = val;
2746 static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2748 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2750 return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
2751 (unsigned short)ucontrol->value.enumerated.item[0] << 12,
2755 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
2756 AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
2757 /* disable this controls since it doesn't work as expected */
2758 /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
2760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2761 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2762 .info = alc655_iec958_route_info,
2763 .get = alc655_iec958_route_get,
2764 .put = alc655_iec958_route_put,
2768 static int patch_alc655_specific(struct snd_ac97 * ac97)
2772 err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655));
2775 if (ac97->ext_id & AC97_EI_SPDIF) {
2776 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2783 static const struct snd_ac97_build_ops patch_alc655_ops = {
2784 .build_specific = patch_alc655_specific,
2785 .update_jacks = alc655_update_jacks
2788 static int patch_alc655(struct snd_ac97 * ac97)
2792 if (ac97->id == AC97_ID_ALC658) {
2793 ac97->spec.dev_flags = 1; /* ALC658 */
2794 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
2795 ac97->id = AC97_ID_ALC658D;
2796 ac97->spec.dev_flags = 2;
2800 ac97->build_ops = &patch_alc655_ops;
2802 /* assume only page 0 for writing cache */
2803 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2805 /* adjust default values */
2806 val = snd_ac97_read(ac97, 0x7a); /* misc control */
2807 if (ac97->spec.dev_flags) /* ALC658 */
2808 val &= ~(1 << 1); /* Pin 47 is spdif input pin */
2810 if (ac97->subsystem_vendor == 0x1462 &&
2811 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
2812 ac97->subsystem_device == 0x0161 || /* LG K1 Express */
2813 ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
2814 ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */
2815 ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */
2816 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
2818 val |= (1 << 1); /* Pin 47 is spdif input pin */
2819 /* this seems missing on some hardwares */
2820 ac97->ext_id |= AC97_EI_SPDIF;
2822 val &= ~(1 << 12); /* vref enable */
2823 snd_ac97_write_cache(ac97, 0x7a, val);
2824 /* set default: spdif-in enabled,
2825 spdif-in monitor off, spdif-in PCM off
2826 center on mic off, surround on line-in off
2829 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2831 /* full DAC volume */
2832 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2833 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2835 /* update undocumented bit... */
2836 if (ac97->id == AC97_ID_ALC658D)
2837 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2843 #define AC97_ALC850_JACK_SELECT 0x76
2844 #define AC97_ALC850_MISC1 0x7a
2845 #define AC97_ALC850_MULTICH 0x6a
2847 static void alc850_update_jacks(struct snd_ac97 *ac97)
2850 int aux_is_back_surround;
2852 /* shared Line-In / Surround Out */
2853 shared = is_shared_surrout(ac97);
2854 /* SURR 1kOhm (bit4), Amp (bit5) */
2855 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2856 shared ? (1<<5) : (1<<4));
2857 /* LINE-IN = 0, SURROUND = 2 */
2858 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2859 shared ? (2<<12) : (0<<12));
2860 /* update shared Mic In / Center/LFE Out */
2861 shared = is_shared_clfeout(ac97);
2862 /* Vref disable (bit12), 1kOhm (bit13) */
2863 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2864 shared ? (1<<12) : (1<<13));
2865 /* MIC-IN = 1, CENTER-LFE = 5 */
2866 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
2867 shared ? (5<<4) : (1<<4));
2869 aux_is_back_surround = alc850_is_aux_back_surround(ac97);
2870 /* Aux is Back Surround */
2871 snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
2872 aux_is_back_surround ? (1<<10) : (0<<10));
2875 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
2876 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2877 AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
2878 AC97_SURROUND_JACK_MODE_CTL,
2879 AC97_CHANNEL_MODE_8CH_CTL,
2882 static int patch_alc850_specific(struct snd_ac97 *ac97)
2886 err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850));
2889 if (ac97->ext_id & AC97_EI_SPDIF) {
2890 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2897 static const struct snd_ac97_build_ops patch_alc850_ops = {
2898 .build_specific = patch_alc850_specific,
2899 .update_jacks = alc850_update_jacks
2902 static int patch_alc850(struct snd_ac97 *ac97)
2904 ac97->build_ops = &patch_alc850_ops;
2906 ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
2907 ac97->flags |= AC97_HAS_8CH;
2909 /* assume only page 0 for writing cache */
2910 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2912 /* adjust default values */
2913 /* set default: spdif-in enabled,
2914 spdif-in monitor off, spdif-in PCM off
2915 center on mic off, surround on line-in off
2917 NB default bit 10=0 = Aux is Capture, not Back Surround
2919 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2920 /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
2921 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
2923 snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
2924 (1<<7)|(0<<12)|(1<<13)|(0<<14));
2925 /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
2926 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
2928 snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
2929 (1<<11)|(0<<12)|(1<<15));
2931 /* full DAC volume */
2932 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2933 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2937 static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
2939 struct snd_kcontrol *kctl_3d_center =
2940 snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
2941 struct snd_kcontrol *kctl_3d_depth =
2942 snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
2945 * 3D register is different from AC97 standard layout
2946 * (also do some renaming, to resemble Windows driver naming)
2948 if (kctl_3d_center) {
2949 kctl_3d_center->private_value =
2950 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
2951 snd_ac97_rename_vol_ctl(ac97,
2952 "3D Control - Center", "3D Control - Width"
2956 kctl_3d_depth->private_value =
2957 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
2959 /* Aztech Windows driver calls the
2960 equivalent control "Modem Playback", thus rename it: */
2961 snd_ac97_rename_vol_ctl(ac97,
2962 "Master Mono Playback", "Modem Playback"
2964 snd_ac97_rename_vol_ctl(ac97,
2965 "Headphone Playback", "FM Synth Playback"
2971 static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
2972 .build_specific = patch_aztech_azf3328_specific
2975 static int patch_aztech_azf3328(struct snd_ac97 *ac97)
2977 ac97->build_ops = &patch_aztech_azf3328_ops;
2982 * C-Media CM97xx codecs
2984 static void cm9738_update_jacks(struct snd_ac97 *ac97)
2986 /* shared Line-In / Surround Out */
2987 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2988 is_shared_surrout(ac97) ? (1 << 10) : 0);
2991 static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
2992 AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
2993 AC97_SURROUND_JACK_MODE_CTL,
2994 AC97_CHANNEL_MODE_4CH_CTL,
2997 static int patch_cm9738_specific(struct snd_ac97 * ac97)
2999 return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
3002 static const struct snd_ac97_build_ops patch_cm9738_ops = {
3003 .build_specific = patch_cm9738_specific,
3004 .update_jacks = cm9738_update_jacks
3007 static int patch_cm9738(struct snd_ac97 * ac97)
3009 ac97->build_ops = &patch_cm9738_ops;
3010 /* FIXME: can anyone confirm below? */
3011 /* CM9738 has no PCM volume although the register reacts */
3012 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3013 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3018 static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3020 static const char * const texts[] = { "Analog", "Digital" };
3022 return snd_ctl_enum_info(uinfo, 1, 2, texts);
3025 static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3027 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3030 val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
3031 ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
3035 static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3037 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3039 return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
3041 (ucontrol->value.enumerated.item[0] & 0x01) << 1);
3044 static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
3045 /* BIT 0: SPDI_EN - always true */
3046 { /* BIT 1: SPDIFS */
3047 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3048 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3049 .info = snd_ac97_cmedia_spdif_playback_source_info,
3050 .get = snd_ac97_cmedia_spdif_playback_source_get,
3051 .put = snd_ac97_cmedia_spdif_playback_source_put,
3053 /* BIT 2: IG_SPIV */
3054 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
3056 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
3057 /* BIT 4: SPI2SDI */
3058 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
3059 /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
3062 static void cm9739_update_jacks(struct snd_ac97 *ac97)
3064 /* shared Line-In / Surround Out */
3065 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
3066 is_shared_surrout(ac97) ? (1 << 10) : 0);
3067 /* shared Mic In / Center/LFE Out **/
3068 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
3069 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
3072 static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
3073 AC97_SURROUND_JACK_MODE_CTL,
3074 AC97_CHANNEL_MODE_CTL,
3077 static int patch_cm9739_specific(struct snd_ac97 * ac97)
3079 return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
3082 static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
3084 return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
3087 static const struct snd_ac97_build_ops patch_cm9739_ops = {
3088 .build_specific = patch_cm9739_specific,
3089 .build_post_spdif = patch_cm9739_post_spdif,
3090 .update_jacks = cm9739_update_jacks
3093 static int patch_cm9739(struct snd_ac97 * ac97)
3097 ac97->build_ops = &patch_cm9739_ops;
3099 /* CM9739/A has no Master and PCM volume although the register reacts */
3100 ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
3101 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
3102 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3105 val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
3106 if (val & AC97_EA_SPCV) {
3107 /* enable spdif in */
3108 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3109 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
3110 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3112 ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
3113 ac97->rates[AC97_RATES_SPDIF] = 0;
3116 /* set-up multi channel */
3117 /* bit 14: 0 = SPDIF, 1 = EAPD */
3118 /* bit 13: enable internal vref output for mic */
3119 /* bit 12: disable center/lfe (switchable) */
3120 /* bit 10: disable surround/line (switchable) */
3121 /* bit 9: mix 2 surround off */
3122 /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */
3123 /* bit 3: undocumented; surround? */
3125 val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
3128 if (! (ac97->ext_id & AC97_EI_SPDIF))
3130 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
3132 /* FIXME: set up GPIO */
3133 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3134 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3135 /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */
3137 ac97->subsystem_vendor == 0x1043 &&
3138 ac97->subsystem_device == 0x1843) {
3139 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3140 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
3141 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
3142 snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
3148 #define AC97_CM9761_MULTI_CHAN 0x64
3149 #define AC97_CM9761_FUNC 0x66
3150 #define AC97_CM9761_SPDIF_CTRL 0x6c
3152 static void cm9761_update_jacks(struct snd_ac97 *ac97)
3154 /* FIXME: check the bits for each model
3155 * model 83 is confirmed to work
3157 static const unsigned short surr_on[3][2] = {
3158 { 0x0008, 0x0000 }, /* 9761-78 & 82 */
3159 { 0x0000, 0x0008 }, /* 9761-82 rev.B */
3160 { 0x0000, 0x0008 }, /* 9761-83 */
3162 static const unsigned short clfe_on[3][2] = {
3163 { 0x0000, 0x1000 }, /* 9761-78 & 82 */
3164 { 0x1000, 0x0000 }, /* 9761-82 rev.B */
3165 { 0x0000, 0x1000 }, /* 9761-83 */
3167 static const unsigned short surr_shared[3][2] = {
3168 { 0x0000, 0x0400 }, /* 9761-78 & 82 */
3169 { 0x0000, 0x0400 }, /* 9761-82 rev.B */
3170 { 0x0000, 0x0400 }, /* 9761-83 */
3172 static const unsigned short clfe_shared[3][2] = {
3173 { 0x2000, 0x0880 }, /* 9761-78 & 82 */
3174 { 0x0000, 0x2880 }, /* 9761-82 rev.B */
3175 { 0x2000, 0x0800 }, /* 9761-83 */
3177 unsigned short val = 0;
3179 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
3180 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
3181 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
3182 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
3184 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
3187 static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
3188 AC97_SURROUND_JACK_MODE_CTL,
3189 AC97_CHANNEL_MODE_CTL,
3192 static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3194 static const char * const texts[] = { "AC-Link", "ADC", "SPDIF-In" };
3196 return snd_ctl_enum_info(uinfo, 1, 3, texts);
3199 static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3201 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3203 if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
3204 ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
3205 else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
3206 ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
3208 ucontrol->value.enumerated.item[0] = 0; /* AC-link */
3212 static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3214 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3216 if (ucontrol->value.enumerated.item[0] == 2)
3217 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
3218 snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
3219 return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
3220 ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
3223 static const char * const cm9761_dac_clock[] = {
3224 "AC-Link", "SPDIF-In", "Both"
3226 static const struct ac97_enum cm9761_dac_clock_enum =
3227 AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
3229 static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
3230 { /* BIT 1: SPDIFS */
3231 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3232 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3233 .info = cm9761_spdif_out_source_info,
3234 .get = cm9761_spdif_out_source_get,
3235 .put = cm9761_spdif_out_source_put,
3237 /* BIT 2: IG_SPIV */
3238 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
3240 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
3241 /* BIT 4: SPI2SDI */
3242 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
3243 /* BIT 9-10: DAC_CTL */
3244 AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
3247 static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
3249 return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
3252 static int patch_cm9761_specific(struct snd_ac97 * ac97)
3254 return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
3257 static const struct snd_ac97_build_ops patch_cm9761_ops = {
3258 .build_specific = patch_cm9761_specific,
3259 .build_post_spdif = patch_cm9761_post_spdif,
3260 .update_jacks = cm9761_update_jacks
3263 static int patch_cm9761(struct snd_ac97 *ac97)
3267 /* CM9761 has no PCM volume although the register reacts */
3268 /* Master volume seems to have _some_ influence on the analog
3271 ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
3272 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
3273 snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
3275 ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */
3276 if (ac97->id == AC97_ID_CM9761_82) {
3278 /* check page 1, reg 0x60 */
3279 val = snd_ac97_read(ac97, AC97_INT_PAGING);
3280 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
3281 tmp = snd_ac97_read(ac97, 0x60);
3282 ac97->spec.dev_flags = tmp & 1; /* revision B? */
3283 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
3284 } else if (ac97->id == AC97_ID_CM9761_83)
3285 ac97->spec.dev_flags = 2;
3287 ac97->build_ops = &patch_cm9761_ops;
3290 /* force the SPDIF bit in ext_id - codec doesn't set this bit! */
3291 ac97->ext_id |= AC97_EI_SPDIF;
3292 /* to be sure: we overwrite the ext status bits */
3293 snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
3294 /* Don't set 0x0200 here. This results in the silent analog output */
3295 snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
3296 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3298 /* set-up multi channel */
3299 /* bit 15: pc master beep off
3300 * bit 14: pin47 = EAPD/SPDIF
3301 * bit 13: vref ctl [= cm9739]
3302 * bit 12: CLFE control (reverted on rev B)
3303 * bit 11: Mic/center share (reverted on rev B)
3304 * bit 10: suddound/line share
3305 * bit 9: Analog-in mix -> surround
3306 * bit 8: Analog-in mix -> CLFE
3307 * bit 7: Mic/LFE share (mic/center/lfe)
3308 * bit 5: vref select (9761A)
3309 * bit 4: front control
3310 * bit 3: surround control (revereted with rev B)
3313 * bit 0: mic boost level (0=20dB, 1=30dB)
3317 if (ac97->spec.dev_flags)
3322 val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
3323 val |= (1 << 4); /* front on */
3324 snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
3326 /* FIXME: set up GPIO */
3327 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3328 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3333 #define AC97_CM9780_SIDE 0x60
3334 #define AC97_CM9780_JACK 0x62
3335 #define AC97_CM9780_MIXER 0x64
3336 #define AC97_CM9780_MULTI_CHAN 0x66
3337 #define AC97_CM9780_SPDIF 0x6c
3339 static const char * const cm9780_ch_select[] = {
3340 "Front", "Side", "Center/LFE", "Rear"
3342 static const struct ac97_enum cm9780_ch_select_enum =
3343 AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
3344 static const struct snd_kcontrol_new cm9780_controls[] = {
3345 AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
3346 AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
3347 AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
3350 static int patch_cm9780_specific(struct snd_ac97 *ac97)
3352 return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
3355 static const struct snd_ac97_build_ops patch_cm9780_ops = {
3356 .build_specific = patch_cm9780_specific,
3357 .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
3360 static int patch_cm9780(struct snd_ac97 *ac97)
3364 ac97->build_ops = &patch_cm9780_ops;
3367 if (ac97->ext_id & AC97_EI_SPDIF) {
3368 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3369 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
3370 val |= 0x1; /* SPDI_EN */
3371 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
3380 static const struct snd_kcontrol_new snd_ac97_controls_vt1613[] = {
3381 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3384 static int patch_vt1613_specific(struct snd_ac97 *ac97)
3386 return patch_build_controls(ac97, &snd_ac97_controls_vt1613[0],
3387 ARRAY_SIZE(snd_ac97_controls_vt1613));
3390 static const struct snd_ac97_build_ops patch_vt1613_ops = {
3391 .build_specific = patch_vt1613_specific
3394 static int patch_vt1613(struct snd_ac97 *ac97)
3396 ac97->build_ops = &patch_vt1613_ops;
3398 ac97->flags |= AC97_HAS_NO_VIDEO;
3399 ac97->caps |= AC97_BC_HEADPHONE;
3407 static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
3408 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3409 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
3410 AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
3411 AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
3414 static const char * const follower_vols_vt1616[] = {
3415 "Front Playback Volume",
3416 "Surround Playback Volume",
3417 "Center Playback Volume",
3418 "LFE Playback Volume",
3422 static const char * const follower_sws_vt1616[] = {
3423 "Front Playback Switch",
3424 "Surround Playback Switch",
3425 "Center Playback Switch",
3426 "LFE Playback Switch",
3430 /* find a mixer control element with the given name */
3431 static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
3434 return snd_ctl_find_id_mixer(ac97->bus->card, name);
3437 /* create a virtual master control and add followers */
3438 static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
3439 const unsigned int *tlv,
3440 const char * const *followers)
3442 struct snd_kcontrol *kctl;
3445 kctl = snd_ctl_make_virtual_master(name, tlv);
3448 err = snd_ctl_add(ac97->bus->card, kctl);
3452 return snd_ctl_add_followers(ac97->bus->card, kctl, followers);
3455 static int patch_vt1616_specific(struct snd_ac97 * ac97)
3457 struct snd_kcontrol *kctl;
3460 if (snd_ac97_try_bit(ac97, 0x5a, 9)) {
3461 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1);
3465 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1);
3469 /* There is already a misnamed master switch. Rename it. */
3470 kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
3474 snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
3476 err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
3477 kctl->tlv.p, follower_vols_vt1616);
3481 err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
3482 NULL, follower_sws_vt1616);
3489 static const struct snd_ac97_build_ops patch_vt1616_ops = {
3490 .build_specific = patch_vt1616_specific
3493 static int patch_vt1616(struct snd_ac97 * ac97)
3495 ac97->build_ops = &patch_vt1616_ops;
3504 * unfortunately, the vt1617a stashes the twiddlers required for
3505 * noodling the i/o jacks on 2 different regs. that means that we can't
3506 * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
3509 * NB: this is absolutely and utterly different from the vt1618. dunno
3513 /* copied from ac97_surround_jack_mode_info() */
3514 static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
3515 struct snd_ctl_elem_info *uinfo)
3517 /* ordering in this list reflects vt1617a docs for Reg 20 and
3518 * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
3519 * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
3520 * counter-intuitive */
3522 static const char * const texts[] = {"LineIn Mic1", "LineIn Mic1 Mic3",
3523 "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
3524 "LineIn Mic2", "LineIn Mic2 Mic1",
3525 "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
3527 return snd_ctl_enum_info(uinfo, 1, 8, texts);
3530 static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
3531 struct snd_ctl_elem_value *ucontrol)
3533 ushort usSM51, usMS;
3535 struct snd_ac97 *pac97;
3537 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3539 /* grab our desired bits, then mash them together in a manner
3540 * consistent with Table 6 on page 17 in the 1617a docs */
3542 usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
3543 usMS = snd_ac97_read(pac97, 0x20) >> 8;
3545 ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
3550 static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
3551 struct snd_ctl_elem_value *ucontrol)
3553 ushort usSM51, usMS, usReg;
3555 struct snd_ac97 *pac97;
3557 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3559 usSM51 = ucontrol->value.enumerated.item[0] >> 1;
3560 usMS = ucontrol->value.enumerated.item[0] & 1;
3562 /* push our values into the register - consider that things will be left
3563 * in a funky state if the write fails */
3565 usReg = snd_ac97_read(pac97, 0x7a);
3566 snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
3567 usReg = snd_ac97_read(pac97, 0x20);
3568 snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8));
3573 static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
3575 AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
3577 * These are used to enable/disable surround sound on motherboards
3578 * that have 3 bidirectional analog jacks
3581 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3582 .name = "Smart 5.1 Select",
3583 .info = snd_ac97_vt1617a_smart51_info,
3584 .get = snd_ac97_vt1617a_smart51_get,
3585 .put = snd_ac97_vt1617a_smart51_put,
3589 static int patch_vt1617a(struct snd_ac97 * ac97)
3594 /* we choose to not fail out at this point, but we tell the
3595 caller when we return */
3597 err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
3598 ARRAY_SIZE(snd_ac97_controls_vt1617a));
3600 /* bring analog power consumption to normal by turning off the
3601 * headphone amplifier, like WinXP driver for EPIA SP
3603 /* We need to check the bit before writing it.
3604 * On some (many?) hardwares, setting bit actually clears it!
3606 val = snd_ac97_read(ac97, 0x5c);
3608 snd_ac97_write_cache(ac97, 0x5c, 0x20);
3610 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
3611 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3612 ac97->build_ops = &patch_vt1616_ops;
3617 /* VIA VT1618 8 CHANNEL AC97 CODEC
3619 * VIA implements 'Smart 5.1' completely differently on the 1618 than
3620 * it does on the 1617a. awesome! They seem to have sourced this
3621 * particular revision of the technology from somebody else, it's
3622 * called Universal Audio Jack and it shows up on some other folk's chips
3625 * ordering in this list reflects vt1618 docs for Reg 60h and
3626 * the block diagram, DACs are as follows:
3629 * OUT_1 -> Surround,
3632 * Unlike the 1617a, each OUT has a consistent set of mappings
3633 * for all bitpatterns other than 00:
3639 * Special Case of 00:
3641 * OUT_0 Mixed Output
3645 * I have no idea what the hell Reserved does, but on an MSI
3646 * CN700T, i have to set it to get 5.1 output - YMMV, bad
3649 * If other chips use Universal Audio Jack, then this code might be applicable
3653 struct vt1618_uaj_item {
3654 unsigned short mask;
3655 unsigned short shift;
3656 const char * const items[4];
3659 /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */
3661 static const struct vt1618_uaj_item vt1618_uaj[3] = {
3667 "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
3675 "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
3683 "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
3688 static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
3689 struct snd_ctl_elem_info *uinfo)
3691 return snd_ctl_enum_info(uinfo, 1, 4,
3692 vt1618_uaj[kcontrol->private_value].items);
3695 /* All of the vt1618 Universal Audio Jack twiddlers are on
3696 * Vendor Defined Register 0x60, page 0. The bits, and thus
3697 * the mask, are the only thing that changes
3699 static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
3700 struct snd_ctl_elem_value *ucontrol)
3702 unsigned short datpag, uaj;
3703 struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
3705 mutex_lock(&pac97->page_mutex);
3707 datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
3708 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
3710 uaj = snd_ac97_read(pac97, 0x60) &
3711 vt1618_uaj[kcontrol->private_value].mask;
3713 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
3714 mutex_unlock(&pac97->page_mutex);
3716 ucontrol->value.enumerated.item[0] = uaj >>
3717 vt1618_uaj[kcontrol->private_value].shift;
3722 static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
3723 struct snd_ctl_elem_value *ucontrol)
3725 return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
3726 vt1618_uaj[kcontrol->private_value].mask,
3727 ucontrol->value.enumerated.item[0]<<
3728 vt1618_uaj[kcontrol->private_value].shift,
3732 /* config aux in jack - not found on 3 jack motherboards or soundcards */
3734 static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
3735 struct snd_ctl_elem_info *uinfo)
3737 static const char * const txt_aux[] = {"Aux In", "Back Surr Out"};
3739 return snd_ctl_enum_info(uinfo, 1, 2, txt_aux);
3742 static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
3743 struct snd_ctl_elem_value *ucontrol)
3745 ucontrol->value.enumerated.item[0] =
3746 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
3750 static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
3751 struct snd_ctl_elem_value *ucontrol)
3753 /* toggle surround rear dac power */
3755 snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
3756 ucontrol->value.enumerated.item[0] << 3);
3758 /* toggle aux in surround rear out jack */
3760 return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
3761 ucontrol->value.enumerated.item[0] << 3);
3764 static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
3765 AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
3766 AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
3767 AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
3768 AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
3769 AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
3770 AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
3772 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3773 .name = "Speaker Jack Mode",
3774 .info = snd_ac97_vt1618_UAJ_info,
3775 .get = snd_ac97_vt1618_UAJ_get,
3776 .put = snd_ac97_vt1618_UAJ_put,
3780 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3781 .name = "Line Jack Mode",
3782 .info = snd_ac97_vt1618_UAJ_info,
3783 .get = snd_ac97_vt1618_UAJ_get,
3784 .put = snd_ac97_vt1618_UAJ_put,
3788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3789 .name = "Mic Jack Mode",
3790 .info = snd_ac97_vt1618_UAJ_info,
3791 .get = snd_ac97_vt1618_UAJ_get,
3792 .put = snd_ac97_vt1618_UAJ_put,
3796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3797 .name = "Aux Jack Mode",
3798 .info = snd_ac97_vt1618_aux_info,
3799 .get = snd_ac97_vt1618_aux_get,
3800 .put = snd_ac97_vt1618_aux_put,
3804 static int patch_vt1618(struct snd_ac97 *ac97)
3806 return patch_build_controls(ac97, snd_ac97_controls_vt1618,
3807 ARRAY_SIZE(snd_ac97_controls_vt1618));
3812 static void it2646_update_jacks(struct snd_ac97 *ac97)
3814 /* shared Line-In / Surround Out */
3815 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
3816 is_shared_surrout(ac97) ? (1<<9) : 0);
3817 /* shared Mic / Center/LFE Out */
3818 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
3819 is_shared_clfeout(ac97) ? (1<<10) : 0);
3822 static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
3823 AC97_SURROUND_JACK_MODE_CTL,
3824 AC97_CHANNEL_MODE_CTL,
3827 static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
3828 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
3829 AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
3830 AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
3833 static int patch_it2646_specific(struct snd_ac97 * ac97)
3836 err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646));
3839 err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646));
3845 static const struct snd_ac97_build_ops patch_it2646_ops = {
3846 .build_specific = patch_it2646_specific,
3847 .update_jacks = it2646_update_jacks
3850 static int patch_it2646(struct snd_ac97 * ac97)
3852 ac97->build_ops = &patch_it2646_ops;
3853 /* full DAC volume */
3854 snd_ac97_write_cache(ac97, 0x5E, 0x0808);
3855 snd_ac97_write_cache(ac97, 0x7A, 0x0808);
3863 #define AC97_SI3036_CHIP_ID 0x5a
3864 #define AC97_SI3036_LINE_CFG 0x5c
3866 static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
3867 AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
3870 static int patch_si3036_specific(struct snd_ac97 * ac97)
3873 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) {
3874 err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97));
3881 static const struct snd_ac97_build_ops patch_si3036_ops = {
3882 .build_specific = patch_si3036_specific,
3885 static int mpatch_si3036(struct snd_ac97 * ac97)
3887 ac97->build_ops = &patch_si3036_ops;
3888 snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
3889 snd_ac97_write_cache(ac97, 0x68, 0);
3896 * We use a static resolution table since LM4550 codec cannot be
3897 * properly autoprobed to determine the resolution via
3898 * check_volume_resolution().
3901 static const struct snd_ac97_res_table lm4550_restbl[] = {
3902 { AC97_MASTER, 0x1f1f },
3903 { AC97_HEADPHONE, 0x1f1f },
3904 { AC97_MASTER_MONO, 0x001f },
3905 { AC97_PC_BEEP, 0x001f }, /* LSB is ignored */
3906 { AC97_PHONE, 0x001f },
3907 { AC97_MIC, 0x001f },
3908 { AC97_LINE, 0x1f1f },
3909 { AC97_CD, 0x1f1f },
3910 { AC97_VIDEO, 0x1f1f },
3911 { AC97_AUX, 0x1f1f },
3912 { AC97_PCM, 0x1f1f },
3913 { AC97_REC_GAIN, 0x0f0f },
3914 { } /* terminator */
3917 static int patch_lm4550(struct snd_ac97 *ac97)
3919 ac97->res_table = lm4550_restbl;