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 0x103c300d,
1913 0x17340088,
1914 0
1915};
1916
1917static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
1918{
1919 if (check_list(ac97, ad1981_jacks_whitelist))
1920
1921 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
1922}
1923
1924static int patch_ad1981a(struct snd_ac97 *ac97)
1925{
1926 patch_ad1881(ac97);
1927 ac97->build_ops = &patch_ad1981a_build_ops;
1928 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1929 ac97->flags |= AC97_STEREO_MUTES;
1930 check_ad1981_hp_jack_sense(ac97);
1931 return 0;
1932}
1933
1934static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
1935AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
1936
1937static int patch_ad1981b_specific(struct snd_ac97 *ac97)
1938{
1939 int err;
1940
1941 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
1942 return err;
1943 if (check_list(ac97, ad1981_jacks_blacklist))
1944 return 0;
1945 return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
1946 ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
1947}
1948
1949static const struct snd_ac97_build_ops patch_ad1981b_build_ops = {
1950 .build_post_spdif = patch_ad198x_post_spdif,
1951 .build_specific = patch_ad1981b_specific,
1952#ifdef CONFIG_PM
1953 .resume = ad18xx_resume
1954#endif
1955};
1956
1957static int patch_ad1981b(struct snd_ac97 *ac97)
1958{
1959 patch_ad1881(ac97);
1960 ac97->build_ops = &patch_ad1981b_build_ops;
1961 snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
1962 ac97->flags |= AC97_STEREO_MUTES;
1963 check_ad1981_hp_jack_sense(ac97);
1964 return 0;
1965}
1966
1967#define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
1968
1969static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1970{
1971 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1972 unsigned short val;
1973
1974 val = ac97->regs[AC97_AD_MISC];
1975 ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
1976 if (ac97->spec.ad18xx.lo_as_master)
1977 ucontrol->value.integer.value[0] =
1978 !ucontrol->value.integer.value[0];
1979 return 0;
1980}
1981
1982static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1983{
1984 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1985 unsigned short val;
1986
1987 val = !ucontrol->value.integer.value[0];
1988 if (ac97->spec.ad18xx.lo_as_master)
1989 val = !val;
1990 val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
1991 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
1992 AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
1993}
1994
1995static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1996{
1997 static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
1998
1999 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2000 uinfo->count = 1;
2001 uinfo->value.enumerated.items = 3;
2002 if (uinfo->value.enumerated.item > 2)
2003 uinfo->value.enumerated.item = 2;
2004 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2005 return 0;
2006}
2007
2008static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2009{
2010 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2011 unsigned short val;
2012
2013 val = ac97->regs[AC97_AD_MISC];
2014 if (!(val & AC97_AD198X_DMIX1))
2015 ucontrol->value.enumerated.item[0] = 0;
2016 else
2017 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
2018 return 0;
2019}
2020
2021static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2022{
2023 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2024 unsigned short val;
2025
2026 if (ucontrol->value.enumerated.item[0] > 2)
2027 return -EINVAL;
2028 if (ucontrol->value.enumerated.item[0] == 0)
2029 val = 0;
2030 else
2031 val = AC97_AD198X_DMIX1 |
2032 ((ucontrol->value.enumerated.item[0] - 1) << 8);
2033 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2034 AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
2035}
2036
2037static void ad1888_update_jacks(struct snd_ac97 *ac97)
2038{
2039 unsigned short val = 0;
2040
2041 if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
2042 val |= (1 << 12);
2043
2044 if (is_shared_micin(ac97))
2045 val |= (1 << 11);
2046
2047 snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
2048}
2049
2050static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
2051 {
2052 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2053 .name = "Exchange Front/Surround",
2054 .info = snd_ac97_ad1888_lohpsel_info,
2055 .get = snd_ac97_ad1888_lohpsel_get,
2056 .put = snd_ac97_ad1888_lohpsel_put
2057 },
2058 AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
2059 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
2060 AC97_AD_HPFD_SHIFT, 1, 1),
2061 AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
2062 {
2063 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2064 .name = "Downmix",
2065 .info = snd_ac97_ad1888_downmix_info,
2066 .get = snd_ac97_ad1888_downmix_get,
2067 .put = snd_ac97_ad1888_downmix_put
2068 },
2069 AC97_SURROUND_JACK_MODE_CTL,
2070 AC97_CHANNEL_MODE_CTL,
2071
2072 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2073 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2074};
2075
2076static int patch_ad1888_specific(struct snd_ac97 *ac97)
2077{
2078 if (!ac97->spec.ad18xx.lo_as_master) {
2079
2080 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2081 "Master Surround Playback");
2082 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
2083 "Master Playback");
2084 }
2085 return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
2086}
2087
2088static const struct snd_ac97_build_ops patch_ad1888_build_ops = {
2089 .build_post_spdif = patch_ad198x_post_spdif,
2090 .build_specific = patch_ad1888_specific,
2091#ifdef CONFIG_PM
2092 .resume = ad1888_resume,
2093#endif
2094 .update_jacks = ad1888_update_jacks,
2095};
2096
2097static int patch_ad1888(struct snd_ac97 * ac97)
2098{
2099 unsigned short misc;
2100
2101 patch_ad1881(ac97);
2102 ac97->build_ops = &patch_ad1888_build_ops;
2103
2104
2105
2106
2107
2108 if (ac97->subsystem_vendor == 0x1043 &&
2109 ac97->subsystem_device == 0x1193)
2110 ac97->spec.ad18xx.lo_as_master = 1;
2111
2112 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2113
2114
2115 misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
2116 if (!ac97->spec.ad18xx.lo_as_master)
2117
2118
2119
2120
2121 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
2122
2123 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
2124 ac97->flags |= AC97_STEREO_MUTES;
2125 return 0;
2126}
2127
2128static int patch_ad1980_specific(struct snd_ac97 *ac97)
2129{
2130 int err;
2131
2132 if ((err = patch_ad1888_specific(ac97)) < 0)
2133 return err;
2134 return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
2135}
2136
2137static const struct snd_ac97_build_ops patch_ad1980_build_ops = {
2138 .build_post_spdif = patch_ad198x_post_spdif,
2139 .build_specific = patch_ad1980_specific,
2140#ifdef CONFIG_PM
2141 .resume = ad18xx_resume,
2142#endif
2143 .update_jacks = ad1888_update_jacks,
2144};
2145
2146static int patch_ad1980(struct snd_ac97 * ac97)
2147{
2148 patch_ad1888(ac97);
2149 ac97->build_ops = &patch_ad1980_build_ops;
2150 return 0;
2151}
2152
2153static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2154 struct snd_ctl_elem_info *uinfo)
2155{
2156 static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
2157
2158 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2159 uinfo->count = 1;
2160 uinfo->value.enumerated.items = 4;
2161 if (uinfo->value.enumerated.item > 3)
2162 uinfo->value.enumerated.item = 3;
2163 strcpy(uinfo->value.enumerated.name,
2164 texts[uinfo->value.enumerated.item]);
2165 return 0;
2166}
2167
2168static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2169 struct snd_ctl_elem_value *ucontrol)
2170{
2171 static const int reg2ctrl[4] = {2, 0, 1, 3};
2172 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2173 unsigned short val;
2174 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2175 >> AC97_AD198X_VREF_SHIFT;
2176 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2177 return 0;
2178}
2179
2180static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2181 struct snd_ctl_elem_value *ucontrol)
2182{
2183 static const int ctrl2reg[4] = {1, 2, 0, 3};
2184 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2185 unsigned short val;
2186
2187 if (ucontrol->value.enumerated.item[0] > 3)
2188 return -EINVAL;
2189 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2190 << AC97_AD198X_VREF_SHIFT;
2191 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2192 AC97_AD198X_VREF_MASK, val);
2193}
2194
2195static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
2196 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2197 {
2198 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2199 .name = "Exchange Front/Surround",
2200 .info = snd_ac97_ad1888_lohpsel_info,
2201 .get = snd_ac97_ad1888_lohpsel_get,
2202 .put = snd_ac97_ad1888_lohpsel_put
2203 },
2204 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2205 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2206 AC97_AD_MISC, 7, 1, 0),
2207 {
2208 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2209 .name = "Downmix",
2210 .info = snd_ac97_ad1888_downmix_info,
2211 .get = snd_ac97_ad1888_downmix_get,
2212 .put = snd_ac97_ad1888_downmix_put
2213 },
2214 {
2215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2216 .name = "V_REFOUT",
2217 .info = snd_ac97_ad1985_vrefout_info,
2218 .get = snd_ac97_ad1985_vrefout_get,
2219 .put = snd_ac97_ad1985_vrefout_put
2220 },
2221 AC97_SURROUND_JACK_MODE_CTL,
2222 AC97_CHANNEL_MODE_CTL,
2223
2224 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2225 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
2226};
2227
2228static void ad1985_update_jacks(struct snd_ac97 *ac97)
2229{
2230 ad1888_update_jacks(ac97);
2231
2232 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
2233 is_shared_micin(ac97) ? 1 << 9 : 0);
2234}
2235
2236static int patch_ad1985_specific(struct snd_ac97 *ac97)
2237{
2238 int err;
2239
2240
2241 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2242 "Master Surround Playback");
2243 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2244
2245 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2246 return err;
2247
2248 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2249 ARRAY_SIZE(snd_ac97_ad1985_controls));
2250}
2251
2252static const struct snd_ac97_build_ops patch_ad1985_build_ops = {
2253 .build_post_spdif = patch_ad198x_post_spdif,
2254 .build_specific = patch_ad1985_specific,
2255#ifdef CONFIG_PM
2256 .resume = ad18xx_resume,
2257#endif
2258 .update_jacks = ad1985_update_jacks,
2259};
2260
2261static int patch_ad1985(struct snd_ac97 * ac97)
2262{
2263 unsigned short misc;
2264
2265 patch_ad1881(ac97);
2266 ac97->build_ops = &patch_ad1985_build_ops;
2267 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2268
2269
2270
2271 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2272 AC97_AD198X_LOSEL |
2273 AC97_AD198X_HPSEL |
2274 AC97_AD198X_MSPLT |
2275 AC97_AD198X_AC97NC);
2276 ac97->flags |= AC97_STEREO_MUTES;
2277
2278
2279 ad1985_update_jacks(ac97);
2280
2281
2282 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2283 return 0;
2284}
2285
2286#define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
2287
2288static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2289 struct snd_ctl_elem_value *ucontrol)
2290{
2291 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2292 unsigned short val;
2293
2294 val = ac97->regs[AC97_AD_MISC3];
2295 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2296 return 0;
2297}
2298
2299static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2300 struct snd_ctl_elem_value *ucontrol)
2301{
2302 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2303 int ret0;
2304 int ret1;
2305 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2306
2307 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2308 ucontrol->value.integer.value[0] != 0
2309 ? AC97_AD1986_LOSEL : 0);
2310 if (ret0 < 0)
2311 return ret0;
2312
2313
2314 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2315 (ucontrol->value.integer.value[0] != 0
2316 || sprd)
2317 ? AC97_AD1986_SOSEL : 0);
2318 if (ret1 < 0)
2319 return ret1;
2320
2321 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2322}
2323
2324static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2325 struct snd_ctl_elem_value *ucontrol)
2326{
2327 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2328 unsigned short val;
2329
2330 val = ac97->regs[AC97_AD_MISC];
2331 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2332 return 0;
2333}
2334
2335static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2336 struct snd_ctl_elem_value *ucontrol)
2337{
2338 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2339 int ret0;
2340 int ret1;
2341 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2342
2343 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2344 ucontrol->value.integer.value[0] != 0
2345 ? AC97_AD1986_SPRD : 0);
2346 if (ret0 < 0)
2347 return ret0;
2348
2349
2350 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2351 (ucontrol->value.integer.value[0] != 0
2352 || sprd)
2353 ? AC97_AD1986_SOSEL : 0);
2354 if (ret1 < 0)
2355 return ret1;
2356
2357 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2358}
2359
2360static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2361 struct snd_ctl_elem_value *ucontrol)
2362{
2363 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2364
2365 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2366 return 0;
2367}
2368
2369static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2370 struct snd_ctl_elem_value *ucontrol)
2371{
2372 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2373 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2374
2375 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2376 ac97->spec.ad18xx.swap_mic_linein = swap;
2377 if (ac97->build_ops->update_jacks)
2378 ac97->build_ops->update_jacks(ac97);
2379 return 1;
2380 }
2381 return 0;
2382}
2383
2384static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2385 struct snd_ctl_elem_value *ucontrol)
2386{
2387
2388 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2389 unsigned short val;
2390 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2391 if ((reg & AC97_AD1986_MVREF0) != 0)
2392 val = 2;
2393 else if ((reg & AC97_AD1986_MVREF1) != 0)
2394 val = 3;
2395 else if ((reg & AC97_AD1986_MVREF2) != 0)
2396 val = 1;
2397 else
2398 val = 0;
2399 ucontrol->value.enumerated.item[0] = val;
2400 return 0;
2401}
2402
2403static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2404 struct snd_ctl_elem_value *ucontrol)
2405{
2406 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2407 unsigned short cval;
2408 unsigned short lval;
2409 unsigned short mval;
2410 int cret;
2411 int lret;
2412 int mret;
2413
2414 switch (ucontrol->value.enumerated.item[0])
2415 {
2416 case 0:
2417 cval = 0;
2418 lval = 0;
2419 mval = 0;
2420 break;
2421 case 1:
2422 cval = AC97_AD1986_CVREF2;
2423 lval = AC97_AD1986_LVREF2;
2424 mval = AC97_AD1986_MVREF2;
2425 break;
2426 case 2:
2427 cval = AC97_AD1986_CVREF0;
2428 lval = AC97_AD1986_LVREF0;
2429 mval = AC97_AD1986_MVREF0;
2430 break;
2431 case 3:
2432 cval = AC97_AD1986_CVREF1;
2433 lval = AC97_AD1986_LVREF1;
2434 mval = AC97_AD1986_MVREF1;
2435 break;
2436 default:
2437 return -EINVAL;
2438 }
2439
2440 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2441 AC97_AD1986_CVREF_MASK, cval);
2442 if (cret < 0)
2443 return cret;
2444 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2445 AC97_AD1986_LVREF_MASK, lval);
2446 if (lret < 0)
2447 return lret;
2448 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2449 AC97_AD1986_MVREF_MASK, mval);
2450 if (mret < 0)
2451 return mret;
2452
2453 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2454}
2455
2456static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2457 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2458 {
2459 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2460 .name = "Exchange Front/Surround",
2461 .info = snd_ac97_ad1986_bool_info,
2462 .get = snd_ac97_ad1986_lososel_get,
2463 .put = snd_ac97_ad1986_lososel_put
2464 },
2465 {
2466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2467 .name = "Exchange Mic/Line In",
2468 .info = snd_ac97_ad1986_bool_info,
2469 .get = snd_ac97_ad1986_miclisel_get,
2470 .put = snd_ac97_ad1986_miclisel_put
2471 },
2472 {
2473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2474 .name = "Spread Front to Surround and Center/LFE",
2475 .info = snd_ac97_ad1986_bool_info,
2476 .get = snd_ac97_ad1986_spread_get,
2477 .put = snd_ac97_ad1986_spread_put
2478 },
2479 {
2480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2481 .name = "Downmix",
2482 .info = snd_ac97_ad1888_downmix_info,
2483 .get = snd_ac97_ad1888_downmix_get,
2484 .put = snd_ac97_ad1888_downmix_put
2485 },
2486 {
2487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2488 .name = "V_REFOUT",
2489 .info = snd_ac97_ad1985_vrefout_info,
2490 .get = snd_ac97_ad1986_vrefout_get,
2491 .put = snd_ac97_ad1986_vrefout_put
2492 },
2493 AC97_SURROUND_JACK_MODE_CTL,
2494 AC97_CHANNEL_MODE_CTL,
2495
2496 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2497 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2498};
2499
2500static void ad1986_update_jacks(struct snd_ac97 *ac97)
2501{
2502 unsigned short misc_val = 0;
2503 unsigned short ser_val;
2504
2505
2506 if (!is_surround_on(ac97))
2507 misc_val |= AC97_AD1986_SODIS;
2508 if (!is_clfe_on(ac97))
2509 misc_val |= AC97_AD1986_CLDIS;
2510
2511
2512 if (is_shared_linein(ac97))
2513 misc_val |= AC97_AD1986_LISEL_SURR;
2514 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2515 misc_val |= AC97_AD1986_LISEL_MIC;
2516 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2517 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2518 AC97_AD1986_LISEL_MASK,
2519 misc_val);
2520
2521
2522 if (is_shared_micin(ac97))
2523 ser_val = AC97_AD1986_OMS_C;
2524 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2525 ser_val = AC97_AD1986_OMS_L;
2526 else
2527 ser_val = AC97_AD1986_OMS_M;
2528 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2529 AC97_AD1986_OMS_MASK,
2530 ser_val);
2531}
2532
2533static int patch_ad1986_specific(struct snd_ac97 *ac97)
2534{
2535 int err;
2536
2537 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2538 return err;
2539
2540 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2541 ARRAY_SIZE(snd_ac97_ad1985_controls));
2542}
2543
2544static const struct snd_ac97_build_ops patch_ad1986_build_ops = {
2545 .build_post_spdif = patch_ad198x_post_spdif,
2546 .build_specific = patch_ad1986_specific,
2547#ifdef CONFIG_PM
2548 .resume = ad18xx_resume,
2549#endif
2550 .update_jacks = ad1986_update_jacks,
2551};
2552
2553static int patch_ad1986(struct snd_ac97 * ac97)
2554{
2555 patch_ad1881(ac97);
2556 ac97->build_ops = &patch_ad1986_build_ops;
2557 ac97->flags |= AC97_STEREO_MUTES;
2558
2559
2560 ad1986_update_jacks(ac97);
2561
2562 return 0;
2563}
2564
2565
2566
2567
2568static int patch_alc203(struct snd_ac97 *ac97)
2569{
2570 snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
2571 return 0;
2572}
2573
2574
2575
2576
2577static void alc650_update_jacks(struct snd_ac97 *ac97)
2578{
2579 int shared;
2580
2581
2582 shared = is_shared_surrout(ac97);
2583 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2584 shared ? (1 << 9) : 0);
2585
2586 shared = is_shared_clfeout(ac97);
2587
2588 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2589 shared ? (1 << 12) : 0);
2590
2591 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
2592 shared ? (1 << 10) : 0);
2593
2594 snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
2595 shared ? 0 : 0x100);
2596}
2597
2598static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
2599 struct snd_ctl_elem_value *ucontrol)
2600{
2601 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2602 struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
2603
2604 if (map) {
2605 if (ucontrol->value.integer.value[0])
2606 map->chmap = snd_pcm_std_chmaps;
2607 else
2608 map->chmap = snd_pcm_alt_chmaps;
2609 }
2610 return snd_ac97_put_volsw(kcontrol, ucontrol);
2611}
2612
2613static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2614 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2615 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
2616 AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
2617 AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
2618
2619
2620
2621
2622
2623
2624
2625
2626 {
2627 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2628 .name = "Swap Surround Slot",
2629 .info = snd_ac97_info_volsw,
2630 .get = snd_ac97_get_volsw,
2631 .put = alc650_swap_surround_put,
2632 .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
2633 },
2634#if 0
2635 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2636 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
2637 AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
2638 AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
2639 AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
2640 AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
2641#endif
2642 AC97_SURROUND_JACK_MODE_CTL,
2643 AC97_CHANNEL_MODE_CTL,
2644};
2645
2646static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2647 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
2648 AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
2649
2650
2651};
2652
2653static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2654
2655static int patch_alc650_specific(struct snd_ac97 * ac97)
2656{
2657 int err;
2658
2659 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
2660 return err;
2661 if (ac97->ext_id & AC97_EI_SPDIF) {
2662 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
2663 return err;
2664 }
2665 if (ac97->id != AC97_ID_ALC650F)
2666 reset_tlv(ac97, "Master Playback Volume",
2667 db_scale_5bit_3db_max);
2668 return 0;
2669}
2670
2671static const struct snd_ac97_build_ops patch_alc650_ops = {
2672 .build_specific = patch_alc650_specific,
2673 .update_jacks = alc650_update_jacks
2674};
2675
2676static int patch_alc650(struct snd_ac97 * ac97)
2677{
2678 unsigned short val;
2679
2680 ac97->build_ops = &patch_alc650_ops;
2681
2682
2683 val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
2684 if (val < 3)
2685 ac97->id = 0x414c4720;
2686 else if (val < 0x10)
2687 ac97->id = 0x414c4721;
2688 else if (val < 0x20)
2689 ac97->id = 0x414c4722;
2690 else if (val < 0x30)
2691 ac97->id = 0x414c4723;
2692
2693
2694
2695 ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
2696 ac97->id == 0x414c4723);
2697
2698
2699 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2700 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
2701
2702
2703 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2704
2705 if (ac97->spec.dev_flags &&
2706
2707 ! (ac97->subsystem_vendor == 0x1043 &&
2708 ac97->subsystem_device == 0x1103))
2709 val |= 0x03;
2710 else
2711 val &= ~0x03;
2712 snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
2713
2714
2715
2716
2717
2718
2719 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
2720
2721
2722
2723 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
2724 snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
2725 snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
2726 (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
2727
2728
2729 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2730 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2731 return 0;
2732}
2733
2734static void alc655_update_jacks(struct snd_ac97 *ac97)
2735{
2736 int shared;
2737
2738
2739 shared = is_shared_surrout(ac97);
2740 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2741 shared ? (1 << 9) : 0, 0);
2742
2743 shared = is_shared_clfeout(ac97);
2744
2745 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2746 shared ? (1 << 12) : 0);
2747 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
2748 shared ? (1 << 10) : 0, 0);
2749}
2750
2751static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
2752 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2753 AC97_SURROUND_JACK_MODE_CTL,
2754 AC97_CHANNEL_MODE_CTL,
2755};
2756
2757static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2758{
2759 static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" };
2760 static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" };
2761 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2762
2763 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2764 uinfo->count = 1;
2765 uinfo->value.enumerated.items = ac97->spec.dev_flags ? 4 : 3;
2766 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2767 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2768 strcpy(uinfo->value.enumerated.name,
2769 ac97->spec.dev_flags ?
2770 texts_658[uinfo->value.enumerated.item] :
2771 texts_655[uinfo->value.enumerated.item]);
2772 return 0;
2773}
2774
2775static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2776{
2777 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2778 unsigned short val;
2779
2780 val = ac97->regs[AC97_ALC650_MULTICH];
2781 val = (val >> 12) & 3;
2782 if (ac97->spec.dev_flags && val == 3)
2783 val = 0;
2784 ucontrol->value.enumerated.item[0] = val;
2785 return 0;
2786}
2787
2788static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2789{
2790 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2791
2792 return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
2793 (unsigned short)ucontrol->value.enumerated.item[0] << 12,
2794 0);
2795}
2796
2797static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
2798 AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
2799
2800
2801 {
2802 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2803 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2804 .info = alc655_iec958_route_info,
2805 .get = alc655_iec958_route_get,
2806 .put = alc655_iec958_route_put,
2807 },
2808};
2809
2810static int patch_alc655_specific(struct snd_ac97 * ac97)
2811{
2812 int err;
2813
2814 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0)
2815 return err;
2816 if (ac97->ext_id & AC97_EI_SPDIF) {
2817 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
2818 return err;
2819 }
2820 return 0;
2821}
2822
2823static const struct snd_ac97_build_ops patch_alc655_ops = {
2824 .build_specific = patch_alc655_specific,
2825 .update_jacks = alc655_update_jacks
2826};
2827
2828static int patch_alc655(struct snd_ac97 * ac97)
2829{
2830 unsigned int val;
2831
2832 if (ac97->id == AC97_ID_ALC658) {
2833 ac97->spec.dev_flags = 1;
2834 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
2835 ac97->id = AC97_ID_ALC658D;
2836 ac97->spec.dev_flags = 2;
2837 }
2838 }
2839
2840 ac97->build_ops = &patch_alc655_ops;
2841
2842
2843 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2844
2845
2846 val = snd_ac97_read(ac97, 0x7a);
2847 if (ac97->spec.dev_flags)
2848 val &= ~(1 << 1);
2849 else {
2850 if (ac97->subsystem_vendor == 0x1462 &&
2851 (ac97->subsystem_device == 0x0131 ||
2852 ac97->subsystem_device == 0x0161 ||
2853 ac97->subsystem_device == 0x0351 ||
2854 ac97->subsystem_device == 0x0471 ||
2855 ac97->subsystem_device == 0x0061))
2856 val &= ~(1 << 1);
2857 else
2858 val |= (1 << 1);
2859
2860 ac97->ext_id |= AC97_EI_SPDIF;
2861 }
2862 val &= ~(1 << 12);
2863 snd_ac97_write_cache(ac97, 0x7a, val);
2864
2865
2866
2867
2868
2869 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2870
2871
2872 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2873 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2874
2875
2876 if (ac97->id == AC97_ID_ALC658D)
2877 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2878
2879 return 0;
2880}
2881
2882
2883#define AC97_ALC850_JACK_SELECT 0x76
2884#define AC97_ALC850_MISC1 0x7a
2885#define AC97_ALC850_MULTICH 0x6a
2886
2887static void alc850_update_jacks(struct snd_ac97 *ac97)
2888{
2889 int shared;
2890 int aux_is_back_surround;
2891
2892
2893 shared = is_shared_surrout(ac97);
2894
2895 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2896 shared ? (1<<5) : (1<<4));
2897
2898 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2899 shared ? (2<<12) : (0<<12));
2900
2901 shared = is_shared_clfeout(ac97);
2902
2903 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2904 shared ? (1<<12) : (1<<13));
2905
2906 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
2907 shared ? (5<<4) : (1<<4));
2908
2909 aux_is_back_surround = alc850_is_aux_back_surround(ac97);
2910
2911 snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
2912 aux_is_back_surround ? (1<<10) : (0<<10));
2913}
2914
2915static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
2916 AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
2917 AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
2918 AC97_SURROUND_JACK_MODE_CTL,
2919 AC97_CHANNEL_MODE_8CH_CTL,
2920};
2921
2922static int patch_alc850_specific(struct snd_ac97 *ac97)
2923{
2924 int err;
2925
2926 if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
2927 return err;
2928 if (ac97->ext_id & AC97_EI_SPDIF) {
2929 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
2930 return err;
2931 }
2932 return 0;
2933}
2934
2935static const struct snd_ac97_build_ops patch_alc850_ops = {
2936 .build_specific = patch_alc850_specific,
2937 .update_jacks = alc850_update_jacks
2938};
2939
2940static int patch_alc850(struct snd_ac97 *ac97)
2941{
2942 ac97->build_ops = &patch_alc850_ops;
2943
2944 ac97->spec.dev_flags = 0;
2945 ac97->flags |= AC97_HAS_8CH;
2946
2947
2948 snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
2949
2950
2951
2952
2953
2954
2955
2956
2957 snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
2958
2959
2960
2961 snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
2962 (1<<7)|(0<<12)|(1<<13)|(0<<14));
2963
2964
2965
2966 snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
2967 (1<<11)|(0<<12)|(1<<15));
2968
2969
2970 snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
2971 snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
2972 return 0;
2973}
2974
2975static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
2976{
2977 struct snd_kcontrol *kctl_3d_center =
2978 snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
2979 struct snd_kcontrol *kctl_3d_depth =
2980 snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
2981
2982
2983
2984
2985
2986 if (kctl_3d_center) {
2987 kctl_3d_center->private_value =
2988 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
2989 snd_ac97_rename_vol_ctl(ac97,
2990 "3D Control - Center", "3D Control - Width"
2991 );
2992 }
2993 if (kctl_3d_depth)
2994 kctl_3d_depth->private_value =
2995 AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
2996
2997
2998
2999 snd_ac97_rename_vol_ctl(ac97,
3000 "Master Mono Playback", "Modem Playback"
3001 );
3002 snd_ac97_rename_vol_ctl(ac97,
3003 "Headphone Playback", "FM Synth Playback"
3004 );
3005
3006 return 0;
3007}
3008
3009static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
3010 .build_specific = patch_aztech_azf3328_specific
3011};
3012
3013static int patch_aztech_azf3328(struct snd_ac97 *ac97)
3014{
3015 ac97->build_ops = &patch_aztech_azf3328_ops;
3016 return 0;
3017}
3018
3019
3020
3021
3022static void cm9738_update_jacks(struct snd_ac97 *ac97)
3023{
3024
3025 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
3026 is_shared_surrout(ac97) ? (1 << 10) : 0);
3027}
3028
3029static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
3030 AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
3031 AC97_SURROUND_JACK_MODE_CTL,
3032 AC97_CHANNEL_MODE_4CH_CTL,
3033};
3034
3035static int patch_cm9738_specific(struct snd_ac97 * ac97)
3036{
3037 return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
3038}
3039
3040static const struct snd_ac97_build_ops patch_cm9738_ops = {
3041 .build_specific = patch_cm9738_specific,
3042 .update_jacks = cm9738_update_jacks
3043};
3044
3045static int patch_cm9738(struct snd_ac97 * ac97)
3046{
3047 ac97->build_ops = &patch_cm9738_ops;
3048
3049
3050 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3051 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3052
3053 return 0;
3054}
3055
3056static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3057{
3058 static char *texts[] = { "Analog", "Digital" };
3059
3060 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3061 uinfo->count = 1;
3062 uinfo->value.enumerated.items = 2;
3063 if (uinfo->value.enumerated.item > 1)
3064 uinfo->value.enumerated.item = 1;
3065 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3066 return 0;
3067}
3068
3069static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3070{
3071 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3072 unsigned short val;
3073
3074 val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
3075 ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
3076 return 0;
3077}
3078
3079static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3080{
3081 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3082
3083 return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
3084 0x01 << 1,
3085 (ucontrol->value.enumerated.item[0] & 0x01) << 1);
3086}
3087
3088static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
3089
3090 {
3091 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3092 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3093 .info = snd_ac97_cmedia_spdif_playback_source_info,
3094 .get = snd_ac97_cmedia_spdif_playback_source_get,
3095 .put = snd_ac97_cmedia_spdif_playback_source_put,
3096 },
3097
3098 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
3099
3100 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
3101
3102 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
3103
3104};
3105
3106static void cm9739_update_jacks(struct snd_ac97 *ac97)
3107{
3108
3109 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
3110 is_shared_surrout(ac97) ? (1 << 10) : 0);
3111
3112 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
3113 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
3114}
3115
3116static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
3117 AC97_SURROUND_JACK_MODE_CTL,
3118 AC97_CHANNEL_MODE_CTL,
3119};
3120
3121static int patch_cm9739_specific(struct snd_ac97 * ac97)
3122{
3123 return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
3124}
3125
3126static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
3127{
3128 return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
3129}
3130
3131static const struct snd_ac97_build_ops patch_cm9739_ops = {
3132 .build_specific = patch_cm9739_specific,
3133 .build_post_spdif = patch_cm9739_post_spdif,
3134 .update_jacks = cm9739_update_jacks
3135};
3136
3137static int patch_cm9739(struct snd_ac97 * ac97)
3138{
3139 unsigned short val;
3140
3141 ac97->build_ops = &patch_cm9739_ops;
3142
3143
3144 ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
3145 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
3146 snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
3147
3148
3149 val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
3150 if (val & AC97_EA_SPCV) {
3151
3152 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3153 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
3154 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3155 } else {
3156 ac97->ext_id &= ~AC97_EI_SPDIF;
3157 ac97->rates[AC97_RATES_SPDIF] = 0;
3158 }
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169 val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
3170 val |= (1 << 3);
3171 val |= (1 << 13);
3172 if (! (ac97->ext_id & AC97_EI_SPDIF))
3173 val |= (1 << 14);
3174 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
3175
3176
3177 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3178 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3179
3180 if (ac97->pci &&
3181 ac97->subsystem_vendor == 0x1043 &&
3182 ac97->subsystem_device == 0x1843) {
3183 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
3184 snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
3185 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
3186 snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
3187 }
3188
3189 return 0;
3190}
3191
3192#define AC97_CM9761_MULTI_CHAN 0x64
3193#define AC97_CM9761_FUNC 0x66
3194#define AC97_CM9761_SPDIF_CTRL 0x6c
3195
3196static void cm9761_update_jacks(struct snd_ac97 *ac97)
3197{
3198
3199
3200
3201 static unsigned short surr_on[3][2] = {
3202 { 0x0008, 0x0000 },
3203 { 0x0000, 0x0008 },
3204 { 0x0000, 0x0008 },
3205 };
3206 static unsigned short clfe_on[3][2] = {
3207 { 0x0000, 0x1000 },
3208 { 0x1000, 0x0000 },
3209 { 0x0000, 0x1000 },
3210 };
3211 static unsigned short surr_shared[3][2] = {
3212 { 0x0000, 0x0400 },
3213 { 0x0000, 0x0400 },
3214 { 0x0000, 0x0400 },
3215 };
3216 static unsigned short clfe_shared[3][2] = {
3217 { 0x2000, 0x0880 },
3218 { 0x0000, 0x2880 },
3219 { 0x2000, 0x0800 },
3220 };
3221 unsigned short val = 0;
3222
3223 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
3224 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
3225 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
3226 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
3227
3228 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
3229}
3230
3231static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
3232 AC97_SURROUND_JACK_MODE_CTL,
3233 AC97_CHANNEL_MODE_CTL,
3234};
3235
3236static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3237{
3238 static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
3239
3240 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3241 uinfo->count = 1;
3242 uinfo->value.enumerated.items = 3;
3243 if (uinfo->value.enumerated.item > 2)
3244 uinfo->value.enumerated.item = 2;
3245 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3246 return 0;
3247}
3248
3249static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3250{
3251 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3252
3253 if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
3254 ucontrol->value.enumerated.item[0] = 2;
3255 else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
3256 ucontrol->value.enumerated.item[0] = 1;
3257 else
3258 ucontrol->value.enumerated.item[0] = 0;
3259 return 0;
3260}
3261
3262static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3263{
3264 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
3265
3266 if (ucontrol->value.enumerated.item[0] == 2)
3267 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
3268 snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
3269 return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
3270 ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
3271}
3272
3273static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
3274static const struct ac97_enum cm9761_dac_clock_enum =
3275 AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
3276
3277static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
3278 {
3279 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3280 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3281 .info = cm9761_spdif_out_source_info,
3282 .get = cm9761_spdif_out_source_get,
3283 .put = cm9761_spdif_out_source_put,
3284 },
3285
3286 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
3287
3288 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
3289
3290 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
3291
3292 AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
3293};
3294
3295static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
3296{
3297 return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
3298}
3299
3300static int patch_cm9761_specific(struct snd_ac97 * ac97)
3301{
3302 return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
3303}
3304
3305static const struct snd_ac97_build_ops patch_cm9761_ops = {
3306 .build_specific = patch_cm9761_specific,
3307 .build_post_spdif = patch_cm9761_post_spdif,
3308 .update_jacks = cm9761_update_jacks
3309};
3310
3311static int patch_cm9761(struct snd_ac97 *ac97)
3312{
3313 unsigned short val;
3314
3315
3316
3317
3318
3319 ac97->flags |= AC97_HAS_NO_PCM_VOL;
3320 snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
3321 snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
3322
3323 ac97->spec.dev_flags = 0;
3324 if (ac97->id == AC97_ID_CM9761_82) {
3325 unsigned short tmp;
3326
3327 val = snd_ac97_read(ac97, AC97_INT_PAGING);
3328 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
3329 tmp = snd_ac97_read(ac97, 0x60);
3330 ac97->spec.dev_flags = tmp & 1;
3331 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
3332 } else if (ac97->id == AC97_ID_CM9761_83)
3333 ac97->spec.dev_flags = 2;
3334
3335 ac97->build_ops = &patch_cm9761_ops;
3336
3337
3338
3339 ac97->ext_id |= AC97_EI_SPDIF;
3340
3341 snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
3342
3343 snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001);
3344 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364#if 0
3365 if (ac97->spec.dev_flags)
3366 val = 0x0214;
3367 else
3368 val = 0x321c;
3369#endif
3370 val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
3371 val |= (1 << 4);
3372 snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
3373
3374
3375 snd_ac97_write_cache(ac97, 0x70, 0x0100);
3376 snd_ac97_write_cache(ac97, 0x72, 0x0020);
3377
3378 return 0;
3379}
3380
3381#define AC97_CM9780_SIDE 0x60
3382#define AC97_CM9780_JACK 0x62
3383#define AC97_CM9780_MIXER 0x64
3384#define AC97_CM9780_MULTI_CHAN 0x66
3385#define AC97_CM9780_SPDIF 0x6c
3386
3387static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
3388static const struct ac97_enum cm9780_ch_select_enum =
3389 AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
3390static const struct snd_kcontrol_new cm9780_controls[] = {
3391 AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
3392 AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
3393 AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
3394};
3395
3396static int patch_cm9780_specific(struct snd_ac97 *ac97)
3397{
3398 return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
3399}
3400
3401static const struct snd_ac97_build_ops patch_cm9780_ops = {
3402 .build_specific = patch_cm9780_specific,
3403 .build_post_spdif = patch_cm9761_post_spdif
3404};
3405
3406static int patch_cm9780(struct snd_ac97 *ac97)
3407{
3408 unsigned short val;
3409
3410 ac97->build_ops = &patch_cm9780_ops;
3411
3412
3413 if (ac97->ext_id & AC97_EI_SPDIF) {
3414 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
3415 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
3416 val |= 0x1;
3417 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
3418 }
3419
3420 return 0;
3421}
3422
3423
3424
3425
3426static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
3427AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
3428AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
3429AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
3430AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
3431};
3432
3433static const char *slave_vols_vt1616[] = {
3434 "Front Playback Volume",
3435 "Surround Playback Volume",
3436 "Center Playback Volume",
3437 "LFE Playback Volume",
3438 NULL
3439};
3440
3441static const char *slave_sws_vt1616[] = {
3442 "Front Playback Switch",
3443 "Surround Playback Switch",
3444 "Center Playback Switch",
3445 "LFE Playback Switch",
3446 NULL
3447};
3448
3449
3450static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
3451 const char *name)
3452{
3453 struct snd_ctl_elem_id id;
3454 memset(&id, 0, sizeof(id));
3455 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
3456 strcpy(id.name, name);
3457 return snd_ctl_find_id(ac97->bus->card, &id);
3458}
3459
3460
3461static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
3462 const unsigned int *tlv, const char **slaves)
3463{
3464 struct snd_kcontrol *kctl;
3465 const char **s;
3466 int err;
3467
3468 kctl = snd_ctl_make_virtual_master(name, tlv);
3469 if (!kctl)
3470 return -ENOMEM;
3471 err = snd_ctl_add(ac97->bus->card, kctl);
3472 if (err < 0)
3473 return err;
3474
3475 for (s = slaves; *s; s++) {
3476 struct snd_kcontrol *sctl;
3477
3478 sctl = snd_ac97_find_mixer_ctl(ac97, *s);
3479 if (!sctl) {
3480 snd_printdd("Cannot find slave %s, skipped\n", *s);
3481 continue;
3482 }
3483 err = snd_ctl_add_slave(kctl, sctl);
3484 if (err < 0)
3485 return err;
3486 }
3487 return 0;
3488}
3489
3490static int patch_vt1616_specific(struct snd_ac97 * ac97)
3491{
3492 struct snd_kcontrol *kctl;
3493 int err;
3494
3495 if (snd_ac97_try_bit(ac97, 0x5a, 9))
3496 if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
3497 return err;
3498 if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
3499 return err;
3500
3501
3502 kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
3503 if (!kctl)
3504 return -EINVAL;
3505
3506 snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
3507
3508 err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
3509 kctl->tlv.p, slave_vols_vt1616);
3510 if (err < 0)
3511 return err;
3512
3513 err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
3514 NULL, slave_sws_vt1616);
3515 if (err < 0)
3516 return err;
3517
3518 return 0;
3519}
3520
3521static const struct snd_ac97_build_ops patch_vt1616_ops = {
3522 .build_specific = patch_vt1616_specific
3523};
3524
3525static int patch_vt1616(struct snd_ac97 * ac97)
3526{
3527 ac97->build_ops = &patch_vt1616_ops;
3528 return 0;
3529}
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
3547 struct snd_ctl_elem_info *uinfo)
3548{
3549
3550
3551
3552
3553
3554 static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3",
3555 "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
3556 "LineIn Mic2", "LineIn Mic2 Mic1",
3557 "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
3558 return ac97_enum_text_info(kcontrol, uinfo, texts, 8);
3559}
3560
3561static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
3562 struct snd_ctl_elem_value *ucontrol)
3563{
3564 ushort usSM51, usMS;
3565
3566 struct snd_ac97 *pac97;
3567
3568 pac97 = snd_kcontrol_chip(kcontrol);
3569
3570
3571
3572
3573 usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
3574 usMS = snd_ac97_read(pac97, 0x20) >> 8;
3575
3576 ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
3577
3578 return 0;
3579}
3580
3581static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
3582 struct snd_ctl_elem_value *ucontrol)
3583{
3584 ushort usSM51, usMS, usReg;
3585
3586 struct snd_ac97 *pac97;
3587
3588 pac97 = snd_kcontrol_chip(kcontrol);
3589
3590 usSM51 = ucontrol->value.enumerated.item[0] >> 1;
3591 usMS = ucontrol->value.enumerated.item[0] & 1;
3592
3593
3594
3595
3596 usReg = snd_ac97_read(pac97, 0x7a);
3597 snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
3598 usReg = snd_ac97_read(pac97, 0x20);
3599 snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8));
3600
3601 return 0;
3602}
3603
3604static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
3605
3606 AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
3607
3608
3609
3610
3611 {
3612 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3613 .name = "Smart 5.1 Select",
3614 .info = snd_ac97_vt1617a_smart51_info,
3615 .get = snd_ac97_vt1617a_smart51_get,
3616 .put = snd_ac97_vt1617a_smart51_put,
3617 },
3618};
3619
3620static int patch_vt1617a(struct snd_ac97 * ac97)
3621{
3622 int err = 0;
3623 int val;
3624
3625
3626
3627
3628 err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
3629 ARRAY_SIZE(snd_ac97_controls_vt1617a));
3630
3631
3632
3633
3634
3635
3636
3637 val = snd_ac97_read(ac97, 0x5c);
3638 if (!(val & 0x20))
3639 snd_ac97_write_cache(ac97, 0x5c, 0x20);
3640
3641 ac97->ext_id |= AC97_EI_SPDIF;
3642 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3643 ac97->build_ops = &patch_vt1616_ops;
3644
3645 return err;
3646}
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684struct vt1618_uaj_item {
3685 unsigned short mask;
3686 unsigned short shift;
3687 const char *items[4];
3688};
3689
3690
3691
3692static struct vt1618_uaj_item vt1618_uaj[3] = {
3693 {
3694
3695 .mask = 0x03,
3696 .shift = 0,
3697 .items = {
3698 "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
3699 }
3700 },
3701 {
3702
3703 .mask = 0x0c,
3704 .shift = 2,
3705 .items = {
3706 "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
3707 }
3708 },
3709 {
3710
3711 .mask = 0x30,
3712 .shift = 4,
3713 .items = {
3714 "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
3715 },
3716 },
3717};
3718
3719static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
3720 struct snd_ctl_elem_info *uinfo)
3721{
3722 return ac97_enum_text_info(kcontrol, uinfo,
3723 vt1618_uaj[kcontrol->private_value].items,
3724 4);
3725}
3726
3727
3728
3729
3730
3731static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
3732 struct snd_ctl_elem_value *ucontrol)
3733{
3734 unsigned short datpag, uaj;
3735 struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
3736
3737 mutex_lock(&pac97->page_mutex);
3738
3739 datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
3740 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
3741
3742 uaj = snd_ac97_read(pac97, 0x60) &
3743 vt1618_uaj[kcontrol->private_value].mask;
3744
3745 snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
3746 mutex_unlock(&pac97->page_mutex);
3747
3748 ucontrol->value.enumerated.item[0] = uaj >>
3749 vt1618_uaj[kcontrol->private_value].shift;
3750
3751 return 0;
3752}
3753
3754static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
3755 struct snd_ctl_elem_value *ucontrol)
3756{
3757 return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
3758 vt1618_uaj[kcontrol->private_value].mask,
3759 ucontrol->value.enumerated.item[0]<<
3760 vt1618_uaj[kcontrol->private_value].shift,
3761 0);
3762}
3763
3764
3765
3766static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
3767 struct snd_ctl_elem_info *uinfo)
3768{
3769 static const char *txt_aux[] = {"Aux In", "Back Surr Out"};
3770
3771 return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2);
3772}
3773
3774static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
3775 struct snd_ctl_elem_value *ucontrol)
3776{
3777 ucontrol->value.enumerated.item[0] =
3778 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
3779 return 0;
3780}
3781
3782static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
3783 struct snd_ctl_elem_value *ucontrol)
3784{
3785
3786
3787 snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
3788 ucontrol->value.enumerated.item[0] << 3);
3789
3790
3791
3792 return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
3793 ucontrol->value.enumerated.item[0] << 3);
3794}
3795
3796static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
3797 AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
3798 AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
3799 AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
3800 AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
3801 AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
3802 AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
3803 {
3804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3805 .name = "Speaker Jack Mode",
3806 .info = snd_ac97_vt1618_UAJ_info,
3807 .get = snd_ac97_vt1618_UAJ_get,
3808 .put = snd_ac97_vt1618_UAJ_put,
3809 .private_value = 0
3810 },
3811 {
3812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3813 .name = "Line Jack Mode",
3814 .info = snd_ac97_vt1618_UAJ_info,
3815 .get = snd_ac97_vt1618_UAJ_get,
3816 .put = snd_ac97_vt1618_UAJ_put,
3817 .private_value = 1
3818 },
3819 {
3820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3821 .name = "Mic Jack Mode",
3822 .info = snd_ac97_vt1618_UAJ_info,
3823 .get = snd_ac97_vt1618_UAJ_get,
3824 .put = snd_ac97_vt1618_UAJ_put,
3825 .private_value = 2
3826 },
3827 {
3828 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3829 .name = "Aux Jack Mode",
3830 .info = snd_ac97_vt1618_aux_info,
3831 .get = snd_ac97_vt1618_aux_get,
3832 .put = snd_ac97_vt1618_aux_put,
3833 }
3834};
3835
3836static int patch_vt1618(struct snd_ac97 *ac97)
3837{
3838 return patch_build_controls(ac97, snd_ac97_controls_vt1618,
3839 ARRAY_SIZE(snd_ac97_controls_vt1618));
3840}
3841
3842
3843
3844static void it2646_update_jacks(struct snd_ac97 *ac97)
3845{
3846
3847 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
3848 is_shared_surrout(ac97) ? (1<<9) : 0);
3849
3850 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
3851 is_shared_clfeout(ac97) ? (1<<10) : 0);
3852}
3853
3854static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
3855 AC97_SURROUND_JACK_MODE_CTL,
3856 AC97_CHANNEL_MODE_CTL,
3857};
3858
3859static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
3860 AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
3861 AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
3862 AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
3863};
3864
3865static int patch_it2646_specific(struct snd_ac97 * ac97)
3866{
3867 int err;
3868 if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0)
3869 return err;
3870 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0)
3871 return err;
3872 return 0;
3873}
3874
3875static const struct snd_ac97_build_ops patch_it2646_ops = {
3876 .build_specific = patch_it2646_specific,
3877 .update_jacks = it2646_update_jacks
3878};
3879
3880static int patch_it2646(struct snd_ac97 * ac97)
3881{
3882 ac97->build_ops = &patch_it2646_ops;
3883
3884 snd_ac97_write_cache(ac97, 0x5E, 0x0808);
3885 snd_ac97_write_cache(ac97, 0x7A, 0x0808);
3886 return 0;
3887}
3888
3889
3890
3891
3892
3893#define AC97_SI3036_CHIP_ID 0x5a
3894#define AC97_SI3036_LINE_CFG 0x5c
3895
3896static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
3897AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
3898};
3899
3900static int patch_si3036_specific(struct snd_ac97 * ac97)
3901{
3902 int idx, err;
3903 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++)
3904 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0)
3905 return err;
3906 return 0;
3907}
3908
3909static const struct snd_ac97_build_ops patch_si3036_ops = {
3910 .build_specific = patch_si3036_specific,
3911};
3912
3913static int mpatch_si3036(struct snd_ac97 * ac97)
3914{
3915 ac97->build_ops = &patch_si3036_ops;
3916 snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
3917 snd_ac97_write_cache(ac97, 0x68, 0);
3918 return 0;
3919}
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929static struct snd_ac97_res_table lm4550_restbl[] = {
3930 { AC97_MASTER, 0x1f1f },
3931 { AC97_HEADPHONE, 0x1f1f },
3932 { AC97_MASTER_MONO, 0x001f },
3933 { AC97_PC_BEEP, 0x001f },
3934 { AC97_PHONE, 0x001f },
3935 { AC97_MIC, 0x001f },
3936 { AC97_LINE, 0x1f1f },
3937 { AC97_CD, 0x1f1f },
3938 { AC97_VIDEO, 0x1f1f },
3939 { AC97_AUX, 0x1f1f },
3940 { AC97_PCM, 0x1f1f },
3941 { AC97_REC_GAIN, 0x0f0f },
3942 { }
3943};
3944
3945static int patch_lm4550(struct snd_ac97 *ac97)
3946{
3947 ac97->res_table = lm4550_restbl;
3948 return 0;
3949}
3950
3951
3952
3953
3954static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = {
3955
3956
3957
3958AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0),
3959
3960
3961AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0),
3962
3963
3964AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0),
3965};
3966
3967static int patch_ucb1400_specific(struct snd_ac97 * ac97)
3968{
3969 int idx, err;
3970 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++)
3971 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0)
3972 return err;
3973 return 0;
3974}
3975
3976static const struct snd_ac97_build_ops patch_ucb1400_ops = {
3977 .build_specific = patch_ucb1400_specific,
3978};
3979
3980static int patch_ucb1400(struct snd_ac97 * ac97)
3981{
3982 ac97->build_ops = &patch_ucb1400_ops;
3983
3984 snd_ac97_write_cache(ac97, 0x6a, 0x0050);
3985 snd_ac97_write_cache(ac97, 0x6c, 0x0030);
3986 return 0;
3987}
3988