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_kcontrol *kctl;
46 kctl = snd_ctl_find_id_mixer(ac97->bus->card, name);
47 if (kctl && kctl->tlv.p)
51 /* set to the page, update bits and restore the page */
52 static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
54 unsigned short page_save;
57 mutex_lock(&ac97->page_mutex);
58 page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
59 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
60 ret = snd_ac97_update_bits(ac97, reg, mask, value);
61 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
62 mutex_unlock(&ac97->page_mutex); /* unlock paging */
67 * shared line-in/mic controls
69 static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
71 static const char * const texts[] = { "Shared", "Independent" };
73 return snd_ctl_enum_info(uinfo, 1, 2, texts);
76 static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
78 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
80 ucontrol->value.enumerated.item[0] = ac97->indep_surround;
84 static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
86 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
87 unsigned char indep = !!ucontrol->value.enumerated.item[0];
89 if (indep != ac97->indep_surround) {
90 ac97->indep_surround = indep;
91 if (ac97->build_ops->update_jacks)
92 ac97->build_ops->update_jacks(ac97);
98 static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
100 static const char * const texts[] = { "2ch", "4ch", "6ch", "8ch" };
102 return snd_ctl_enum_info(uinfo, 1, kcontrol->private_value, texts);
105 static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
107 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
109 ucontrol->value.enumerated.item[0] = ac97->channel_mode;
113 static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
115 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
116 unsigned char mode = ucontrol->value.enumerated.item[0];
118 if (mode >= kcontrol->private_value)
121 if (mode != ac97->channel_mode) {
122 ac97->channel_mode = mode;
123 if (ac97->build_ops->update_jacks)
124 ac97->build_ops->update_jacks(ac97);
130 #define AC97_SURROUND_JACK_MODE_CTL \
132 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
133 .name = "Surround Jack Mode", \
134 .info = ac97_surround_jack_mode_info, \
135 .get = ac97_surround_jack_mode_get, \
136 .put = ac97_surround_jack_mode_put, \
139 #define AC97_CHANNEL_MODE_CTL \
141 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
142 .name = "Channel Mode", \
143 .info = ac97_channel_mode_info, \
144 .get = ac97_channel_mode_get, \
145 .put = ac97_channel_mode_put, \
146 .private_value = 3, \
149 #define AC97_CHANNEL_MODE_4CH_CTL \
151 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
152 .name = "Channel Mode", \
153 .info = ac97_channel_mode_info, \
154 .get = ac97_channel_mode_get, \
155 .put = ac97_channel_mode_put, \
156 .private_value = 2, \
159 #define AC97_CHANNEL_MODE_8CH_CTL \
161 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
162 .name = "Channel Mode", \
163 .info = ac97_channel_mode_info, \
164 .get = ac97_channel_mode_get, \
165 .put = ac97_channel_mode_put, \
166 .private_value = 4, \
169 static inline int is_surround_on(struct snd_ac97 *ac97)
171 return ac97->channel_mode >= 1;
174 static inline int is_clfe_on(struct snd_ac97 *ac97)
176 return ac97->channel_mode >= 2;
179 /* system has shared jacks with surround out enabled */
180 static inline int is_shared_surrout(struct snd_ac97 *ac97)
182 return !ac97->indep_surround && is_surround_on(ac97);
185 /* system has shared jacks with center/lfe out enabled */
186 static inline int is_shared_clfeout(struct snd_ac97 *ac97)
188 return !ac97->indep_surround && is_clfe_on(ac97);
191 /* system has shared jacks with line in enabled */
192 static inline int is_shared_linein(struct snd_ac97 *ac97)
194 return !ac97->indep_surround && !is_surround_on(ac97);
197 /* system has shared jacks with mic in enabled */
198 static inline int is_shared_micin(struct snd_ac97 *ac97)
200 return !ac97->indep_surround && !is_clfe_on(ac97);
203 static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
205 return is_surround_on(ac97);
208 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
209 /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
211 /* It is possible to indicate to the Yamaha YMF7x3 the type of
212 speakers being used. */
214 static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
215 struct snd_ctl_elem_info *uinfo)
217 static const char * const texts[3] = {
218 "Standard", "Small", "Smaller"
221 return snd_ctl_enum_info(uinfo, 1, 3, texts);
224 static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
225 struct snd_ctl_elem_value *ucontrol)
227 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
230 val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
231 val = (val >> 10) & 3;
232 if (val > 0) /* 0 = invalid */
234 ucontrol->value.enumerated.item[0] = val;
238 static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
239 struct snd_ctl_elem_value *ucontrol)
241 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
244 if (ucontrol->value.enumerated.item[0] > 2)
246 val = (ucontrol->value.enumerated.item[0] + 1) << 10;
247 return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
250 static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
252 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
253 .name = "3D Control - Speaker",
254 .info = snd_ac97_ymf7x3_info_speaker,
255 .get = snd_ac97_ymf7x3_get_speaker,
256 .put = snd_ac97_ymf7x3_put_speaker,
259 /* It is possible to indicate to the Yamaha YMF7x3 the source to
260 direct to the S/PDIF output. */
261 static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_info *uinfo)
264 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
266 return snd_ctl_enum_info(uinfo, 1, 2, texts);
269 static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
270 struct snd_ctl_elem_value *ucontrol)
272 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
275 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
276 ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
280 static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
281 struct snd_ctl_elem_value *ucontrol)
283 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
286 if (ucontrol->value.enumerated.item[0] > 1)
288 val = ucontrol->value.enumerated.item[0] << 1;
289 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
292 static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
294 struct snd_kcontrol *kctl;
297 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
298 err = snd_ctl_add(ac97->bus->card, kctl);
301 strcpy(kctl->id.name, "3D Control - Wide");
302 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
303 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
304 err = snd_ctl_add(ac97->bus->card,
305 snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
309 snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
313 static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
315 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
316 AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
318 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
319 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
320 .info = snd_ac97_ymf7x3_spdif_source_info,
321 .get = snd_ac97_ymf7x3_spdif_source_get,
322 .put = snd_ac97_ymf7x3_spdif_source_put,
324 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
325 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
328 static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
332 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
335 err = patch_build_controls(ac97,
336 snd_ac97_yamaha_ymf743_controls_spdif, 3);
339 /* set default PCM S/PDIF params */
340 /* PCM audio,no copyright,no preemphasis,PCM coder,original */
341 snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
345 static const struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
346 .build_spdif = patch_yamaha_ymf743_build_spdif,
347 .build_3d = patch_yamaha_ymf7x3_3d,
350 static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
352 ac97->build_ops = &patch_yamaha_ymf743_ops;
353 ac97->caps |= AC97_BC_BASS_TREBLE;
354 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
355 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
356 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
360 /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
361 The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
362 By default, no output pin is selected, and the S/PDIF signal is not output.
363 There is also a bit to mute S/PDIF output in a vendor-specific register. */
364 static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
366 static const char * const texts[3] = { "Disabled", "Pin 43", "Pin 48" };
368 return snd_ctl_enum_info(uinfo, 1, 3, texts);
371 static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
373 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
376 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
377 ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
381 static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
383 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
386 if (ucontrol->value.enumerated.item[0] > 2)
388 val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
389 (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
390 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
391 /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
392 snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
395 static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
397 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
398 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
399 .info = snd_ac97_ymf7x3_spdif_source_info,
400 .get = snd_ac97_ymf7x3_spdif_source_get,
401 .put = snd_ac97_ymf7x3_spdif_source_put,
404 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
405 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
406 .info = snd_ac97_ymf753_spdif_output_pin_info,
407 .get = snd_ac97_ymf753_spdif_output_pin_get,
408 .put = snd_ac97_ymf753_spdif_output_pin_put,
410 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
411 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
414 static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
418 err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif));
424 static const struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
425 .build_3d = patch_yamaha_ymf7x3_3d,
426 .build_post_spdif = patch_yamaha_ymf753_post_spdif
429 static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
431 /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
432 This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
433 The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
434 The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
435 By default, no output pin is selected, and the S/PDIF signal is not output.
436 There is also a bit to mute S/PDIF output in a vendor-specific register.
438 ac97->build_ops = &patch_yamaha_ymf753_ops;
439 ac97->caps |= AC97_BC_BASS_TREBLE;
440 ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
445 * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
446 * removed broken wolfson00 patch.
447 * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
450 static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = {
451 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
452 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
455 static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
457 /* This is known to work for the ViewSonic ViewPad 1000
458 * Randolph Bentson <bentson@holmsjoen.com>
459 * WM9703/9707/9708/9717
463 for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
464 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97));
468 snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
472 static const struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
473 .build_specific = patch_wolfson_wm9703_specific,
476 static int patch_wolfson03(struct snd_ac97 * ac97)
478 ac97->build_ops = &patch_wolfson_wm9703_ops;
482 static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = {
483 AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
484 AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
485 AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
486 AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
487 AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
488 AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
491 static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
494 for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
495 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97));
499 /* patch for DVD noise */
500 snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
504 static const struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
505 .build_specific = patch_wolfson_wm9704_specific,
508 static int patch_wolfson04(struct snd_ac97 * ac97)
511 ac97->build_ops = &patch_wolfson_wm9704_ops;
515 static int patch_wolfson05(struct snd_ac97 * ac97)
518 ac97->build_ops = &patch_wolfson_wm9703_ops;
519 #ifdef CONFIG_TOUCHSCREEN_WM9705
520 /* WM9705 touchscreen uses AUX and VIDEO for touch */
521 ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
526 static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
527 static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
528 static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
529 static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
530 static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
531 static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
532 static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
533 static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
534 static const char* wm9711_rec_sel[] =
535 {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
536 static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
538 static const struct ac97_enum wm9711_enum[] = {
539 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
540 AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
541 AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
542 AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
543 AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
544 AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
545 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
546 AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
547 AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
548 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
551 static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = {
552 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
553 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
554 AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
555 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
556 AC97_ENUM("ALC Function", wm9711_enum[0]),
557 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
558 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
559 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
560 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
561 AC97_ENUM("ALC NG Type", wm9711_enum[9]),
562 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
564 AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
565 AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
566 AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
567 AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
569 AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
570 AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
571 AC97_ENUM("Out3 Mux", wm9711_enum[2]),
572 AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
573 AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
575 AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
576 AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
577 AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
578 AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
579 AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
580 AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
582 AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
583 AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
584 AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
585 AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
586 AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
587 AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
589 AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
590 AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
592 AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
593 AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
594 AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
596 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
597 AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
598 AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
600 AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
601 AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
602 AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
603 AC97_ENUM("Capture Select", wm9711_enum[8]),
605 AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
606 AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
608 AC97_ENUM("Bass Control", wm9711_enum[5]),
609 AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
610 AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
611 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
613 AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
614 AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
615 AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
616 AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
618 AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
619 AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
620 AC97_ENUM("Mic Select Source", wm9711_enum[7]),
621 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
622 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
623 AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
625 AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
626 AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
627 AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
628 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
631 static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
635 for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
636 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97));
640 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808);
641 snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808);
642 snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808);
643 snd_ac97_write_cache(ac97, AC97_AUX, 0x0808);
644 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
645 snd_ac97_write_cache(ac97, AC97_CD, 0x0000);
649 static const struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
650 .build_specific = patch_wolfson_wm9711_specific,
653 static int patch_wolfson11(struct snd_ac97 * ac97)
656 ac97->build_ops = &patch_wolfson_wm9711_ops;
658 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
659 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
664 static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
665 static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
666 static const char* wm9713_rec_src[] =
667 {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix",
669 static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
670 static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
671 static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
672 static const char* wm9713_spk_pga[] =
673 {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
674 static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
675 static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
676 static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
677 static const char* wm9713_dac_inv[] =
678 {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R",
679 "Headphone Mix Mono", "NC", "Vmid"};
680 static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
681 static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
683 static const struct ac97_enum wm9713_enum[] = {
684 AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
685 AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
686 AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
687 AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
688 AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
689 AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
690 AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
691 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
692 AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
693 AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
694 AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
695 AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
696 AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
697 AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
700 static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
701 AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
702 AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
703 AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
704 AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
706 AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
707 AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
708 AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
709 AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
711 AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
712 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
713 AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
714 AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
715 AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
716 AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
717 AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
719 AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
720 AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
721 AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
722 AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
724 AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
725 AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
726 AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
727 AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
728 AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
729 AC97_ENUM("Capture Select", wm9713_enum[3]),
731 AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
732 AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
733 AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
734 AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
735 AC97_ENUM("ALC Function", wm9713_enum[5]),
736 AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
737 AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
738 AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
739 AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
740 AC97_ENUM("ALC NG Type", wm9713_enum[13]),
741 AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
743 AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
744 AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
745 AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
746 AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
747 AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
748 AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
750 AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
751 AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
752 AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
753 AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
754 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
755 AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
757 AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
758 AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
759 AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
760 AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
761 AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
762 AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
764 AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
765 AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
766 AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
767 AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
768 AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
769 AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
771 AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
772 AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
773 AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
774 AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
775 AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
776 AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
778 AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
779 AC97_ENUM("Master Input Mux", wm9713_enum[7]),
780 AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
781 AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
782 AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
784 AC97_ENUM("Bass Control", wm9713_enum[12]),
785 AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
786 AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
787 AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
788 AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
789 AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
792 static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {
793 AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
794 AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
795 AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
796 AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
799 static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
803 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
804 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97));
811 static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
815 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
816 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97));
820 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
821 snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
822 snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
823 snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
824 snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
825 snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
826 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
831 static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
833 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
834 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
837 static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
839 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
840 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
841 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
845 static const struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
846 .build_specific = patch_wolfson_wm9713_specific,
847 .build_3d = patch_wolfson_wm9713_3d,
849 .suspend = patch_wolfson_wm9713_suspend,
850 .resume = patch_wolfson_wm9713_resume
854 static int patch_wolfson13(struct snd_ac97 * ac97)
857 ac97->build_ops = &patch_wolfson_wm9713_ops;
859 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
860 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
862 ac97->scaps &= ~AC97_SCAP_MODEM;
864 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
865 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
866 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
874 static int patch_tritech_tr28028(struct snd_ac97 * ac97)
876 snd_ac97_write_cache(ac97, 0x26, 0x0300);
877 snd_ac97_write_cache(ac97, 0x26, 0x0000);
878 snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
879 snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
884 * Sigmatel STAC97xx codecs
886 static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
888 struct snd_kcontrol *kctl;
891 err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97));
894 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
895 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
896 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
900 static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
902 struct snd_kcontrol *kctl;
905 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
906 err = snd_ctl_add(ac97->bus->card, kctl);
909 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
910 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
911 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
912 err = snd_ctl_add(ac97->bus->card, kctl);
915 strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
916 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
917 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
921 static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
922 AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch",
923 AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
925 /* "Sigmatel " removed due to excessive name length: */
926 static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
927 AC97_SINGLE("Surround Phase Inversion Playback Switch",
928 AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
930 static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
931 AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
932 AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
935 static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
939 snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
940 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) {
941 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1);
945 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) {
946 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1);
950 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) {
951 err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1);
955 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) {
956 err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1);
963 static const struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
964 .build_3d = patch_sigmatel_stac9700_3d,
965 .build_specific = patch_sigmatel_stac97xx_specific
968 static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
970 ac97->build_ops = &patch_sigmatel_stac9700_ops;
974 static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
976 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
979 mutex_lock(&ac97->page_mutex);
980 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
981 err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
982 (ucontrol->value.integer.value[0] & 1) << 4);
983 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
984 mutex_unlock(&ac97->page_mutex);
988 static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
989 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
990 .name = "Sigmatel Output Bias Switch",
991 .info = snd_ac97_info_volsw,
992 .get = snd_ac97_get_volsw,
993 .put = snd_ac97_stac9708_put_bias,
994 .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
997 static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
1001 /* the register bit is writable, but the function is not implemented: */
1002 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
1004 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
1005 err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1);
1008 return patch_sigmatel_stac97xx_specific(ac97);
1011 static const struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
1012 .build_3d = patch_sigmatel_stac9708_3d,
1013 .build_specific = patch_sigmatel_stac9708_specific
1016 static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
1018 unsigned int codec72, codec6c;
1020 ac97->build_ops = &patch_sigmatel_stac9708_ops;
1021 ac97->caps |= 0x10; /* HP (sigmatel surround) support */
1023 codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
1024 codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
1026 if ((codec72==0) && (codec6c==0)) {
1027 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1028 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
1029 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1030 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
1031 } else if ((codec72==0x8000) && (codec6c==0)) {
1032 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1033 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
1034 snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
1035 } else if ((codec72==0x8000) && (codec6c==0x0080)) {
1038 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1042 static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
1044 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1045 if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
1046 // patch for SigmaTel
1047 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1048 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
1049 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1050 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1052 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1056 static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
1058 // patch for SigmaTel
1059 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1060 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1061 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1062 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1063 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1064 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1068 static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
1070 // patch for SigmaTel
1071 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1072 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1073 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
1074 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1075 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1076 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1080 static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1082 static const char * const texts[5] = {
1083 "Input/Disabled", "Front Output",
1084 "Rear Output", "Center/LFE Output", "Mixer Output" };
1086 return snd_ctl_enum_info(uinfo, 1, 5, texts);
1089 static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1091 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1092 int shift = kcontrol->private_value;
1095 val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
1097 ucontrol->value.enumerated.item[0] = 0;
1099 ucontrol->value.enumerated.item[0] = 1 + (val & 3);
1103 static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1105 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1106 int shift = kcontrol->private_value;
1109 if (ucontrol->value.enumerated.item[0] > 4)
1111 if (ucontrol->value.enumerated.item[0] == 0)
1114 val = 4 | (ucontrol->value.enumerated.item[0] - 1);
1115 return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
1116 7 << shift, val << shift, 0);
1119 static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1121 static const char * const texts[7] = {
1122 "Mic2 Jack", "Mic1 Jack", "Line In Jack",
1123 "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
1125 return snd_ctl_enum_info(uinfo, 1, 7, texts);
1128 static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1130 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1131 int shift = kcontrol->private_value;
1134 val = ac97->regs[AC97_SIGMATEL_INSEL];
1135 ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
1139 static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1141 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1142 int shift = kcontrol->private_value;
1144 return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
1145 ucontrol->value.enumerated.item[0] << shift, 0);
1148 static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1150 static const char * const texts[3] = {
1151 "None", "Front Jack", "Rear Jack"
1154 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1157 static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1159 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1161 ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
1165 static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1167 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1169 return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
1170 ucontrol->value.enumerated.item[0], 0);
1173 #define STAC9758_OUTPUT_JACK(xname, shift) \
1174 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1175 .info = snd_ac97_stac9758_output_jack_info, \
1176 .get = snd_ac97_stac9758_output_jack_get, \
1177 .put = snd_ac97_stac9758_output_jack_put, \
1178 .private_value = shift }
1179 #define STAC9758_INPUT_JACK(xname, shift) \
1180 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1181 .info = snd_ac97_stac9758_input_jack_info, \
1182 .get = snd_ac97_stac9758_input_jack_get, \
1183 .put = snd_ac97_stac9758_input_jack_put, \
1184 .private_value = shift }
1185 static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
1186 STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
1187 STAC9758_OUTPUT_JACK("LineIn Jack", 4),
1188 STAC9758_OUTPUT_JACK("Front Jack", 7),
1189 STAC9758_OUTPUT_JACK("Rear Jack", 10),
1190 STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
1191 STAC9758_INPUT_JACK("Mic Input Source", 0),
1192 STAC9758_INPUT_JACK("Line Input Source", 8),
1194 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1195 .name = "Headphone Amp",
1196 .info = snd_ac97_stac9758_phonesel_info,
1197 .get = snd_ac97_stac9758_phonesel_get,
1198 .put = snd_ac97_stac9758_phonesel_put
1200 AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
1201 AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
1204 static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
1208 err = patch_sigmatel_stac97xx_specific(ac97);
1211 err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
1212 ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
1216 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
1217 /* DAC-A to Mix = PCM */
1218 /* DAC-B direct = Surround */
1220 snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
1221 /* DAC-C direct = Center/LFE */
1226 static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
1227 .build_3d = patch_sigmatel_stac9700_3d,
1228 .build_specific = patch_sigmatel_stac9758_specific
1231 static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
1233 static const unsigned short regs[4] = {
1234 AC97_SIGMATEL_OUTSEL,
1235 AC97_SIGMATEL_IOMISC,
1236 AC97_SIGMATEL_INSEL,
1237 AC97_SIGMATEL_VARIOUS
1239 static const unsigned short def_regs[4] = {
1240 /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
1241 /* IOMISC */ 0x2001,
1242 /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
1243 /* VARIOUS */ 0x0040
1245 static const unsigned short m675_regs[4] = {
1246 /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
1247 /* IOMISC */ 0x2102, /* HP amp on */
1248 /* INSEL */ 0x0203, /* LI:LI, MI:FR */
1249 /* VARIOUS */ 0x0041 /* stereo mic */
1251 const unsigned short *pregs = def_regs;
1254 /* Gateway M675 notebook */
1256 ac97->subsystem_vendor == 0x107b &&
1257 ac97->subsystem_device == 0x0601)
1260 // patch for SigmaTel
1261 ac97->build_ops = &patch_sigmatel_stac9758_ops;
1262 /* FIXME: assume only page 0 for writing cache */
1263 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
1264 for (i = 0; i < 4; i++)
1265 snd_ac97_write_cache(ac97, regs[i], pregs[i]);
1267 ac97->flags |= AC97_STEREO_MUTES;
1272 * Cirrus Logic CS42xx codecs
1274 static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
1275 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
1276 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
1279 static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
1283 /* con mask, pro mask, default */
1284 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1288 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1);
1291 switch (ac97->id & AC97_ID_CS_MASK) {
1292 case AC97_ID_CS4205:
1293 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1);
1298 /* set default PCM S/PDIF params */
1299 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1300 snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
1304 static const struct snd_ac97_build_ops patch_cirrus_ops = {
1305 .build_spdif = patch_cirrus_build_spdif
1308 static int patch_cirrus_spdif(struct snd_ac97 * ac97)
1310 /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
1311 WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh*
1312 - sp/dif EA ID is not set, but sp/dif is always present.
1313 - enable/disable is spdif register bit 15.
1314 - sp/dif control register is 0x68. differs from AC97:
1315 - valid is bit 14 (vs 15)
1317 - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48)
1318 - sp/dif ssource select is in 0x5e bits 0,1.
1321 ac97->build_ops = &patch_cirrus_ops;
1322 ac97->flags |= AC97_CS_SPDIF;
1323 ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
1324 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1325 snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
1329 static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
1331 /* force the detection of PC Beep */
1332 ac97->flags |= AC97_HAS_PC_BEEP;
1334 return patch_cirrus_spdif(ac97);
1340 static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
1341 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
1344 static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
1348 /* con mask, pro mask, default */
1349 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1353 err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1);
1356 /* set default PCM S/PDIF params */
1357 /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1358 snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
1359 snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
1363 static const struct snd_ac97_build_ops patch_conexant_ops = {
1364 .build_spdif = patch_conexant_build_spdif
1367 static int patch_conexant(struct snd_ac97 * ac97)
1369 ac97->build_ops = &patch_conexant_ops;
1370 ac97->flags |= AC97_CX_SPDIF;
1371 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
1372 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
1376 static int patch_cx20551(struct snd_ac97 *ac97)
1378 snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
1383 * Analog Devices AD18xx, AD19xx codecs
1386 static void ad18xx_resume(struct snd_ac97 *ac97)
1388 static const unsigned short setup_regs[] = {
1389 AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
1393 for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
1394 unsigned short reg = setup_regs[i];
1395 if (test_bit(reg, ac97->reg_accessed)) {
1396 snd_ac97_write(ac97, reg, ac97->regs[reg]);
1397 snd_ac97_read(ac97, reg);
1401 if (! (ac97->flags & AC97_AD_MULTI))
1402 /* normal restore */
1403 snd_ac97_restore_status(ac97);
1405 /* restore the AD18xx codec configurations */
1406 for (codec = 0; codec < 3; codec++) {
1407 if (! ac97->spec.ad18xx.id[codec])
1409 /* select single codec */
1410 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1411 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1412 ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
1414 /* select all codecs */
1415 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1417 /* restore status */
1418 for (i = 2; i < 0x7c ; i += 2) {
1419 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
1421 if (test_bit(i, ac97->reg_accessed)) {
1422 /* handle multi codecs for AD18xx */
1423 if (i == AC97_PCM) {
1424 for (codec = 0; codec < 3; codec++) {
1425 if (! ac97->spec.ad18xx.id[codec])
1427 /* select single codec */
1428 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1429 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1430 /* update PCM bits */
1431 ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
1433 /* select all codecs */
1434 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1436 } else if (i == AC97_AD_TEST ||
1437 i == AC97_AD_CODEC_CFG ||
1438 i == AC97_AD_SERIAL_CFG)
1439 continue; /* ignore */
1441 snd_ac97_write(ac97, i, ac97->regs[i]);
1442 snd_ac97_read(ac97, i);
1446 snd_ac97_restore_iec958(ac97);
1449 static void ad1888_resume(struct snd_ac97 *ac97)
1451 ad18xx_resume(ac97);
1452 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
1457 static const struct snd_ac97_res_table ad1819_restbl[] = {
1458 { AC97_PHONE, 0x9f1f },
1459 { AC97_MIC, 0x9f1f },
1460 { AC97_LINE, 0x9f1f },
1461 { AC97_CD, 0x9f1f },
1462 { AC97_VIDEO, 0x9f1f },
1463 { AC97_AUX, 0x9f1f },
1464 { AC97_PCM, 0x9f1f },
1465 { } /* terminator */
1468 static int patch_ad1819(struct snd_ac97 * ac97)
1470 unsigned short scfg;
1472 // patch for Analog Devices
1473 scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1474 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
1475 ac97->res_table = ad1819_restbl;
1479 static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
1483 // test for unchained codec
1484 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
1485 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */
1486 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1487 if ((val & 0xff40) != 0x5340)
1489 ac97->spec.ad18xx.unchained[idx] = mask;
1490 ac97->spec.ad18xx.id[idx] = val;
1491 ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
1495 static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
1497 static const int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
1500 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
1501 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE
1502 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1503 if ((val & 0xff40) != 0x5340)
1506 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
1507 ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
1508 ac97->spec.ad18xx.id[idx] = val;
1509 ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
1513 static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
1515 // already detected?
1516 if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
1518 if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
1520 if (cidx1 < 0 && cidx2 < 0)
1522 // test for chained codecs
1523 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1524 ac97->spec.ad18xx.unchained[unchained_idx]);
1525 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
1526 ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
1529 patch_ad1881_chained1(ac97, cidx1, 0);
1530 else if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
1531 patch_ad1881_chained1(ac97, cidx2, 0);
1532 else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C
1533 patch_ad1881_chained1(ac97, cidx1, 0);
1534 } else if (cidx2 >= 0) {
1535 patch_ad1881_chained1(ac97, cidx2, 0);
1539 static const struct snd_ac97_build_ops patch_ad1881_build_ops = {
1541 .resume = ad18xx_resume
1545 static int patch_ad1881(struct snd_ac97 * ac97)
1547 static const char cfg_idxs[3][2] = {
1553 // patch for Analog Devices
1554 unsigned short codecs[3];
1558 val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1559 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
1560 codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
1561 codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
1562 codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
1564 if (! (codecs[0] || codecs[1] || codecs[2]))
1567 for (idx = 0; idx < 3; idx++)
1568 if (ac97->spec.ad18xx.unchained[idx])
1569 patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
1571 if (ac97->spec.ad18xx.id[1]) {
1572 ac97->flags |= AC97_AD_MULTI;
1573 ac97->scaps |= AC97_SCAP_SURROUND_DAC;
1575 if (ac97->spec.ad18xx.id[2]) {
1576 ac97->flags |= AC97_AD_MULTI;
1577 ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
1581 /* select all codecs */
1582 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1583 /* check if only one codec is present */
1584 for (idx = num = 0; idx < 3; idx++)
1585 if (ac97->spec.ad18xx.id[idx])
1588 /* ok, deselect all ID bits */
1589 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
1590 ac97->spec.ad18xx.codec_cfg[0] =
1591 ac97->spec.ad18xx.codec_cfg[1] =
1592 ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
1594 /* required for AD1886/AD1885 combination */
1595 ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
1596 if (ac97->spec.ad18xx.id[0]) {
1597 ac97->id &= 0xffff0000;
1598 ac97->id |= ac97->spec.ad18xx.id[0];
1600 ac97->build_ops = &patch_ad1881_build_ops;
1604 static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1605 AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
1606 /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
1607 AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
1608 AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
1609 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
1610 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1613 static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1615 static int patch_ad1885_specific(struct snd_ac97 * ac97)
1619 err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885));
1622 reset_tlv(ac97, "Headphone Playback Volume",
1623 db_scale_6bit_6db_max);
1627 static const struct snd_ac97_build_ops patch_ad1885_build_ops = {
1628 .build_specific = &patch_ad1885_specific,
1630 .resume = ad18xx_resume
1634 static int patch_ad1885(struct snd_ac97 * ac97)
1637 /* This is required to deal with the Intel D815EEAL2 */
1638 /* i.e. Line out is actually headphone out from codec */
1641 snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
1643 ac97->build_ops = &patch_ad1885_build_ops;
1647 static int patch_ad1886_specific(struct snd_ac97 * ac97)
1649 reset_tlv(ac97, "Headphone Playback Volume",
1650 db_scale_6bit_6db_max);
1654 static const struct snd_ac97_build_ops patch_ad1886_build_ops = {
1655 .build_specific = &patch_ad1886_specific,
1657 .resume = ad18xx_resume
1661 static int patch_ad1886(struct snd_ac97 * ac97)
1664 /* Presario700 workaround */
1665 /* for Jack Sense/SPDIF Register misetting causing */
1666 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
1667 ac97->build_ops = &patch_ad1886_build_ops;
1671 /* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
1672 #define AC97_AD198X_MBC 0x0003 /* mic boost */
1673 #define AC97_AD198X_MBC_20 0x0000 /* +20dB */
1674 #define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1675 #define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1676 #define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1677 #define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1678 #define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */
1679 #define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1680 #define AC97_AD198X_VREF_SHIFT 2
1681 #define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1682 #define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1683 #define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1684 #define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1685 #define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */
1686 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1687 #define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1688 #define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1689 #define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
1690 #define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */
1691 #define AC97_AD198X_MSPLT 0x2000 /* mute split */
1692 #define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
1693 #define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
1695 /* MISC 1 bits (AD1986 register 0x76) */
1696 #define AC97_AD1986_MBC 0x0003 /* mic boost */
1697 #define AC97_AD1986_MBC_20 0x0000 /* +20dB */
1698 #define AC97_AD1986_MBC_10 0x0001 /* +10dB */
1699 #define AC97_AD1986_MBC_30 0x0002 /* +30dB */
1700 #define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */
1701 #define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */
1702 #define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1703 #define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */
1704 #define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */
1705 #define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */
1706 #define AC97_AD1986_SRU 0x0010 /* sample rate unlock */
1707 #define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */
1708 #define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */
1709 #define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */
1710 #define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */
1711 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1712 #define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1713 #define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */
1714 #define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */
1715 #define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */
1716 #define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */
1717 #define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */
1719 /* MISC 2 bits (AD1986 register 0x70) */
1720 #define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */
1722 #define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */
1723 #define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */
1724 #define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */
1725 #define AC97_AD1986_CVREF_MASK \
1726 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1727 #define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */
1728 #define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */
1729 #define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */
1730 #define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */
1731 #define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */
1732 #define AC97_AD1986_MVREF_MASK \
1733 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1735 /* MISC 3 bits (AD1986 register 0x7a) */
1736 #define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */
1738 #define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */
1739 #define AC97_AD1986_GPO 0x0008 /* General Purpose Out */
1740 #define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */
1741 #define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */
1742 #define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */
1743 #define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */
1744 #define AC97_AD1986_LVREF_MASK \
1745 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1746 #define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */
1747 #define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */
1748 #define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */
1749 /* input select Surround DACs */
1750 #define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */
1751 /* select C/LFE DACs */
1752 #define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */
1754 /* Serial Config bits (AD1986 register 0x74) (incomplete) */
1755 #define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */
1756 #define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */
1757 #define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */
1758 #define AC97_AD1986_OMS_MASK \
1759 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1760 #define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */
1761 #define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */
1762 #define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */
1763 #define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */
1764 /* are MIC sources */
1765 #define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */
1766 /* are MIC sources */
1767 #define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */
1768 /* are MIC sources */
1769 #define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */
1770 /* are MIC sources */
1773 static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1775 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
1777 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1780 static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1782 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1785 val = ac97->regs[AC97_AD_SERIAL_CFG];
1786 ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
1790 static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1792 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1795 if (ucontrol->value.enumerated.item[0] > 1)
1797 val = ucontrol->value.enumerated.item[0] << 2;
1798 return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
1801 static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
1802 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1803 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1804 .info = snd_ac97_ad198x_spdif_source_info,
1805 .get = snd_ac97_ad198x_spdif_source_get,
1806 .put = snd_ac97_ad198x_spdif_source_put,
1809 static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
1811 return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
1814 static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
1815 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
1816 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1819 /* deny list to avoid HP/Line jack-sense controls
1820 * (SS vendor << 16 | device)
1822 static const unsigned int ad1981_jacks_denylist[] = {
1823 0x10140523, /* Thinkpad R40 */
1824 0x10140534, /* Thinkpad X31 */
1825 0x10140537, /* Thinkpad T41p */
1826 0x1014053e, /* Thinkpad R40e */
1827 0x10140554, /* Thinkpad T42p/R50p */
1828 0x10140567, /* Thinkpad T43p 2668-G7U */
1829 0x10140581, /* Thinkpad X41-2527 */
1830 0x10280160, /* Dell Dimension 2400 */
1831 0x104380b0, /* Asus A7V8X-MX */
1832 0x11790241, /* Toshiba Satellite A-15 S127 */
1833 0x1179ff10, /* Toshiba P500 */
1834 0x144dc01a, /* Samsung NP-X20C004/SEG */
1838 static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
1840 u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
1841 for (; *list; list++)
1847 static int patch_ad1981a_specific(struct snd_ac97 * ac97)
1849 if (check_list(ac97, ad1981_jacks_denylist))
1851 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1852 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1855 static const struct snd_ac97_build_ops patch_ad1981a_build_ops = {
1856 .build_post_spdif = patch_ad198x_post_spdif,
1857 .build_specific = patch_ad1981a_specific,
1859 .resume = ad18xx_resume
1863 /* allow list to enable HP jack-sense bits
1864 * (SS vendor << 16 | device)
1866 static const unsigned int ad1981_jacks_allowlist[] = {
1867 0x0e11005a, /* HP nc4000/4010 */
1868 0x103c0890, /* HP nc6000 */
1869 0x103c0938, /* HP nc4220 */
1870 0x103c099c, /* HP nx6110 */
1871 0x103c0944, /* HP nc6220 */
1872 0x103c0934, /* HP nc8220 */
1873 0x103c006d, /* HP nx9105 */
1874 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
1875 0x17340088, /* FSC Scenic-W */
1879 static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
1881 if (check_list(ac97, ad1981_jacks_allowlist))
1882 /* enable headphone jack sense */
1883 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
1886 static int patch_ad1981a(struct snd_ac97 *ac97)
1889 ac97->build_ops = &patch_ad1981a_build_ops;
1890 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1891 ac97->flags |= AC97_STEREO_MUTES;
1892 check_ad1981_hp_jack_sense(ac97);
1896 static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
1897 AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
1899 static int patch_ad1981b_specific(struct snd_ac97 *ac97)
1903 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
1906 if (check_list(ac97, ad1981_jacks_denylist))
1908 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1909 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1912 static const struct snd_ac97_build_ops patch_ad1981b_build_ops = {
1913 .build_post_spdif = patch_ad198x_post_spdif,
1914 .build_specific = patch_ad1981b_specific,
1916 .resume = ad18xx_resume
1920 static int patch_ad1981b(struct snd_ac97 *ac97)
1923 ac97->build_ops = &patch_ad1981b_build_ops;
1924 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1925 ac97->flags |= AC97_STEREO_MUTES;
1926 check_ad1981_hp_jack_sense(ac97);
1930 #define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
1932 static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1934 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1937 val = ac97->regs[AC97_AD_MISC];
1938 ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
1939 if (ac97->spec.ad18xx.lo_as_master)
1940 ucontrol->value.integer.value[0] =
1941 !ucontrol->value.integer.value[0];
1945 static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1947 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1950 val = !ucontrol->value.integer.value[0];
1951 if (ac97->spec.ad18xx.lo_as_master)
1953 val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
1954 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1955 AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
1958 static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1960 static const char * const texts[3] = {"Off", "6 -> 4", "6 -> 2"};
1962 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1965 static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1967 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1970 val = ac97->regs[AC97_AD_MISC];
1971 if (!(val & AC97_AD198X_DMIX1))
1972 ucontrol->value.enumerated.item[0] = 0;
1974 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
1978 static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1980 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1983 if (ucontrol->value.enumerated.item[0] > 2)
1985 if (ucontrol->value.enumerated.item[0] == 0)
1988 val = AC97_AD198X_DMIX1 |
1989 ((ucontrol->value.enumerated.item[0] - 1) << 8);
1990 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1991 AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
1994 static void ad1888_update_jacks(struct snd_ac97 *ac97)
1996 unsigned short val = 0;
1997 /* clear LODIS if shared jack is to be used for Surround out */
1998 if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
2000 /* clear CLDIS if shared jack is to be used for C/LFE out */
2001 if (is_shared_micin(ac97))
2003 /* shared Line-In */
2004 snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
2007 static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
2009 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2010 .name = "Exchange Front/Surround",
2011 .info = snd_ac97_ad1888_lohpsel_info,
2012 .get = snd_ac97_ad1888_lohpsel_get,
2013 .put = snd_ac97_ad1888_lohpsel_put
2015 AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
2016 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
2017 AC97_AD_HPFD_SHIFT, 1, 1),
2018 AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
2020 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2022 .info = snd_ac97_ad1888_downmix_info,
2023 .get = snd_ac97_ad1888_downmix_get,
2024 .put = snd_ac97_ad1888_downmix_put
2026 AC97_SURROUND_JACK_MODE_CTL,
2027 AC97_CHANNEL_MODE_CTL,
2029 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2030 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2033 static int patch_ad1888_specific(struct snd_ac97 *ac97)
2035 if (!ac97->spec.ad18xx.lo_as_master) {
2036 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2037 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2038 "Master Surround Playback");
2039 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
2042 return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
2045 static const struct snd_ac97_build_ops patch_ad1888_build_ops = {
2046 .build_post_spdif = patch_ad198x_post_spdif,
2047 .build_specific = patch_ad1888_specific,
2049 .resume = ad1888_resume,
2051 .update_jacks = ad1888_update_jacks,
2054 static int patch_ad1888(struct snd_ac97 * ac97)
2056 unsigned short misc;
2059 ac97->build_ops = &patch_ad1888_build_ops;
2062 * LO can be used as a real line-out on some devices,
2063 * and we need to revert the front/surround mixer switches
2065 if (ac97->subsystem_vendor == 0x1043 &&
2066 ac97->subsystem_device == 0x1193) /* ASUS A9T laptop */
2067 ac97->spec.ad18xx.lo_as_master = 1;
2069 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2070 /* AD-compatible mode */
2071 /* Stereo mutes enabled */
2072 misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
2073 if (!ac97->spec.ad18xx.lo_as_master)
2074 /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
2075 /* it seems that most vendors connect line-out connector to
2076 * headphone out of AC'97
2078 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
2080 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
2081 ac97->flags |= AC97_STEREO_MUTES;
2085 static int patch_ad1980_specific(struct snd_ac97 *ac97)
2089 err = patch_ad1888_specific(ac97);
2092 return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2095 static const struct snd_ac97_build_ops patch_ad1980_build_ops = {
2096 .build_post_spdif = patch_ad198x_post_spdif,
2097 .build_specific = patch_ad1980_specific,
2099 .resume = ad18xx_resume,
2101 .update_jacks = ad1888_update_jacks,
2104 static int patch_ad1980(struct snd_ac97 * ac97)
2107 ac97->build_ops = &patch_ad1980_build_ops;
2111 static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2112 struct snd_ctl_elem_info *uinfo)
2114 static const char * const texts[4] = {
2115 "High-Z", "3.7 V", "2.25 V", "0 V"
2118 return snd_ctl_enum_info(uinfo, 1, 4, texts);
2121 static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2122 struct snd_ctl_elem_value *ucontrol)
2124 static const int reg2ctrl[4] = {2, 0, 1, 3};
2125 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2127 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2128 >> AC97_AD198X_VREF_SHIFT;
2129 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2133 static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2134 struct snd_ctl_elem_value *ucontrol)
2136 static const int ctrl2reg[4] = {1, 2, 0, 3};
2137 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2140 if (ucontrol->value.enumerated.item[0] > 3)
2142 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2143 << AC97_AD198X_VREF_SHIFT;
2144 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2145 AC97_AD198X_VREF_MASK, val);
2148 static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
2149 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2151 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2152 .name = "Exchange Front/Surround",
2153 .info = snd_ac97_ad1888_lohpsel_info,
2154 .get = snd_ac97_ad1888_lohpsel_get,
2155 .put = snd_ac97_ad1888_lohpsel_put
2157 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2158 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2159 AC97_AD_MISC, 7, 1, 0),
2161 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2163 .info = snd_ac97_ad1888_downmix_info,
2164 .get = snd_ac97_ad1888_downmix_get,
2165 .put = snd_ac97_ad1888_downmix_put
2168 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2170 .info = snd_ac97_ad1985_vrefout_info,
2171 .get = snd_ac97_ad1985_vrefout_get,
2172 .put = snd_ac97_ad1985_vrefout_put
2174 AC97_SURROUND_JACK_MODE_CTL,
2175 AC97_CHANNEL_MODE_CTL,
2177 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2178 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2181 static void ad1985_update_jacks(struct snd_ac97 *ac97)
2183 ad1888_update_jacks(ac97);
2184 /* clear OMS if shared jack is to be used for C/LFE out */
2185 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
2186 is_shared_micin(ac97) ? 1 << 9 : 0);
2189 static int patch_ad1985_specific(struct snd_ac97 *ac97)
2193 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2194 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2195 "Master Surround Playback");
2196 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2198 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2202 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2203 ARRAY_SIZE(snd_ac97_ad1985_controls));
2206 static const struct snd_ac97_build_ops patch_ad1985_build_ops = {
2207 .build_post_spdif = patch_ad198x_post_spdif,
2208 .build_specific = patch_ad1985_specific,
2210 .resume = ad18xx_resume,
2212 .update_jacks = ad1985_update_jacks,
2215 static int patch_ad1985(struct snd_ac97 * ac97)
2217 unsigned short misc;
2220 ac97->build_ops = &patch_ad1985_build_ops;
2221 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2222 /* switch front/surround line-out/hp-out */
2223 /* AD-compatible mode */
2224 /* Stereo mutes enabled */
2225 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2229 AC97_AD198X_AC97NC);
2230 ac97->flags |= AC97_STEREO_MUTES;
2232 /* update current jack configuration */
2233 ad1985_update_jacks(ac97);
2235 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2236 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2240 #define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
2242 static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2243 struct snd_ctl_elem_value *ucontrol)
2245 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2248 val = ac97->regs[AC97_AD_MISC3];
2249 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2253 static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2254 struct snd_ctl_elem_value *ucontrol)
2256 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2259 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2261 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2262 ucontrol->value.integer.value[0] != 0
2263 ? AC97_AD1986_LOSEL : 0);
2267 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2268 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2269 (ucontrol->value.integer.value[0] != 0
2271 ? AC97_AD1986_SOSEL : 0);
2275 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2278 static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2279 struct snd_ctl_elem_value *ucontrol)
2281 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2284 val = ac97->regs[AC97_AD_MISC];
2285 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2289 static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2290 struct snd_ctl_elem_value *ucontrol)
2292 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2295 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2297 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2298 ucontrol->value.integer.value[0] != 0
2299 ? AC97_AD1986_SPRD : 0);
2303 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2304 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2305 (ucontrol->value.integer.value[0] != 0
2307 ? AC97_AD1986_SOSEL : 0);
2311 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2314 static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2315 struct snd_ctl_elem_value *ucontrol)
2317 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2319 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2323 static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2324 struct snd_ctl_elem_value *ucontrol)
2326 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2327 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2329 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2330 ac97->spec.ad18xx.swap_mic_linein = swap;
2331 if (ac97->build_ops->update_jacks)
2332 ac97->build_ops->update_jacks(ac97);
2338 static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2339 struct snd_ctl_elem_value *ucontrol)
2341 /* Use MIC_1/2 V_REFOUT as the "get" value */
2342 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2344 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2345 if ((reg & AC97_AD1986_MVREF0) != 0)
2347 else if ((reg & AC97_AD1986_MVREF1) != 0)
2349 else if ((reg & AC97_AD1986_MVREF2) != 0)
2353 ucontrol->value.enumerated.item[0] = val;
2357 static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2358 struct snd_ctl_elem_value *ucontrol)
2360 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2361 unsigned short cval;
2362 unsigned short lval;
2363 unsigned short mval;
2368 switch (ucontrol->value.enumerated.item[0])
2370 case 0: /* High-Z */
2376 cval = AC97_AD1986_CVREF2;
2377 lval = AC97_AD1986_LVREF2;
2378 mval = AC97_AD1986_MVREF2;
2380 case 2: /* 2.25 V */
2381 cval = AC97_AD1986_CVREF0;
2382 lval = AC97_AD1986_LVREF0;
2383 mval = AC97_AD1986_MVREF0;
2386 cval = AC97_AD1986_CVREF1;
2387 lval = AC97_AD1986_LVREF1;
2388 mval = AC97_AD1986_MVREF1;
2394 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2395 AC97_AD1986_CVREF_MASK, cval);
2398 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2399 AC97_AD1986_LVREF_MASK, lval);
2402 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2403 AC97_AD1986_MVREF_MASK, mval);
2407 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2410 static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2411 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2413 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2414 .name = "Exchange Front/Surround",
2415 .info = snd_ac97_ad1986_bool_info,
2416 .get = snd_ac97_ad1986_lososel_get,
2417 .put = snd_ac97_ad1986_lososel_put
2420 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2421 .name = "Exchange Mic/Line In",
2422 .info = snd_ac97_ad1986_bool_info,
2423 .get = snd_ac97_ad1986_miclisel_get,
2424 .put = snd_ac97_ad1986_miclisel_put
2427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2428 .name = "Spread Front to Surround and Center/LFE",
2429 .info = snd_ac97_ad1986_bool_info,
2430 .get = snd_ac97_ad1986_spread_get,
2431 .put = snd_ac97_ad1986_spread_put
2434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2436 .info = snd_ac97_ad1888_downmix_info,
2437 .get = snd_ac97_ad1888_downmix_get,
2438 .put = snd_ac97_ad1888_downmix_put
2441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2443 .info = snd_ac97_ad1985_vrefout_info,
2444 .get = snd_ac97_ad1986_vrefout_get,
2445 .put = snd_ac97_ad1986_vrefout_put
2447 AC97_SURROUND_JACK_MODE_CTL,
2448 AC97_CHANNEL_MODE_CTL,
2450 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2451 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2454 static void ad1986_update_jacks(struct snd_ac97 *ac97)
2456 unsigned short misc_val = 0;
2457 unsigned short ser_val;
2459 /* disable SURROUND and CENTER/LFE if not surround mode */
2460 if (!is_surround_on(ac97))
2461 misc_val |= AC97_AD1986_SODIS;
2462 if (!is_clfe_on(ac97))
2463 misc_val |= AC97_AD1986_CLDIS;
2465 /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
2466 if (is_shared_linein(ac97))
2467 misc_val |= AC97_AD1986_LISEL_SURR;
2468 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2469 misc_val |= AC97_AD1986_LISEL_MIC;
2470 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2471 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2472 AC97_AD1986_LISEL_MASK,
2475 /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
2476 if (is_shared_micin(ac97))
2477 ser_val = AC97_AD1986_OMS_C;
2478 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2479 ser_val = AC97_AD1986_OMS_L;
2481 ser_val = AC97_AD1986_OMS_M;
2482 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2483 AC97_AD1986_OMS_MASK,
2487 static int patch_ad1986_specific(struct snd_ac97 *ac97)
2491 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2495 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2496 ARRAY_SIZE(snd_ac97_ad1985_controls));
2499 static const struct snd_ac97_build_ops patch_ad1986_build_ops = {
2500 .build_post_spdif = patch_ad198x_post_spdif,
2501 .build_specific = patch_ad1986_specific,
2503 .resume = ad18xx_resume,
2505 .update_jacks = ad1986_update_jacks,
2508 static int patch_ad1986(struct snd_ac97 * ac97)
2511 ac97->build_ops = &patch_ad1986_build_ops;
2512 ac97->flags |= AC97_STEREO_MUTES;
2514 /* update current jack configuration */
2515 ad1986_update_jacks(ac97);
2521 * realtek ALC203: use mono-out for pin 37
2523 static int patch_alc203(struct snd_ac97 *ac97)
2525 snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
2530 * realtek ALC65x/850 codecs
2532 static void alc650_update_jacks(struct snd_ac97 *ac97)
2536 /* shared Line-In / Surround Out */
2537 shared = is_shared_surrout(ac97);
2538 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2539 shared ? (1 << 9) : 0);
2540 /* update shared Mic In / Center/LFE Out */
2541 shared = is_shared_clfeout(ac97);
2542 /* disable/enable vref */
2543 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2544 shared ? (1 << 12) : 0);
2545 /* turn on/off center-on-mic */
2546 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
2547 shared ? (1 << 10) : 0);
2548 /* GPIO0 high for mic */
2549 snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
2550 shared ? 0 : 0x100);
2553 static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
2554 struct snd_ctl_elem_value *ucontrol)
2556 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2557 struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
2560 if (ucontrol->value.integer.value[0])
2561 map->chmap = snd_pcm_std_chmaps;
2563 map->chmap = snd_pcm_alt_chmaps;
2565 return snd_ac97_put_volsw(kcontrol, ucontrol);
2568 static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2569 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2570 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
2571 AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
2572 AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
2573 /* 4: Analog Input To Surround */
2574 /* 5: Analog Input To Center/LFE */
2575 /* 6: Independent Master Volume Right */
2576 /* 7: Independent Master Volume Left */
2578 /* 9: Line-In/Surround share */
2579 /* 10: Mic/CLFE share */
2580 /* 11-13: in IEC958 controls */
2582 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2583 .name = "Swap Surround Slot",
2584 .info = snd_ac97_info_volsw,
2585 .get = snd_ac97_get_volsw,
2586 .put = alc650_swap_surround_put,
2587 .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
2589 #if 0 /* always set in patch_alc650 */
2590 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2591 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
2592 AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
2593 AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
2594 AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
2595 AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
2597 AC97_SURROUND_JACK_MODE_CTL,
2598 AC97_CHANNEL_MODE_CTL,
2601 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2602 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
2603 AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
2604 /* disable this controls since it doesn't work as expected */
2605 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2608 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2610 static int patch_alc650_specific(struct snd_ac97 * ac97)
2614 err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650));
2617 if (ac97->ext_id & AC97_EI_SPDIF) {
2618 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650));
2622 if (ac97->id != AC97_ID_ALC650F)
2623 reset_tlv(ac97, "Master Playback Volume",
2624 db_scale_5bit_3db_max);
2628 static const struct snd_ac97_build_ops patch_alc650_ops = {
2629 .build_specific = patch_alc650_specific,
2630 .update_jacks = alc650_update_jacks
2633 static int patch_alc650(struct snd_ac97 * ac97)
2637 ac97->build_ops = &patch_alc650_ops;
2639 /* determine the revision */
2640 val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
2642 ac97->id = 0x414c4720; /* Old version */
2643 else if (val < 0x10)
2644 ac97->id = 0x414c4721; /* D version */
2645 else if (val < 0x20)
2646 ac97->id = 0x414c4722; /* E version */
2647 else if (val < 0x30)
2648 ac97->id = 0x414c4723; /* F version */
2650 /* revision E or F */
2651 /* FIXME: what about revision D ? */
2652 ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
2653 ac97->id == 0x414c4723);
2655 /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
2656 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2657 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
2659 /* Enable SPDIF-IN only on Rev.E and above */
2660 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2661 /* SPDIF IN with pin 47 */
2662 if (ac97->spec.dev_flags &&
2663 /* ASUS A6KM requires EAPD */
2664 ! (ac97->subsystem_vendor == 0x1043 &&
2665 ac97->subsystem_device == 0x1103))
2666 val |= 0x03; /* enable */
2668 val &= ~0x03; /* disable */
2669 snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
2671 /* set default: slot 3,4,7,8,6,9
2672 spdif-in monitor off, analog-spdif off, spdif-in off
2673 center on mic off, surround on line-in off
2674 downmix off, duplicate front off
2676 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
2678 /* set GPIO0 for mic bias */
2679 /* GPIO0 pin output, no interrupt, high */
2680 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
2681 snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
2682 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2683 (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
2685 /* full DAC volume */
2686 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2687 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2691 static void alc655_update_jacks(struct snd_ac97 *ac97)
2695 /* shared Line-In / Surround Out */
2696 shared = is_shared_surrout(ac97);
2697 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2698 shared ? (1 << 9) : 0, 0);
2699 /* update shared Mic In / Center/LFE Out */
2700 shared = is_shared_clfeout(ac97);
2701 /* misc control; vrefout disable */
2702 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2703 shared ? (1 << 12) : 0);
2704 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
2705 shared ? (1 << 10) : 0, 0);
2708 static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
2709 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2710 AC97_SURROUND_JACK_MODE_CTL,
2711 AC97_CHANNEL_MODE_CTL,
2714 static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2716 static const char * const texts_655[3] = {
2717 "PCM", "Analog In", "IEC958 In"
2719 static const char * const texts_658[4] = {
2720 "PCM", "Analog1 In", "Analog2 In", "IEC958 In"
2722 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2724 if (ac97->spec.dev_flags)
2725 return snd_ctl_enum_info(uinfo, 1, 4, texts_658);
2727 return snd_ctl_enum_info(uinfo, 1, 3, texts_655);
2730 static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2732 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2735 val = ac97->regs[AC97_ALC650_MULTICH];
2736 val = (val >> 12) & 3;
2737 if (ac97->spec.dev_flags && val == 3)
2739 ucontrol->value.enumerated.item[0] = val;
2743 static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2745 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2747 return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
2748 (unsigned short)ucontrol->value.enumerated.item[0] << 12,
2752 static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
2753 AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
2754 /* disable this controls since it doesn't work as expected */
2755 /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
2757 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2758 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2759 .info = alc655_iec958_route_info,
2760 .get = alc655_iec958_route_get,
2761 .put = alc655_iec958_route_put,
2765 static int patch_alc655_specific(struct snd_ac97 * ac97)
2769 err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655));
2772 if (ac97->ext_id & AC97_EI_SPDIF) {
2773 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2780 static const struct snd_ac97_build_ops patch_alc655_ops = {
2781 .build_specific = patch_alc655_specific,
2782 .update_jacks = alc655_update_jacks
2785 static int patch_alc655(struct snd_ac97 * ac97)
2789 if (ac97->id == AC97_ID_ALC658) {
2790 ac97->spec.dev_flags = 1; /* ALC658 */
2791 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
2792 ac97->id = AC97_ID_ALC658D;
2793 ac97->spec.dev_flags = 2;
2797 ac97->build_ops = &patch_alc655_ops;
2799 /* assume only page 0 for writing cache */
2800 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2802 /* adjust default values */
2803 val = snd_ac97_read(ac97, 0x7a); /* misc control */
2804 if (ac97->spec.dev_flags) /* ALC658 */
2805 val &= ~(1 << 1); /* Pin 47 is spdif input pin */
2807 if (ac97->subsystem_vendor == 0x1462 &&
2808 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
2809 ac97->subsystem_device == 0x0161 || /* LG K1 Express */
2810 ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
2811 ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */
2812 ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */
2813 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
2815 val |= (1 << 1); /* Pin 47 is spdif input pin */
2816 /* this seems missing on some hardwares */
2817 ac97->ext_id |= AC97_EI_SPDIF;
2819 val &= ~(1 << 12); /* vref enable */
2820 snd_ac97_write_cache(ac97, 0x7a, val);
2821 /* set default: spdif-in enabled,
2822 spdif-in monitor off, spdif-in PCM off
2823 center on mic off, surround on line-in off
2826 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2828 /* full DAC volume */
2829 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2830 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2832 /* update undocumented bit... */
2833 if (ac97->id == AC97_ID_ALC658D)
2834 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2840 #define AC97_ALC850_JACK_SELECT 0x76
2841 #define AC97_ALC850_MISC1 0x7a
2842 #define AC97_ALC850_MULTICH 0x6a
2844 static void alc850_update_jacks(struct snd_ac97 *ac97)
2847 int aux_is_back_surround;
2849 /* shared Line-In / Surround Out */
2850 shared = is_shared_surrout(ac97);
2851 /* SURR 1kOhm (bit4), Amp (bit5) */
2852 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2853 shared ? (1<<5) : (1<<4));
2854 /* LINE-IN = 0, SURROUND = 2 */
2855 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2856 shared ? (2<<12) : (0<<12));
2857 /* update shared Mic In / Center/LFE Out */
2858 shared = is_shared_clfeout(ac97);
2859 /* Vref disable (bit12), 1kOhm (bit13) */
2860 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2861 shared ? (1<<12) : (1<<13));
2862 /* MIC-IN = 1, CENTER-LFE = 5 */
2863 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
2864 shared ? (5<<4) : (1<<4));
2866 aux_is_back_surround = alc850_is_aux_back_surround(ac97);
2867 /* Aux is Back Surround */
2868 snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
2869 aux_is_back_surround ? (1<<10) : (0<<10));
2872 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
2873 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2874 AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
2875 AC97_SURROUND_JACK_MODE_CTL,
2876 AC97_CHANNEL_MODE_8CH_CTL,
2879 static int patch_alc850_specific(struct snd_ac97 *ac97)
2883 err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850));
2886 if (ac97->ext_id & AC97_EI_SPDIF) {
2887 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2894 static const struct snd_ac97_build_ops patch_alc850_ops = {
2895 .build_specific = patch_alc850_specific,
2896 .update_jacks = alc850_update_jacks
2899 static int patch_alc850(struct snd_ac97 *ac97)
2901 ac97->build_ops = &patch_alc850_ops;
2903 ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
2904 ac97->flags |= AC97_HAS_8CH;
2906 /* assume only page 0 for writing cache */
2907 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2909 /* adjust default values */
2910 /* set default: spdif-in enabled,
2911 spdif-in monitor off, spdif-in PCM off
2912 center on mic off, surround on line-in off
2914 NB default bit 10=0 = Aux is Capture, not Back Surround
2916 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2917 /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
2918 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
2920 snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
2921 (1<<7)|(0<<12)|(1<<13)|(0<<14));
2922 /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
2923 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
2925 snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
2926 (1<<11)|(0<<12)|(1<<15));
2928 /* full DAC volume */
2929 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2930 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2934 static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
2936 struct snd_kcontrol *kctl_3d_center =
2937 snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
2938 struct snd_kcontrol *kctl_3d_depth =
2939 snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
2942 * 3D register is different from AC97 standard layout
2943 * (also do some renaming, to resemble Windows driver naming)
2945 if (kctl_3d_center) {
2946 kctl_3d_center->private_value =
2947 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
2948 snd_ac97_rename_vol_ctl(ac97,
2949 "3D Control - Center", "3D Control - Width"
2953 kctl_3d_depth->private_value =
2954 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
2956 /* Aztech Windows driver calls the
2957 equivalent control "Modem Playback", thus rename it: */
2958 snd_ac97_rename_vol_ctl(ac97,
2959 "Master Mono Playback", "Modem Playback"
2961 snd_ac97_rename_vol_ctl(ac97,
2962 "Headphone Playback", "FM Synth Playback"
2968 static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
2969 .build_specific = patch_aztech_azf3328_specific
2972 static int patch_aztech_azf3328(struct snd_ac97 *ac97)
2974 ac97->build_ops = &patch_aztech_azf3328_ops;
2979 * C-Media CM97xx codecs
2981 static void cm9738_update_jacks(struct snd_ac97 *ac97)
2983 /* shared Line-In / Surround Out */
2984 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2985 is_shared_surrout(ac97) ? (1 << 10) : 0);
2988 static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
2989 AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
2990 AC97_SURROUND_JACK_MODE_CTL,
2991 AC97_CHANNEL_MODE_4CH_CTL,
2994 static int patch_cm9738_specific(struct snd_ac97 * ac97)
2996 return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
2999 static const struct snd_ac97_build_ops patch_cm9738_ops = {
3000 .build_specific = patch_cm9738_specific,
3001 .update_jacks = cm9738_update_jacks
3004 static int patch_cm9738(struct snd_ac97 * ac97)
3006 ac97->build_ops = &patch_cm9738_ops;
3007 /* FIXME: can anyone confirm below? */
3008 /* CM9738 has no PCM volume although the register reacts */
3009 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3010 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3015 static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3017 static const char * const texts[] = { "Analog", "Digital" };
3019 return snd_ctl_enum_info(uinfo, 1, 2, texts);
3022 static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3024 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3027 val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
3028 ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
3032 static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3034 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3036 return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
3038 (ucontrol->value.enumerated.item[0] & 0x01) << 1);
3041 static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
3042 /* BIT 0: SPDI_EN - always true */
3043 { /* BIT 1: SPDIFS */
3044 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3045 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3046 .info = snd_ac97_cmedia_spdif_playback_source_info,
3047 .get = snd_ac97_cmedia_spdif_playback_source_get,
3048 .put = snd_ac97_cmedia_spdif_playback_source_put,
3050 /* BIT 2: IG_SPIV */
3051 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
3053 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
3054 /* BIT 4: SPI2SDI */
3055 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
3056 /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
3059 static void cm9739_update_jacks(struct snd_ac97 *ac97)
3061 /* shared Line-In / Surround Out */
3062 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
3063 is_shared_surrout(ac97) ? (1 << 10) : 0);
3064 /* shared Mic In / Center/LFE Out **/
3065 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
3066 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
3069 static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
3070 AC97_SURROUND_JACK_MODE_CTL,
3071 AC97_CHANNEL_MODE_CTL,
3074 static int patch_cm9739_specific(struct snd_ac97 * ac97)
3076 return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
3079 static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
3081 return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
3084 static const struct snd_ac97_build_ops patch_cm9739_ops = {
3085 .build_specific = patch_cm9739_specific,
3086 .build_post_spdif = patch_cm9739_post_spdif,
3087 .update_jacks = cm9739_update_jacks
3090 static int patch_cm9739(struct snd_ac97 * ac97)
3094 ac97->build_ops = &patch_cm9739_ops;
3096 /* CM9739/A has no Master and PCM volume although the register reacts */
3097 ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
3098 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
3099 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3102 val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
3103 if (val & AC97_EA_SPCV) {
3104 /* enable spdif in */
3105 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3106 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
3107 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3109 ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
3110 ac97->rates[AC97_RATES_SPDIF] = 0;
3113 /* set-up multi channel */
3114 /* bit 14: 0 = SPDIF, 1 = EAPD */
3115 /* bit 13: enable internal vref output for mic */
3116 /* bit 12: disable center/lfe (switchable) */
3117 /* bit 10: disable surround/line (switchable) */
3118 /* bit 9: mix 2 surround off */
3119 /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */
3120 /* bit 3: undocumented; surround? */
3122 val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
3125 if (! (ac97->ext_id & AC97_EI_SPDIF))
3127 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
3129 /* FIXME: set up GPIO */
3130 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3131 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3132 /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */
3134 ac97->subsystem_vendor == 0x1043 &&
3135 ac97->subsystem_device == 0x1843) {
3136 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3137 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
3138 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
3139 snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
3145 #define AC97_CM9761_MULTI_CHAN 0x64
3146 #define AC97_CM9761_FUNC 0x66
3147 #define AC97_CM9761_SPDIF_CTRL 0x6c
3149 static void cm9761_update_jacks(struct snd_ac97 *ac97)
3151 /* FIXME: check the bits for each model
3152 * model 83 is confirmed to work
3154 static const unsigned short surr_on[3][2] = {
3155 { 0x0008, 0x0000 }, /* 9761-78 & 82 */
3156 { 0x0000, 0x0008 }, /* 9761-82 rev.B */
3157 { 0x0000, 0x0008 }, /* 9761-83 */
3159 static const unsigned short clfe_on[3][2] = {
3160 { 0x0000, 0x1000 }, /* 9761-78 & 82 */
3161 { 0x1000, 0x0000 }, /* 9761-82 rev.B */
3162 { 0x0000, 0x1000 }, /* 9761-83 */
3164 static const unsigned short surr_shared[3][2] = {
3165 { 0x0000, 0x0400 }, /* 9761-78 & 82 */
3166 { 0x0000, 0x0400 }, /* 9761-82 rev.B */
3167 { 0x0000, 0x0400 }, /* 9761-83 */
3169 static const unsigned short clfe_shared[3][2] = {
3170 { 0x2000, 0x0880 }, /* 9761-78 & 82 */
3171 { 0x0000, 0x2880 }, /* 9761-82 rev.B */
3172 { 0x2000, 0x0800 }, /* 9761-83 */
3174 unsigned short val = 0;
3176 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
3177 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
3178 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
3179 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
3181 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
3184 static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
3185 AC97_SURROUND_JACK_MODE_CTL,
3186 AC97_CHANNEL_MODE_CTL,
3189 static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3191 static const char * const texts[] = { "AC-Link", "ADC", "SPDIF-In" };
3193 return snd_ctl_enum_info(uinfo, 1, 3, texts);
3196 static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3198 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3200 if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
3201 ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
3202 else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
3203 ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
3205 ucontrol->value.enumerated.item[0] = 0; /* AC-link */
3209 static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3211 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3213 if (ucontrol->value.enumerated.item[0] == 2)
3214 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
3215 snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
3216 return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
3217 ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
3220 static const char * const cm9761_dac_clock[] = {
3221 "AC-Link", "SPDIF-In", "Both"
3223 static const struct ac97_enum cm9761_dac_clock_enum =
3224 AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
3226 static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
3227 { /* BIT 1: SPDIFS */
3228 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3229 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3230 .info = cm9761_spdif_out_source_info,
3231 .get = cm9761_spdif_out_source_get,
3232 .put = cm9761_spdif_out_source_put,
3234 /* BIT 2: IG_SPIV */
3235 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
3237 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
3238 /* BIT 4: SPI2SDI */
3239 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
3240 /* BIT 9-10: DAC_CTL */
3241 AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
3244 static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
3246 return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
3249 static int patch_cm9761_specific(struct snd_ac97 * ac97)
3251 return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
3254 static const struct snd_ac97_build_ops patch_cm9761_ops = {
3255 .build_specific = patch_cm9761_specific,
3256 .build_post_spdif = patch_cm9761_post_spdif,
3257 .update_jacks = cm9761_update_jacks
3260 static int patch_cm9761(struct snd_ac97 *ac97)
3264 /* CM9761 has no PCM volume although the register reacts */
3265 /* Master volume seems to have _some_ influence on the analog
3268 ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
3269 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
3270 snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
3272 ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */
3273 if (ac97->id == AC97_ID_CM9761_82) {
3275 /* check page 1, reg 0x60 */
3276 val = snd_ac97_read(ac97, AC97_INT_PAGING);
3277 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
3278 tmp = snd_ac97_read(ac97, 0x60);
3279 ac97->spec.dev_flags = tmp & 1; /* revision B? */
3280 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
3281 } else if (ac97->id == AC97_ID_CM9761_83)
3282 ac97->spec.dev_flags = 2;
3284 ac97->build_ops = &patch_cm9761_ops;
3287 /* force the SPDIF bit in ext_id - codec doesn't set this bit! */
3288 ac97->ext_id |= AC97_EI_SPDIF;
3289 /* to be sure: we overwrite the ext status bits */
3290 snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
3291 /* Don't set 0x0200 here. This results in the silent analog output */
3292 snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
3293 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3295 /* set-up multi channel */
3296 /* bit 15: pc master beep off
3297 * bit 14: pin47 = EAPD/SPDIF
3298 * bit 13: vref ctl [= cm9739]
3299 * bit 12: CLFE control (reverted on rev B)
3300 * bit 11: Mic/center share (reverted on rev B)
3301 * bit 10: suddound/line share
3302 * bit 9: Analog-in mix -> surround
3303 * bit 8: Analog-in mix -> CLFE
3304 * bit 7: Mic/LFE share (mic/center/lfe)
3305 * bit 5: vref select (9761A)
3306 * bit 4: front control
3307 * bit 3: surround control (revereted with rev B)
3310 * bit 0: mic boost level (0=20dB, 1=30dB)
3314 if (ac97->spec.dev_flags)
3319 val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
3320 val |= (1 << 4); /* front on */
3321 snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
3323 /* FIXME: set up GPIO */
3324 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3325 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3330 #define AC97_CM9780_SIDE 0x60
3331 #define AC97_CM9780_JACK 0x62
3332 #define AC97_CM9780_MIXER 0x64
3333 #define AC97_CM9780_MULTI_CHAN 0x66
3334 #define AC97_CM9780_SPDIF 0x6c
3336 static const char * const cm9780_ch_select[] = {
3337 "Front", "Side", "Center/LFE", "Rear"
3339 static const struct ac97_enum cm9780_ch_select_enum =
3340 AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
3341 static const struct snd_kcontrol_new cm9780_controls[] = {
3342 AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
3343 AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
3344 AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
3347 static int patch_cm9780_specific(struct snd_ac97 *ac97)
3349 return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
3352 static const struct snd_ac97_build_ops patch_cm9780_ops = {
3353 .build_specific = patch_cm9780_specific,
3354 .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
3357 static int patch_cm9780(struct snd_ac97 *ac97)
3361 ac97->build_ops = &patch_cm9780_ops;
3364 if (ac97->ext_id & AC97_EI_SPDIF) {
3365 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
3366 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
3367 val |= 0x1; /* SPDI_EN */
3368 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
3377 static const struct snd_kcontrol_new snd_ac97_controls_vt1613[] = {
3378 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3381 static int patch_vt1613_specific(struct snd_ac97 *ac97)
3383 return patch_build_controls(ac97, &snd_ac97_controls_vt1613[0],
3384 ARRAY_SIZE(snd_ac97_controls_vt1613));
3387 static const struct snd_ac97_build_ops patch_vt1613_ops = {
3388 .build_specific = patch_vt1613_specific
3391 static int patch_vt1613(struct snd_ac97 *ac97)
3393 ac97->build_ops = &patch_vt1613_ops;
3395 ac97->flags |= AC97_HAS_NO_VIDEO;
3396 ac97->caps |= AC97_BC_HEADPHONE;
3404 static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
3405 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3406 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
3407 AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
3408 AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
3411 static const char * const follower_vols_vt1616[] = {
3412 "Front Playback Volume",
3413 "Surround Playback Volume",
3414 "Center Playback Volume",
3415 "LFE Playback Volume",
3419 static const char * const follower_sws_vt1616[] = {
3420 "Front Playback Switch",
3421 "Surround Playback Switch",
3422 "Center Playback Switch",
3423 "LFE Playback Switch",
3427 /* find a mixer control element with the given name */
3428 static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
3431 return snd_ctl_find_id_mixer(ac97->bus->card, name);
3434 /* create a virtual master control and add followers */
3435 static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
3436 const unsigned int *tlv,
3437 const char * const *followers)
3439 struct snd_kcontrol *kctl;
3442 kctl = snd_ctl_make_virtual_master(name, tlv);
3445 err = snd_ctl_add(ac97->bus->card, kctl);
3449 return snd_ctl_add_followers(ac97->bus->card, kctl, followers);
3452 static int patch_vt1616_specific(struct snd_ac97 * ac97)
3454 struct snd_kcontrol *kctl;
3457 if (snd_ac97_try_bit(ac97, 0x5a, 9)) {
3458 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1);
3462 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1);
3466 /* There is already a misnamed master switch. Rename it. */
3467 kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
3471 snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
3473 err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
3474 kctl->tlv.p, follower_vols_vt1616);
3478 err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
3479 NULL, follower_sws_vt1616);
3486 static const struct snd_ac97_build_ops patch_vt1616_ops = {
3487 .build_specific = patch_vt1616_specific
3490 static int patch_vt1616(struct snd_ac97 * ac97)
3492 ac97->build_ops = &patch_vt1616_ops;
3501 * unfortunately, the vt1617a stashes the twiddlers required for
3502 * noodling the i/o jacks on 2 different regs. that means that we can't
3503 * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
3506 * NB: this is absolutely and utterly different from the vt1618. dunno
3510 /* copied from ac97_surround_jack_mode_info() */
3511 static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
3512 struct snd_ctl_elem_info *uinfo)
3514 /* ordering in this list reflects vt1617a docs for Reg 20 and
3515 * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
3516 * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
3517 * counter-intuitive */
3519 static const char * const texts[] = {"LineIn Mic1", "LineIn Mic1 Mic3",
3520 "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
3521 "LineIn Mic2", "LineIn Mic2 Mic1",
3522 "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
3524 return snd_ctl_enum_info(uinfo, 1, 8, texts);
3527 static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
3528 struct snd_ctl_elem_value *ucontrol)
3530 ushort usSM51, usMS;
3532 struct snd_ac97 *pac97;
3534 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3536 /* grab our desired bits, then mash them together in a manner
3537 * consistent with Table 6 on page 17 in the 1617a docs */
3539 usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
3540 usMS = snd_ac97_read(pac97, 0x20) >> 8;
3542 ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
3547 static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
3548 struct snd_ctl_elem_value *ucontrol)
3550 ushort usSM51, usMS, usReg;
3552 struct snd_ac97 *pac97;
3554 pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
3556 usSM51 = ucontrol->value.enumerated.item[0] >> 1;
3557 usMS = ucontrol->value.enumerated.item[0] & 1;
3559 /* push our values into the register - consider that things will be left
3560 * in a funky state if the write fails */
3562 usReg = snd_ac97_read(pac97, 0x7a);
3563 snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
3564 usReg = snd_ac97_read(pac97, 0x20);
3565 snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8));
3570 static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
3572 AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
3574 * These are used to enable/disable surround sound on motherboards
3575 * that have 3 bidirectional analog jacks
3578 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3579 .name = "Smart 5.1 Select",
3580 .info = snd_ac97_vt1617a_smart51_info,
3581 .get = snd_ac97_vt1617a_smart51_get,
3582 .put = snd_ac97_vt1617a_smart51_put,
3586 static int patch_vt1617a(struct snd_ac97 * ac97)
3591 /* we choose to not fail out at this point, but we tell the
3592 caller when we return */
3594 err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
3595 ARRAY_SIZE(snd_ac97_controls_vt1617a));
3597 /* bring analog power consumption to normal by turning off the
3598 * headphone amplifier, like WinXP driver for EPIA SP
3600 /* We need to check the bit before writing it.
3601 * On some (many?) hardwares, setting bit actually clears it!
3603 val = snd_ac97_read(ac97, 0x5c);
3605 snd_ac97_write_cache(ac97, 0x5c, 0x20);
3607 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
3608 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3609 ac97->build_ops = &patch_vt1616_ops;
3614 /* VIA VT1618 8 CHANNEL AC97 CODEC
3616 * VIA implements 'Smart 5.1' completely differently on the 1618 than
3617 * it does on the 1617a. awesome! They seem to have sourced this
3618 * particular revision of the technology from somebody else, it's
3619 * called Universal Audio Jack and it shows up on some other folk's chips
3622 * ordering in this list reflects vt1618 docs for Reg 60h and
3623 * the block diagram, DACs are as follows:
3626 * OUT_1 -> Surround,
3629 * Unlike the 1617a, each OUT has a consistent set of mappings
3630 * for all bitpatterns other than 00:
3636 * Special Case of 00:
3638 * OUT_0 Mixed Output
3642 * I have no idea what the hell Reserved does, but on an MSI
3643 * CN700T, i have to set it to get 5.1 output - YMMV, bad
3646 * If other chips use Universal Audio Jack, then this code might be applicable
3650 struct vt1618_uaj_item {
3651 unsigned short mask;
3652 unsigned short shift;
3653 const char * const items[4];
3656 /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */
3658 static const struct vt1618_uaj_item vt1618_uaj[3] = {
3664 "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
3672 "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
3680 "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
3685 static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
3686 struct snd_ctl_elem_info *uinfo)
3688 return snd_ctl_enum_info(uinfo, 1, 4,
3689 vt1618_uaj[kcontrol->private_value].items);
3692 /* All of the vt1618 Universal Audio Jack twiddlers are on
3693 * Vendor Defined Register 0x60, page 0. The bits, and thus
3694 * the mask, are the only thing that changes
3696 static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
3697 struct snd_ctl_elem_value *ucontrol)
3699 unsigned short datpag, uaj;
3700 struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
3702 mutex_lock(&pac97->page_mutex);
3704 datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
3705 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
3707 uaj = snd_ac97_read(pac97, 0x60) &
3708 vt1618_uaj[kcontrol->private_value].mask;
3710 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
3711 mutex_unlock(&pac97->page_mutex);
3713 ucontrol->value.enumerated.item[0] = uaj >>
3714 vt1618_uaj[kcontrol->private_value].shift;
3719 static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
3720 struct snd_ctl_elem_value *ucontrol)
3722 return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
3723 vt1618_uaj[kcontrol->private_value].mask,
3724 ucontrol->value.enumerated.item[0]<<
3725 vt1618_uaj[kcontrol->private_value].shift,
3729 /* config aux in jack - not found on 3 jack motherboards or soundcards */
3731 static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
3732 struct snd_ctl_elem_info *uinfo)
3734 static const char * const txt_aux[] = {"Aux In", "Back Surr Out"};
3736 return snd_ctl_enum_info(uinfo, 1, 2, txt_aux);
3739 static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
3740 struct snd_ctl_elem_value *ucontrol)
3742 ucontrol->value.enumerated.item[0] =
3743 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
3747 static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
3748 struct snd_ctl_elem_value *ucontrol)
3750 /* toggle surround rear dac power */
3752 snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
3753 ucontrol->value.enumerated.item[0] << 3);
3755 /* toggle aux in surround rear out jack */
3757 return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
3758 ucontrol->value.enumerated.item[0] << 3);
3761 static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
3762 AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
3763 AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
3764 AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
3765 AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
3766 AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
3767 AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
3769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3770 .name = "Speaker Jack Mode",
3771 .info = snd_ac97_vt1618_UAJ_info,
3772 .get = snd_ac97_vt1618_UAJ_get,
3773 .put = snd_ac97_vt1618_UAJ_put,
3777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3778 .name = "Line Jack Mode",
3779 .info = snd_ac97_vt1618_UAJ_info,
3780 .get = snd_ac97_vt1618_UAJ_get,
3781 .put = snd_ac97_vt1618_UAJ_put,
3785 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3786 .name = "Mic Jack Mode",
3787 .info = snd_ac97_vt1618_UAJ_info,
3788 .get = snd_ac97_vt1618_UAJ_get,
3789 .put = snd_ac97_vt1618_UAJ_put,
3793 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3794 .name = "Aux Jack Mode",
3795 .info = snd_ac97_vt1618_aux_info,
3796 .get = snd_ac97_vt1618_aux_get,
3797 .put = snd_ac97_vt1618_aux_put,
3801 static int patch_vt1618(struct snd_ac97 *ac97)
3803 return patch_build_controls(ac97, snd_ac97_controls_vt1618,
3804 ARRAY_SIZE(snd_ac97_controls_vt1618));
3809 static void it2646_update_jacks(struct snd_ac97 *ac97)
3811 /* shared Line-In / Surround Out */
3812 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
3813 is_shared_surrout(ac97) ? (1<<9) : 0);
3814 /* shared Mic / Center/LFE Out */
3815 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
3816 is_shared_clfeout(ac97) ? (1<<10) : 0);
3819 static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
3820 AC97_SURROUND_JACK_MODE_CTL,
3821 AC97_CHANNEL_MODE_CTL,
3824 static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
3825 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
3826 AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
3827 AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
3830 static int patch_it2646_specific(struct snd_ac97 * ac97)
3833 err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646));
3836 err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646));
3842 static const struct snd_ac97_build_ops patch_it2646_ops = {
3843 .build_specific = patch_it2646_specific,
3844 .update_jacks = it2646_update_jacks
3847 static int patch_it2646(struct snd_ac97 * ac97)
3849 ac97->build_ops = &patch_it2646_ops;
3850 /* full DAC volume */
3851 snd_ac97_write_cache(ac97, 0x5E, 0x0808);
3852 snd_ac97_write_cache(ac97, 0x7A, 0x0808);
3860 #define AC97_SI3036_CHIP_ID 0x5a
3861 #define AC97_SI3036_LINE_CFG 0x5c
3863 static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
3864 AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
3867 static int patch_si3036_specific(struct snd_ac97 * ac97)
3870 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) {
3871 err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97));
3878 static const struct snd_ac97_build_ops patch_si3036_ops = {
3879 .build_specific = patch_si3036_specific,
3882 static int mpatch_si3036(struct snd_ac97 * ac97)
3884 ac97->build_ops = &patch_si3036_ops;
3885 snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
3886 snd_ac97_write_cache(ac97, 0x68, 0);
3893 * We use a static resolution table since LM4550 codec cannot be
3894 * properly autoprobed to determine the resolution via
3895 * check_volume_resolution().
3898 static const struct snd_ac97_res_table lm4550_restbl[] = {
3899 { AC97_MASTER, 0x1f1f },
3900 { AC97_HEADPHONE, 0x1f1f },
3901 { AC97_MASTER_MONO, 0x001f },
3902 { AC97_PC_BEEP, 0x001f }, /* LSB is ignored */
3903 { AC97_PHONE, 0x001f },
3904 { AC97_MIC, 0x001f },
3905 { AC97_LINE, 0x1f1f },
3906 { AC97_CD, 0x1f1f },
3907 { AC97_VIDEO, 0x1f1f },
3908 { AC97_AUX, 0x1f1f },
3909 { AC97_PCM, 0x1f1f },
3910 { AC97_REC_GAIN, 0x0f0f },
3911 { } /* terminator */
3914 static int patch_lm4550(struct snd_ac97 *ac97)
3916 ac97->res_table = lm4550_restbl;