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