1
2
3
4
5
6
7
8
9
10
11#include "ac97_local.h"
12#include "ac97_patch.h"
13
14
15
16
17
18static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
19 const char *name);
20static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
21 const unsigned int *tlv,
22 const char * const *followers);
23
24
25
26
27
28static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count)
29{
30 int idx, err;
31
32 for (idx = 0; idx < count; idx++) {
33 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97));
34 if (err < 0)
35 return err;
36 }
37 return 0;
38}
39
40
41static void reset_tlv(struct snd_ac97 *ac97, const char *name,
42 const unsigned int *tlv)
43{
44 struct snd_ctl_elem_id sid;
45 struct snd_kcontrol *kctl;
46 memset(&sid, 0, sizeof(sid));
47 strcpy(sid.name, name);
48 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
49 kctl = snd_ctl_find_id(ac97->bus->card, &sid);
50 if (kctl && kctl->tlv.p)
51 kctl->tlv.p = tlv;
52}
53
54
55static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
56{
57 unsigned short page_save;
58 int ret;
59
60 mutex_lock(&ac97->page_mutex);
61 page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
62 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
63 ret = snd_ac97_update_bits(ac97, reg, mask, value);
64 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
65 mutex_unlock(&ac97->page_mutex);
66 return ret;
67}
68
69
70
71
72static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
73{
74 static const char * const texts[] = { "Shared", "Independent" };
75
76 return snd_ctl_enum_info(uinfo, 1, 2, texts);
77}
78
79static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
80{
81 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
82
83 ucontrol->value.enumerated.item[0] = ac97->indep_surround;
84 return 0;
85}
86
87static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
88{
89 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
90 unsigned char indep = !!ucontrol->value.enumerated.item[0];
91
92 if (indep != ac97->indep_surround) {
93 ac97->indep_surround = indep;
94 if (ac97->build_ops->update_jacks)
95 ac97->build_ops->update_jacks(ac97);
96 return 1;
97 }
98 return 0;
99}
100
101static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
102{
103 static const char * const texts[] = { "2ch", "4ch", "6ch", "8ch" };
104
105 return snd_ctl_enum_info(uinfo, 1, kcontrol->private_value, texts);
106}
107
108static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
109{
110 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
111
112 ucontrol->value.enumerated.item[0] = ac97->channel_mode;
113 return 0;
114}
115
116static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
117{
118 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
119 unsigned char mode = ucontrol->value.enumerated.item[0];
120
121 if (mode >= kcontrol->private_value)
122 return -EINVAL;
123
124 if (mode != ac97->channel_mode) {
125 ac97->channel_mode = mode;
126 if (ac97->build_ops->update_jacks)
127 ac97->build_ops->update_jacks(ac97);
128 return 1;
129 }
130 return 0;
131}
132
133#define AC97_SURROUND_JACK_MODE_CTL \
134 { \
135 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
136 .name = "Surround Jack Mode", \
137 .info = ac97_surround_jack_mode_info, \
138 .get = ac97_surround_jack_mode_get, \
139 .put = ac97_surround_jack_mode_put, \
140 }
141
142#define AC97_CHANNEL_MODE_CTL \
143 { \
144 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
145 .name = "Channel Mode", \
146 .info = ac97_channel_mode_info, \
147 .get = ac97_channel_mode_get, \
148 .put = ac97_channel_mode_put, \
149 .private_value = 3, \
150 }
151
152#define AC97_CHANNEL_MODE_4CH_CTL \
153 { \
154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
155 .name = "Channel Mode", \
156 .info = ac97_channel_mode_info, \
157 .get = ac97_channel_mode_get, \
158 .put = ac97_channel_mode_put, \
159 .private_value = 2, \
160 }
161
162#define AC97_CHANNEL_MODE_8CH_CTL \
163 { \
164 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
165 .name = "Channel Mode", \
166 .info = ac97_channel_mode_info, \
167 .get = ac97_channel_mode_get, \
168 .put = ac97_channel_mode_put, \
169 .private_value = 4, \
170 }
171
172static inline int is_surround_on(struct snd_ac97 *ac97)
173{
174 return ac97->channel_mode >= 1;
175}
176
177static inline int is_clfe_on(struct snd_ac97 *ac97)
178{
179 return ac97->channel_mode >= 2;
180}
181
182
183static inline int is_shared_surrout(struct snd_ac97 *ac97)
184{
185 return !ac97->indep_surround && is_surround_on(ac97);
186}
187
188
189static inline int is_shared_clfeout(struct snd_ac97 *ac97)
190{
191 return !ac97->indep_surround && is_clfe_on(ac97);
192}
193
194
195static inline int is_shared_linein(struct snd_ac97 *ac97)
196{
197 return !ac97->indep_surround && !is_surround_on(ac97);
198}
199
200
201static inline int is_shared_micin(struct snd_ac97 *ac97)
202{
203 return !ac97->indep_surround && !is_clfe_on(ac97);
204}
205
206static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
207{
208 return is_surround_on(ac97);
209}
210
211
212
213
214
215
216
217static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
218 struct snd_ctl_elem_info *uinfo)
219{
220 static const char * const texts[3] = {
221 "Standard", "Small", "Smaller"
222 };
223
224 return snd_ctl_enum_info(uinfo, 1, 3, texts);
225}
226
227static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
228 struct snd_ctl_elem_value *ucontrol)
229{
230 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
231 unsigned short val;
232
233 val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
234 val = (val >> 10) & 3;
235 if (val > 0)
236 val--;
237 ucontrol->value.enumerated.item[0] = val;
238 return 0;
239}
240
241static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243{
244 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
245 unsigned short val;
246
247 if (ucontrol->value.enumerated.item[0] > 2)
248 return -EINVAL;
249 val = (ucontrol->value.enumerated.item[0] + 1) << 10;
250 return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
251}
252
253static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
254{
255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
256 .name = "3D Control - Speaker",
257 .info = snd_ac97_ymf7x3_info_speaker,
258 .get = snd_ac97_ymf7x3_get_speaker,
259 .put = snd_ac97_ymf7x3_put_speaker,
260};
261
262
263
264static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_info *uinfo)
266{
267 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
268
269 return snd_ctl_enum_info(uinfo, 1, 2, texts);
270}
271
272static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
274{
275 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
276 unsigned short val;
277
278 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
279 ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
280 return 0;
281}
282
283static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_value *ucontrol)
285{
286 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
287 unsigned short val;
288
289 if (ucontrol->value.enumerated.item[0] > 1)
290 return -EINVAL;
291 val = ucontrol->value.enumerated.item[0] << 1;
292 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
293}
294
295static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
296{
297 struct snd_kcontrol *kctl;
298 int err;
299
300 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
301 err = snd_ctl_add(ac97->bus->card, kctl);
302 if (err < 0)
303 return err;
304 strcpy(kctl->id.name, "3D Control - Wide");
305 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
306 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
307 err = snd_ctl_add(ac97->bus->card,
308 snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
309 ac97));
310 if (err < 0)
311 return err;
312 snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
313 return 0;
314}
315
316static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
317{
318 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
319 AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
320 {
321 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
322 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
323 .info = snd_ac97_ymf7x3_spdif_source_info,
324 .get = snd_ac97_ymf7x3_spdif_source_get,
325 .put = snd_ac97_ymf7x3_spdif_source_put,
326 },
327 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
328 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
329};
330
331static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
332{
333 int err;
334
335 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
336 if (err < 0)
337 return err;
338 err = patch_build_controls(ac97,
339 snd_ac97_yamaha_ymf743_controls_spdif, 3);
340 if (err < 0)
341 return err;
342
343
344 snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
345 return 0;
346}
347
348static const struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
349 .build_spdif = patch_yamaha_ymf743_build_spdif,
350 .build_3d = patch_yamaha_ymf7x3_3d,
351};
352
353static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
354{
355 ac97->build_ops = &patch_yamaha_ymf743_ops;
356 ac97->caps |= AC97_BC_BASS_TREBLE;
357 ac97->caps |= 0x04 << 10;
358 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
359 ac97->ext_id |= AC97_EI_SPDIF;
360 return 0;
361}
362
363
364
365
366
367static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
368{
369 static const char * const texts[3] = { "Disabled", "Pin 43", "Pin 48" };
370
371 return snd_ctl_enum_info(uinfo, 1, 3, texts);
372}
373
374static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
375{
376 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
377 unsigned short val;
378
379 val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
380 ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
381 return 0;
382}
383
384static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
385{
386 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
387 unsigned short val;
388
389 if (ucontrol->value.enumerated.item[0] > 2)
390 return -EINVAL;
391 val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
392 (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
393 return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
394
395
396}
397
398static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
399 {
400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
401 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
402 .info = snd_ac97_ymf7x3_spdif_source_info,
403 .get = snd_ac97_ymf7x3_spdif_source_get,
404 .put = snd_ac97_ymf7x3_spdif_source_put,
405 },
406 {
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
409 .info = snd_ac97_ymf753_spdif_output_pin_info,
410 .get = snd_ac97_ymf753_spdif_output_pin_get,
411 .put = snd_ac97_ymf753_spdif_output_pin_put,
412 },
413 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
414 AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
415};
416
417static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
418{
419 int err;
420
421 err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif));
422 if (err < 0)
423 return err;
424 return 0;
425}
426
427static const struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
428 .build_3d = patch_yamaha_ymf7x3_3d,
429 .build_post_spdif = patch_yamaha_ymf753_post_spdif
430};
431
432static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
433{
434
435
436
437
438
439
440
441 ac97->build_ops = &patch_yamaha_ymf753_ops;
442 ac97->caps |= AC97_BC_BASS_TREBLE;
443 ac97->caps |= 0x04 << 10;
444 return 0;
445}
446
447
448
449
450
451
452
453static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = {
454AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
455AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
456};
457
458static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
459{
460
461
462
463
464 int err, i;
465
466 for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
467 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97));
468 if (err < 0)
469 return err;
470 }
471 snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
472 return 0;
473}
474
475static const struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
476 .build_specific = patch_wolfson_wm9703_specific,
477};
478
479static int patch_wolfson03(struct snd_ac97 * ac97)
480{
481 ac97->build_ops = &patch_wolfson_wm9703_ops;
482 return 0;
483}
484
485static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = {
486AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
487AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
488AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
489AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
490AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
491AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
492};
493
494static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
495{
496 int err, i;
497 for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
498 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97));
499 if (err < 0)
500 return err;
501 }
502
503 snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
504 return 0;
505}
506
507static const struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
508 .build_specific = patch_wolfson_wm9704_specific,
509};
510
511static int patch_wolfson04(struct snd_ac97 * ac97)
512{
513
514 ac97->build_ops = &patch_wolfson_wm9704_ops;
515 return 0;
516}
517
518static int patch_wolfson05(struct snd_ac97 * ac97)
519{
520
521 ac97->build_ops = &patch_wolfson_wm9703_ops;
522#ifdef CONFIG_TOUCHSCREEN_WM9705
523
524 ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
525#endif
526 return 0;
527}
528
529static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
530static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
531static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
532static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
533static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
534static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
535static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
536static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
537static const char* wm9711_rec_sel[] =
538 {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
539static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
540
541static const struct ac97_enum wm9711_enum[] = {
542AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
543AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
544AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
545AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
546AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
547AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
548AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
549AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
550AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
551AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
552};
553
554static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = {
555AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
556AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
557AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
558AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
559AC97_ENUM("ALC Function", wm9711_enum[0]),
560AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
561AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
562AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
563AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
564AC97_ENUM("ALC NG Type", wm9711_enum[9]),
565AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
566
567AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
568AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
569AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
570AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
571
572AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
573AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
574AC97_ENUM("Out3 Mux", wm9711_enum[2]),
575AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
576AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
577
578AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
579AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
580AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
581AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
582AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
583AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
584
585AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
586AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
587AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
588AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
589AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
590AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
591
592AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
593AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
594
595AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
596AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
597AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
598
599AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
600AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
601AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
602
603AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
604AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
605AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
606AC97_ENUM("Capture Select", wm9711_enum[8]),
607
608AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
609AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
610
611AC97_ENUM("Bass Control", wm9711_enum[5]),
612AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
613AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
614AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
615
616AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
617AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
618AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
619AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
620
621AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
622AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
623AC97_ENUM("Mic Select Source", wm9711_enum[7]),
624AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
625AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
626AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
627
628AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
629AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
630AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
631AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
632};
633
634static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
635{
636 int err, i;
637
638 for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
639 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97));
640 if (err < 0)
641 return err;
642 }
643 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808);
644 snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808);
645 snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808);
646 snd_ac97_write_cache(ac97, AC97_AUX, 0x0808);
647 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
648 snd_ac97_write_cache(ac97, AC97_CD, 0x0000);
649 return 0;
650}
651
652static const struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
653 .build_specific = patch_wolfson_wm9711_specific,
654};
655
656static int patch_wolfson11(struct snd_ac97 * ac97)
657{
658
659 ac97->build_ops = &patch_wolfson_wm9711_ops;
660
661 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
662 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
663
664 return 0;
665}
666
667static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
668static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
669static const char* wm9713_rec_src[] =
670 {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix",
671 "Mono Mix", "Zh"};
672static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
673static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
674static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
675static const char* wm9713_spk_pga[] =
676 {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
677static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
678static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
679static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
680static const char* wm9713_dac_inv[] =
681 {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R",
682 "Headphone Mix Mono", "NC", "Vmid"};
683static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
684static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
685
686static const struct ac97_enum wm9713_enum[] = {
687AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
688AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
689AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
690AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
691AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
692AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
693AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
694AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
695AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
696AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
697AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
698AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
699AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
700AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
701};
702
703static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
704AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
705AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
706AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
707AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
708
709AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
710AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
711AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
712AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
713
714AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
715AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
716AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
717AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
718AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
719AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
720AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
721
722AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
723AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
724AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
725AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
726
727AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
728AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
729AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
730AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
731AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
732AC97_ENUM("Capture Select", wm9713_enum[3]),
733
734AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
735AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
736AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
737AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
738AC97_ENUM("ALC Function", wm9713_enum[5]),
739AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
740AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
741AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
742AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
743AC97_ENUM("ALC NG Type", wm9713_enum[13]),
744AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
745
746AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
747AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
748AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
749AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
750AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
751AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
752
753AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
754AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
755AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
756AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
757AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
758AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
759
760AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
761AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
762AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
763AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
764AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
765AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
766
767AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
768AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
769AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
770AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
771AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
772AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
773
774AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
775AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
776AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
777AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
778AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
779AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
780
781AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
782AC97_ENUM("Master Input Mux", wm9713_enum[7]),
783AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
784AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
785AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
786
787AC97_ENUM("Bass Control", wm9713_enum[12]),
788AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
789AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
790AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
791AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
792AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
793};
794
795static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {
796AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
797AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
798AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
799AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
800};
801
802static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
803{
804 int err, i;
805
806 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
807 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97));
808 if (err < 0)
809 return err;
810 }
811 return 0;
812}
813
814static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
815{
816 int err, i;
817
818 for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
819 err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97));
820 if (err < 0)
821 return err;
822 }
823 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
824 snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
825 snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
826 snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
827 snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
828 snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
829 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
830 return 0;
831}
832
833#ifdef CONFIG_PM
834static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
835{
836 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
837 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
838}
839
840static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
841{
842 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
843 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
844 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
845}
846#endif
847
848static const struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
849 .build_specific = patch_wolfson_wm9713_specific,
850 .build_3d = patch_wolfson_wm9713_3d,
851#ifdef CONFIG_PM
852 .suspend = patch_wolfson_wm9713_suspend,
853 .resume = patch_wolfson_wm9713_resume
854#endif
855};
856
857static int patch_wolfson13(struct snd_ac97 * ac97)
858{
859
860 ac97->build_ops = &patch_wolfson_wm9713_ops;
861
862 ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
863 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
864 AC97_HAS_NO_STD_PCM;
865 ac97->scaps &= ~AC97_SCAP_MODEM;
866
867 snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
868 snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
869 snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
870
871 return 0;
872}
873
874
875
876
877static int patch_tritech_tr28028(struct snd_ac97 * ac97)
878{
879 snd_ac97_write_cache(ac97, 0x26, 0x0300);
880 snd_ac97_write_cache(ac97, 0x26, 0x0000);
881 snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
882 snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
883 return 0;
884}
885
886
887
888
889static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
890{
891 struct snd_kcontrol *kctl;
892 int err;
893
894 err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97));
895 if (err < 0)
896 return err;
897 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
898 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
899 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
900 return 0;
901}
902
903static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
904{
905 struct snd_kcontrol *kctl;
906 int err;
907
908 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
909 err = snd_ctl_add(ac97->bus->card, kctl);
910 if (err < 0)
911 return err;
912 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
913 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
914 kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
915 err = snd_ctl_add(ac97->bus->card, kctl);
916 if (err < 0)
917 return err;
918 strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
919 kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
920 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
921 return 0;
922}
923
924static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
925AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch",
926 AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
927
928
929static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
930AC97_SINGLE("Surround Phase Inversion Playback Switch",
931 AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
932
933static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
934AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
935AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
936};
937
938static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
939{
940 int err;
941
942 snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
943 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) {
944 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1);
945 if (err < 0)
946 return err;
947 }
948 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) {
949 err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1);
950 if (err < 0)
951 return err;
952 }
953 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) {
954 err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1);
955 if (err < 0)
956 return err;
957 }
958 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) {
959 err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1);
960 if (err < 0)
961 return err;
962 }
963 return 0;
964}
965
966static const struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
967 .build_3d = patch_sigmatel_stac9700_3d,
968 .build_specific = patch_sigmatel_stac97xx_specific
969};
970
971static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
972{
973 ac97->build_ops = &patch_sigmatel_stac9700_ops;
974 return 0;
975}
976
977static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
978{
979 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
980 int err;
981
982 mutex_lock(&ac97->page_mutex);
983 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
984 err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
985 (ucontrol->value.integer.value[0] & 1) << 4);
986 snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
987 mutex_unlock(&ac97->page_mutex);
988 return err;
989}
990
991static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
992 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
993 .name = "Sigmatel Output Bias Switch",
994 .info = snd_ac97_info_volsw,
995 .get = snd_ac97_get_volsw,
996 .put = snd_ac97_stac9708_put_bias,
997 .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
998};
999
1000static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
1001{
1002 int err;
1003
1004
1005 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
1006
1007 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
1008 err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1);
1009 if (err < 0)
1010 return err;
1011 return patch_sigmatel_stac97xx_specific(ac97);
1012}
1013
1014static const struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
1015 .build_3d = patch_sigmatel_stac9708_3d,
1016 .build_specific = patch_sigmatel_stac9708_specific
1017};
1018
1019static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
1020{
1021 unsigned int codec72, codec6c;
1022
1023 ac97->build_ops = &patch_sigmatel_stac9708_ops;
1024 ac97->caps |= 0x10;
1025
1026 codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
1027 codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
1028
1029 if ((codec72==0) && (codec6c==0)) {
1030 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1031 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
1032 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1033 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
1034 } else if ((codec72==0x8000) && (codec6c==0)) {
1035 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1036 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
1037 snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
1038 } else if ((codec72==0x8000) && (codec6c==0x0080)) {
1039
1040 }
1041 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1042 return 0;
1043}
1044
1045static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
1046{
1047 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1048 if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
1049
1050 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1051 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
1052 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1053 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1054 }
1055 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1056 return 0;
1057}
1058
1059static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
1060{
1061
1062 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1063 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1064 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000);
1065 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1066 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1067 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1068 return 0;
1069}
1070
1071static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
1072{
1073
1074 ac97->build_ops = &patch_sigmatel_stac9700_ops;
1075 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
1076 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000);
1077 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
1078 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
1079 snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
1080 return 0;
1081}
1082
1083static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1084{
1085 static const char * const texts[5] = {
1086 "Input/Disabled", "Front Output",
1087 "Rear Output", "Center/LFE Output", "Mixer Output" };
1088
1089 return snd_ctl_enum_info(uinfo, 1, 5, texts);
1090}
1091
1092static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1093{
1094 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1095 int shift = kcontrol->private_value;
1096 unsigned short val;
1097
1098 val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
1099 if (!(val & 4))
1100 ucontrol->value.enumerated.item[0] = 0;
1101 else
1102 ucontrol->value.enumerated.item[0] = 1 + (val & 3);
1103 return 0;
1104}
1105
1106static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1107{
1108 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1109 int shift = kcontrol->private_value;
1110 unsigned short val;
1111
1112 if (ucontrol->value.enumerated.item[0] > 4)
1113 return -EINVAL;
1114 if (ucontrol->value.enumerated.item[0] == 0)
1115 val = 0;
1116 else
1117 val = 4 | (ucontrol->value.enumerated.item[0] - 1);
1118 return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
1119 7 << shift, val << shift, 0);
1120}
1121
1122static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1123{
1124 static const char * const texts[7] = {
1125 "Mic2 Jack", "Mic1 Jack", "Line In Jack",
1126 "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
1127
1128 return snd_ctl_enum_info(uinfo, 1, 7, texts);
1129}
1130
1131static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1132{
1133 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1134 int shift = kcontrol->private_value;
1135 unsigned short val;
1136
1137 val = ac97->regs[AC97_SIGMATEL_INSEL];
1138 ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
1139 return 0;
1140}
1141
1142static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1143{
1144 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1145 int shift = kcontrol->private_value;
1146
1147 return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
1148 ucontrol->value.enumerated.item[0] << shift, 0);
1149}
1150
1151static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1152{
1153 static const char * const texts[3] = {
1154 "None", "Front Jack", "Rear Jack"
1155 };
1156
1157 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1158}
1159
1160static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1161{
1162 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1163
1164 ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
1165 return 0;
1166}
1167
1168static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1169{
1170 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1171
1172 return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
1173 ucontrol->value.enumerated.item[0], 0);
1174}
1175
1176#define STAC9758_OUTPUT_JACK(xname, shift) \
1177{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1178 .info = snd_ac97_stac9758_output_jack_info, \
1179 .get = snd_ac97_stac9758_output_jack_get, \
1180 .put = snd_ac97_stac9758_output_jack_put, \
1181 .private_value = shift }
1182#define STAC9758_INPUT_JACK(xname, shift) \
1183{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1184 .info = snd_ac97_stac9758_input_jack_info, \
1185 .get = snd_ac97_stac9758_input_jack_get, \
1186 .put = snd_ac97_stac9758_input_jack_put, \
1187 .private_value = shift }
1188static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
1189 STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
1190 STAC9758_OUTPUT_JACK("LineIn Jack", 4),
1191 STAC9758_OUTPUT_JACK("Front Jack", 7),
1192 STAC9758_OUTPUT_JACK("Rear Jack", 10),
1193 STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
1194 STAC9758_INPUT_JACK("Mic Input Source", 0),
1195 STAC9758_INPUT_JACK("Line Input Source", 8),
1196 {
1197 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1198 .name = "Headphone Amp",
1199 .info = snd_ac97_stac9758_phonesel_info,
1200 .get = snd_ac97_stac9758_phonesel_get,
1201 .put = snd_ac97_stac9758_phonesel_put
1202 },
1203 AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
1204 AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
1205};
1206
1207static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
1208{
1209 int err;
1210
1211 err = patch_sigmatel_stac97xx_specific(ac97);
1212 if (err < 0)
1213 return err;
1214 err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
1215 ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
1216 if (err < 0)
1217 return err;
1218
1219 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
1220
1221
1222
1223 snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
1224
1225
1226 return 0;
1227}
1228
1229static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
1230 .build_3d = patch_sigmatel_stac9700_3d,
1231 .build_specific = patch_sigmatel_stac9758_specific
1232};
1233
1234static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
1235{
1236 static const unsigned short regs[4] = {
1237 AC97_SIGMATEL_OUTSEL,
1238 AC97_SIGMATEL_IOMISC,
1239 AC97_SIGMATEL_INSEL,
1240 AC97_SIGMATEL_VARIOUS
1241 };
1242 static const unsigned short def_regs[4] = {
1243 0xd794,
1244 0x2001,
1245 0x0201,
1246 0x0040
1247 };
1248 static const unsigned short m675_regs[4] = {
1249 0xfc70,
1250 0x2102,
1251 0x0203,
1252 0x0041
1253 };
1254 const unsigned short *pregs = def_regs;
1255 int i;
1256
1257
1258 if (ac97->pci &&
1259 ac97->subsystem_vendor == 0x107b &&
1260 ac97->subsystem_device == 0x0601)
1261 pregs = m675_regs;
1262
1263
1264 ac97->build_ops = &patch_sigmatel_stac9758_ops;
1265
1266 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
1267 for (i = 0; i < 4; i++)
1268 snd_ac97_write_cache(ac97, regs[i], pregs[i]);
1269
1270 ac97->flags |= AC97_STEREO_MUTES;
1271 return 0;
1272}
1273
1274
1275
1276
1277static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
1278 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
1279 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
1280};
1281
1282static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
1283{
1284 int err;
1285
1286
1287 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1288 if (err < 0)
1289 return err;
1290
1291 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1);
1292 if (err < 0)
1293 return err;
1294 switch (ac97->id & AC97_ID_CS_MASK) {
1295 case AC97_ID_CS4205:
1296 err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1);
1297 if (err < 0)
1298 return err;
1299 break;
1300 }
1301
1302
1303 snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
1304 return 0;
1305}
1306
1307static const struct snd_ac97_build_ops patch_cirrus_ops = {
1308 .build_spdif = patch_cirrus_build_spdif
1309};
1310
1311static int patch_cirrus_spdif(struct snd_ac97 * ac97)
1312{
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 ac97->build_ops = &patch_cirrus_ops;
1325 ac97->flags |= AC97_CS_SPDIF;
1326 ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
1327 ac97->ext_id |= AC97_EI_SPDIF;
1328 snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
1329 return 0;
1330}
1331
1332static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
1333{
1334
1335 ac97->flags |= AC97_HAS_PC_BEEP;
1336
1337 return patch_cirrus_spdif(ac97);
1338}
1339
1340
1341
1342
1343static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
1344 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
1345};
1346
1347static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
1348{
1349 int err;
1350
1351
1352 err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
1353 if (err < 0)
1354 return err;
1355
1356 err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1);
1357 if (err < 0)
1358 return err;
1359
1360
1361 snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
1362 snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
1363 return 0;
1364}
1365
1366static const struct snd_ac97_build_ops patch_conexant_ops = {
1367 .build_spdif = patch_conexant_build_spdif
1368};
1369
1370static int patch_conexant(struct snd_ac97 * ac97)
1371{
1372 ac97->build_ops = &patch_conexant_ops;
1373 ac97->flags |= AC97_CX_SPDIF;
1374 ac97->ext_id |= AC97_EI_SPDIF;
1375 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
1376 return 0;
1377}
1378
1379static int patch_cx20551(struct snd_ac97 *ac97)
1380{
1381 snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
1382 return 0;
1383}
1384
1385
1386
1387
1388#ifdef CONFIG_PM
1389static void ad18xx_resume(struct snd_ac97 *ac97)
1390{
1391 static const unsigned short setup_regs[] = {
1392 AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
1393 };
1394 int i, codec;
1395
1396 for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
1397 unsigned short reg = setup_regs[i];
1398 if (test_bit(reg, ac97->reg_accessed)) {
1399 snd_ac97_write(ac97, reg, ac97->regs[reg]);
1400 snd_ac97_read(ac97, reg);
1401 }
1402 }
1403
1404 if (! (ac97->flags & AC97_AD_MULTI))
1405
1406 snd_ac97_restore_status(ac97);
1407 else {
1408
1409 for (codec = 0; codec < 3; codec++) {
1410 if (! ac97->spec.ad18xx.id[codec])
1411 continue;
1412
1413 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1414 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1415 ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
1416 }
1417
1418 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1419
1420
1421 for (i = 2; i < 0x7c ; i += 2) {
1422 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
1423 continue;
1424 if (test_bit(i, ac97->reg_accessed)) {
1425
1426 if (i == AC97_PCM) {
1427 for (codec = 0; codec < 3; codec++) {
1428 if (! ac97->spec.ad18xx.id[codec])
1429 continue;
1430
1431 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1432 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
1433
1434 ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
1435 }
1436
1437 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1438 continue;
1439 } else if (i == AC97_AD_TEST ||
1440 i == AC97_AD_CODEC_CFG ||
1441 i == AC97_AD_SERIAL_CFG)
1442 continue;
1443 }
1444 snd_ac97_write(ac97, i, ac97->regs[i]);
1445 snd_ac97_read(ac97, i);
1446 }
1447 }
1448
1449 snd_ac97_restore_iec958(ac97);
1450}
1451
1452static void ad1888_resume(struct snd_ac97 *ac97)
1453{
1454 ad18xx_resume(ac97);
1455 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
1456}
1457
1458#endif
1459
1460static const struct snd_ac97_res_table ad1819_restbl[] = {
1461 { AC97_PHONE, 0x9f1f },
1462 { AC97_MIC, 0x9f1f },
1463 { AC97_LINE, 0x9f1f },
1464 { AC97_CD, 0x9f1f },
1465 { AC97_VIDEO, 0x9f1f },
1466 { AC97_AUX, 0x9f1f },
1467 { AC97_PCM, 0x9f1f },
1468 { }
1469};
1470
1471static int patch_ad1819(struct snd_ac97 * ac97)
1472{
1473 unsigned short scfg;
1474
1475
1476 scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1477 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000);
1478 ac97->res_table = ad1819_restbl;
1479 return 0;
1480}
1481
1482static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
1483{
1484 unsigned short val;
1485
1486
1487 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
1488 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
1489 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1490 if ((val & 0xff40) != 0x5340)
1491 return 0;
1492 ac97->spec.ad18xx.unchained[idx] = mask;
1493 ac97->spec.ad18xx.id[idx] = val;
1494 ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
1495 return mask;
1496}
1497
1498static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
1499{
1500 static const int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
1501 unsigned short val;
1502
1503 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
1504 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004);
1505 val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
1506 if ((val & 0xff40) != 0x5340)
1507 return 0;
1508 if (codec_bits)
1509 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
1510 ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
1511 ac97->spec.ad18xx.id[idx] = val;
1512 ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
1513 return 1;
1514}
1515
1516static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
1517{
1518
1519 if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
1520 cidx1 = -1;
1521 if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
1522 cidx2 = -1;
1523 if (cidx1 < 0 && cidx2 < 0)
1524 return;
1525
1526 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
1527 ac97->spec.ad18xx.unchained[unchained_idx]);
1528 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002);
1529 ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
1530 if (cidx1 >= 0) {
1531 if (cidx2 < 0)
1532 patch_ad1881_chained1(ac97, cidx1, 0);
1533 else if (patch_ad1881_chained1(ac97, cidx1, 0x0006))
1534 patch_ad1881_chained1(ac97, cidx2, 0);
1535 else if (patch_ad1881_chained1(ac97, cidx2, 0x0006))
1536 patch_ad1881_chained1(ac97, cidx1, 0);
1537 } else if (cidx2 >= 0) {
1538 patch_ad1881_chained1(ac97, cidx2, 0);
1539 }
1540}
1541
1542static const struct snd_ac97_build_ops patch_ad1881_build_ops = {
1543#ifdef CONFIG_PM
1544 .resume = ad18xx_resume
1545#endif
1546};
1547
1548static int patch_ad1881(struct snd_ac97 * ac97)
1549{
1550 static const char cfg_idxs[3][2] = {
1551 {2, 1},
1552 {0, 2},
1553 {0, 1}
1554 };
1555
1556
1557 unsigned short codecs[3];
1558 unsigned short val;
1559 int idx, num;
1560
1561 val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
1562 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
1563 codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
1564 codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
1565 codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
1566
1567 if (! (codecs[0] || codecs[1] || codecs[2]))
1568 goto __end;
1569
1570 for (idx = 0; idx < 3; idx++)
1571 if (ac97->spec.ad18xx.unchained[idx])
1572 patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
1573
1574 if (ac97->spec.ad18xx.id[1]) {
1575 ac97->flags |= AC97_AD_MULTI;
1576 ac97->scaps |= AC97_SCAP_SURROUND_DAC;
1577 }
1578 if (ac97->spec.ad18xx.id[2]) {
1579 ac97->flags |= AC97_AD_MULTI;
1580 ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
1581 }
1582
1583 __end:
1584
1585 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
1586
1587 for (idx = num = 0; idx < 3; idx++)
1588 if (ac97->spec.ad18xx.id[idx])
1589 num++;
1590 if (num == 1) {
1591
1592 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
1593 ac97->spec.ad18xx.codec_cfg[0] =
1594 ac97->spec.ad18xx.codec_cfg[1] =
1595 ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
1596 }
1597
1598 ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
1599 if (ac97->spec.ad18xx.id[0]) {
1600 ac97->id &= 0xffff0000;
1601 ac97->id |= ac97->spec.ad18xx.id[0];
1602 }
1603 ac97->build_ops = &patch_ad1881_build_ops;
1604 return 0;
1605}
1606
1607static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1608 AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
1609
1610 AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
1611 AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
1612 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1),
1613 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1),
1614};
1615
1616static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1617
1618static int patch_ad1885_specific(struct snd_ac97 * ac97)
1619{
1620 int err;
1621
1622 err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885));
1623 if (err < 0)
1624 return err;
1625 reset_tlv(ac97, "Headphone Playback Volume",
1626 db_scale_6bit_6db_max);
1627 return 0;
1628}
1629
1630static const struct snd_ac97_build_ops patch_ad1885_build_ops = {
1631 .build_specific = &patch_ad1885_specific,
1632#ifdef CONFIG_PM
1633 .resume = ad18xx_resume
1634#endif
1635};
1636
1637static int patch_ad1885(struct snd_ac97 * ac97)
1638{
1639 patch_ad1881(ac97);
1640
1641
1642
1643
1644 snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
1645
1646 ac97->build_ops = &patch_ad1885_build_ops;
1647 return 0;
1648}
1649
1650static int patch_ad1886_specific(struct snd_ac97 * ac97)
1651{
1652 reset_tlv(ac97, "Headphone Playback Volume",
1653 db_scale_6bit_6db_max);
1654 return 0;
1655}
1656
1657static const struct snd_ac97_build_ops patch_ad1886_build_ops = {
1658 .build_specific = &patch_ad1886_specific,
1659#ifdef CONFIG_PM
1660 .resume = ad18xx_resume
1661#endif
1662};
1663
1664static int patch_ad1886(struct snd_ac97 * ac97)
1665{
1666 patch_ad1881(ac97);
1667
1668
1669 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
1670 ac97->build_ops = &patch_ad1886_build_ops;
1671 return 0;
1672}
1673
1674
1675#define AC97_AD198X_MBC 0x0003
1676#define AC97_AD198X_MBC_20 0x0000
1677#define AC97_AD198X_MBC_10 0x0001
1678#define AC97_AD198X_MBC_30 0x0002
1679#define AC97_AD198X_VREFD 0x0004
1680#define AC97_AD198X_VREFH 0x0008
1681#define AC97_AD198X_VREF_0 0x000c
1682#define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1683#define AC97_AD198X_VREF_SHIFT 2
1684#define AC97_AD198X_SRU 0x0010
1685#define AC97_AD198X_LOSEL 0x0020
1686#define AC97_AD198X_2MIC 0x0040
1687#define AC97_AD198X_SPRD 0x0080
1688#define AC97_AD198X_DMIX0 0x0100
1689
1690#define AC97_AD198X_DMIX1 0x0200
1691#define AC97_AD198X_HPSEL 0x0400
1692#define AC97_AD198X_CLDIS 0x0800
1693#define AC97_AD198X_LODIS 0x1000
1694#define AC97_AD198X_MSPLT 0x2000
1695#define AC97_AD198X_AC97NC 0x4000
1696#define AC97_AD198X_DACZ 0x8000
1697
1698
1699#define AC97_AD1986_MBC 0x0003
1700#define AC97_AD1986_MBC_20 0x0000
1701#define AC97_AD1986_MBC_10 0x0001
1702#define AC97_AD1986_MBC_30 0x0002
1703#define AC97_AD1986_LISEL0 0x0004
1704#define AC97_AD1986_LISEL1 0x0008
1705#define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1706#define AC97_AD1986_LISEL_LI 0x0000
1707#define AC97_AD1986_LISEL_SURR 0x0004
1708#define AC97_AD1986_LISEL_MIC 0x0008
1709#define AC97_AD1986_SRU 0x0010
1710#define AC97_AD1986_SOSEL 0x0020
1711#define AC97_AD1986_2MIC 0x0040
1712#define AC97_AD1986_SPRD 0x0080
1713#define AC97_AD1986_DMIX0 0x0100
1714
1715#define AC97_AD1986_DMIX1 0x0200
1716#define AC97_AD1986_CLDIS 0x0800
1717#define AC97_AD1986_SODIS 0x1000
1718#define AC97_AD1986_MSPLT 0x2000
1719#define AC97_AD1986_AC97NC 0x4000
1720#define AC97_AD1986_DACZ 0x8000
1721
1722
1723#define AC97_AD_MISC2 0x70
1724
1725#define AC97_AD1986_CVREF0 0x0004
1726#define AC97_AD1986_CVREF1 0x0008
1727#define AC97_AD1986_CVREF2 0x0010
1728#define AC97_AD1986_CVREF_MASK \
1729 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1730#define AC97_AD1986_JSMAP 0x0020
1731#define AC97_AD1986_MMDIS 0x0080
1732#define AC97_AD1986_MVREF0 0x0400
1733#define AC97_AD1986_MVREF1 0x0800
1734#define AC97_AD1986_MVREF2 0x1000
1735#define AC97_AD1986_MVREF_MASK \
1736 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1737
1738
1739#define AC97_AD_MISC3 0x7a
1740
1741#define AC97_AD1986_MMIX 0x0004
1742#define AC97_AD1986_GPO 0x0008
1743#define AC97_AD1986_LOHPEN 0x0010
1744#define AC97_AD1986_LVREF0 0x0100
1745#define AC97_AD1986_LVREF1 0x0200
1746#define AC97_AD1986_LVREF2 0x0400
1747#define AC97_AD1986_LVREF_MASK \
1748 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1749#define AC97_AD1986_JSINVA 0x0800
1750#define AC97_AD1986_LOSEL 0x1000
1751#define AC97_AD1986_HPSEL0 0x2000
1752
1753#define AC97_AD1986_HPSEL1 0x4000
1754
1755#define AC97_AD1986_JSINVB 0x8000
1756
1757
1758#define AC97_AD1986_OMS0 0x0100
1759#define AC97_AD1986_OMS1 0x0200
1760#define AC97_AD1986_OMS2 0x0400
1761#define AC97_AD1986_OMS_MASK \
1762 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1763#define AC97_AD1986_OMS_M 0x0000
1764#define AC97_AD1986_OMS_L 0x0100
1765#define AC97_AD1986_OMS_C 0x0200
1766#define AC97_AD1986_OMS_MC 0x0400
1767
1768#define AC97_AD1986_OMS_ML 0x0500
1769
1770#define AC97_AD1986_OMS_LC 0x0600
1771
1772#define AC97_AD1986_OMS_MLC 0x0700
1773
1774
1775
1776static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1777{
1778 static const char * const texts[2] = { "AC-Link", "A/D Converter" };
1779
1780 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1781}
1782
1783static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1784{
1785 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1786 unsigned short val;
1787
1788 val = ac97->regs[AC97_AD_SERIAL_CFG];
1789 ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
1790 return 0;
1791}
1792
1793static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1794{
1795 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1796 unsigned short val;
1797
1798 if (ucontrol->value.enumerated.item[0] > 1)
1799 return -EINVAL;
1800 val = ucontrol->value.enumerated.item[0] << 2;
1801 return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
1802}
1803
1804static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
1805 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1806 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1807 .info = snd_ac97_ad198x_spdif_source_info,
1808 .get = snd_ac97_ad198x_spdif_source_get,
1809 .put = snd_ac97_ad198x_spdif_source_put,
1810};
1811
1812static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
1813{
1814 return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
1815}
1816
1817static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
1818 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
1819 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1820};
1821
1822
1823
1824
1825static const unsigned int ad1981_jacks_denylist[] = {
1826 0x10140523,
1827 0x10140534,
1828 0x10140537,
1829 0x1014053e,
1830 0x10140554,
1831 0x10140567,
1832 0x10140581,
1833 0x10280160,
1834 0x104380b0,
1835 0x11790241,
1836 0x1179ff10,
1837 0x144dc01a,
1838 0
1839};
1840
1841static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
1842{
1843 u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
1844 for (; *list; list++)
1845 if (*list == subid)
1846 return 1;
1847 return 0;
1848}
1849
1850static int patch_ad1981a_specific(struct snd_ac97 * ac97)
1851{
1852 if (check_list(ac97, ad1981_jacks_denylist))
1853 return 0;
1854 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1855 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1856}
1857
1858static const struct snd_ac97_build_ops patch_ad1981a_build_ops = {
1859 .build_post_spdif = patch_ad198x_post_spdif,
1860 .build_specific = patch_ad1981a_specific,
1861#ifdef CONFIG_PM
1862 .resume = ad18xx_resume
1863#endif
1864};
1865
1866
1867
1868
1869static const unsigned int ad1981_jacks_allowlist[] = {
1870 0x0e11005a,
1871 0x103c0890,
1872 0x103c0938,
1873 0x103c099c,
1874 0x103c0944,
1875 0x103c0934,
1876 0x103c006d,
1877 0x103c300d,
1878 0x17340088,
1879 0
1880};
1881
1882static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
1883{
1884 if (check_list(ac97, ad1981_jacks_allowlist))
1885
1886 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
1887}
1888
1889static int patch_ad1981a(struct snd_ac97 *ac97)
1890{
1891 patch_ad1881(ac97);
1892 ac97->build_ops = &patch_ad1981a_build_ops;
1893 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1894 ac97->flags |= AC97_STEREO_MUTES;
1895 check_ad1981_hp_jack_sense(ac97);
1896 return 0;
1897}
1898
1899static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
1900AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
1901
1902static int patch_ad1981b_specific(struct snd_ac97 *ac97)
1903{
1904 int err;
1905
1906 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
1907 if (err < 0)
1908 return err;
1909 if (check_list(ac97, ad1981_jacks_denylist))
1910 return 0;
1911 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1912 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1913}
1914
1915static const struct snd_ac97_build_ops patch_ad1981b_build_ops = {
1916 .build_post_spdif = patch_ad198x_post_spdif,
1917 .build_specific = patch_ad1981b_specific,
1918#ifdef CONFIG_PM
1919 .resume = ad18xx_resume
1920#endif
1921};
1922
1923static int patch_ad1981b(struct snd_ac97 *ac97)
1924{
1925 patch_ad1881(ac97);
1926 ac97->build_ops = &patch_ad1981b_build_ops;
1927 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1928 ac97->flags |= AC97_STEREO_MUTES;
1929 check_ad1981_hp_jack_sense(ac97);
1930 return 0;
1931}
1932
1933#define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
1934
1935static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1936{
1937 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1938 unsigned short val;
1939
1940 val = ac97->regs[AC97_AD_MISC];
1941 ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
1942 if (ac97->spec.ad18xx.lo_as_master)
1943 ucontrol->value.integer.value[0] =
1944 !ucontrol->value.integer.value[0];
1945 return 0;
1946}
1947
1948static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1949{
1950 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1951 unsigned short val;
1952
1953 val = !ucontrol->value.integer.value[0];
1954 if (ac97->spec.ad18xx.lo_as_master)
1955 val = !val;
1956 val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
1957 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1958 AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
1959}
1960
1961static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1962{
1963 static const char * const texts[3] = {"Off", "6 -> 4", "6 -> 2"};
1964
1965 return snd_ctl_enum_info(uinfo, 1, 3, texts);
1966}
1967
1968static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1969{
1970 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1971 unsigned short val;
1972
1973 val = ac97->regs[AC97_AD_MISC];
1974 if (!(val & AC97_AD198X_DMIX1))
1975 ucontrol->value.enumerated.item[0] = 0;
1976 else
1977 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
1978 return 0;
1979}
1980
1981static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1982{
1983 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1984 unsigned short val;
1985
1986 if (ucontrol->value.enumerated.item[0] > 2)
1987 return -EINVAL;
1988 if (ucontrol->value.enumerated.item[0] == 0)
1989 val = 0;
1990 else
1991 val = AC97_AD198X_DMIX1 |
1992 ((ucontrol->value.enumerated.item[0] - 1) << 8);
1993 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1994 AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
1995}
1996
1997static void ad1888_update_jacks(struct snd_ac97 *ac97)
1998{
1999 unsigned short val = 0;
2000
2001 if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
2002 val |= (1 << 12);
2003
2004 if (is_shared_micin(ac97))
2005 val |= (1 << 11);
2006
2007 snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
2008}
2009
2010static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
2011 {
2012 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2013 .name = "Exchange Front/Surround",
2014 .info = snd_ac97_ad1888_lohpsel_info,
2015 .get = snd_ac97_ad1888_lohpsel_get,
2016 .put = snd_ac97_ad1888_lohpsel_put
2017 },
2018 AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
2019 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
2020 AC97_AD_HPFD_SHIFT, 1, 1),
2021 AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
2022 {
2023 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2024 .name = "Downmix",
2025 .info = snd_ac97_ad1888_downmix_info,
2026 .get = snd_ac97_ad1888_downmix_get,
2027 .put = snd_ac97_ad1888_downmix_put
2028 },
2029 AC97_SURROUND_JACK_MODE_CTL,
2030 AC97_CHANNEL_MODE_CTL,
2031
2032 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2033 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2034};
2035
2036static int patch_ad1888_specific(struct snd_ac97 *ac97)
2037{
2038 if (!ac97->spec.ad18xx.lo_as_master) {
2039
2040 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2041 "Master Surround Playback");
2042 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
2043 "Master Playback");
2044 }
2045 return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
2046}
2047
2048static const struct snd_ac97_build_ops patch_ad1888_build_ops = {
2049 .build_post_spdif = patch_ad198x_post_spdif,
2050 .build_specific = patch_ad1888_specific,
2051#ifdef CONFIG_PM
2052 .resume = ad1888_resume,
2053#endif
2054 .update_jacks = ad1888_update_jacks,
2055};
2056
2057static int patch_ad1888(struct snd_ac97 * ac97)
2058{
2059 unsigned short misc;
2060
2061 patch_ad1881(ac97);
2062 ac97->build_ops = &patch_ad1888_build_ops;
2063
2064
2065
2066
2067
2068 if (ac97->subsystem_vendor == 0x1043 &&
2069 ac97->subsystem_device == 0x1193)
2070 ac97->spec.ad18xx.lo_as_master = 1;
2071
2072 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2073
2074
2075 misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
2076 if (!ac97->spec.ad18xx.lo_as_master)
2077
2078
2079
2080
2081 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
2082
2083 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
2084 ac97->flags |= AC97_STEREO_MUTES;
2085 return 0;
2086}
2087
2088static int patch_ad1980_specific(struct snd_ac97 *ac97)
2089{
2090 int err;
2091
2092 err = patch_ad1888_specific(ac97);
2093 if (err < 0)
2094 return err;
2095 return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2096}
2097
2098static const struct snd_ac97_build_ops patch_ad1980_build_ops = {
2099 .build_post_spdif = patch_ad198x_post_spdif,
2100 .build_specific = patch_ad1980_specific,
2101#ifdef CONFIG_PM
2102 .resume = ad18xx_resume,
2103#endif
2104 .update_jacks = ad1888_update_jacks,
2105};
2106
2107static int patch_ad1980(struct snd_ac97 * ac97)
2108{
2109 patch_ad1888(ac97);
2110 ac97->build_ops = &patch_ad1980_build_ops;
2111 return 0;
2112}
2113
2114static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2115 struct snd_ctl_elem_info *uinfo)
2116{
2117 static const char * const texts[4] = {
2118 "High-Z", "3.7 V", "2.25 V", "0 V"
2119 };
2120
2121 return snd_ctl_enum_info(uinfo, 1, 4, texts);
2122}
2123
2124static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2125 struct snd_ctl_elem_value *ucontrol)
2126{
2127 static const int reg2ctrl[4] = {2, 0, 1, 3};
2128 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2129 unsigned short val;
2130 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2131 >> AC97_AD198X_VREF_SHIFT;
2132 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2133 return 0;
2134}
2135
2136static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2137 struct snd_ctl_elem_value *ucontrol)
2138{
2139 static const int ctrl2reg[4] = {1, 2, 0, 3};
2140 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2141 unsigned short val;
2142
2143 if (ucontrol->value.enumerated.item[0] > 3)
2144 return -EINVAL;
2145 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2146 << AC97_AD198X_VREF_SHIFT;
2147 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2148 AC97_AD198X_VREF_MASK, val);
2149}
2150
2151static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
2152 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2153 {
2154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2155 .name = "Exchange Front/Surround",
2156 .info = snd_ac97_ad1888_lohpsel_info,
2157 .get = snd_ac97_ad1888_lohpsel_get,
2158 .put = snd_ac97_ad1888_lohpsel_put
2159 },
2160 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2161 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2162 AC97_AD_MISC, 7, 1, 0),
2163 {
2164 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2165 .name = "Downmix",
2166 .info = snd_ac97_ad1888_downmix_info,
2167 .get = snd_ac97_ad1888_downmix_get,
2168 .put = snd_ac97_ad1888_downmix_put
2169 },
2170 {
2171 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2172 .name = "V_REFOUT",
2173 .info = snd_ac97_ad1985_vrefout_info,
2174 .get = snd_ac97_ad1985_vrefout_get,
2175 .put = snd_ac97_ad1985_vrefout_put
2176 },
2177 AC97_SURROUND_JACK_MODE_CTL,
2178 AC97_CHANNEL_MODE_CTL,
2179
2180 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2181 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2182};
2183
2184static void ad1985_update_jacks(struct snd_ac97 *ac97)
2185{
2186 ad1888_update_jacks(ac97);
2187
2188 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
2189 is_shared_micin(ac97) ? 1 << 9 : 0);
2190}
2191
2192static int patch_ad1985_specific(struct snd_ac97 *ac97)
2193{
2194 int err;
2195
2196
2197 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2198 "Master Surround Playback");
2199 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2200
2201 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2202 if (err < 0)
2203 return err;
2204
2205 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2206 ARRAY_SIZE(snd_ac97_ad1985_controls));
2207}
2208
2209static const struct snd_ac97_build_ops patch_ad1985_build_ops = {
2210 .build_post_spdif = patch_ad198x_post_spdif,
2211 .build_specific = patch_ad1985_specific,
2212#ifdef CONFIG_PM
2213 .resume = ad18xx_resume,
2214#endif
2215 .update_jacks = ad1985_update_jacks,
2216};
2217
2218static int patch_ad1985(struct snd_ac97 * ac97)
2219{
2220 unsigned short misc;
2221
2222 patch_ad1881(ac97);
2223 ac97->build_ops = &patch_ad1985_build_ops;
2224 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2225
2226
2227
2228 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2229 AC97_AD198X_LOSEL |
2230 AC97_AD198X_HPSEL |
2231 AC97_AD198X_MSPLT |
2232 AC97_AD198X_AC97NC);
2233 ac97->flags |= AC97_STEREO_MUTES;
2234
2235
2236 ad1985_update_jacks(ac97);
2237
2238
2239 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2240 return 0;
2241}
2242
2243#define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
2244
2245static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2246 struct snd_ctl_elem_value *ucontrol)
2247{
2248 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2249 unsigned short val;
2250
2251 val = ac97->regs[AC97_AD_MISC3];
2252 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2253 return 0;
2254}
2255
2256static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2257 struct snd_ctl_elem_value *ucontrol)
2258{
2259 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2260 int ret0;
2261 int ret1;
2262 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2263
2264 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2265 ucontrol->value.integer.value[0] != 0
2266 ? AC97_AD1986_LOSEL : 0);
2267 if (ret0 < 0)
2268 return ret0;
2269
2270
2271 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2272 (ucontrol->value.integer.value[0] != 0
2273 || sprd)
2274 ? AC97_AD1986_SOSEL : 0);
2275 if (ret1 < 0)
2276 return ret1;
2277
2278 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2279}
2280
2281static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2282 struct snd_ctl_elem_value *ucontrol)
2283{
2284 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2285 unsigned short val;
2286
2287 val = ac97->regs[AC97_AD_MISC];
2288 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2289 return 0;
2290}
2291
2292static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2293 struct snd_ctl_elem_value *ucontrol)
2294{
2295 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2296 int ret0;
2297 int ret1;
2298 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2299
2300 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2301 ucontrol->value.integer.value[0] != 0
2302 ? AC97_AD1986_SPRD : 0);
2303 if (ret0 < 0)
2304 return ret0;
2305
2306
2307 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2308 (ucontrol->value.integer.value[0] != 0
2309 || sprd)
2310 ? AC97_AD1986_SOSEL : 0);
2311 if (ret1 < 0)
2312 return ret1;
2313
2314 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2315}
2316
2317static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2318 struct snd_ctl_elem_value *ucontrol)
2319{
2320 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2321
2322 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2323 return 0;
2324}
2325
2326static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2327 struct snd_ctl_elem_value *ucontrol)
2328{
2329 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2330 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2331
2332 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2333 ac97->spec.ad18xx.swap_mic_linein = swap;
2334 if (ac97->build_ops->update_jacks)
2335 ac97->build_ops->update_jacks(ac97);
2336 return 1;
2337 }
2338 return 0;
2339}
2340
2341static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2342 struct snd_ctl_elem_value *ucontrol)
2343{
2344
2345 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2346 unsigned short val;
2347 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2348 if ((reg & AC97_AD1986_MVREF0) != 0)
2349 val = 2;
2350 else if ((reg & AC97_AD1986_MVREF1) != 0)
2351 val = 3;
2352 else if ((reg & AC97_AD1986_MVREF2) != 0)
2353 val = 1;
2354 else
2355 val = 0;
2356 ucontrol->value.enumerated.item[0] = val;
2357 return 0;
2358}
2359
2360static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2361 struct snd_ctl_elem_value *ucontrol)
2362{
2363 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2364 unsigned short cval;
2365 unsigned short lval;
2366 unsigned short mval;
2367 int cret;
2368 int lret;
2369 int mret;
2370
2371 switch (ucontrol->value.enumerated.item[0])
2372 {
2373 case 0:
2374 cval = 0;
2375 lval = 0;
2376 mval = 0;
2377 break;
2378 case 1:
2379 cval = AC97_AD1986_CVREF2;
2380 lval = AC97_AD1986_LVREF2;
2381 mval = AC97_AD1986_MVREF2;
2382 break;
2383 case 2:
2384 cval = AC97_AD1986_CVREF0;
2385 lval = AC97_AD1986_LVREF0;
2386 mval = AC97_AD1986_MVREF0;
2387 break;
2388 case 3:
2389 cval = AC97_AD1986_CVREF1;
2390 lval = AC97_AD1986_LVREF1;
2391 mval = AC97_AD1986_MVREF1;
2392 break;
2393 default:
2394 return -EINVAL;
2395 }
2396
2397 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2398 AC97_AD1986_CVREF_MASK, cval);
2399 if (cret < 0)
2400 return cret;
2401 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2402 AC97_AD1986_LVREF_MASK, lval);
2403 if (lret < 0)
2404 return lret;
2405 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2406 AC97_AD1986_MVREF_MASK, mval);
2407 if (mret < 0)
2408 return mret;
2409
2410 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2411}
2412
2413static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2414 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2415 {
2416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2417 .name = "Exchange Front/Surround",
2418 .info = snd_ac97_ad1986_bool_info,
2419 .get = snd_ac97_ad1986_lososel_get,
2420 .put = snd_ac97_ad1986_lososel_put
2421 },
2422 {
2423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2424 .name = "Exchange Mic/Line In",
2425 .info = snd_ac97_ad1986_bool_info,
2426 .get = snd_ac97_ad1986_miclisel_get,
2427 .put = snd_ac97_ad1986_miclisel_put
2428 },
2429 {
2430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2431 .name = "Spread Front to Surround and Center/LFE",
2432 .info = snd_ac97_ad1986_bool_info,
2433 .get = snd_ac97_ad1986_spread_get,
2434 .put = snd_ac97_ad1986_spread_put
2435 },
2436 {
2437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2438 .name = "Downmix",
2439 .info = snd_ac97_ad1888_downmix_info,
2440 .get = snd_ac97_ad1888_downmix_get,
2441 .put = snd_ac97_ad1888_downmix_put
2442 },
2443 {
2444 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2445 .name = "V_REFOUT",
2446 .info = snd_ac97_ad1985_vrefout_info,
2447 .get = snd_ac97_ad1986_vrefout_get,
2448 .put = snd_ac97_ad1986_vrefout_put
2449 },
2450 AC97_SURROUND_JACK_MODE_CTL,
2451 AC97_CHANNEL_MODE_CTL,
2452
2453 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2454 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2455};
2456
2457static void ad1986_update_jacks(struct snd_ac97 *ac97)
2458{
2459 unsigned short misc_val = 0;
2460 unsigned short ser_val;
2461
2462
2463 if (!is_surround_on(ac97))
2464 misc_val |= AC97_AD1986_SODIS;
2465 if (!is_clfe_on(ac97))
2466 misc_val |= AC97_AD1986_CLDIS;
2467
2468
2469 if (is_shared_linein(ac97))
2470 misc_val |= AC97_AD1986_LISEL_SURR;
2471 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2472 misc_val |= AC97_AD1986_LISEL_MIC;
2473 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2474 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2475 AC97_AD1986_LISEL_MASK,
2476 misc_val);
2477
2478
2479 if (is_shared_micin(ac97))
2480 ser_val = AC97_AD1986_OMS_C;
2481 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2482 ser_val = AC97_AD1986_OMS_L;
2483 else
2484 ser_val = AC97_AD1986_OMS_M;
2485 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2486 AC97_AD1986_OMS_MASK,
2487 ser_val);
2488}
2489
2490static int patch_ad1986_specific(struct snd_ac97 *ac97)
2491{
2492 int err;
2493
2494 err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2495 if (err < 0)
2496 return err;
2497
2498 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2499 ARRAY_SIZE(snd_ac97_ad1985_controls));
2500}
2501
2502static const struct snd_ac97_build_ops patch_ad1986_build_ops = {
2503 .build_post_spdif = patch_ad198x_post_spdif,
2504 .build_specific = patch_ad1986_specific,
2505#ifdef CONFIG_PM
2506 .resume = ad18xx_resume,
2507#endif
2508 .update_jacks = ad1986_update_jacks,
2509};
2510
2511static int patch_ad1986(struct snd_ac97 * ac97)
2512{
2513 patch_ad1881(ac97);
2514 ac97->build_ops = &patch_ad1986_build_ops;
2515 ac97->flags |= AC97_STEREO_MUTES;
2516
2517
2518 ad1986_update_jacks(ac97);
2519
2520 return 0;
2521}
2522
2523
2524
2525
2526static int patch_alc203(struct snd_ac97 *ac97)
2527{
2528 snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
2529 return 0;
2530}
2531
2532
2533
2534
2535static void alc650_update_jacks(struct snd_ac97 *ac97)
2536{
2537 int shared;
2538
2539
2540 shared = is_shared_surrout(ac97);
2541 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2542 shared ? (1 << 9) : 0);
2543
2544 shared = is_shared_clfeout(ac97);
2545
2546 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2547 shared ? (1 << 12) : 0);
2548
2549 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
2550 shared ? (1 << 10) : 0);
2551
2552 snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
2553 shared ? 0 : 0x100);
2554}
2555
2556static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
2557 struct snd_ctl_elem_value *ucontrol)
2558{
2559 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2560 struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
2561
2562 if (map) {
2563 if (ucontrol->value.integer.value[0])
2564 map->chmap = snd_pcm_std_chmaps;
2565 else
2566 map->chmap = snd_pcm_alt_chmaps;
2567 }
2568 return snd_ac97_put_volsw(kcontrol, ucontrol);
2569}
2570
2571static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2572 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2573 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
2574 AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
2575 AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
2576
2577
2578
2579
2580
2581
2582
2583
2584 {
2585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2586 .name = "Swap Surround Slot",
2587 .info = snd_ac97_info_volsw,
2588 .get = snd_ac97_get_volsw,
2589 .put = alc650_swap_surround_put,
2590 .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
2591 },
2592#if 0
2593 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2594 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
2595 AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
2596 AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
2597 AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
2598 AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
2599#endif
2600 AC97_SURROUND_JACK_MODE_CTL,
2601 AC97_CHANNEL_MODE_CTL,
2602};
2603
2604static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2605 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
2606 AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
2607
2608
2609};
2610
2611static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2612
2613static int patch_alc650_specific(struct snd_ac97 * ac97)
2614{
2615 int err;
2616
2617 err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650));
2618 if (err < 0)
2619 return err;
2620 if (ac97->ext_id & AC97_EI_SPDIF) {
2621 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650));
2622 if (err < 0)
2623 return err;
2624 }
2625 if (ac97->id != AC97_ID_ALC650F)
2626 reset_tlv(ac97, "Master Playback Volume",
2627 db_scale_5bit_3db_max);
2628 return 0;
2629}
2630
2631static const struct snd_ac97_build_ops patch_alc650_ops = {
2632 .build_specific = patch_alc650_specific,
2633 .update_jacks = alc650_update_jacks
2634};
2635
2636static int patch_alc650(struct snd_ac97 * ac97)
2637{
2638 unsigned short val;
2639
2640 ac97->build_ops = &patch_alc650_ops;
2641
2642
2643 val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
2644 if (val < 3)
2645 ac97->id = 0x414c4720;
2646 else if (val < 0x10)
2647 ac97->id = 0x414c4721;
2648 else if (val < 0x20)
2649 ac97->id = 0x414c4722;
2650 else if (val < 0x30)
2651 ac97->id = 0x414c4723;
2652
2653
2654
2655 ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
2656 ac97->id == 0x414c4723);
2657
2658
2659 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2660 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
2661
2662
2663 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2664
2665 if (ac97->spec.dev_flags &&
2666
2667 ! (ac97->subsystem_vendor == 0x1043 &&
2668 ac97->subsystem_device == 0x1103))
2669 val |= 0x03;
2670 else
2671 val &= ~0x03;
2672 snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
2673
2674
2675
2676
2677
2678
2679 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
2680
2681
2682
2683 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
2684 snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
2685 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2686 (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
2687
2688
2689 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2690 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2691 return 0;
2692}
2693
2694static void alc655_update_jacks(struct snd_ac97 *ac97)
2695{
2696 int shared;
2697
2698
2699 shared = is_shared_surrout(ac97);
2700 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2701 shared ? (1 << 9) : 0, 0);
2702
2703 shared = is_shared_clfeout(ac97);
2704
2705 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2706 shared ? (1 << 12) : 0);
2707 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
2708 shared ? (1 << 10) : 0, 0);
2709}
2710
2711static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
2712 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2713 AC97_SURROUND_JACK_MODE_CTL,
2714 AC97_CHANNEL_MODE_CTL,
2715};
2716
2717static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2718{
2719 static const char * const texts_655[3] = {
2720 "PCM", "Analog In", "IEC958 In"
2721 };
2722 static const char * const texts_658[4] = {
2723 "PCM", "Analog1 In", "Analog2 In", "IEC958 In"
2724 };
2725 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2726
2727 if (ac97->spec.dev_flags)
2728 return snd_ctl_enum_info(uinfo, 1, 4, texts_658);
2729 else
2730 return snd_ctl_enum_info(uinfo, 1, 3, texts_655);
2731}
2732
2733static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2734{
2735 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2736 unsigned short val;
2737
2738 val = ac97->regs[AC97_ALC650_MULTICH];
2739 val = (val >> 12) & 3;
2740 if (ac97->spec.dev_flags && val == 3)
2741 val = 0;
2742 ucontrol->value.enumerated.item[0] = val;
2743 return 0;
2744}
2745
2746static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2747{
2748 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2749
2750 return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
2751 (unsigned short)ucontrol->value.enumerated.item[0] << 12,
2752 0);
2753}
2754
2755static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
2756 AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
2757
2758
2759 {
2760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2761 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2762 .info = alc655_iec958_route_info,
2763 .get = alc655_iec958_route_get,
2764 .put = alc655_iec958_route_put,
2765 },
2766};
2767
2768static int patch_alc655_specific(struct snd_ac97 * ac97)
2769{
2770 int err;
2771
2772 err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655));
2773 if (err < 0)
2774 return err;
2775 if (ac97->ext_id & AC97_EI_SPDIF) {
2776 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2777 if (err < 0)
2778 return err;
2779 }
2780 return 0;
2781}
2782
2783static const struct snd_ac97_build_ops patch_alc655_ops = {
2784 .build_specific = patch_alc655_specific,
2785 .update_jacks = alc655_update_jacks
2786};
2787
2788static int patch_alc655(struct snd_ac97 * ac97)
2789{
2790 unsigned int val;
2791
2792 if (ac97->id == AC97_ID_ALC658) {
2793 ac97->spec.dev_flags = 1;
2794 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
2795 ac97->id = AC97_ID_ALC658D;
2796 ac97->spec.dev_flags = 2;
2797 }
2798 }
2799
2800 ac97->build_ops = &patch_alc655_ops;
2801
2802
2803 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2804
2805
2806 val = snd_ac97_read(ac97, 0x7a);
2807 if (ac97->spec.dev_flags)
2808 val &= ~(1 << 1);
2809 else {
2810 if (ac97->subsystem_vendor == 0x1462 &&
2811 (ac97->subsystem_device == 0x0131 ||
2812 ac97->subsystem_device == 0x0161 ||
2813 ac97->subsystem_device == 0x0351 ||
2814 ac97->subsystem_device == 0x0471 ||
2815 ac97->subsystem_device == 0x0061))
2816 val &= ~(1 << 1);
2817 else
2818 val |= (1 << 1);
2819
2820 ac97->ext_id |= AC97_EI_SPDIF;
2821 }
2822 val &= ~(1 << 12);
2823 snd_ac97_write_cache(ac97, 0x7a, val);
2824
2825
2826
2827
2828
2829 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2830
2831
2832 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2833 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2834
2835
2836 if (ac97->id == AC97_ID_ALC658D)
2837 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2838
2839 return 0;
2840}
2841
2842
2843#define AC97_ALC850_JACK_SELECT 0x76
2844#define AC97_ALC850_MISC1 0x7a
2845#define AC97_ALC850_MULTICH 0x6a
2846
2847static void alc850_update_jacks(struct snd_ac97 *ac97)
2848{
2849 int shared;
2850 int aux_is_back_surround;
2851
2852
2853 shared = is_shared_surrout(ac97);
2854
2855 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2856 shared ? (1<<5) : (1<<4));
2857
2858 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2859 shared ? (2<<12) : (0<<12));
2860
2861 shared = is_shared_clfeout(ac97);
2862
2863 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2864 shared ? (1<<12) : (1<<13));
2865
2866 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
2867 shared ? (5<<4) : (1<<4));
2868
2869 aux_is_back_surround = alc850_is_aux_back_surround(ac97);
2870
2871 snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
2872 aux_is_back_surround ? (1<<10) : (0<<10));
2873}
2874
2875static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
2876 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2877 AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
2878 AC97_SURROUND_JACK_MODE_CTL,
2879 AC97_CHANNEL_MODE_8CH_CTL,
2880};
2881
2882static int patch_alc850_specific(struct snd_ac97 *ac97)
2883{
2884 int err;
2885
2886 err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850));
2887 if (err < 0)
2888 return err;
2889 if (ac97->ext_id & AC97_EI_SPDIF) {
2890 err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655));
2891 if (err < 0)
2892 return err;
2893 }
2894 return 0;
2895}
2896
2897static const struct snd_ac97_build_ops patch_alc850_ops = {
2898 .build_specific = patch_alc850_specific,
2899 .update_jacks = alc850_update_jacks
2900};
2901
2902static int patch_alc850(struct snd_ac97 *ac97)
2903{
2904 ac97->build_ops = &patch_alc850_ops;
2905
2906 ac97->spec.dev_flags = 0;
2907 ac97->flags |= AC97_HAS_8CH;
2908
2909
2910 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2911
2912
2913
2914
2915
2916
2917
2918
2919 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2920
2921
2922
2923 snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
2924 (1<<7)|(0<<12)|(1<<13)|(0<<14));
2925
2926
2927
2928 snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
2929 (1<<11)|(0<<12)|(1<<15));
2930
2931
2932 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2933 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2934 return 0;
2935}
2936
2937static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
2938{
2939 struct snd_kcontrol *kctl_3d_center =
2940 snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
2941 struct snd_kcontrol *kctl_3d_depth =
2942 snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
2943
2944
2945
2946
2947
2948 if (kctl_3d_center) {
2949 kctl_3d_center->private_value =
2950 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
2951 snd_ac97_rename_vol_ctl(ac97,
2952 "3D Control - Center", "3D Control - Width"
2953 );
2954 }
2955 if (kctl_3d_depth)
2956 kctl_3d_depth->private_value =
2957 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
2958
2959
2960
2961 snd_ac97_rename_vol_ctl(ac97,
2962 "Master Mono Playback", "Modem Playback"
2963 );
2964 snd_ac97_rename_vol_ctl(ac97,
2965 "Headphone Playback", "FM Synth Playback"
2966 );
2967
2968 return 0;
2969}
2970
2971static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
2972 .build_specific = patch_aztech_azf3328_specific
2973};
2974
2975static int patch_aztech_azf3328(struct snd_ac97 *ac97)
2976{
2977 ac97->build_ops = &patch_aztech_azf3328_ops;
2978 return 0;
2979}
2980
2981
2982
2983
2984static void cm9738_update_jacks(struct snd_ac97 *ac97)
2985{
2986
2987 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2988 is_shared_surrout(ac97) ? (1 << 10) : 0);
2989}
2990
2991static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
2992 AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
2993 AC97_SURROUND_JACK_MODE_CTL,
2994 AC97_CHANNEL_MODE_4CH_CTL,
2995};
2996
2997static int patch_cm9738_specific(struct snd_ac97 * ac97)
2998{
2999 return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
3000}
3001
3002static const struct snd_ac97_build_ops patch_cm9738_ops = {
3003 .build_specific = patch_cm9738_specific,
3004 .update_jacks = cm9738_update_jacks
3005};
3006
3007static int patch_cm9738(struct snd_ac97 * ac97)
3008{
3009 ac97->build_ops = &patch_cm9738_ops;
3010
3011
3012 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3013 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3014
3015 return 0;
3016}
3017
3018static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3019{
3020 static const char * const texts[] = { "Analog", "Digital" };
3021
3022 return snd_ctl_enum_info(uinfo, 1, 2, texts);
3023}
3024
3025static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3026{
3027 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3028 unsigned short val;
3029
3030 val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
3031 ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
3032 return 0;
3033}
3034
3035static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3036{
3037 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3038
3039 return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
3040 0x01 << 1,
3041 (ucontrol->value.enumerated.item[0] & 0x01) << 1);
3042}
3043
3044static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
3045
3046 {
3047 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3048 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3049 .info = snd_ac97_cmedia_spdif_playback_source_info,
3050 .get = snd_ac97_cmedia_spdif_playback_source_get,
3051 .put = snd_ac97_cmedia_spdif_playback_source_put,
3052 },
3053
3054 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
3055
3056 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
3057
3058 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
3059
3060};
3061
3062static void cm9739_update_jacks(struct snd_ac97 *ac97)
3063{
3064
3065 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
3066 is_shared_surrout(ac97) ? (1 << 10) : 0);
3067
3068 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
3069 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
3070}
3071
3072static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
3073 AC97_SURROUND_JACK_MODE_CTL,
3074 AC97_CHANNEL_MODE_CTL,
3075};
3076
3077static int patch_cm9739_specific(struct snd_ac97 * ac97)
3078{
3079 return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
3080}
3081
3082static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
3083{
3084 return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
3085}
3086
3087static const struct snd_ac97_build_ops patch_cm9739_ops = {
3088 .build_specific = patch_cm9739_specific,
3089 .build_post_spdif = patch_cm9739_post_spdif,
3090 .update_jacks = cm9739_update_jacks
3091};
3092
3093static int patch_cm9739(struct snd_ac97 * ac97)
3094{
3095 unsigned short val;
3096
3097 ac97->build_ops = &patch_cm9739_ops;
3098
3099
3100 ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
3101 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
3102 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3103
3104
3105 val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
3106 if (val & AC97_EA_SPCV) {
3107
3108 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3109 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
3110 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3111 } else {
3112 ac97->ext_id &= ~AC97_EI_SPDIF;
3113 ac97->rates[AC97_RATES_SPDIF] = 0;
3114 }
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125 val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
3126 val |= (1 << 3);
3127 val |= (1 << 13);
3128 if (! (ac97->ext_id & AC97_EI_SPDIF))
3129 val |= (1 << 14);
3130 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
3131
3132
3133 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3134 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3135
3136 if (ac97->pci &&
3137 ac97->subsystem_vendor == 0x1043 &&
3138 ac97->subsystem_device == 0x1843) {
3139 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3140 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
3141 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
3142 snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
3143 }
3144
3145 return 0;
3146}
3147
3148#define AC97_CM9761_MULTI_CHAN 0x64
3149#define AC97_CM9761_FUNC 0x66
3150#define AC97_CM9761_SPDIF_CTRL 0x6c
3151
3152static void cm9761_update_jacks(struct snd_ac97 *ac97)
3153{
3154
3155
3156
3157 static const unsigned short surr_on[3][2] = {
3158 { 0x0008, 0x0000 },
3159 { 0x0000, 0x0008 },
3160 { 0x0000, 0x0008 },
3161 };
3162 static const unsigned short clfe_on[3][2] = {
3163 { 0x0000, 0x1000 },
3164 { 0x1000, 0x0000 },
3165 { 0x0000, 0x1000 },
3166 };
3167 static const unsigned short surr_shared[3][2] = {
3168 { 0x0000, 0x0400 },
3169 { 0x0000, 0x0400 },
3170 { 0x0000, 0x0400 },
3171 };
3172 static const unsigned short clfe_shared[3][2] = {
3173 { 0x2000, 0x0880 },
3174 { 0x0000, 0x2880 },
3175 { 0x2000, 0x0800 },
3176 };
3177 unsigned short val = 0;
3178
3179 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
3180 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
3181 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
3182 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
3183
3184 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
3185}
3186
3187static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
3188 AC97_SURROUND_JACK_MODE_CTL,
3189 AC97_CHANNEL_MODE_CTL,
3190};
3191
3192static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3193{
3194 static const char * const texts[] = { "AC-Link", "ADC", "SPDIF-In" };
3195
3196 return snd_ctl_enum_info(uinfo, 1, 3, texts);
3197}
3198
3199static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3200{
3201 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3202
3203 if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
3204 ucontrol->value.enumerated.item[0] = 2;
3205 else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
3206 ucontrol->value.enumerated.item[0] = 1;
3207 else
3208 ucontrol->value.enumerated.item[0] = 0;
3209 return 0;
3210}
3211
3212static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3213{
3214 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3215
3216 if (ucontrol->value.enumerated.item[0] == 2)
3217 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
3218 snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
3219 return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
3220 ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
3221}
3222
3223static const char * const cm9761_dac_clock[] = {
3224 "AC-Link", "SPDIF-In", "Both"
3225};
3226static const struct ac97_enum cm9761_dac_clock_enum =
3227 AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
3228
3229static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
3230 {
3231 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3232 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3233 .info = cm9761_spdif_out_source_info,
3234 .get = cm9761_spdif_out_source_get,
3235 .put = cm9761_spdif_out_source_put,
3236 },
3237
3238 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
3239
3240 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
3241
3242 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
3243
3244 AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
3245};
3246
3247static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
3248{
3249 return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
3250}
3251
3252static int patch_cm9761_specific(struct snd_ac97 * ac97)
3253{
3254 return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
3255}
3256
3257static const struct snd_ac97_build_ops patch_cm9761_ops = {
3258 .build_specific = patch_cm9761_specific,
3259 .build_post_spdif = patch_cm9761_post_spdif,
3260 .update_jacks = cm9761_update_jacks
3261};
3262
3263static int patch_cm9761(struct snd_ac97 *ac97)
3264{
3265 unsigned short val;
3266
3267
3268
3269
3270
3271 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3272 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
3273 snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
3274
3275 ac97->spec.dev_flags = 0;
3276 if (ac97->id == AC97_ID_CM9761_82) {
3277 unsigned short tmp;
3278
3279 val = snd_ac97_read(ac97, AC97_INT_PAGING);
3280 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
3281 tmp = snd_ac97_read(ac97, 0x60);
3282 ac97->spec.dev_flags = tmp & 1;
3283 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
3284 } else if (ac97->id == AC97_ID_CM9761_83)
3285 ac97->spec.dev_flags = 2;
3286
3287 ac97->build_ops = &patch_cm9761_ops;
3288
3289
3290
3291 ac97->ext_id |= AC97_EI_SPDIF;
3292
3293 snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
3294
3295 snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001);
3296 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316#if 0
3317 if (ac97->spec.dev_flags)
3318 val = 0x0214;
3319 else
3320 val = 0x321c;
3321#endif
3322 val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
3323 val |= (1 << 4);
3324 snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
3325
3326
3327 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3328 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3329
3330 return 0;
3331}
3332
3333#define AC97_CM9780_SIDE 0x60
3334#define AC97_CM9780_JACK 0x62
3335#define AC97_CM9780_MIXER 0x64
3336#define AC97_CM9780_MULTI_CHAN 0x66
3337#define AC97_CM9780_SPDIF 0x6c
3338
3339static const char * const cm9780_ch_select[] = {
3340 "Front", "Side", "Center/LFE", "Rear"
3341};
3342static const struct ac97_enum cm9780_ch_select_enum =
3343 AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
3344static const struct snd_kcontrol_new cm9780_controls[] = {
3345 AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
3346 AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
3347 AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
3348};
3349
3350static int patch_cm9780_specific(struct snd_ac97 *ac97)
3351{
3352 return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
3353}
3354
3355static const struct snd_ac97_build_ops patch_cm9780_ops = {
3356 .build_specific = patch_cm9780_specific,
3357 .build_post_spdif = patch_cm9761_post_spdif
3358};
3359
3360static int patch_cm9780(struct snd_ac97 *ac97)
3361{
3362 unsigned short val;
3363
3364 ac97->build_ops = &patch_cm9780_ops;
3365
3366
3367 if (ac97->ext_id & AC97_EI_SPDIF) {
3368 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3369 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
3370 val |= 0x1;
3371 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
3372 }
3373
3374 return 0;
3375}
3376
3377
3378
3379
3380static const struct snd_kcontrol_new snd_ac97_controls_vt1613[] = {
3381AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3382};
3383
3384static int patch_vt1613_specific(struct snd_ac97 *ac97)
3385{
3386 return patch_build_controls(ac97, &snd_ac97_controls_vt1613[0],
3387 ARRAY_SIZE(snd_ac97_controls_vt1613));
3388};
3389
3390static const struct snd_ac97_build_ops patch_vt1613_ops = {
3391 .build_specific = patch_vt1613_specific
3392};
3393
3394static int patch_vt1613(struct snd_ac97 *ac97)
3395{
3396 ac97->build_ops = &patch_vt1613_ops;
3397
3398 ac97->flags |= AC97_HAS_NO_VIDEO;
3399 ac97->caps |= AC97_BC_HEADPHONE;
3400
3401 return 0;
3402}
3403
3404
3405
3406
3407static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
3408AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3409AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
3410AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
3411AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
3412};
3413
3414static const char * const follower_vols_vt1616[] = {
3415 "Front Playback Volume",
3416 "Surround Playback Volume",
3417 "Center Playback Volume",
3418 "LFE Playback Volume",
3419 NULL
3420};
3421
3422static const char * const follower_sws_vt1616[] = {
3423 "Front Playback Switch",
3424 "Surround Playback Switch",
3425 "Center Playback Switch",
3426 "LFE Playback Switch",
3427 NULL
3428};
3429
3430
3431static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
3432 const char *name)
3433{
3434 struct snd_ctl_elem_id id;
3435 memset(&id, 0, sizeof(id));
3436 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
3437 strcpy(id.name, name);
3438 return snd_ctl_find_id(ac97->bus->card, &id);
3439}
3440
3441
3442static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
3443 const unsigned int *tlv,
3444 const char * const *followers)
3445{
3446 struct snd_kcontrol *kctl;
3447 const char * const *s;
3448 int err;
3449
3450 kctl = snd_ctl_make_virtual_master(name, tlv);
3451 if (!kctl)
3452 return -ENOMEM;
3453 err = snd_ctl_add(ac97->bus->card, kctl);
3454 if (err < 0)
3455 return err;
3456
3457 for (s = followers; *s; s++) {
3458 struct snd_kcontrol *sctl;
3459
3460 sctl = snd_ac97_find_mixer_ctl(ac97, *s);
3461 if (!sctl) {
3462 dev_dbg(ac97->bus->card->dev,
3463 "Cannot find follower %s, skipped\n", *s);
3464 continue;
3465 }
3466 err = snd_ctl_add_follower(kctl, sctl);
3467 if (err < 0)
3468 return err;
3469 }
3470 return 0;
3471}
3472
3473static int patch_vt1616_specific(struct snd_ac97 * ac97)
3474{
3475 struct snd_kcontrol *kctl;
3476 int err;
3477
3478 if (snd_ac97_try_bit(ac97, 0x5a, 9)) {
3479 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1);
3480 if (err < 0)
3481 return err;
3482 }
3483 err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1);
3484 if (err < 0)
3485 return err;
3486
3487
3488 kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
3489 if (!kctl)
3490 return -EINVAL;
3491
3492 snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
3493
3494 err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
3495 kctl->tlv.p, follower_vols_vt1616);
3496 if (err < 0)
3497 return err;
3498
3499 err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
3500 NULL, follower_sws_vt1616);
3501 if (err < 0)
3502 return err;
3503
3504 return 0;
3505}
3506
3507static const struct snd_ac97_build_ops patch_vt1616_ops = {
3508 .build_specific = patch_vt1616_specific
3509};
3510
3511static int patch_vt1616(struct snd_ac97 * ac97)
3512{
3513 ac97->build_ops = &patch_vt1616_ops;
3514 return 0;
3515}
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
3533 struct snd_ctl_elem_info *uinfo)
3534{
3535
3536
3537
3538
3539
3540 static const char * const texts[] = {"LineIn Mic1", "LineIn Mic1 Mic3",
3541 "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
3542 "LineIn Mic2", "LineIn Mic2 Mic1",
3543 "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
3544
3545 return snd_ctl_enum_info(uinfo, 1, 8, texts);
3546}
3547
3548static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
3549 struct snd_ctl_elem_value *ucontrol)
3550{
3551 ushort usSM51, usMS;
3552
3553 struct snd_ac97 *pac97;
3554
3555 pac97 = snd_kcontrol_chip(kcontrol);
3556
3557
3558
3559
3560 usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
3561 usMS = snd_ac97_read(pac97, 0x20) >> 8;
3562
3563 ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
3564
3565 return 0;
3566}
3567
3568static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
3569 struct snd_ctl_elem_value *ucontrol)
3570{
3571 ushort usSM51, usMS, usReg;
3572
3573 struct snd_ac97 *pac97;
3574
3575 pac97 = snd_kcontrol_chip(kcontrol);
3576
3577 usSM51 = ucontrol->value.enumerated.item[0] >> 1;
3578 usMS = ucontrol->value.enumerated.item[0] & 1;
3579
3580
3581
3582
3583 usReg = snd_ac97_read(pac97, 0x7a);
3584 snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
3585 usReg = snd_ac97_read(pac97, 0x20);
3586 snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8));
3587
3588 return 0;
3589}
3590
3591static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
3592
3593 AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
3594
3595
3596
3597
3598 {
3599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3600 .name = "Smart 5.1 Select",
3601 .info = snd_ac97_vt1617a_smart51_info,
3602 .get = snd_ac97_vt1617a_smart51_get,
3603 .put = snd_ac97_vt1617a_smart51_put,
3604 },
3605};
3606
3607static int patch_vt1617a(struct snd_ac97 * ac97)
3608{
3609 int err = 0;
3610 int val;
3611
3612
3613
3614
3615 err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
3616 ARRAY_SIZE(snd_ac97_controls_vt1617a));
3617
3618
3619
3620
3621
3622
3623
3624 val = snd_ac97_read(ac97, 0x5c);
3625 if (!(val & 0x20))
3626 snd_ac97_write_cache(ac97, 0x5c, 0x20);
3627
3628 ac97->ext_id |= AC97_EI_SPDIF;
3629 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3630 ac97->build_ops = &patch_vt1616_ops;
3631
3632 return err;
3633}
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671struct vt1618_uaj_item {
3672 unsigned short mask;
3673 unsigned short shift;
3674 const char * const items[4];
3675};
3676
3677
3678
3679static const struct vt1618_uaj_item vt1618_uaj[3] = {
3680 {
3681
3682 .mask = 0x03,
3683 .shift = 0,
3684 .items = {
3685 "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
3686 }
3687 },
3688 {
3689
3690 .mask = 0x0c,
3691 .shift = 2,
3692 .items = {
3693 "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
3694 }
3695 },
3696 {
3697
3698 .mask = 0x30,
3699 .shift = 4,
3700 .items = {
3701 "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
3702 },
3703 },
3704};
3705
3706static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
3707 struct snd_ctl_elem_info *uinfo)
3708{
3709 return snd_ctl_enum_info(uinfo, 1, 4,
3710 vt1618_uaj[kcontrol->private_value].items);
3711}
3712
3713
3714
3715
3716
3717static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
3718 struct snd_ctl_elem_value *ucontrol)
3719{
3720 unsigned short datpag, uaj;
3721 struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
3722
3723 mutex_lock(&pac97->page_mutex);
3724
3725 datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
3726 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
3727
3728 uaj = snd_ac97_read(pac97, 0x60) &
3729 vt1618_uaj[kcontrol->private_value].mask;
3730
3731 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
3732 mutex_unlock(&pac97->page_mutex);
3733
3734 ucontrol->value.enumerated.item[0] = uaj >>
3735 vt1618_uaj[kcontrol->private_value].shift;
3736
3737 return 0;
3738}
3739
3740static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
3741 struct snd_ctl_elem_value *ucontrol)
3742{
3743 return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
3744 vt1618_uaj[kcontrol->private_value].mask,
3745 ucontrol->value.enumerated.item[0]<<
3746 vt1618_uaj[kcontrol->private_value].shift,
3747 0);
3748}
3749
3750
3751
3752static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
3753 struct snd_ctl_elem_info *uinfo)
3754{
3755 static const char * const txt_aux[] = {"Aux In", "Back Surr Out"};
3756
3757 return snd_ctl_enum_info(uinfo, 1, 2, txt_aux);
3758}
3759
3760static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
3761 struct snd_ctl_elem_value *ucontrol)
3762{
3763 ucontrol->value.enumerated.item[0] =
3764 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
3765 return 0;
3766}
3767
3768static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
3769 struct snd_ctl_elem_value *ucontrol)
3770{
3771
3772
3773 snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
3774 ucontrol->value.enumerated.item[0] << 3);
3775
3776
3777
3778 return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
3779 ucontrol->value.enumerated.item[0] << 3);
3780}
3781
3782static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
3783 AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
3784 AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
3785 AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
3786 AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
3787 AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
3788 AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
3789 {
3790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3791 .name = "Speaker Jack Mode",
3792 .info = snd_ac97_vt1618_UAJ_info,
3793 .get = snd_ac97_vt1618_UAJ_get,
3794 .put = snd_ac97_vt1618_UAJ_put,
3795 .private_value = 0
3796 },
3797 {
3798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3799 .name = "Line Jack Mode",
3800 .info = snd_ac97_vt1618_UAJ_info,
3801 .get = snd_ac97_vt1618_UAJ_get,
3802 .put = snd_ac97_vt1618_UAJ_put,
3803 .private_value = 1
3804 },
3805 {
3806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3807 .name = "Mic Jack Mode",
3808 .info = snd_ac97_vt1618_UAJ_info,
3809 .get = snd_ac97_vt1618_UAJ_get,
3810 .put = snd_ac97_vt1618_UAJ_put,
3811 .private_value = 2
3812 },
3813 {
3814 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3815 .name = "Aux Jack Mode",
3816 .info = snd_ac97_vt1618_aux_info,
3817 .get = snd_ac97_vt1618_aux_get,
3818 .put = snd_ac97_vt1618_aux_put,
3819 }
3820};
3821
3822static int patch_vt1618(struct snd_ac97 *ac97)
3823{
3824 return patch_build_controls(ac97, snd_ac97_controls_vt1618,
3825 ARRAY_SIZE(snd_ac97_controls_vt1618));
3826}
3827
3828
3829
3830static void it2646_update_jacks(struct snd_ac97 *ac97)
3831{
3832
3833 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
3834 is_shared_surrout(ac97) ? (1<<9) : 0);
3835
3836 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
3837 is_shared_clfeout(ac97) ? (1<<10) : 0);
3838}
3839
3840static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
3841 AC97_SURROUND_JACK_MODE_CTL,
3842 AC97_CHANNEL_MODE_CTL,
3843};
3844
3845static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
3846 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
3847 AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
3848 AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
3849};
3850
3851static int patch_it2646_specific(struct snd_ac97 * ac97)
3852{
3853 int err;
3854 err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646));
3855 if (err < 0)
3856 return err;
3857 err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646));
3858 if (err < 0)
3859 return err;
3860 return 0;
3861}
3862
3863static const struct snd_ac97_build_ops patch_it2646_ops = {
3864 .build_specific = patch_it2646_specific,
3865 .update_jacks = it2646_update_jacks
3866};
3867
3868static int patch_it2646(struct snd_ac97 * ac97)
3869{
3870 ac97->build_ops = &patch_it2646_ops;
3871
3872 snd_ac97_write_cache(ac97, 0x5E, 0x0808);
3873 snd_ac97_write_cache(ac97, 0x7A, 0x0808);
3874 return 0;
3875}
3876
3877
3878
3879
3880
3881#define AC97_SI3036_CHIP_ID 0x5a
3882#define AC97_SI3036_LINE_CFG 0x5c
3883
3884static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
3885AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
3886};
3887
3888static int patch_si3036_specific(struct snd_ac97 * ac97)
3889{
3890 int idx, err;
3891 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) {
3892 err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97));
3893 if (err < 0)
3894 return err;
3895 }
3896 return 0;
3897}
3898
3899static const struct snd_ac97_build_ops patch_si3036_ops = {
3900 .build_specific = patch_si3036_specific,
3901};
3902
3903static int mpatch_si3036(struct snd_ac97 * ac97)
3904{
3905 ac97->build_ops = &patch_si3036_ops;
3906 snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
3907 snd_ac97_write_cache(ac97, 0x68, 0);
3908 return 0;
3909}
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919static const struct snd_ac97_res_table lm4550_restbl[] = {
3920 { AC97_MASTER, 0x1f1f },
3921 { AC97_HEADPHONE, 0x1f1f },
3922 { AC97_MASTER_MONO, 0x001f },
3923 { AC97_PC_BEEP, 0x001f },
3924 { AC97_PHONE, 0x001f },
3925 { AC97_MIC, 0x001f },
3926 { AC97_LINE, 0x1f1f },
3927 { AC97_CD, 0x1f1f },
3928 { AC97_VIDEO, 0x1f1f },
3929 { AC97_AUX, 0x1f1f },
3930 { AC97_PCM, 0x1f1f },
3931 { AC97_REC_GAIN, 0x0f0f },
3932 { }
3933};
3934
3935static int patch_lm4550(struct snd_ac97 *ac97)
3936{
3937 ac97->res_table = lm4550_restbl;
3938 return 0;
3939}
3940
3941
3942
3943
3944static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = {
3945
3946
3947
3948AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0),
3949
3950
3951AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0),
3952
3953
3954AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0),
3955};
3956
3957static int patch_ucb1400_specific(struct snd_ac97 * ac97)
3958{
3959 int idx, err;
3960 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) {
3961 err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97));
3962 if (err < 0)
3963 return err;
3964 }
3965 return 0;
3966}
3967
3968static const struct snd_ac97_build_ops patch_ucb1400_ops = {
3969 .build_specific = patch_ucb1400_specific,
3970};
3971
3972static int patch_ucb1400(struct snd_ac97 * ac97)
3973{
3974 ac97->build_ops = &patch_ucb1400_ops;
3975
3976 snd_ac97_write_cache(ac97, 0x6a, 0x0050);
3977 snd_ac97_write_cache(ac97, 0x6c, 0x0030);
3978 return 0;
3979}
3980