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