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