]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/pci/hda/patch_analog.c
[ALSA] via82xx - Add dxs entry for ASRock mobo
[net-next-2.6.git] / sound / pci / hda / patch_analog.c
CommitLineData
1da177e4 1/*
d32410b1 2 * HD audio interface patch for AD1981HD, AD1983, AD1986A, AD1988
1da177e4
LT
3 *
4 * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
5 *
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This driver is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
62932df8
IM
26#include <linux/mutex.h>
27
1da177e4
LT
28#include <sound/core.h>
29#include "hda_codec.h"
30#include "hda_local.h"
31
4a3fdf3d 32struct ad198x_spec {
c8b6bf9b 33 struct snd_kcontrol_new *mixers[5];
985be54b
TI
34 int num_mixers;
35
d32410b1 36 const struct hda_verb *init_verbs[5]; /* initialization verbs
985be54b
TI
37 * don't forget NULL termination!
38 */
39 unsigned int num_init_verbs;
40
41 /* playback */
42 struct hda_multi_out multiout; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
45 */
fd66e0d0 46 unsigned int cur_eapd;
985be54b
TI
47
48 /* capture */
49 unsigned int num_adc_nids;
50 hda_nid_t *adc_nids;
51 hda_nid_t dig_in_nid; /* digital-in NID; optional */
52
53 /* capture source */
4a3fdf3d 54 const struct hda_input_mux *input_mux;
2e5b9567 55 hda_nid_t *capsrc_nids;
985be54b
TI
56 unsigned int cur_mux[3];
57
58 /* channel model */
d2a6d7dc 59 const struct hda_channel_mode *channel_mode;
985be54b
TI
60 int num_channel_mode;
61
62 /* PCM information */
63 struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */
64
62932df8 65 struct mutex amp_mutex; /* PCM volume/mute control mutex */
4a3fdf3d 66 unsigned int spdif_route;
d32410b1
TI
67
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg;
70 unsigned int num_kctl_alloc, num_kctl_used;
71 struct snd_kcontrol_new *kctl_alloc;
72 struct hda_input_mux private_imux;
73 hda_nid_t private_dac_nids[4];
1da177e4
LT
74};
75
4a3fdf3d
TI
76/*
77 * input MUX handling (common part)
78 */
c8b6bf9b 79static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
4a3fdf3d
TI
80{
81 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
82 struct ad198x_spec *spec = codec->spec;
83
84 return snd_hda_input_mux_info(spec->input_mux, uinfo);
85}
86
c8b6bf9b 87static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4a3fdf3d
TI
88{
89 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
90 struct ad198x_spec *spec = codec->spec;
985be54b 91 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4a3fdf3d 92
985be54b 93 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
4a3fdf3d
TI
94 return 0;
95}
96
c8b6bf9b 97static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4a3fdf3d
TI
98{
99 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
100 struct ad198x_spec *spec = codec->spec;
985be54b 101 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4a3fdf3d
TI
102
103 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
2e5b9567
TI
104 spec->capsrc_nids[adc_idx],
105 &spec->cur_mux[adc_idx]);
4a3fdf3d
TI
106}
107
108/*
109 * initialization (common callbacks)
110 */
111static int ad198x_init(struct hda_codec *codec)
112{
113 struct ad198x_spec *spec = codec->spec;
985be54b
TI
114 int i;
115
116 for (i = 0; i < spec->num_init_verbs; i++)
117 snd_hda_sequence_write(codec, spec->init_verbs[i]);
4a3fdf3d
TI
118 return 0;
119}
120
121static int ad198x_build_controls(struct hda_codec *codec)
122{
123 struct ad198x_spec *spec = codec->spec;
985be54b 124 unsigned int i;
4a3fdf3d
TI
125 int err;
126
985be54b
TI
127 for (i = 0; i < spec->num_mixers; i++) {
128 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
129 if (err < 0)
130 return err;
131 }
132 if (spec->multiout.dig_out_nid) {
4a3fdf3d 133 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
985be54b
TI
134 if (err < 0)
135 return err;
136 }
137 if (spec->dig_in_nid) {
138 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
139 if (err < 0)
140 return err;
141 }
4a3fdf3d
TI
142 return 0;
143}
144
145/*
146 * Analog playback callbacks
147 */
148static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
149 struct hda_codec *codec,
c8b6bf9b 150 struct snd_pcm_substream *substream)
4a3fdf3d
TI
151{
152 struct ad198x_spec *spec = codec->spec;
153 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
154}
155
156static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
157 struct hda_codec *codec,
158 unsigned int stream_tag,
159 unsigned int format,
c8b6bf9b 160 struct snd_pcm_substream *substream)
4a3fdf3d
TI
161{
162 struct ad198x_spec *spec = codec->spec;
163 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
164 format, substream);
165}
166
167static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
168 struct hda_codec *codec,
c8b6bf9b 169 struct snd_pcm_substream *substream)
4a3fdf3d
TI
170{
171 struct ad198x_spec *spec = codec->spec;
172 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
173}
174
175/*
176 * Digital out
177 */
178static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
179 struct hda_codec *codec,
c8b6bf9b 180 struct snd_pcm_substream *substream)
4a3fdf3d
TI
181{
182 struct ad198x_spec *spec = codec->spec;
183 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
184}
185
186static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
187 struct hda_codec *codec,
c8b6bf9b 188 struct snd_pcm_substream *substream)
4a3fdf3d
TI
189{
190 struct ad198x_spec *spec = codec->spec;
191 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
192}
193
194/*
195 * Analog capture
196 */
197static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
198 struct hda_codec *codec,
199 unsigned int stream_tag,
200 unsigned int format,
c8b6bf9b 201 struct snd_pcm_substream *substream)
4a3fdf3d
TI
202{
203 struct ad198x_spec *spec = codec->spec;
985be54b
TI
204 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
205 stream_tag, 0, format);
4a3fdf3d
TI
206 return 0;
207}
208
209static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
210 struct hda_codec *codec,
c8b6bf9b 211 struct snd_pcm_substream *substream)
4a3fdf3d
TI
212{
213 struct ad198x_spec *spec = codec->spec;
985be54b
TI
214 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
215 0, 0, 0);
4a3fdf3d
TI
216 return 0;
217}
218
219
220/*
221 */
222static struct hda_pcm_stream ad198x_pcm_analog_playback = {
223 .substreams = 1,
224 .channels_min = 2,
985be54b 225 .channels_max = 6, /* changed later */
4a3fdf3d
TI
226 .nid = 0, /* fill later */
227 .ops = {
228 .open = ad198x_playback_pcm_open,
229 .prepare = ad198x_playback_pcm_prepare,
230 .cleanup = ad198x_playback_pcm_cleanup
231 },
232};
233
234static struct hda_pcm_stream ad198x_pcm_analog_capture = {
985be54b 235 .substreams = 1,
4a3fdf3d
TI
236 .channels_min = 2,
237 .channels_max = 2,
238 .nid = 0, /* fill later */
239 .ops = {
240 .prepare = ad198x_capture_pcm_prepare,
241 .cleanup = ad198x_capture_pcm_cleanup
242 },
243};
244
245static struct hda_pcm_stream ad198x_pcm_digital_playback = {
246 .substreams = 1,
247 .channels_min = 2,
248 .channels_max = 2,
249 .nid = 0, /* fill later */
250 .ops = {
251 .open = ad198x_dig_playback_pcm_open,
252 .close = ad198x_dig_playback_pcm_close
253 },
254};
255
985be54b
TI
256static struct hda_pcm_stream ad198x_pcm_digital_capture = {
257 .substreams = 1,
258 .channels_min = 2,
259 .channels_max = 2,
260 /* NID is set in alc_build_pcms */
261};
262
4a3fdf3d
TI
263static int ad198x_build_pcms(struct hda_codec *codec)
264{
265 struct ad198x_spec *spec = codec->spec;
266 struct hda_pcm *info = spec->pcm_rec;
267
268 codec->num_pcms = 1;
269 codec->pcm_info = info;
270
271 info->name = "AD198x Analog";
272 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
273 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
274 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
275 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
985be54b
TI
276 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
277 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4a3fdf3d
TI
278
279 if (spec->multiout.dig_out_nid) {
280 info++;
281 codec->num_pcms++;
282 info->name = "AD198x Digital";
283 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
284 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
985be54b
TI
285 if (spec->dig_in_nid) {
286 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
287 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
288 }
4a3fdf3d
TI
289 }
290
291 return 0;
292}
293
294static void ad198x_free(struct hda_codec *codec)
295{
d32410b1
TI
296 struct ad198x_spec *spec = codec->spec;
297 unsigned int i;
298
299 if (spec->kctl_alloc) {
300 for (i = 0; i < spec->num_kctl_used; i++)
301 kfree(spec->kctl_alloc[i].name);
302 kfree(spec->kctl_alloc);
303 }
4a3fdf3d
TI
304 kfree(codec->spec);
305}
306
307#ifdef CONFIG_PM
308static int ad198x_resume(struct hda_codec *codec)
309{
310 struct ad198x_spec *spec = codec->spec;
985be54b 311 int i;
4a3fdf3d
TI
312
313 ad198x_init(codec);
985be54b
TI
314 for (i = 0; i < spec->num_mixers; i++)
315 snd_hda_resume_ctls(codec, spec->mixers[i]);
316 if (spec->multiout.dig_out_nid)
317 snd_hda_resume_spdif_out(codec);
318 if (spec->dig_in_nid)
319 snd_hda_resume_spdif_in(codec);
4a3fdf3d
TI
320 return 0;
321}
322#endif
323
324static struct hda_codec_ops ad198x_patch_ops = {
325 .build_controls = ad198x_build_controls,
326 .build_pcms = ad198x_build_pcms,
327 .init = ad198x_init,
328 .free = ad198x_free,
329#ifdef CONFIG_PM
330 .resume = ad198x_resume,
331#endif
332};
333
334
335/*
336 * AD1986A specific
337 */
338
1da177e4
LT
339#define AD1986A_SPDIF_OUT 0x02
340#define AD1986A_FRONT_DAC 0x03
341#define AD1986A_SURR_DAC 0x04
342#define AD1986A_CLFE_DAC 0x05
343#define AD1986A_ADC 0x06
344
345static hda_nid_t ad1986a_dac_nids[3] = {
346 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
347};
985be54b 348static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
1da177e4
LT
349
350static struct hda_input_mux ad1986a_capture_source = {
351 .num_items = 7,
352 .items = {
353 { "Mic", 0x0 },
354 { "CD", 0x1 },
355 { "Aux", 0x3 },
356 { "Line", 0x4 },
357 { "Mix", 0x5 },
358 { "Mono", 0x6 },
359 { "Phone", 0x7 },
360 },
361};
362
363/*
364 * PCM control
365 *
366 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
367 */
368
369#define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
370
c8b6bf9b 371static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
372{
373 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4a3fdf3d 374 struct ad198x_spec *ad = codec->spec;
1da177e4 375
62932df8 376 mutex_lock(&ad->amp_mutex);
1da177e4 377 snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
62932df8 378 mutex_unlock(&ad->amp_mutex);
1da177e4
LT
379 return 0;
380}
381
c8b6bf9b 382static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
383{
384 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4a3fdf3d 385 struct ad198x_spec *ad = codec->spec;
1da177e4
LT
386 int i, change = 0;
387
62932df8 388 mutex_lock(&ad->amp_mutex);
1da177e4
LT
389 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
390 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
391 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
392 }
393 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
62932df8 394 mutex_unlock(&ad->amp_mutex);
1da177e4
LT
395 return change;
396}
397
ead9b7c3 398#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
1da177e4 399
c8b6bf9b 400static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
401{
402 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4a3fdf3d 403 struct ad198x_spec *ad = codec->spec;
1da177e4 404
62932df8 405 mutex_lock(&ad->amp_mutex);
1da177e4 406 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
62932df8 407 mutex_unlock(&ad->amp_mutex);
1da177e4
LT
408 return 0;
409}
410
c8b6bf9b 411static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
412{
413 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4a3fdf3d 414 struct ad198x_spec *ad = codec->spec;
1da177e4
LT
415 int i, change = 0;
416
62932df8 417 mutex_lock(&ad->amp_mutex);
1da177e4
LT
418 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
419 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
420 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
421 }
422 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
62932df8 423 mutex_unlock(&ad->amp_mutex);
1da177e4
LT
424 return change;
425}
426
1da177e4
LT
427/*
428 * mixers
429 */
c8b6bf9b 430static struct snd_kcontrol_new ad1986a_mixers[] = {
1da177e4
LT
431 {
432 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
433 .name = "PCM Playback Volume",
434 .info = ad1986a_pcm_amp_vol_info,
435 .get = ad1986a_pcm_amp_vol_get,
436 .put = ad1986a_pcm_amp_vol_put,
437 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
438 },
439 {
440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
441 .name = "PCM Playback Switch",
442 .info = ad1986a_pcm_amp_sw_info,
443 .get = ad1986a_pcm_amp_sw_get,
444 .put = ad1986a_pcm_amp_sw_put,
445 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
446 },
447 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
448 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
449 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
450 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
451 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
452 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
453 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
454 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
455 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
456 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
457 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
458 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
459 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
460 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
461 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
462 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
464 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
465 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
466 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
467 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
468 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
469 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
470 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
471 {
472 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
473 .name = "Capture Source",
4a3fdf3d
TI
474 .info = ad198x_mux_enum_info,
475 .get = ad198x_mux_enum_get,
476 .put = ad198x_mux_enum_put,
1da177e4
LT
477 },
478 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
479 { } /* end */
480};
481
482/*
483 * initialization verbs
484 */
485static struct hda_verb ad1986a_init_verbs[] = {
486 /* Front, Surround, CLFE DAC; mute as default */
487 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
488 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
489 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
490 /* Downmix - off */
491 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
492 /* HP, Line-Out, Surround, CLFE selectors */
493 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
494 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
495 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
496 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
497 /* Mono selector */
498 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
499 /* Mic selector: Mic 1/2 pin */
500 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
501 /* Line-in selector: Line-in */
502 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
503 /* Mic 1/2 swap */
504 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
505 /* Record selector: mic */
506 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
507 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
508 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
509 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
510 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
511 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
512 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
513 /* PC beep */
514 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
515 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
516 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
517 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
518 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
519 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
520 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
4a3fdf3d
TI
521 /* HP Pin */
522 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
523 /* Front, Surround, CLFE Pins */
524 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
525 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
526 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
527 /* Mono Pin */
528 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
529 /* Mic Pin */
530 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
531 /* Line, Aux, CD, Beep-In Pin */
532 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
533 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
534 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
535 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
536 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1da177e4
LT
537 { } /* end */
538};
539
540
4a3fdf3d 541static int patch_ad1986a(struct hda_codec *codec)
1da177e4 542{
4a3fdf3d 543 struct ad198x_spec *spec;
1da177e4 544
e560d8d8 545 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4a3fdf3d
TI
546 if (spec == NULL)
547 return -ENOMEM;
548
62932df8 549 mutex_init(&spec->amp_mutex);
4a3fdf3d
TI
550 codec->spec = spec;
551
552 spec->multiout.max_channels = 6;
553 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
554 spec->multiout.dac_nids = ad1986a_dac_nids;
555 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
985be54b
TI
556 spec->num_adc_nids = 1;
557 spec->adc_nids = ad1986a_adc_nids;
2e5b9567 558 spec->capsrc_nids = ad1986a_adc_nids;
4a3fdf3d 559 spec->input_mux = &ad1986a_capture_source;
985be54b
TI
560 spec->num_mixers = 1;
561 spec->mixers[0] = ad1986a_mixers;
562 spec->num_init_verbs = 1;
563 spec->init_verbs[0] = ad1986a_init_verbs;
4a3fdf3d
TI
564
565 codec->patch_ops = ad198x_patch_ops;
1da177e4 566
1da177e4
LT
567 return 0;
568}
569
570/*
4a3fdf3d 571 * AD1983 specific
1da177e4 572 */
1da177e4 573
4a3fdf3d
TI
574#define AD1983_SPDIF_OUT 0x02
575#define AD1983_DAC 0x03
576#define AD1983_ADC 0x04
1da177e4 577
4a3fdf3d 578static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
985be54b 579static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
4a3fdf3d
TI
580
581static struct hda_input_mux ad1983_capture_source = {
582 .num_items = 4,
583 .items = {
584 { "Mic", 0x0 },
585 { "Line", 0x1 },
586 { "Mix", 0x2 },
587 { "Mix Mono", 0x3 },
588 },
589};
1da177e4
LT
590
591/*
4a3fdf3d 592 * SPDIF playback route
1da177e4 593 */
c8b6bf9b 594static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 595{
4a3fdf3d
TI
596 static char *texts[] = { "PCM", "ADC" };
597
598 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
599 uinfo->count = 1;
600 uinfo->value.enumerated.items = 2;
601 if (uinfo->value.enumerated.item > 1)
602 uinfo->value.enumerated.item = 1;
603 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
604 return 0;
1da177e4
LT
605}
606
c8b6bf9b 607static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 608{
4a3fdf3d
TI
609 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
610 struct ad198x_spec *spec = codec->spec;
1da177e4 611
4a3fdf3d 612 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1da177e4
LT
613 return 0;
614}
615
c8b6bf9b 616static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 617{
4a3fdf3d
TI
618 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
619 struct ad198x_spec *spec = codec->spec;
620
621 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
622 spec->spdif_route = ucontrol->value.enumerated.item[0];
623 snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
624 AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
625 return 1;
626 }
1da177e4
LT
627 return 0;
628}
629
c8b6bf9b 630static struct snd_kcontrol_new ad1983_mixers[] = {
4a3fdf3d
TI
631 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
632 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
633 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
634 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
635 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
636 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
637 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
638 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
639 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
640 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
641 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
642 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
643 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
644 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
645 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
646 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
647 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
648 {
649 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
650 .name = "Capture Source",
651 .info = ad198x_mux_enum_info,
652 .get = ad198x_mux_enum_get,
653 .put = ad198x_mux_enum_put,
1da177e4 654 },
4a3fdf3d
TI
655 {
656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10e8d78a 657 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
4a3fdf3d
TI
658 .info = ad1983_spdif_route_info,
659 .get = ad1983_spdif_route_get,
660 .put = ad1983_spdif_route_put,
1da177e4 661 },
4a3fdf3d 662 { } /* end */
1da177e4
LT
663};
664
4a3fdf3d
TI
665static struct hda_verb ad1983_init_verbs[] = {
666 /* Front, HP, Mono; mute as default */
667 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
668 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
669 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
670 /* Beep, PCM, Mic, Line-In: mute */
671 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
672 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
673 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
674 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
675 /* Front, HP selectors; from Mix */
676 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
677 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
678 /* Mono selector; from Mix */
679 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
680 /* Mic selector; Mic */
681 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
682 /* Line-in selector: Line-in */
683 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
684 /* Mic boost: 0dB */
685 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
686 /* Record selector: mic */
687 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
688 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
689 /* SPDIF route: PCM */
690 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
691 /* Front Pin */
692 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
693 /* HP Pin */
694 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
695 /* Mono Pin */
696 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
697 /* Mic Pin */
698 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
699 /* Line Pin */
700 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
701 { } /* end */
1da177e4
LT
702};
703
985be54b 704
4a3fdf3d 705static int patch_ad1983(struct hda_codec *codec)
1da177e4 706{
4a3fdf3d 707 struct ad198x_spec *spec;
1da177e4 708
e560d8d8 709 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4a3fdf3d
TI
710 if (spec == NULL)
711 return -ENOMEM;
1da177e4 712
62932df8 713 mutex_init(&spec->amp_mutex);
4a3fdf3d
TI
714 codec->spec = spec;
715
716 spec->multiout.max_channels = 2;
717 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
718 spec->multiout.dac_nids = ad1983_dac_nids;
719 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
985be54b
TI
720 spec->num_adc_nids = 1;
721 spec->adc_nids = ad1983_adc_nids;
2e5b9567 722 spec->capsrc_nids = ad1983_adc_nids;
4a3fdf3d 723 spec->input_mux = &ad1983_capture_source;
985be54b
TI
724 spec->num_mixers = 1;
725 spec->mixers[0] = ad1983_mixers;
726 spec->num_init_verbs = 1;
727 spec->init_verbs[0] = ad1983_init_verbs;
4a3fdf3d 728 spec->spdif_route = 0;
1da177e4 729
4a3fdf3d 730 codec->patch_ops = ad198x_patch_ops;
1da177e4
LT
731
732 return 0;
733}
734
1da177e4 735
4a3fdf3d
TI
736/*
737 * AD1981 HD specific
738 */
1da177e4 739
4a3fdf3d
TI
740#define AD1981_SPDIF_OUT 0x02
741#define AD1981_DAC 0x03
742#define AD1981_ADC 0x04
743
744static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
985be54b 745static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
4a3fdf3d
TI
746
747/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
748static struct hda_input_mux ad1981_capture_source = {
749 .num_items = 7,
750 .items = {
751 { "Front Mic", 0x0 },
752 { "Line", 0x1 },
753 { "Mix", 0x2 },
754 { "Mix Mono", 0x3 },
755 { "CD", 0x4 },
756 { "Mic", 0x6 },
757 { "Aux", 0x7 },
758 },
1da177e4
LT
759};
760
c8b6bf9b 761static struct snd_kcontrol_new ad1981_mixers[] = {
4a3fdf3d
TI
762 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
763 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
764 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
765 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
766 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
767 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
768 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
769 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
770 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
771 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
772 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
773 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
774 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
775 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
776 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
777 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
778 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
779 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
780 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
781 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
782 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
783 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
784 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
785 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
786 {
787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
788 .name = "Capture Source",
789 .info = ad198x_mux_enum_info,
790 .get = ad198x_mux_enum_get,
791 .put = ad198x_mux_enum_put,
792 },
793 /* identical with AD1983 */
794 {
795 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
10e8d78a 796 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
4a3fdf3d
TI
797 .info = ad1983_spdif_route_info,
798 .get = ad1983_spdif_route_get,
799 .put = ad1983_spdif_route_put,
800 },
801 { } /* end */
802};
803
804static struct hda_verb ad1981_init_verbs[] = {
805 /* Front, HP, Mono; mute as default */
806 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
807 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
808 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
809 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
810 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
811 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
812 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
813 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
814 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
815 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
816 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
817 /* Front, HP selectors; from Mix */
818 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
819 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
820 /* Mono selector; from Mix */
821 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
822 /* Mic Mixer; select Front Mic */
823 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
824 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
825 /* Mic boost: 0dB */
826 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
827 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
828 /* Record selector: Front mic */
829 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
830 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
831 /* SPDIF route: PCM */
832 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
833 /* Front Pin */
834 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
835 /* HP Pin */
836 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
837 /* Mono Pin */
838 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
839 /* Front & Rear Mic Pins */
840 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
841 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
842 /* Line Pin */
843 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
844 /* Digital Beep */
845 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
846 /* Line-Out as Input: disabled */
847 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
848 { } /* end */
849};
850
851static int patch_ad1981(struct hda_codec *codec)
1da177e4 852{
4a3fdf3d 853 struct ad198x_spec *spec;
1da177e4 854
e560d8d8 855 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1da177e4
LT
856 if (spec == NULL)
857 return -ENOMEM;
858
62932df8 859 mutex_init(&spec->amp_mutex);
1da177e4
LT
860 codec->spec = spec;
861
4a3fdf3d
TI
862 spec->multiout.max_channels = 2;
863 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
864 spec->multiout.dac_nids = ad1981_dac_nids;
865 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
985be54b
TI
866 spec->num_adc_nids = 1;
867 spec->adc_nids = ad1981_adc_nids;
2e5b9567 868 spec->capsrc_nids = ad1981_adc_nids;
4a3fdf3d 869 spec->input_mux = &ad1981_capture_source;
985be54b
TI
870 spec->num_mixers = 1;
871 spec->mixers[0] = ad1981_mixers;
872 spec->num_init_verbs = 1;
873 spec->init_verbs[0] = ad1981_init_verbs;
4a3fdf3d 874 spec->spdif_route = 0;
1da177e4 875
4a3fdf3d 876 codec->patch_ops = ad198x_patch_ops;
1da177e4
LT
877
878 return 0;
879}
880
4a3fdf3d 881
fd66e0d0
TI
882/*
883 * AD1988
884 *
885 * Output pins and routes
886 *
d32410b1 887 * Pin Mix Sel DAC (*)
fd66e0d0
TI
888 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
889 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
890 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
891 * port-D 0x12 (mute/hp) <- 0x29 <- 04
892 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
893 * port-F 0x16 (mute) <- 0x2a <- 06
894 * port-G 0x24 (mute) <- 0x27 <- 05
895 * port-H 0x25 (mute) <- 0x28 <- 0a
896 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
897 *
d32410b1
TI
898 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
899 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
fd66e0d0
TI
900 *
901 * Input pins and routes
902 *
903 * pin boost mix input # / adc input #
904 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
905 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
906 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
907 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
908 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
909 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
910 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
911 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
912 *
913 *
914 * DAC assignment
d32410b1 915 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
f8c7c7b8 916 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
fd66e0d0
TI
917 *
918 * Inputs of Analog Mix (0x20)
919 * 0:Port-B (front mic)
920 * 1:Port-C/G/H (line-in)
921 * 2:Port-A
922 * 3:Port-D (line-in/2)
923 * 4:Port-E/G/H (mic-in)
924 * 5:Port-F (mic2-in)
925 * 6:CD
926 * 7:Beep
927 *
928 * ADC selection
929 * 0:Port-A
930 * 1:Port-B (front mic-in)
931 * 2:Port-C (line-in)
932 * 3:Port-F (mic2-in)
933 * 4:Port-E (mic-in)
934 * 5:CD
935 * 6:Port-G
936 * 7:Port-H
937 * 8:Port-D (line-in/2)
938 * 9:Mix
939 *
940 * Proposed pin assignments by the datasheet
941 *
942 * 6-stack
943 * Port-A front headphone
944 * B front mic-in
945 * C rear line-in
946 * D rear front-out
947 * E rear mic-in
948 * F rear surround
949 * G rear CLFE
950 * H rear side
951 *
952 * 3-stack
953 * Port-A front headphone
954 * B front mic
955 * C rear line-in/surround
956 * D rear front-out
957 * E rear mic-in/CLFE
958 *
959 * laptop
960 * Port-A headphone
961 * B mic-in
962 * C docking station
963 * D internal speaker (with EAPD)
964 * E/F quad mic array
965 */
966
967
968/* models */
969enum {
970 AD1988_6STACK,
971 AD1988_6STACK_DIG,
972 AD1988_3STACK,
973 AD1988_3STACK_DIG,
974 AD1988_LAPTOP,
975 AD1988_LAPTOP_DIG,
d32410b1 976 AD1988_AUTO,
fd66e0d0
TI
977 AD1988_MODEL_LAST,
978};
979
d32410b1
TI
980/* reivision id to check workarounds */
981#define AD1988A_REV2 0x100200
982
fd66e0d0
TI
983
984/*
985 * mixers
986 */
987
d32410b1 988static hda_nid_t ad1988_6stack_dac_nids[4] = {
fd66e0d0
TI
989 0x04, 0x06, 0x05, 0x0a
990};
991
d32410b1 992static hda_nid_t ad1988_3stack_dac_nids[3] = {
f8c7c7b8 993 0x04, 0x05, 0x0a
d32410b1
TI
994};
995
996/* for AD1988A revision-2, DAC2-4 are swapped */
997static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
998 0x04, 0x05, 0x0a, 0x06
999};
1000
1001static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
f8c7c7b8 1002 0x04, 0x0a, 0x06
d32410b1
TI
1003};
1004
fd66e0d0
TI
1005static hda_nid_t ad1988_adc_nids[3] = {
1006 0x08, 0x09, 0x0f
1007};
1008
2e5b9567
TI
1009static hda_nid_t ad1988_capsrc_nids[3] = {
1010 0x0c, 0x0d, 0x0e
1011};
1012
fd66e0d0
TI
1013#define AD1988_SPDIF_OUT 0x02
1014#define AD1988_SPDIF_IN 0x07
1015
1016static struct hda_input_mux ad1988_6stack_capture_source = {
1017 .num_items = 5,
1018 .items = {
1019 { "Front Mic", 0x0 },
1020 { "Line", 0x1 },
1021 { "Mic", 0x4 },
1022 { "CD", 0x5 },
1023 { "Mix", 0x9 },
1024 },
1025};
1026
1027static struct hda_input_mux ad1988_laptop_capture_source = {
1028 .num_items = 3,
1029 .items = {
1030 { "Mic/Line", 0x0 },
1031 { "CD", 0x5 },
1032 { "Mix", 0x9 },
1033 },
1034};
1035
1036/*
1037 */
1038static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1039 struct snd_ctl_elem_info *uinfo)
1040{
1041 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1042 struct ad198x_spec *spec = codec->spec;
1043 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1044 spec->num_channel_mode);
1045}
1046
1047static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1048 struct snd_ctl_elem_value *ucontrol)
1049{
1050 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1051 struct ad198x_spec *spec = codec->spec;
1052 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1053 spec->num_channel_mode, spec->multiout.max_channels);
1054}
1055
1056static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1057 struct snd_ctl_elem_value *ucontrol)
1058{
1059 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1060 struct ad198x_spec *spec = codec->spec;
1061 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1062 spec->num_channel_mode, &spec->multiout.max_channels);
1063}
1064
1065/*
1066 * EAPD control
1067 */
1068static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
1069 struct snd_ctl_elem_info *uinfo)
1070{
1071 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1072 uinfo->count = 1;
1073 uinfo->value.integer.min = 0;
1074 uinfo->value.integer.max = 1;
1075 return 0;
1076}
1077
1078static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
1079 struct snd_ctl_elem_value *ucontrol)
1080{
1081 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1082 struct ad198x_spec *spec = codec->spec;
1083 ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
1084 return 0;
1085}
1086
1087static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
1088 struct snd_ctl_elem_value *ucontrol)
1089{
1090 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1091 struct ad198x_spec *spec = codec->spec;
1092 unsigned int eapd;
1093 eapd = ! ucontrol->value.enumerated.item[0];
1094 if (eapd == spec->cur_eapd && ! codec->in_resume)
1095 return 0;
1096 spec->cur_eapd = eapd;
1097 snd_hda_codec_write(codec, 0x12 /* port-D */,
1098 0, AC_VERB_SET_EAPD_BTLENABLE,
1099 eapd ? 0x02 : 0x00);
1100 return 0;
1101}
1102
1103/* 6-stack mode */
d32410b1 1104static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
fd66e0d0
TI
1105 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1106 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1107 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1108 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1109 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
d32410b1
TI
1110};
1111
1112static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
1113 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1114 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1115 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1116 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
1117 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1118};
fd66e0d0 1119
d32410b1 1120static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
fd66e0d0
TI
1121 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1122 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1123 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1124 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1125 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1126 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1127 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1128
1129 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1130 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1131 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1132 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1133 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1134 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1135 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1136 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1137
1138 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1139 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1140
2e5b9567 1141 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1142 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1143
1144 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1145 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1146
1147 { } /* end */
1148};
1149
1150/* 3-stack mode */
d32410b1 1151static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
fd66e0d0 1152 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
d32410b1 1153 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1154 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1155 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
d32410b1
TI
1156};
1157
1158static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
1159 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
f8c7c7b8
TI
1160 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1161 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
1162 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
d32410b1 1163};
fd66e0d0 1164
d32410b1 1165static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
fd66e0d0 1166 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
d32410b1
TI
1167 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
1168 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
1169 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
fd66e0d0
TI
1170 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1171 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1172
1173 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1174 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1175 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1176 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1177 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1178 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1179 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1180 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1181
1182 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1183 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1184
2e5b9567 1185 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1186 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1187
1188 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1189 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1190 {
1191 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1192 .name = "Channel Mode",
1193 .info = ad198x_ch_mode_info,
1194 .get = ad198x_ch_mode_get,
1195 .put = ad198x_ch_mode_put,
1196 },
1197
1198 { } /* end */
1199};
1200
1201/* laptop mode */
1202static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1203 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1204 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1205 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1206
1207 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1208 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1209 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1210 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1211 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1212 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1213
1214 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1215 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1216
2e5b9567 1217 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1218 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1219
1220 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1221
1222 {
1223 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1224 .name = "External Amplifier",
1225 .info = ad1988_eapd_info,
1226 .get = ad1988_eapd_get,
1227 .put = ad1988_eapd_put,
1228 },
1229
1230 { } /* end */
1231};
1232
1233/* capture */
1234static struct snd_kcontrol_new ad1988_capture_mixers[] = {
1235 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
1236 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
1237 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
1238 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
1239 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
1240 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
1241 {
1242 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1243 /* The multiple "Capture Source" controls confuse alsamixer
1244 * So call somewhat different..
1245 * FIXME: the controls appear in the "playback" view!
1246 */
1247 /* .name = "Capture Source", */
1248 .name = "Input Source",
1249 .count = 3,
1250 .info = ad198x_mux_enum_info,
1251 .get = ad198x_mux_enum_get,
1252 .put = ad198x_mux_enum_put,
1253 },
1254 { } /* end */
1255};
1256
1257static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
1258 struct snd_ctl_elem_info *uinfo)
1259{
1260 static char *texts[] = {
1261 "PCM", "ADC1", "ADC2", "ADC3"
1262 };
1263 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1264 uinfo->count = 1;
1265 uinfo->value.enumerated.items = 4;
1266 if (uinfo->value.enumerated.item >= 4)
1267 uinfo->value.enumerated.item = 3;
1268 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1269 return 0;
1270}
1271
1272static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
1273 struct snd_ctl_elem_value *ucontrol)
1274{
1275 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1276 unsigned int sel;
1277
1278 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1279 if (sel > 0) {
1280 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
1281 if (sel <= 3)
1282 sel++;
1283 else
1284 sel = 0;
1285 }
1286 ucontrol->value.enumerated.item[0] = sel;
1287 return 0;
1288}
1289
1290static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1291 struct snd_ctl_elem_value *ucontrol)
1292{
1293 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1294 unsigned int sel;
1295 int change;
1296
1297 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1298 if (! ucontrol->value.enumerated.item[0]) {
1299 change = sel != 0;
1300 if (change)
1301 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
1302 } else {
1303 change = sel == 0;
1304 if (change)
1305 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
1306 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
1307 change |= sel == ucontrol->value.enumerated.item[0];
1308 if (change)
1309 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
1310 ucontrol->value.enumerated.item[0] - 1);
1311 }
1312 return change;
1313}
1314
1315static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
1316 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1317 {
1318 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1319 .name = "IEC958 Playback Source",
1320 .info = ad1988_spdif_playback_source_info,
1321 .get = ad1988_spdif_playback_source_get,
1322 .put = ad1988_spdif_playback_source_put,
1323 },
1324 { } /* end */
1325};
1326
1327static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
1328 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
1329 { } /* end */
1330};
1331
1332
1333/*
1334 * initialization verbs
1335 */
1336
1337/*
1338 * for 6-stack (+dig)
1339 */
1340static struct hda_verb ad1988_6stack_init_verbs[] = {
2e5b9567
TI
1341 /* Front, Surround, CLFE, side DAC; unmute as default */
1342 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1343 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1344 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1345 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
1346 /* Port-A front headphon path */
1347 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1348 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1349 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1350 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1351 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1352 /* Port-D line-out path */
1353 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1354 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1355 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1356 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1357 /* Port-F surround path */
1358 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1359 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1360 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1361 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1362 /* Port-G CLFE path */
1363 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1364 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1365 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1366 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1367 /* Port-H side path */
1368 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1369 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1370 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1371 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1372 /* Mono out path */
1373 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1374 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1375 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1376 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1377 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1378 /* Port-B front mic-in path */
1379 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1380 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1381 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1382 /* Port-C line-in path */
1383 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1384 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1385 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1386 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1387 /* Port-E mic-in path */
1388 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1389 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1390 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1391 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1392
1393 { }
1394};
1395
1396static struct hda_verb ad1988_capture_init_verbs[] = {
1397 /* mute analog mix */
1398 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1399 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1400 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1401 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1402 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1403 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1404 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1405 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1406 /* select ADCs - front-mic */
1407 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1408 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1409 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1410 /* ADCs; muted */
1411 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1412 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1413 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1414
1415 { }
1416};
1417
1418static struct hda_verb ad1988_spdif_init_verbs[] = {
1419 /* SPDIF out sel */
1420 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
1421 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
1422 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1423 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1424 /* SPDIF out pin */
1425 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
1426 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
1427
1428 { }
1429};
1430
1431/*
1432 * verbs for 3stack (+dig)
1433 */
1434static struct hda_verb ad1988_3stack_ch2_init[] = {
1435 /* set port-C to line-in */
1436 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1437 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1438 /* set port-E to mic-in */
1439 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1440 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1441 { } /* end */
1442};
1443
1444static struct hda_verb ad1988_3stack_ch6_init[] = {
1445 /* set port-C to surround out */
fd66e0d0 1446 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 1447 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0 1448 /* set port-E to CLFE out */
fd66e0d0 1449 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 1450 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0
TI
1451 { } /* end */
1452};
1453
1454static struct hda_channel_mode ad1988_3stack_modes[2] = {
1455 { 2, ad1988_3stack_ch2_init },
1456 { 6, ad1988_3stack_ch6_init },
1457};
1458
1459static struct hda_verb ad1988_3stack_init_verbs[] = {
2e5b9567
TI
1460 /* Front, Surround, CLFE, side DAC; unmute as default */
1461 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1462 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1463 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1464 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
1465 /* Port-A front headphon path */
1466 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1467 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1468 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1469 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1470 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1471 /* Port-D line-out path */
1472 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1473 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1474 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1475 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1476 /* Mono out path */
1477 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1478 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1479 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1480 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1481 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1482 /* Port-B front mic-in path */
1483 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1484 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1485 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1
TI
1486 /* Port-C line-in/surround path - 6ch mode as default */
1487 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1488 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 1489 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1 1490 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
fd66e0d0 1491 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
d32410b1
TI
1492 /* Port-E mic-in/CLFE path - 6ch mode as default */
1493 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1494 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 1495 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
f8c7c7b8 1496 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
fd66e0d0
TI
1497 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1498 /* mute analog mix */
1499 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1500 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1501 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1502 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1503 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1504 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1505 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1506 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1507 /* select ADCs - front-mic */
1508 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1509 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1510 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1511 /* ADCs; muted */
1512 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1513 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1514 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1515 { }
1516};
1517
1518/*
1519 * verbs for laptop mode (+dig)
1520 */
1521static struct hda_verb ad1988_laptop_hp_on[] = {
1522 /* unmute port-A and mute port-D */
1523 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1524 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1525 { } /* end */
1526};
1527static struct hda_verb ad1988_laptop_hp_off[] = {
1528 /* mute port-A and unmute port-D */
1529 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1530 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1531 { } /* end */
1532};
1533
1534#define AD1988_HP_EVENT 0x01
1535
1536static struct hda_verb ad1988_laptop_init_verbs[] = {
2e5b9567
TI
1537 /* Front, Surround, CLFE, side DAC; unmute as default */
1538 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1539 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1540 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1541 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
1542 /* Port-A front headphon path */
1543 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1544 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1545 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1546 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1547 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1548 /* unsolicited event for pin-sense */
1549 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
1550 /* Port-D line-out path + EAPD */
1551 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1552 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1553 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1554 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1555 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
1556 /* Mono out path */
1557 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1558 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1559 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1560 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1561 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1562 /* Port-B mic-in path */
1563 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1564 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1565 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1566 /* Port-C docking station - try to output */
1567 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1568 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1569 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1570 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1571 /* mute analog mix */
1572 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1573 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1574 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1575 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1576 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1577 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1578 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1579 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1580 /* select ADCs - mic */
1581 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1582 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1583 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1584 /* ADCs; muted */
1585 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1586 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1587 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1588 { }
1589};
1590
1591static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
1592{
1593 if ((res >> 26) != AD1988_HP_EVENT)
1594 return;
1595 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
1596 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
1597 else
1598 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
1599}
1600
1601
d32410b1
TI
1602/*
1603 * Automatic parse of I/O pins from the BIOS configuration
1604 */
1605
1606#define NUM_CONTROL_ALLOC 32
1607#define NUM_VERB_ALLOC 32
1608
1609enum {
1610 AD_CTL_WIDGET_VOL,
1611 AD_CTL_WIDGET_MUTE,
1612 AD_CTL_BIND_MUTE,
1613};
1614static struct snd_kcontrol_new ad1988_control_templates[] = {
1615 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
1616 HDA_CODEC_MUTE(NULL, 0, 0, 0),
1617 HDA_BIND_MUTE(NULL, 0, 0, 0),
1618};
1619
1620/* add dynamic controls */
1621static int add_control(struct ad198x_spec *spec, int type, const char *name,
1622 unsigned long val)
1623{
1624 struct snd_kcontrol_new *knew;
1625
1626 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
1627 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
1628
1629 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
1630 if (! knew)
1631 return -ENOMEM;
1632 if (spec->kctl_alloc) {
1633 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
1634 kfree(spec->kctl_alloc);
1635 }
1636 spec->kctl_alloc = knew;
1637 spec->num_kctl_alloc = num;
1638 }
1639
1640 knew = &spec->kctl_alloc[spec->num_kctl_used];
1641 *knew = ad1988_control_templates[type];
1642 knew->name = kstrdup(name, GFP_KERNEL);
1643 if (! knew->name)
1644 return -ENOMEM;
1645 knew->private_value = val;
1646 spec->num_kctl_used++;
1647 return 0;
1648}
1649
1650#define AD1988_PIN_CD_NID 0x18
1651#define AD1988_PIN_BEEP_NID 0x10
1652
1653static hda_nid_t ad1988_mixer_nids[8] = {
1654 /* A B C D E F G H */
1655 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
1656};
1657
1658static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
1659{
1660 static hda_nid_t idx_to_dac[8] = {
1661 /* A B C D E F G H */
f8c7c7b8 1662 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
d32410b1
TI
1663 };
1664 static hda_nid_t idx_to_dac_rev2[8] = {
1665 /* A B C D E F G H */
f8c7c7b8 1666 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
d32410b1
TI
1667 };
1668 if (codec->revision_id == AD1988A_REV2)
1669 return idx_to_dac_rev2[idx];
1670 else
1671 return idx_to_dac[idx];
1672}
1673
1674static hda_nid_t ad1988_boost_nids[8] = {
1675 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
1676};
1677
1678static int ad1988_pin_idx(hda_nid_t nid)
1679{
1680 static hda_nid_t ad1988_io_pins[8] = {
1681 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
1682 };
1683 int i;
1684 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
1685 if (ad1988_io_pins[i] == nid)
1686 return i;
1687 return 0; /* should be -1 */
1688}
1689
1690static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
1691{
1692 static int loopback_idx[8] = {
1693 2, 0, 1, 3, 4, 5, 1, 4
1694 };
1695 switch (nid) {
1696 case AD1988_PIN_CD_NID:
1697 return 6;
1698 default:
1699 return loopback_idx[ad1988_pin_idx(nid)];
1700 }
1701}
1702
1703static int ad1988_pin_to_adc_idx(hda_nid_t nid)
1704{
1705 static int adc_idx[8] = {
1706 0, 1, 2, 8, 4, 3, 6, 7
1707 };
1708 switch (nid) {
1709 case AD1988_PIN_CD_NID:
1710 return 5;
1711 default:
1712 return adc_idx[ad1988_pin_idx(nid)];
1713 }
1714}
1715
1716/* fill in the dac_nids table from the parsed pin configuration */
1717static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
1718 const struct auto_pin_cfg *cfg)
1719{
1720 struct ad198x_spec *spec = codec->spec;
1721 int i, idx;
1722
1723 spec->multiout.dac_nids = spec->private_dac_nids;
1724
1725 /* check the pins hardwired to audio widget */
1726 for (i = 0; i < cfg->line_outs; i++) {
1727 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
1728 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
1729 }
1730 spec->multiout.num_dacs = cfg->line_outs;
1731 return 0;
1732}
1733
1734/* add playback controls from the parsed DAC table */
1735static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
1736 const struct auto_pin_cfg *cfg)
1737{
1738 char name[32];
1739 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
1740 hda_nid_t nid;
1741 int i, err;
1742
1743 for (i = 0; i < cfg->line_outs; i++) {
1744 hda_nid_t dac = spec->multiout.dac_nids[i];
1745 if (! dac)
1746 continue;
1747 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
1748 if (i == 2) {
1749 /* Center/LFE */
1750 err = add_control(spec, AD_CTL_WIDGET_VOL,
1751 "Center Playback Volume",
1752 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
1753 if (err < 0)
1754 return err;
1755 err = add_control(spec, AD_CTL_WIDGET_VOL,
1756 "LFE Playback Volume",
1757 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
1758 if (err < 0)
1759 return err;
1760 err = add_control(spec, AD_CTL_BIND_MUTE,
1761 "Center Playback Switch",
1762 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
1763 if (err < 0)
1764 return err;
1765 err = add_control(spec, AD_CTL_BIND_MUTE,
1766 "LFE Playback Switch",
1767 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
1768 if (err < 0)
1769 return err;
1770 } else {
1771 sprintf(name, "%s Playback Volume", chname[i]);
1772 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
1773 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
1774 if (err < 0)
1775 return err;
1776 sprintf(name, "%s Playback Switch", chname[i]);
1777 err = add_control(spec, AD_CTL_BIND_MUTE, name,
1778 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
1779 if (err < 0)
1780 return err;
1781 }
1782 }
1783 return 0;
1784}
1785
1786/* add playback controls for speaker and HP outputs */
1787static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
1788 const char *pfx)
1789{
1790 struct ad198x_spec *spec = codec->spec;
1791 hda_nid_t nid;
1792 int idx, err;
1793 char name[32];
1794
1795 if (! pin)
1796 return 0;
1797
1798 idx = ad1988_pin_idx(pin);
1799 nid = ad1988_idx_to_dac(codec, idx);
1800 if (! spec->multiout.dac_nids[0]) {
1801 /* use this as the primary output */
1802 spec->multiout.dac_nids[0] = nid;
1803 if (! spec->multiout.num_dacs)
1804 spec->multiout.num_dacs = 1;
1805 } else
1806 /* specify the DAC as the extra output */
1807 spec->multiout.hp_nid = nid;
1808 /* control HP volume/switch on the output mixer amp */
1809 sprintf(name, "%s Playback Volume", pfx);
1810 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
1811 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1812 return err;
1813 nid = ad1988_mixer_nids[idx];
1814 sprintf(name, "%s Playback Switch", pfx);
1815 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
1816 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
1817 return err;
1818 return 0;
1819}
1820
1821/* create input playback/capture controls for the given pin */
1822static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
1823 const char *ctlname, int boost)
1824{
1825 char name[32];
1826 int err, idx;
1827
1828 sprintf(name, "%s Playback Volume", ctlname);
1829 idx = ad1988_pin_to_loopback_idx(pin);
1830 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
1831 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
1832 return err;
1833 sprintf(name, "%s Playback Switch", ctlname);
1834 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
1835 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
1836 return err;
1837 if (boost) {
1838 hda_nid_t bnid;
1839 idx = ad1988_pin_idx(pin);
1840 bnid = ad1988_boost_nids[idx];
1841 if (bnid) {
1842 sprintf(name, "%s Boost", ctlname);
1843 return add_control(spec, AD_CTL_WIDGET_VOL, name,
1844 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
1845
1846 }
1847 }
1848 return 0;
1849}
1850
1851/* create playback/capture controls for input pins */
1852static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
1853 const struct auto_pin_cfg *cfg)
1854{
d32410b1
TI
1855 struct hda_input_mux *imux = &spec->private_imux;
1856 int i, err;
1857
1858 for (i = 0; i < AUTO_PIN_LAST; i++) {
4a471b7d
TI
1859 err = new_analog_input(spec, cfg->input_pins[i],
1860 auto_pin_cfg_labels[i],
d32410b1
TI
1861 i <= AUTO_PIN_FRONT_MIC);
1862 if (err < 0)
1863 return err;
4a471b7d 1864 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
d32410b1
TI
1865 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
1866 imux->num_items++;
1867 }
1868 imux->items[imux->num_items].label = "Mix";
1869 imux->items[imux->num_items].index = 9;
1870 imux->num_items++;
1871
1872 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
1873 "Analog Mix Playback Volume",
1874 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
1875 return err;
1876 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
1877 "Analog Mix Playback Switch",
1878 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
1879 return err;
1880
1881 return 0;
1882}
1883
1884static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
1885 hda_nid_t nid, int pin_type,
1886 int dac_idx)
1887{
1888 /* set as output */
1889 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
1890 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1891 switch (nid) {
1892 case 0x11: /* port-A - DAC 04 */
1893 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
1894 break;
1895 case 0x14: /* port-B - DAC 06 */
1896 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
1897 break;
1898 case 0x15: /* port-C - DAC 05 */
1899 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
1900 break;
f8c7c7b8 1901 case 0x17: /* port-E - DAC 0a */
d32410b1
TI
1902 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
1903 break;
1904 case 0x13: /* mono - DAC 04 */
1905 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
1906 break;
1907 }
1908}
1909
1910static void ad1988_auto_init_multi_out(struct hda_codec *codec)
1911{
1912 struct ad198x_spec *spec = codec->spec;
1913 int i;
1914
1915 for (i = 0; i < spec->autocfg.line_outs; i++) {
1916 hda_nid_t nid = spec->autocfg.line_out_pins[i];
1917 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
1918 }
1919}
1920
1921static void ad1988_auto_init_extra_out(struct hda_codec *codec)
1922{
1923 struct ad198x_spec *spec = codec->spec;
1924 hda_nid_t pin;
1925
1926 pin = spec->autocfg.speaker_pin;
1927 if (pin) /* connect to front */
1928 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
1929 pin = spec->autocfg.hp_pin;
1930 if (pin) /* connect to front */
1931 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
1932}
1933
1934static void ad1988_auto_init_analog_input(struct hda_codec *codec)
1935{
1936 struct ad198x_spec *spec = codec->spec;
1937 int i, idx;
1938
1939 for (i = 0; i < AUTO_PIN_LAST; i++) {
1940 hda_nid_t nid = spec->autocfg.input_pins[i];
1941 if (! nid)
1942 continue;
1943 switch (nid) {
1944 case 0x15: /* port-C */
1945 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
1946 break;
1947 case 0x17: /* port-E */
1948 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
1949 break;
1950 }
1951 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1952 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
1953 if (nid != AD1988_PIN_CD_NID)
1954 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1955 AMP_OUT_MUTE);
1956 idx = ad1988_pin_idx(nid);
1957 if (ad1988_boost_nids[idx])
1958 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
1959 AC_VERB_SET_AMP_GAIN_MUTE,
1960 AMP_OUT_ZERO);
1961 }
1962}
1963
1964/* parse the BIOS configuration and set up the alc_spec */
1965/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
1966static int ad1988_parse_auto_config(struct hda_codec *codec)
1967{
1968 struct ad198x_spec *spec = codec->spec;
1969 int err;
1970
df694daa 1971 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
d32410b1
TI
1972 return err;
1973 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
1974 return err;
1975 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
1976 ! spec->autocfg.hp_pin)
1977 return 0; /* can't find valid BIOS pin config */
1978 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
1979 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin,
1980 "Speaker")) < 0 ||
1981 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin,
1982 "Headphone")) < 0 ||
1983 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
1984 return err;
1985
1986 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1987
1988 if (spec->autocfg.dig_out_pin)
1989 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1990 if (spec->autocfg.dig_in_pin)
1991 spec->dig_in_nid = AD1988_SPDIF_IN;
1992
1993 if (spec->kctl_alloc)
1994 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1995
1996 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
1997
1998 spec->input_mux = &spec->private_imux;
1999
2000 return 1;
2001}
2002
2003/* init callback for auto-configuration model -- overriding the default init */
2004static int ad1988_auto_init(struct hda_codec *codec)
2005{
2006 ad198x_init(codec);
2007 ad1988_auto_init_multi_out(codec);
2008 ad1988_auto_init_extra_out(codec);
2009 ad1988_auto_init_analog_input(codec);
2010 return 0;
2011}
2012
2013
fd66e0d0
TI
2014/*
2015 */
2016
2017static struct hda_board_config ad1988_cfg_tbl[] = {
2018 { .modelname = "6stack", .config = AD1988_6STACK },
2019 { .modelname = "6stack-dig", .config = AD1988_6STACK_DIG },
2020 { .modelname = "3stack", .config = AD1988_3STACK },
2021 { .modelname = "3stack-dig", .config = AD1988_3STACK_DIG },
2022 { .modelname = "laptop", .config = AD1988_LAPTOP },
2023 { .modelname = "laptop-dig", .config = AD1988_LAPTOP_DIG },
d32410b1 2024 { .modelname = "auto", .config = AD1988_AUTO },
fd66e0d0
TI
2025 {}
2026};
2027
2028static int patch_ad1988(struct hda_codec *codec)
2029{
2030 struct ad198x_spec *spec;
2031 int board_config;
2032
2033 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2034 if (spec == NULL)
2035 return -ENOMEM;
2036
62932df8 2037 mutex_init(&spec->amp_mutex);
fd66e0d0
TI
2038 codec->spec = spec;
2039
f8c7c7b8
TI
2040 if (codec->revision_id == AD1988A_REV2)
2041 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2042
fd66e0d0
TI
2043 board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
2044 if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
d32410b1
TI
2045 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2046 board_config = AD1988_AUTO;
2047 }
2048
2049 if (board_config == AD1988_AUTO) {
2050 /* automatic parse from the BIOS config */
2051 int err = ad1988_parse_auto_config(codec);
2052 if (err < 0) {
2053 ad198x_free(codec);
2054 return err;
2055 } else if (! err) {
2056 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2057 board_config = AD1988_6STACK;
2058 }
fd66e0d0
TI
2059 }
2060
2061 switch (board_config) {
2062 case AD1988_6STACK:
2063 case AD1988_6STACK_DIG:
2064 spec->multiout.max_channels = 8;
2065 spec->multiout.num_dacs = 4;
d32410b1
TI
2066 if (codec->revision_id == AD1988A_REV2)
2067 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2068 else
2069 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
fd66e0d0 2070 spec->input_mux = &ad1988_6stack_capture_source;
d32410b1
TI
2071 spec->num_mixers = 2;
2072 if (codec->revision_id == AD1988A_REV2)
2073 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2074 else
2075 spec->mixers[0] = ad1988_6stack_mixers1;
2076 spec->mixers[1] = ad1988_6stack_mixers2;
fd66e0d0
TI
2077 spec->num_init_verbs = 1;
2078 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2079 if (board_config == AD1988_6STACK_DIG) {
2080 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2081 spec->dig_in_nid = AD1988_SPDIF_IN;
2082 }
2083 break;
2084 case AD1988_3STACK:
2085 case AD1988_3STACK_DIG:
2086 spec->multiout.max_channels = 6;
2087 spec->multiout.num_dacs = 3;
d32410b1
TI
2088 if (codec->revision_id == AD1988A_REV2)
2089 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2090 else
2091 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
2092 spec->input_mux = &ad1988_6stack_capture_source;
2093 spec->channel_mode = ad1988_3stack_modes;
2094 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
d32410b1
TI
2095 spec->num_mixers = 2;
2096 if (codec->revision_id == AD1988A_REV2)
2097 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
2098 else
2099 spec->mixers[0] = ad1988_3stack_mixers1;
2100 spec->mixers[1] = ad1988_3stack_mixers2;
fd66e0d0
TI
2101 spec->num_init_verbs = 1;
2102 spec->init_verbs[0] = ad1988_3stack_init_verbs;
2103 if (board_config == AD1988_3STACK_DIG)
2104 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2105 break;
2106 case AD1988_LAPTOP:
2107 case AD1988_LAPTOP_DIG:
2108 spec->multiout.max_channels = 2;
2109 spec->multiout.num_dacs = 1;
d32410b1 2110 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
2111 spec->input_mux = &ad1988_laptop_capture_source;
2112 spec->num_mixers = 1;
2113 spec->mixers[0] = ad1988_laptop_mixers;
2114 spec->num_init_verbs = 1;
2115 spec->init_verbs[0] = ad1988_laptop_init_verbs;
2116 if (board_config == AD1988_LAPTOP_DIG)
2117 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2118 break;
2119 }
2120
d32410b1
TI
2121 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
2122 spec->adc_nids = ad1988_adc_nids;
2123 spec->capsrc_nids = ad1988_capsrc_nids;
fd66e0d0
TI
2124 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
2125 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
2126 if (spec->multiout.dig_out_nid) {
2127 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
2128 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
2129 }
2130 if (spec->dig_in_nid)
2131 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
2132
2133 codec->patch_ops = ad198x_patch_ops;
2134 switch (board_config) {
d32410b1
TI
2135 case AD1988_AUTO:
2136 codec->patch_ops.init = ad1988_auto_init;
2137 break;
fd66e0d0
TI
2138 case AD1988_LAPTOP:
2139 case AD1988_LAPTOP_DIG:
2140 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
2141 break;
2142 }
2143
2144 return 0;
2145}
2146
2147
1da177e4
LT
2148/*
2149 * patch entries
2150 */
2151struct hda_codec_preset snd_hda_preset_analog[] = {
4a3fdf3d
TI
2152 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
2153 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
1da177e4 2154 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
fd66e0d0 2155 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
1da177e4
LT
2156 {} /* terminator */
2157};