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