ALSA: hda - Modularize HD-audio driver
[deliverable/linux.git] / sound / pci / hda / patch_analog.c
CommitLineData
1da177e4 1/*
0ac8551e
TI
2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
3 * AD1986A, AD1988
1da177e4 4 *
2bac647c 5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
1da177e4
LT
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
1da177e4
LT
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
62932df8 26
1da177e4
LT
27#include <sound/core.h>
28#include "hda_codec.h"
29#include "hda_local.h"
30
4a3fdf3d 31struct ad198x_spec {
c8b6bf9b 32 struct snd_kcontrol_new *mixers[5];
985be54b
TI
33 int num_mixers;
34
d32410b1 35 const struct hda_verb *init_verbs[5]; /* initialization verbs
985be54b
TI
36 * don't forget NULL termination!
37 */
38 unsigned int num_init_verbs;
39
40 /* playback */
41 struct hda_multi_out multiout; /* playback set-up
42 * max_channels, dacs must be set
43 * dig_out_nid and hp_nid are optional
44 */
fd66e0d0 45 unsigned int cur_eapd;
2125cad2 46 unsigned int need_dac_fix;
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 */
2bac647c 63 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
985be54b 64
4a3fdf3d 65 unsigned int spdif_route;
d32410b1
TI
66
67 /* dynamic controls, init_verbs and input_mux */
68 struct auto_pin_cfg autocfg;
603c4019 69 struct snd_array kctls;
d32410b1 70 struct hda_input_mux private_imux;
41923e44 71 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
cb53c626 72
8ab78c74
TI
73 unsigned int jack_present :1;
74
cb53c626
TI
75#ifdef CONFIG_SND_HDA_POWER_SAVE
76 struct hda_loopback_check loopback;
77#endif
2134ea4f
TI
78 /* for virtual master */
79 hda_nid_t vmaster_nid;
2134ea4f
TI
80 const char **slave_vols;
81 const char **slave_sws;
1da177e4
LT
82};
83
4a3fdf3d
TI
84/*
85 * input MUX handling (common part)
86 */
c8b6bf9b 87static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
4a3fdf3d
TI
88{
89 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
90 struct ad198x_spec *spec = codec->spec;
91
92 return snd_hda_input_mux_info(spec->input_mux, uinfo);
93}
94
c8b6bf9b 95static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4a3fdf3d
TI
96{
97 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
98 struct ad198x_spec *spec = codec->spec;
985be54b 99 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4a3fdf3d 100
985be54b 101 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
4a3fdf3d
TI
102 return 0;
103}
104
c8b6bf9b 105static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4a3fdf3d
TI
106{
107 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
108 struct ad198x_spec *spec = codec->spec;
985be54b 109 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4a3fdf3d
TI
110
111 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
2e5b9567
TI
112 spec->capsrc_nids[adc_idx],
113 &spec->cur_mux[adc_idx]);
4a3fdf3d
TI
114}
115
116/*
117 * initialization (common callbacks)
118 */
119static int ad198x_init(struct hda_codec *codec)
120{
121 struct ad198x_spec *spec = codec->spec;
985be54b
TI
122 int i;
123
124 for (i = 0; i < spec->num_init_verbs; i++)
125 snd_hda_sequence_write(codec, spec->init_verbs[i]);
4a3fdf3d
TI
126 return 0;
127}
128
2134ea4f
TI
129static const char *ad_slave_vols[] = {
130 "Front Playback Volume",
131 "Surround Playback Volume",
132 "Center Playback Volume",
133 "LFE Playback Volume",
134 "Side Playback Volume",
135 "Headphone Playback Volume",
136 "Mono Playback Volume",
628ed133 137 "Speaker Playback Volume",
4806ef0c 138 "IEC958 Playback Volume",
2134ea4f
TI
139 NULL
140};
141
142static const char *ad_slave_sws[] = {
143 "Front Playback Switch",
144 "Surround Playback Switch",
145 "Center Playback Switch",
146 "LFE Playback Switch",
147 "Side Playback Switch",
148 "Headphone Playback Switch",
149 "Mono Playback Switch",
628ed133 150 "Speaker Playback Switch",
4806ef0c 151 "IEC958 Playback Switch",
2134ea4f
TI
152 NULL
153};
154
603c4019
TI
155static void ad198x_free_kctls(struct hda_codec *codec);
156
4a3fdf3d
TI
157static int ad198x_build_controls(struct hda_codec *codec)
158{
159 struct ad198x_spec *spec = codec->spec;
985be54b 160 unsigned int i;
4a3fdf3d
TI
161 int err;
162
985be54b
TI
163 for (i = 0; i < spec->num_mixers; i++) {
164 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
165 if (err < 0)
166 return err;
167 }
168 if (spec->multiout.dig_out_nid) {
4a3fdf3d 169 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
985be54b
TI
170 if (err < 0)
171 return err;
9a08160b
TI
172 err = snd_hda_create_spdif_share_sw(codec,
173 &spec->multiout);
174 if (err < 0)
175 return err;
176 spec->multiout.share_spdif = 1;
985be54b
TI
177 }
178 if (spec->dig_in_nid) {
179 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
180 if (err < 0)
181 return err;
182 }
2134ea4f
TI
183
184 /* if we have no master control, let's create it */
185 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
1c82ed1b 186 unsigned int vmaster_tlv[4];
2134ea4f 187 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
1c82ed1b 188 HDA_OUTPUT, vmaster_tlv);
2134ea4f 189 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1c82ed1b 190 vmaster_tlv,
2134ea4f
TI
191 (spec->slave_vols ?
192 spec->slave_vols : ad_slave_vols));
193 if (err < 0)
194 return err;
195 }
196 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
197 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
198 NULL,
199 (spec->slave_sws ?
200 spec->slave_sws : ad_slave_sws));
201 if (err < 0)
202 return err;
203 }
204
603c4019 205 ad198x_free_kctls(codec); /* no longer needed */
4a3fdf3d
TI
206 return 0;
207}
208
cb53c626
TI
209#ifdef CONFIG_SND_HDA_POWER_SAVE
210static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
211{
212 struct ad198x_spec *spec = codec->spec;
213 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
214}
215#endif
216
4a3fdf3d
TI
217/*
218 * Analog playback callbacks
219 */
220static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
221 struct hda_codec *codec,
c8b6bf9b 222 struct snd_pcm_substream *substream)
4a3fdf3d
TI
223{
224 struct ad198x_spec *spec = codec->spec;
9a08160b
TI
225 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
226 hinfo);
4a3fdf3d
TI
227}
228
229static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
230 struct hda_codec *codec,
231 unsigned int stream_tag,
232 unsigned int format,
c8b6bf9b 233 struct snd_pcm_substream *substream)
4a3fdf3d
TI
234{
235 struct ad198x_spec *spec = codec->spec;
236 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
237 format, substream);
238}
239
240static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
241 struct hda_codec *codec,
c8b6bf9b 242 struct snd_pcm_substream *substream)
4a3fdf3d
TI
243{
244 struct ad198x_spec *spec = codec->spec;
245 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
246}
247
248/*
249 * Digital out
250 */
251static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
252 struct hda_codec *codec,
c8b6bf9b 253 struct snd_pcm_substream *substream)
4a3fdf3d
TI
254{
255 struct ad198x_spec *spec = codec->spec;
256 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
257}
258
259static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
260 struct hda_codec *codec,
c8b6bf9b 261 struct snd_pcm_substream *substream)
4a3fdf3d
TI
262{
263 struct ad198x_spec *spec = codec->spec;
264 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
265}
266
6b97eb45
TI
267static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
268 struct hda_codec *codec,
269 unsigned int stream_tag,
270 unsigned int format,
271 struct snd_pcm_substream *substream)
272{
273 struct ad198x_spec *spec = codec->spec;
274 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
275 format, substream);
276}
277
4a3fdf3d
TI
278/*
279 * Analog capture
280 */
281static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
282 struct hda_codec *codec,
283 unsigned int stream_tag,
284 unsigned int format,
c8b6bf9b 285 struct snd_pcm_substream *substream)
4a3fdf3d
TI
286{
287 struct ad198x_spec *spec = codec->spec;
985be54b
TI
288 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
289 stream_tag, 0, format);
4a3fdf3d
TI
290 return 0;
291}
292
293static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
294 struct hda_codec *codec,
c8b6bf9b 295 struct snd_pcm_substream *substream)
4a3fdf3d
TI
296{
297 struct ad198x_spec *spec = codec->spec;
888afa15 298 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
4a3fdf3d
TI
299 return 0;
300}
301
302
303/*
304 */
305static struct hda_pcm_stream ad198x_pcm_analog_playback = {
306 .substreams = 1,
307 .channels_min = 2,
985be54b 308 .channels_max = 6, /* changed later */
4a3fdf3d
TI
309 .nid = 0, /* fill later */
310 .ops = {
311 .open = ad198x_playback_pcm_open,
312 .prepare = ad198x_playback_pcm_prepare,
313 .cleanup = ad198x_playback_pcm_cleanup
314 },
315};
316
317static struct hda_pcm_stream ad198x_pcm_analog_capture = {
985be54b 318 .substreams = 1,
4a3fdf3d
TI
319 .channels_min = 2,
320 .channels_max = 2,
321 .nid = 0, /* fill later */
322 .ops = {
323 .prepare = ad198x_capture_pcm_prepare,
324 .cleanup = ad198x_capture_pcm_cleanup
325 },
326};
327
328static struct hda_pcm_stream ad198x_pcm_digital_playback = {
329 .substreams = 1,
330 .channels_min = 2,
331 .channels_max = 2,
332 .nid = 0, /* fill later */
333 .ops = {
334 .open = ad198x_dig_playback_pcm_open,
6b97eb45
TI
335 .close = ad198x_dig_playback_pcm_close,
336 .prepare = ad198x_dig_playback_pcm_prepare
4a3fdf3d
TI
337 },
338};
339
985be54b
TI
340static struct hda_pcm_stream ad198x_pcm_digital_capture = {
341 .substreams = 1,
342 .channels_min = 2,
343 .channels_max = 2,
344 /* NID is set in alc_build_pcms */
345};
346
4a3fdf3d
TI
347static int ad198x_build_pcms(struct hda_codec *codec)
348{
349 struct ad198x_spec *spec = codec->spec;
350 struct hda_pcm *info = spec->pcm_rec;
351
352 codec->num_pcms = 1;
353 codec->pcm_info = info;
354
355 info->name = "AD198x Analog";
356 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
357 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
358 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
359 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
985be54b
TI
360 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
361 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4a3fdf3d
TI
362
363 if (spec->multiout.dig_out_nid) {
364 info++;
365 codec->num_pcms++;
366 info->name = "AD198x Digital";
7ba72ba1 367 info->pcm_type = HDA_PCM_TYPE_SPDIF;
4a3fdf3d
TI
368 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
369 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
985be54b
TI
370 if (spec->dig_in_nid) {
371 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
372 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
373 }
4a3fdf3d
TI
374 }
375
376 return 0;
377}
378
603c4019 379static void ad198x_free_kctls(struct hda_codec *codec)
4a3fdf3d 380{
d32410b1 381 struct ad198x_spec *spec = codec->spec;
d32410b1 382
603c4019
TI
383 if (spec->kctls.list) {
384 struct snd_kcontrol_new *kctl = spec->kctls.list;
385 int i;
386 for (i = 0; i < spec->kctls.used; i++)
387 kfree(kctl[i].name);
d32410b1 388 }
603c4019
TI
389 snd_array_free(&spec->kctls);
390}
391
392static void ad198x_free(struct hda_codec *codec)
393{
394 struct ad198x_spec *spec = codec->spec;
395
396 if (!spec)
397 return;
398
399 ad198x_free_kctls(codec);
4a3fdf3d
TI
400 kfree(codec->spec);
401}
402
4a3fdf3d
TI
403static struct hda_codec_ops ad198x_patch_ops = {
404 .build_controls = ad198x_build_controls,
405 .build_pcms = ad198x_build_pcms,
406 .init = ad198x_init,
407 .free = ad198x_free,
cb53c626
TI
408#ifdef CONFIG_SND_HDA_POWER_SAVE
409 .check_power_status = ad198x_check_power_status,
410#endif
4a3fdf3d
TI
411};
412
413
18a815d7
TI
414/*
415 * EAPD control
416 * the private value = nid | (invert << 8)
417 */
a5ce8890 418#define ad198x_eapd_info snd_ctl_boolean_mono_info
18a815d7
TI
419
420static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
421 struct snd_ctl_elem_value *ucontrol)
422{
423 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
424 struct ad198x_spec *spec = codec->spec;
425 int invert = (kcontrol->private_value >> 8) & 1;
426 if (invert)
427 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
428 else
429 ucontrol->value.integer.value[0] = spec->cur_eapd;
430 return 0;
431}
432
433static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
434 struct snd_ctl_elem_value *ucontrol)
435{
436 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
437 struct ad198x_spec *spec = codec->spec;
438 int invert = (kcontrol->private_value >> 8) & 1;
439 hda_nid_t nid = kcontrol->private_value & 0xff;
440 unsigned int eapd;
68ea7b2f 441 eapd = !!ucontrol->value.integer.value[0];
18a815d7
TI
442 if (invert)
443 eapd = !eapd;
82beb8fd 444 if (eapd == spec->cur_eapd)
18a815d7
TI
445 return 0;
446 spec->cur_eapd = eapd;
82beb8fd
TI
447 snd_hda_codec_write_cache(codec, nid,
448 0, AC_VERB_SET_EAPD_BTLENABLE,
449 eapd ? 0x02 : 0x00);
18a815d7
TI
450 return 1;
451}
452
9230d214
TI
453static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
454 struct snd_ctl_elem_info *uinfo);
455static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
456 struct snd_ctl_elem_value *ucontrol);
457static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
458 struct snd_ctl_elem_value *ucontrol);
459
460
4a3fdf3d
TI
461/*
462 * AD1986A specific
463 */
464
1da177e4
LT
465#define AD1986A_SPDIF_OUT 0x02
466#define AD1986A_FRONT_DAC 0x03
467#define AD1986A_SURR_DAC 0x04
468#define AD1986A_CLFE_DAC 0x05
469#define AD1986A_ADC 0x06
470
471static hda_nid_t ad1986a_dac_nids[3] = {
472 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
473};
985be54b 474static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
18a815d7 475static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
1da177e4
LT
476
477static struct hda_input_mux ad1986a_capture_source = {
478 .num_items = 7,
479 .items = {
480 { "Mic", 0x0 },
481 { "CD", 0x1 },
482 { "Aux", 0x3 },
483 { "Line", 0x4 },
484 { "Mix", 0x5 },
485 { "Mono", 0x6 },
486 { "Phone", 0x7 },
487 },
488};
489
1da177e4 490
532d5381
TI
491static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
492 .ops = &snd_hda_bind_vol,
493 .values = {
494 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
495 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
496 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
497 0
498 },
499};
1da177e4 500
532d5381
TI
501static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
502 .ops = &snd_hda_bind_sw,
503 .values = {
504 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
505 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
506 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
507 0
508 },
509};
1da177e4 510
1da177e4
LT
511/*
512 * mixers
513 */
c8b6bf9b 514static struct snd_kcontrol_new ad1986a_mixers[] = {
532d5381
TI
515 /*
516 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
517 */
518 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
519 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
1da177e4
LT
520 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
521 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
522 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
523 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
524 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
525 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
526 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
527 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
528 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
529 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
530 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
531 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
532 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
533 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
534 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
535 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
536 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
537 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
fe8970b4 538 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
1da177e4
LT
539 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
540 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
541 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
542 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
543 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
544 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
545 {
546 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
547 .name = "Capture Source",
4a3fdf3d
TI
548 .info = ad198x_mux_enum_info,
549 .get = ad198x_mux_enum_get,
550 .put = ad198x_mux_enum_put,
1da177e4
LT
551 },
552 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
553 { } /* end */
554};
555
9230d214
TI
556/* additional mixers for 3stack mode */
557static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
558 {
559 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
560 .name = "Channel Mode",
561 .info = ad198x_ch_mode_info,
562 .get = ad198x_ch_mode_get,
563 .put = ad198x_ch_mode_put,
564 },
565 { } /* end */
566};
567
568/* laptop model - 2ch only */
569static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
570
20a45e86
TI
571/* master controls both pins 0x1a and 0x1b */
572static struct hda_bind_ctls ad1986a_laptop_master_vol = {
573 .ops = &snd_hda_bind_vol,
574 .values = {
575 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
576 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
577 0,
578 },
579};
580
581static struct hda_bind_ctls ad1986a_laptop_master_sw = {
582 .ops = &snd_hda_bind_sw,
583 .values = {
584 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
585 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
586 0,
587 },
588};
589
9230d214
TI
590static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
591 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
592 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
20a45e86
TI
593 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
594 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
9230d214
TI
595 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
596 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
597 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
598 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
599 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
600 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
601 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
602 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
fe8970b4 603 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
9230d214
TI
604 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
605 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
606 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
607 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
608 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
609 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
610 {
611 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
612 .name = "Capture Source",
613 .info = ad198x_mux_enum_info,
614 .get = ad198x_mux_enum_get,
615 .put = ad198x_mux_enum_put,
616 },
617 { } /* end */
618};
619
825aa972
TI
620/* laptop-eapd model - 2ch only */
621
825aa972
TI
622static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
623 .num_items = 3,
624 .items = {
625 { "Mic", 0x0 },
626 { "Internal Mic", 0x4 },
627 { "Mix", 0x5 },
628 },
629};
630
5d5d5f43
TI
631static struct hda_input_mux ad1986a_automic_capture_source = {
632 .num_items = 2,
633 .items = {
634 { "Mic", 0x0 },
635 { "Mix", 0x5 },
636 },
637};
638
825aa972 639static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
1725b82a
TI
640 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
641 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
642 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
643 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
644 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
645 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
646 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
647 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
648 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
649 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
650 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
651 {
652 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
653 .name = "Capture Source",
654 .info = ad198x_mux_enum_info,
655 .get = ad198x_mux_enum_get,
656 .put = ad198x_mux_enum_put,
657 },
658 {
659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
660 .name = "External Amplifier",
661 .info = ad198x_eapd_info,
662 .get = ad198x_eapd_get,
663 .put = ad198x_eapd_put,
664 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
665 },
666 { } /* end */
667};
668
669static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
532d5381
TI
670 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
671 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
825aa972
TI
672 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
673 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
825aa972
TI
674 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
675 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
fe8970b4 676 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
825aa972
TI
677 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
678 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
679 {
680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
681 .name = "Capture Source",
682 .info = ad198x_mux_enum_info,
683 .get = ad198x_mux_enum_get,
684 .put = ad198x_mux_enum_put,
685 },
686 {
687 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
688 .name = "External Amplifier",
689 .info = ad198x_eapd_info,
690 .get = ad198x_eapd_get,
691 .put = ad198x_eapd_put,
692 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
693 },
694 { } /* end */
695};
696
5d5d5f43
TI
697/* re-connect the mic boost input according to the jack sensing */
698static void ad1986a_automic(struct hda_codec *codec)
699{
700 unsigned int present;
701 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
702 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
703 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
704 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
705}
706
707#define AD1986A_MIC_EVENT 0x36
708
709static void ad1986a_automic_unsol_event(struct hda_codec *codec,
710 unsigned int res)
711{
712 if ((res >> 26) != AD1986A_MIC_EVENT)
713 return;
714 ad1986a_automic(codec);
715}
716
717static int ad1986a_automic_init(struct hda_codec *codec)
718{
719 ad198x_init(codec);
720 ad1986a_automic(codec);
721 return 0;
722}
723
8ab78c74
TI
724/* laptop-automute - 2ch only */
725
726static void ad1986a_update_hp(struct hda_codec *codec)
727{
728 struct ad198x_spec *spec = codec->spec;
729 unsigned int mute;
730
731 if (spec->jack_present)
732 mute = HDA_AMP_MUTE; /* mute internal speaker */
733 else
734 /* unmute internal speaker if necessary */
735 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
736 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
737 HDA_AMP_MUTE, mute);
738}
739
740static void ad1986a_hp_automute(struct hda_codec *codec)
741{
742 struct ad198x_spec *spec = codec->spec;
743 unsigned int present;
744
745 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
53eb1b85
TI
746 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
747 spec->jack_present = !(present & 0x80000000);
8ab78c74
TI
748 ad1986a_update_hp(codec);
749}
750
751#define AD1986A_HP_EVENT 0x37
752
753static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
754{
755 if ((res >> 26) != AD1986A_HP_EVENT)
756 return;
757 ad1986a_hp_automute(codec);
758}
759
760static int ad1986a_hp_init(struct hda_codec *codec)
761{
762 ad198x_init(codec);
763 ad1986a_hp_automute(codec);
764 return 0;
765}
766
767/* bind hp and internal speaker mute (with plug check) */
768static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
769 struct snd_ctl_elem_value *ucontrol)
770{
771 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
772 long *valp = ucontrol->value.integer.value;
773 int change;
774
775 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
776 HDA_AMP_MUTE,
777 valp[0] ? 0 : HDA_AMP_MUTE);
778 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
779 HDA_AMP_MUTE,
780 valp[1] ? 0 : HDA_AMP_MUTE);
781 if (change)
782 ad1986a_update_hp(codec);
783 return change;
784}
785
786static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
787 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
788 {
789 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
790 .name = "Master Playback Switch",
791 .info = snd_hda_mixer_amp_switch_info,
792 .get = snd_hda_mixer_amp_switch_get,
793 .put = ad1986a_hp_master_sw_put,
794 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
795 },
796 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
797 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
798 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
799 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
800 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
801 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
802 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
803 HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
804 HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
805 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
806 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
807 {
808 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
809 .name = "Capture Source",
810 .info = ad198x_mux_enum_info,
811 .get = ad198x_mux_enum_get,
812 .put = ad198x_mux_enum_put,
813 },
814 {
815 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
816 .name = "External Amplifier",
817 .info = ad198x_eapd_info,
818 .get = ad198x_eapd_get,
819 .put = ad198x_eapd_put,
820 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
821 },
822 { } /* end */
823};
824
1da177e4
LT
825/*
826 * initialization verbs
827 */
828static struct hda_verb ad1986a_init_verbs[] = {
829 /* Front, Surround, CLFE DAC; mute as default */
830 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
831 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
832 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
833 /* Downmix - off */
834 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
835 /* HP, Line-Out, Surround, CLFE selectors */
836 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
837 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
838 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
839 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
840 /* Mono selector */
841 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
842 /* Mic selector: Mic 1/2 pin */
843 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
844 /* Line-in selector: Line-in */
845 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
846 /* Mic 1/2 swap */
847 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
848 /* Record selector: mic */
849 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
850 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
851 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
852 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
853 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
854 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
855 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
856 /* PC beep */
857 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
858 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
859 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
860 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
861 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
862 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
863 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
4a3fdf3d
TI
864 /* HP Pin */
865 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
866 /* Front, Surround, CLFE Pins */
867 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
868 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
869 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
870 /* Mono Pin */
871 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
872 /* Mic Pin */
873 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
874 /* Line, Aux, CD, Beep-In Pin */
875 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
876 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
877 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
878 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
879 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1da177e4
LT
880 { } /* end */
881};
882
9230d214
TI
883static struct hda_verb ad1986a_ch2_init[] = {
884 /* Surround out -> Line In */
fb956c16
TI
885 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
886 /* Line-in selectors */
887 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
9230d214 888 /* CLFE -> Mic in */
fb956c16
TI
889 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
890 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
891 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
9230d214
TI
892 { } /* end */
893};
894
895static struct hda_verb ad1986a_ch4_init[] = {
896 /* Surround out -> Surround */
fb956c16
TI
897 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
898 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
9230d214 899 /* CLFE -> Mic in */
fb956c16
TI
900 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
901 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
9230d214
TI
902 { } /* end */
903};
904
905static struct hda_verb ad1986a_ch6_init[] = {
906 /* Surround out -> Surround out */
fb956c16
TI
907 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
908 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
9230d214 909 /* CLFE -> CLFE */
fb956c16
TI
910 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
911 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
9230d214
TI
912 { } /* end */
913};
914
915static struct hda_channel_mode ad1986a_modes[3] = {
916 { 2, ad1986a_ch2_init },
917 { 4, ad1986a_ch4_init },
918 { 6, ad1986a_ch6_init },
919};
920
825aa972
TI
921/* eapd initialization */
922static struct hda_verb ad1986a_eapd_init_verbs[] = {
f36090fe 923 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
825aa972
TI
924 {}
925};
926
5d5d5f43
TI
927static struct hda_verb ad1986a_automic_verbs[] = {
928 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
929 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
930 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
931 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
932 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
933 {}
934};
935
f36090fe
TD
936/* Ultra initialization */
937static struct hda_verb ad1986a_ultra_init[] = {
938 /* eapd initialization */
939 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
940 /* CLFE -> Mic in */
941 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
942 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
943 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
944 { } /* end */
945};
946
8ab78c74
TI
947/* pin sensing on HP jack */
948static struct hda_verb ad1986a_hp_init_verbs[] = {
949 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
950 {}
951};
952
953
9230d214 954/* models */
f5fcc13c
TI
955enum {
956 AD1986A_6STACK,
957 AD1986A_3STACK,
958 AD1986A_LAPTOP,
959 AD1986A_LAPTOP_EAPD,
8ab78c74 960 AD1986A_LAPTOP_AUTOMUTE,
f36090fe 961 AD1986A_ULTRA,
1725b82a 962 AD1986A_SAMSUNG,
f5fcc13c
TI
963 AD1986A_MODELS
964};
965
966static const char *ad1986a_models[AD1986A_MODELS] = {
967 [AD1986A_6STACK] = "6stack",
968 [AD1986A_3STACK] = "3stack",
969 [AD1986A_LAPTOP] = "laptop",
970 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
8ab78c74 971 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
f36090fe 972 [AD1986A_ULTRA] = "ultra",
1725b82a 973 [AD1986A_SAMSUNG] = "samsung",
f5fcc13c
TI
974};
975
976static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
977 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
f5fcc13c 978 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
f5fcc13c 979 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
ac3e3741 980 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
f5fcc13c
TI
981 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
982 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
983 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
984 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
d9f9b8ba 985 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
658fba0e 986 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
f5fcc13c
TI
987 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
988 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
989 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
990 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
991 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
ac3e3741 992 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
7db756f2 993 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
18768991 994 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
f5fcc13c 995 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1725b82a
TI
996 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG),
997 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG),
998 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG),
f36090fe 999 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
ac3e3741 1000 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
18768991 1001 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
f5fcc13c 1002 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
8ab78c74 1003 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
f5fcc13c 1004 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
9230d214
TI
1005 {}
1006};
1da177e4 1007
cb53c626
TI
1008#ifdef CONFIG_SND_HDA_POWER_SAVE
1009static struct hda_amp_list ad1986a_loopbacks[] = {
1010 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1011 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1012 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1013 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1014 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1015 { } /* end */
1016};
1017#endif
1018
8c0d9649
TI
1019static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1020{
1021 unsigned int conf = snd_hda_codec_read(codec, nid, 0,
1022 AC_VERB_GET_CONFIG_DEFAULT, 0);
1023 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1024}
1025
4a3fdf3d 1026static int patch_ad1986a(struct hda_codec *codec)
1da177e4 1027{
4a3fdf3d 1028 struct ad198x_spec *spec;
9230d214 1029 int board_config;
1da177e4 1030
e560d8d8 1031 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4a3fdf3d
TI
1032 if (spec == NULL)
1033 return -ENOMEM;
1034
4a3fdf3d
TI
1035 codec->spec = spec;
1036
1037 spec->multiout.max_channels = 6;
1038 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1039 spec->multiout.dac_nids = ad1986a_dac_nids;
1040 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
985be54b
TI
1041 spec->num_adc_nids = 1;
1042 spec->adc_nids = ad1986a_adc_nids;
a7ee8201 1043 spec->capsrc_nids = ad1986a_capsrc_nids;
4a3fdf3d 1044 spec->input_mux = &ad1986a_capture_source;
985be54b
TI
1045 spec->num_mixers = 1;
1046 spec->mixers[0] = ad1986a_mixers;
1047 spec->num_init_verbs = 1;
1048 spec->init_verbs[0] = ad1986a_init_verbs;
cb53c626
TI
1049#ifdef CONFIG_SND_HDA_POWER_SAVE
1050 spec->loopback.amplist = ad1986a_loopbacks;
1051#endif
2134ea4f 1052 spec->vmaster_nid = 0x1b;
4a3fdf3d
TI
1053
1054 codec->patch_ops = ad198x_patch_ops;
1da177e4 1055
9230d214 1056 /* override some parameters */
f5fcc13c
TI
1057 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1058 ad1986a_models,
1059 ad1986a_cfg_tbl);
9230d214
TI
1060 switch (board_config) {
1061 case AD1986A_3STACK:
1062 spec->num_mixers = 2;
1063 spec->mixers[1] = ad1986a_3st_mixers;
fb956c16
TI
1064 spec->num_init_verbs = 2;
1065 spec->init_verbs[1] = ad1986a_ch2_init;
9230d214
TI
1066 spec->channel_mode = ad1986a_modes;
1067 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
2125cad2
TI
1068 spec->need_dac_fix = 1;
1069 spec->multiout.max_channels = 2;
1070 spec->multiout.num_dacs = 1;
9230d214
TI
1071 break;
1072 case AD1986A_LAPTOP:
1073 spec->mixers[0] = ad1986a_laptop_mixers;
1074 spec->multiout.max_channels = 2;
1075 spec->multiout.num_dacs = 1;
1076 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1077 break;
825aa972
TI
1078 case AD1986A_LAPTOP_EAPD:
1079 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1725b82a
TI
1080 spec->num_init_verbs = 2;
1081 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1082 spec->multiout.max_channels = 2;
1083 spec->multiout.num_dacs = 1;
1084 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1085 if (!is_jack_available(codec, 0x25))
1086 spec->multiout.dig_out_nid = 0;
1087 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1088 break;
1089 case AD1986A_SAMSUNG:
1090 spec->mixers[0] = ad1986a_samsung_mixers;
5d5d5f43 1091 spec->num_init_verbs = 3;
825aa972 1092 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
5d5d5f43 1093 spec->init_verbs[2] = ad1986a_automic_verbs;
825aa972
TI
1094 spec->multiout.max_channels = 2;
1095 spec->multiout.num_dacs = 1;
1096 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
8c0d9649
TI
1097 if (!is_jack_available(codec, 0x25))
1098 spec->multiout.dig_out_nid = 0;
5d5d5f43
TI
1099 spec->input_mux = &ad1986a_automic_capture_source;
1100 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1101 codec->patch_ops.init = ad1986a_automic_init;
825aa972 1102 break;
8ab78c74
TI
1103 case AD1986A_LAPTOP_AUTOMUTE:
1104 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1105 spec->num_init_verbs = 3;
1106 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1107 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1108 spec->multiout.max_channels = 2;
1109 spec->multiout.num_dacs = 1;
1110 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
8c0d9649
TI
1111 if (!is_jack_available(codec, 0x25))
1112 spec->multiout.dig_out_nid = 0;
8ab78c74
TI
1113 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1114 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1115 codec->patch_ops.init = ad1986a_hp_init;
1116 break;
f36090fe
TD
1117 case AD1986A_ULTRA:
1118 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1119 spec->num_init_verbs = 2;
1120 spec->init_verbs[1] = ad1986a_ultra_init;
1121 spec->multiout.max_channels = 2;
1122 spec->multiout.num_dacs = 1;
1123 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1124 spec->multiout.dig_out_nid = 0;
1125 break;
9230d214
TI
1126 }
1127
d29240ce
TI
1128 /* AD1986A has a hardware problem that it can't share a stream
1129 * with multiple output pins. The copy of front to surrounds
1130 * causes noisy or silent outputs at a certain timing, e.g.
1131 * changing the volume.
1132 * So, let's disable the shared stream.
1133 */
1134 spec->multiout.no_share_stream = 1;
1135
1da177e4
LT
1136 return 0;
1137}
1138
1139/*
4a3fdf3d 1140 * AD1983 specific
1da177e4 1141 */
1da177e4 1142
4a3fdf3d
TI
1143#define AD1983_SPDIF_OUT 0x02
1144#define AD1983_DAC 0x03
1145#define AD1983_ADC 0x04
1da177e4 1146
4a3fdf3d 1147static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
985be54b 1148static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
18a815d7 1149static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
4a3fdf3d
TI
1150
1151static struct hda_input_mux ad1983_capture_source = {
1152 .num_items = 4,
1153 .items = {
1154 { "Mic", 0x0 },
1155 { "Line", 0x1 },
1156 { "Mix", 0x2 },
1157 { "Mix Mono", 0x3 },
1158 },
1159};
1da177e4
LT
1160
1161/*
4a3fdf3d 1162 * SPDIF playback route
1da177e4 1163 */
c8b6bf9b 1164static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1165{
4a3fdf3d
TI
1166 static char *texts[] = { "PCM", "ADC" };
1167
1168 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1169 uinfo->count = 1;
1170 uinfo->value.enumerated.items = 2;
1171 if (uinfo->value.enumerated.item > 1)
1172 uinfo->value.enumerated.item = 1;
1173 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1174 return 0;
1da177e4
LT
1175}
1176
c8b6bf9b 1177static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1178{
4a3fdf3d
TI
1179 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1180 struct ad198x_spec *spec = codec->spec;
1da177e4 1181
4a3fdf3d 1182 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1da177e4
LT
1183 return 0;
1184}
1185
c8b6bf9b 1186static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1187{
4a3fdf3d
TI
1188 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1189 struct ad198x_spec *spec = codec->spec;
1190
68ea7b2f
TI
1191 if (ucontrol->value.enumerated.item[0] > 1)
1192 return -EINVAL;
4a3fdf3d
TI
1193 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1194 spec->spdif_route = ucontrol->value.enumerated.item[0];
82beb8fd
TI
1195 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1196 AC_VERB_SET_CONNECT_SEL,
1197 spec->spdif_route);
4a3fdf3d
TI
1198 return 1;
1199 }
1da177e4
LT
1200 return 0;
1201}
1202
c8b6bf9b 1203static struct snd_kcontrol_new ad1983_mixers[] = {
4a3fdf3d
TI
1204 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1205 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1206 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1207 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1208 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1209 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1210 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1211 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1212 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1213 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1214 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1215 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1216 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
1217 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
1218 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1219 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1220 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1221 {
1222 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1223 .name = "Capture Source",
1224 .info = ad198x_mux_enum_info,
1225 .get = ad198x_mux_enum_get,
1226 .put = ad198x_mux_enum_put,
1da177e4 1227 },
4a3fdf3d
TI
1228 {
1229 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6540dffa 1230 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4a3fdf3d
TI
1231 .info = ad1983_spdif_route_info,
1232 .get = ad1983_spdif_route_get,
1233 .put = ad1983_spdif_route_put,
1da177e4 1234 },
4a3fdf3d 1235 { } /* end */
1da177e4
LT
1236};
1237
4a3fdf3d
TI
1238static struct hda_verb ad1983_init_verbs[] = {
1239 /* Front, HP, Mono; mute as default */
1240 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1241 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1242 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1243 /* Beep, PCM, Mic, Line-In: mute */
1244 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1245 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1246 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1247 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1248 /* Front, HP selectors; from Mix */
1249 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1250 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1251 /* Mono selector; from Mix */
1252 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1253 /* Mic selector; Mic */
1254 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1255 /* Line-in selector: Line-in */
1256 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1257 /* Mic boost: 0dB */
1258 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1259 /* Record selector: mic */
1260 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1261 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1262 /* SPDIF route: PCM */
1263 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1264 /* Front Pin */
1265 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1266 /* HP Pin */
1267 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1268 /* Mono Pin */
1269 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1270 /* Mic Pin */
1271 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1272 /* Line Pin */
1273 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1274 { } /* end */
1da177e4
LT
1275};
1276
cb53c626
TI
1277#ifdef CONFIG_SND_HDA_POWER_SAVE
1278static struct hda_amp_list ad1983_loopbacks[] = {
1279 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1280 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1281 { } /* end */
1282};
1283#endif
985be54b 1284
4a3fdf3d 1285static int patch_ad1983(struct hda_codec *codec)
1da177e4 1286{
4a3fdf3d 1287 struct ad198x_spec *spec;
1da177e4 1288
e560d8d8 1289 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4a3fdf3d
TI
1290 if (spec == NULL)
1291 return -ENOMEM;
1da177e4 1292
4a3fdf3d
TI
1293 codec->spec = spec;
1294
1295 spec->multiout.max_channels = 2;
1296 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1297 spec->multiout.dac_nids = ad1983_dac_nids;
1298 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
985be54b
TI
1299 spec->num_adc_nids = 1;
1300 spec->adc_nids = ad1983_adc_nids;
18a815d7 1301 spec->capsrc_nids = ad1983_capsrc_nids;
4a3fdf3d 1302 spec->input_mux = &ad1983_capture_source;
985be54b
TI
1303 spec->num_mixers = 1;
1304 spec->mixers[0] = ad1983_mixers;
1305 spec->num_init_verbs = 1;
1306 spec->init_verbs[0] = ad1983_init_verbs;
4a3fdf3d 1307 spec->spdif_route = 0;
cb53c626
TI
1308#ifdef CONFIG_SND_HDA_POWER_SAVE
1309 spec->loopback.amplist = ad1983_loopbacks;
1310#endif
2134ea4f 1311 spec->vmaster_nid = 0x05;
1da177e4 1312
4a3fdf3d 1313 codec->patch_ops = ad198x_patch_ops;
1da177e4
LT
1314
1315 return 0;
1316}
1317
1da177e4 1318
4a3fdf3d
TI
1319/*
1320 * AD1981 HD specific
1321 */
1da177e4 1322
4a3fdf3d
TI
1323#define AD1981_SPDIF_OUT 0x02
1324#define AD1981_DAC 0x03
1325#define AD1981_ADC 0x04
1326
1327static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
985be54b 1328static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
18a815d7 1329static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
4a3fdf3d
TI
1330
1331/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1332static struct hda_input_mux ad1981_capture_source = {
1333 .num_items = 7,
1334 .items = {
1335 { "Front Mic", 0x0 },
1336 { "Line", 0x1 },
1337 { "Mix", 0x2 },
1338 { "Mix Mono", 0x3 },
1339 { "CD", 0x4 },
1340 { "Mic", 0x6 },
1341 { "Aux", 0x7 },
1342 },
1da177e4
LT
1343};
1344
c8b6bf9b 1345static struct snd_kcontrol_new ad1981_mixers[] = {
4a3fdf3d
TI
1346 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1347 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1348 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1349 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1350 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1351 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1352 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1353 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1354 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1355 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1356 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1357 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1358 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1359 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1360 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1361 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1362 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1363 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1364 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1365 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
1366 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1367 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1368 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1369 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1370 {
1371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1372 .name = "Capture Source",
1373 .info = ad198x_mux_enum_info,
1374 .get = ad198x_mux_enum_get,
1375 .put = ad198x_mux_enum_put,
1376 },
1377 /* identical with AD1983 */
1378 {
1379 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6540dffa 1380 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4a3fdf3d
TI
1381 .info = ad1983_spdif_route_info,
1382 .get = ad1983_spdif_route_get,
1383 .put = ad1983_spdif_route_put,
1384 },
1385 { } /* end */
1386};
1387
1388static struct hda_verb ad1981_init_verbs[] = {
1389 /* Front, HP, Mono; mute as default */
1390 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1391 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1392 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1393 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1394 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1395 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1396 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1397 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1398 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1399 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1400 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1401 /* Front, HP selectors; from Mix */
1402 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1403 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1404 /* Mono selector; from Mix */
1405 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1406 /* Mic Mixer; select Front Mic */
1407 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1408 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1409 /* Mic boost: 0dB */
1410 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1411 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1412 /* Record selector: Front mic */
1413 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1414 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1415 /* SPDIF route: PCM */
1416 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1417 /* Front Pin */
1418 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1419 /* HP Pin */
1420 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1421 /* Mono Pin */
1422 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1423 /* Front & Rear Mic Pins */
1424 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1425 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1426 /* Line Pin */
1427 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1428 /* Digital Beep */
1429 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1430 /* Line-Out as Input: disabled */
1431 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1432 { } /* end */
1433};
1434
cb53c626
TI
1435#ifdef CONFIG_SND_HDA_POWER_SAVE
1436static struct hda_amp_list ad1981_loopbacks[] = {
1437 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1438 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1439 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1440 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1441 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1442 { } /* end */
1443};
1444#endif
1445
18a815d7
TI
1446/*
1447 * Patch for HP nx6320
1448 *
18768991 1449 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
18a815d7
TI
1450 * speaker output enabled _and_ mute-LED off.
1451 */
1452
1453#define AD1981_HP_EVENT 0x37
1454#define AD1981_MIC_EVENT 0x38
1455
1456static struct hda_verb ad1981_hp_init_verbs[] = {
1457 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1458 /* pin sensing on HP and Mic jacks */
1459 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1460 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1461 {}
1462};
1463
1464/* turn on/off EAPD (+ mute HP) as a master switch */
1465static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1466 struct snd_ctl_elem_value *ucontrol)
1467{
1468 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1469 struct ad198x_spec *spec = codec->spec;
1470
1471 if (! ad198x_eapd_put(kcontrol, ucontrol))
1472 return 0;
f0824812
TI
1473 /* change speaker pin appropriately */
1474 snd_hda_codec_write(codec, 0x05, 0,
1475 AC_VERB_SET_PIN_WIDGET_CONTROL,
1476 spec->cur_eapd ? PIN_OUT : 0);
18a815d7 1477 /* toggle HP mute appropriately */
47fd830a
TI
1478 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1479 HDA_AMP_MUTE,
1480 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
18a815d7
TI
1481 return 1;
1482}
1483
1484/* bind volumes of both NID 0x05 and 0x06 */
cca3b371
TI
1485static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1486 .ops = &snd_hda_bind_vol,
1487 .values = {
1488 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1489 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1490 0
1491 },
1492};
18a815d7
TI
1493
1494/* mute internal speaker if HP is plugged */
1495static void ad1981_hp_automute(struct hda_codec *codec)
1496{
1497 unsigned int present;
1498
1499 present = snd_hda_codec_read(codec, 0x06, 0,
1500 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
47fd830a
TI
1501 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1502 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
18a815d7
TI
1503}
1504
1505/* toggle input of built-in and mic jack appropriately */
1506static void ad1981_hp_automic(struct hda_codec *codec)
1507{
1508 static struct hda_verb mic_jack_on[] = {
1509 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1510 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1511 {}
1512 };
1513 static struct hda_verb mic_jack_off[] = {
1514 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1515 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1516 {}
1517 };
1518 unsigned int present;
1519
1520 present = snd_hda_codec_read(codec, 0x08, 0,
1521 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1522 if (present)
1523 snd_hda_sequence_write(codec, mic_jack_on);
1524 else
1525 snd_hda_sequence_write(codec, mic_jack_off);
1526}
1527
1528/* unsolicited event for HP jack sensing */
1529static void ad1981_hp_unsol_event(struct hda_codec *codec,
1530 unsigned int res)
1531{
1532 res >>= 26;
1533 switch (res) {
1534 case AD1981_HP_EVENT:
1535 ad1981_hp_automute(codec);
1536 break;
1537 case AD1981_MIC_EVENT:
1538 ad1981_hp_automic(codec);
1539 break;
1540 }
1541}
1542
1543static struct hda_input_mux ad1981_hp_capture_source = {
1544 .num_items = 3,
1545 .items = {
1546 { "Mic", 0x0 },
1547 { "Docking-Station", 0x1 },
1548 { "Mix", 0x2 },
1549 },
1550};
1551
1552static struct snd_kcontrol_new ad1981_hp_mixers[] = {
cca3b371 1553 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
18a815d7
TI
1554 {
1555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1556 .name = "Master Playback Switch",
1557 .info = ad198x_eapd_info,
1558 .get = ad198x_eapd_get,
1559 .put = ad1981_hp_master_sw_put,
1560 .private_value = 0x05,
1561 },
1562 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1563 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1564#if 0
1565 /* FIXME: analog mic/line loopback doesn't work with my tests...
1566 * (although recording is OK)
1567 */
1568 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1569 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1570 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1571 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1572 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1573 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1574 /* FIXME: does this laptop have analog CD connection? */
1575 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1576 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1577#endif
1578 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1579 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1580 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1581 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1582 {
1583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584 .name = "Capture Source",
1585 .info = ad198x_mux_enum_info,
1586 .get = ad198x_mux_enum_get,
1587 .put = ad198x_mux_enum_put,
1588 },
1589 { } /* end */
1590};
1591
1592/* initialize jack-sensing, too */
1593static int ad1981_hp_init(struct hda_codec *codec)
1594{
1595 ad198x_init(codec);
1596 ad1981_hp_automute(codec);
1597 ad1981_hp_automic(codec);
1598 return 0;
1599}
1600
18768991
TD
1601/* configuration for Toshiba Laptops */
1602static struct hda_verb ad1981_toshiba_init_verbs[] = {
1603 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1604 /* pin sensing on HP and Mic jacks */
1605 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1606 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1607 {}
1608};
1609
1610static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1611 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1612 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1613 { }
1614};
1615
01686c5f
TI
1616/* configuration for Lenovo Thinkpad T60 */
1617static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1618 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1619 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1620 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1621 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1622 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1623 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1624 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1625 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1626 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1627 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1628 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1629 {
1630 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1631 .name = "Capture Source",
1632 .info = ad198x_mux_enum_info,
1633 .get = ad198x_mux_enum_get,
1634 .put = ad198x_mux_enum_put,
1635 },
6540dffa
TI
1636 /* identical with AD1983 */
1637 {
1638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1639 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1640 .info = ad1983_spdif_route_info,
1641 .get = ad1983_spdif_route_get,
1642 .put = ad1983_spdif_route_put,
1643 },
01686c5f
TI
1644 { } /* end */
1645};
1646
1647static struct hda_input_mux ad1981_thinkpad_capture_source = {
1648 .num_items = 3,
1649 .items = {
1650 { "Mic", 0x0 },
1651 { "Mix", 0x2 },
1652 { "CD", 0x4 },
1653 },
1654};
1655
18a815d7 1656/* models */
f5fcc13c
TI
1657enum {
1658 AD1981_BASIC,
1659 AD1981_HP,
1660 AD1981_THINKPAD,
18768991 1661 AD1981_TOSHIBA,
f5fcc13c
TI
1662 AD1981_MODELS
1663};
18a815d7 1664
f5fcc13c
TI
1665static const char *ad1981_models[AD1981_MODELS] = {
1666 [AD1981_HP] = "hp",
1667 [AD1981_THINKPAD] = "thinkpad",
1668 [AD1981_BASIC] = "basic",
18768991 1669 [AD1981_TOSHIBA] = "toshiba"
f5fcc13c
TI
1670};
1671
1672static struct snd_pci_quirk ad1981_cfg_tbl[] = {
ac3e3741 1673 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
470eaf6b 1674 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
8970ccda 1675 /* All HP models */
f5fcc13c 1676 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
ac3e3741 1677 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
01686c5f 1678 /* Lenovo Thinkpad T60/X60/Z6xx */
f5fcc13c 1679 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
ac3e3741
TI
1680 /* HP nx6320 (reversed SSID, H/W bug) */
1681 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
18a815d7
TI
1682 {}
1683};
1684
4a3fdf3d 1685static int patch_ad1981(struct hda_codec *codec)
1da177e4 1686{
4a3fdf3d 1687 struct ad198x_spec *spec;
18a815d7 1688 int board_config;
1da177e4 1689
e560d8d8 1690 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1da177e4
LT
1691 if (spec == NULL)
1692 return -ENOMEM;
1693
1da177e4
LT
1694 codec->spec = spec;
1695
4a3fdf3d
TI
1696 spec->multiout.max_channels = 2;
1697 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1698 spec->multiout.dac_nids = ad1981_dac_nids;
1699 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
985be54b
TI
1700 spec->num_adc_nids = 1;
1701 spec->adc_nids = ad1981_adc_nids;
18a815d7 1702 spec->capsrc_nids = ad1981_capsrc_nids;
4a3fdf3d 1703 spec->input_mux = &ad1981_capture_source;
985be54b
TI
1704 spec->num_mixers = 1;
1705 spec->mixers[0] = ad1981_mixers;
1706 spec->num_init_verbs = 1;
1707 spec->init_verbs[0] = ad1981_init_verbs;
4a3fdf3d 1708 spec->spdif_route = 0;
cb53c626
TI
1709#ifdef CONFIG_SND_HDA_POWER_SAVE
1710 spec->loopback.amplist = ad1981_loopbacks;
1711#endif
2134ea4f 1712 spec->vmaster_nid = 0x05;
1da177e4 1713
4a3fdf3d 1714 codec->patch_ops = ad198x_patch_ops;
1da177e4 1715
18a815d7 1716 /* override some parameters */
f5fcc13c
TI
1717 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1718 ad1981_models,
1719 ad1981_cfg_tbl);
18a815d7
TI
1720 switch (board_config) {
1721 case AD1981_HP:
1722 spec->mixers[0] = ad1981_hp_mixers;
1723 spec->num_init_verbs = 2;
1724 spec->init_verbs[1] = ad1981_hp_init_verbs;
1725 spec->multiout.dig_out_nid = 0;
1726 spec->input_mux = &ad1981_hp_capture_source;
1727
1728 codec->patch_ops.init = ad1981_hp_init;
1729 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1730 break;
01686c5f
TI
1731 case AD1981_THINKPAD:
1732 spec->mixers[0] = ad1981_thinkpad_mixers;
01686c5f
TI
1733 spec->input_mux = &ad1981_thinkpad_capture_source;
1734 break;
18768991
TD
1735 case AD1981_TOSHIBA:
1736 spec->mixers[0] = ad1981_hp_mixers;
1737 spec->mixers[1] = ad1981_toshiba_mixers;
1738 spec->num_init_verbs = 2;
1739 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1740 spec->multiout.dig_out_nid = 0;
1741 spec->input_mux = &ad1981_hp_capture_source;
1742 codec->patch_ops.init = ad1981_hp_init;
1743 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1744 break;
18a815d7 1745 }
1da177e4
LT
1746 return 0;
1747}
1748
4a3fdf3d 1749
fd66e0d0
TI
1750/*
1751 * AD1988
1752 *
1753 * Output pins and routes
1754 *
d32410b1 1755 * Pin Mix Sel DAC (*)
fd66e0d0
TI
1756 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1757 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1758 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1759 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1760 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1761 * port-F 0x16 (mute) <- 0x2a <- 06
1762 * port-G 0x24 (mute) <- 0x27 <- 05
1763 * port-H 0x25 (mute) <- 0x28 <- 0a
1764 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1765 *
d32410b1
TI
1766 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1767 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
fd66e0d0
TI
1768 *
1769 * Input pins and routes
1770 *
1771 * pin boost mix input # / adc input #
1772 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1773 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1774 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1775 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1776 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1777 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1778 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1779 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1780 *
1781 *
1782 * DAC assignment
d32410b1 1783 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
f8c7c7b8 1784 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
fd66e0d0
TI
1785 *
1786 * Inputs of Analog Mix (0x20)
1787 * 0:Port-B (front mic)
1788 * 1:Port-C/G/H (line-in)
1789 * 2:Port-A
1790 * 3:Port-D (line-in/2)
1791 * 4:Port-E/G/H (mic-in)
1792 * 5:Port-F (mic2-in)
1793 * 6:CD
1794 * 7:Beep
1795 *
1796 * ADC selection
1797 * 0:Port-A
1798 * 1:Port-B (front mic-in)
1799 * 2:Port-C (line-in)
1800 * 3:Port-F (mic2-in)
1801 * 4:Port-E (mic-in)
1802 * 5:CD
1803 * 6:Port-G
1804 * 7:Port-H
1805 * 8:Port-D (line-in/2)
1806 * 9:Mix
1807 *
1808 * Proposed pin assignments by the datasheet
1809 *
1810 * 6-stack
1811 * Port-A front headphone
1812 * B front mic-in
1813 * C rear line-in
1814 * D rear front-out
1815 * E rear mic-in
1816 * F rear surround
1817 * G rear CLFE
1818 * H rear side
1819 *
1820 * 3-stack
1821 * Port-A front headphone
1822 * B front mic
1823 * C rear line-in/surround
1824 * D rear front-out
1825 * E rear mic-in/CLFE
1826 *
1827 * laptop
1828 * Port-A headphone
1829 * B mic-in
1830 * C docking station
1831 * D internal speaker (with EAPD)
1832 * E/F quad mic array
1833 */
1834
1835
1836/* models */
1837enum {
1838 AD1988_6STACK,
1839 AD1988_6STACK_DIG,
1840 AD1988_3STACK,
1841 AD1988_3STACK_DIG,
1842 AD1988_LAPTOP,
1843 AD1988_LAPTOP_DIG,
d32410b1 1844 AD1988_AUTO,
fd66e0d0
TI
1845 AD1988_MODEL_LAST,
1846};
1847
d32410b1
TI
1848/* reivision id to check workarounds */
1849#define AD1988A_REV2 0x100200
1850
1a806f48
TI
1851#define is_rev2(codec) \
1852 ((codec)->vendor_id == 0x11d41988 && \
1853 (codec)->revision_id == AD1988A_REV2)
fd66e0d0
TI
1854
1855/*
1856 * mixers
1857 */
1858
d32410b1 1859static hda_nid_t ad1988_6stack_dac_nids[4] = {
fd66e0d0
TI
1860 0x04, 0x06, 0x05, 0x0a
1861};
1862
d32410b1 1863static hda_nid_t ad1988_3stack_dac_nids[3] = {
f8c7c7b8 1864 0x04, 0x05, 0x0a
d32410b1
TI
1865};
1866
1867/* for AD1988A revision-2, DAC2-4 are swapped */
1868static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1869 0x04, 0x05, 0x0a, 0x06
1870};
1871
1872static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
f8c7c7b8 1873 0x04, 0x0a, 0x06
d32410b1
TI
1874};
1875
fd66e0d0
TI
1876static hda_nid_t ad1988_adc_nids[3] = {
1877 0x08, 0x09, 0x0f
1878};
1879
2e5b9567
TI
1880static hda_nid_t ad1988_capsrc_nids[3] = {
1881 0x0c, 0x0d, 0x0e
1882};
1883
9cae0c63
RJ
1884#define AD1988_SPDIF_OUT 0x02
1885#define AD1988_SPDIF_OUT_HDMI 0x0b
fd66e0d0
TI
1886#define AD1988_SPDIF_IN 0x07
1887
9cae0c63
RJ
1888static hda_nid_t ad1989b_slave_dig_outs[2] = {
1889 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI
1890};
1891
fd66e0d0
TI
1892static struct hda_input_mux ad1988_6stack_capture_source = {
1893 .num_items = 5,
1894 .items = {
fb304ce5
TI
1895 { "Front Mic", 0x1 }, /* port-B */
1896 { "Line", 0x2 }, /* port-C */
1897 { "Mic", 0x4 }, /* port-E */
fd66e0d0
TI
1898 { "CD", 0x5 },
1899 { "Mix", 0x9 },
1900 },
1901};
1902
1903static struct hda_input_mux ad1988_laptop_capture_source = {
1904 .num_items = 3,
1905 .items = {
fb304ce5 1906 { "Mic/Line", 0x1 }, /* port-B */
fd66e0d0
TI
1907 { "CD", 0x5 },
1908 { "Mix", 0x9 },
1909 },
1910};
1911
1912/*
1913 */
1914static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1915 struct snd_ctl_elem_info *uinfo)
1916{
1917 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1918 struct ad198x_spec *spec = codec->spec;
1919 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1920 spec->num_channel_mode);
1921}
1922
1923static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1924 struct snd_ctl_elem_value *ucontrol)
1925{
1926 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1927 struct ad198x_spec *spec = codec->spec;
1928 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1929 spec->num_channel_mode, spec->multiout.max_channels);
1930}
1931
1932static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1933 struct snd_ctl_elem_value *ucontrol)
1934{
1935 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1936 struct ad198x_spec *spec = codec->spec;
4e195a7b
TI
1937 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1938 spec->num_channel_mode,
1939 &spec->multiout.max_channels);
bd2033f2 1940 if (err >= 0 && spec->need_dac_fix)
2125cad2 1941 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
4e195a7b 1942 return err;
fd66e0d0
TI
1943}
1944
fd66e0d0 1945/* 6-stack mode */
d32410b1 1946static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
fd66e0d0
TI
1947 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1948 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1949 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1950 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1951 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2ece5f42 1952 { } /* end */
d32410b1
TI
1953};
1954
1955static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
1956 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1957 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1958 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1959 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
1960 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2ece5f42 1961 { } /* end */
d32410b1 1962};
fd66e0d0 1963
d32410b1 1964static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
fd66e0d0
TI
1965 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1966 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1967 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1968 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1969 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1970 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1971 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1972
1973 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1974 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1975 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1976 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1977 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1978 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1979 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1980 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1981
1982 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1983 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1984
2e5b9567 1985 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1986 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1987
1988 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1989 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1990
1991 { } /* end */
1992};
1993
1994/* 3-stack mode */
d32410b1 1995static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
fd66e0d0 1996 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
d32410b1 1997 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
fd66e0d0
TI
1998 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1999 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2ece5f42 2000 { } /* end */
d32410b1
TI
2001};
2002
2003static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2004 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
f8c7c7b8
TI
2005 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2006 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2007 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2ece5f42 2008 { } /* end */
d32410b1 2009};
fd66e0d0 2010
d32410b1 2011static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
fd66e0d0 2012 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
d32410b1
TI
2013 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2014 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2015 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
fd66e0d0
TI
2016 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2017 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2018
2019 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2020 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2021 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2022 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2023 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2024 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2025 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2026 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2027
2028 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
2029 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2030
2e5b9567 2031 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2032 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2033
2034 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2035 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2036 {
2037 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2038 .name = "Channel Mode",
2039 .info = ad198x_ch_mode_info,
2040 .get = ad198x_ch_mode_get,
2041 .put = ad198x_ch_mode_put,
2042 },
2043
2044 { } /* end */
2045};
2046
2047/* laptop mode */
2048static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2049 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2050 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2051 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2052
2053 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2054 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2055 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2056 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2057 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2058 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2059
2060 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
2061 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2062
2e5b9567 2063 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2064 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2065
2066 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2067
2068 {
2069 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2070 .name = "External Amplifier",
18a815d7
TI
2071 .info = ad198x_eapd_info,
2072 .get = ad198x_eapd_get,
2073 .put = ad198x_eapd_put,
2074 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
fd66e0d0
TI
2075 },
2076
2077 { } /* end */
2078};
2079
2080/* capture */
2081static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2082 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2083 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2084 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2085 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2086 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2087 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2088 {
2089 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2090 /* The multiple "Capture Source" controls confuse alsamixer
2091 * So call somewhat different..
fd66e0d0
TI
2092 */
2093 /* .name = "Capture Source", */
2094 .name = "Input Source",
2095 .count = 3,
2096 .info = ad198x_mux_enum_info,
2097 .get = ad198x_mux_enum_get,
2098 .put = ad198x_mux_enum_put,
2099 },
2100 { } /* end */
2101};
2102
2103static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2104 struct snd_ctl_elem_info *uinfo)
2105{
2106 static char *texts[] = {
2107 "PCM", "ADC1", "ADC2", "ADC3"
2108 };
2109 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2110 uinfo->count = 1;
2111 uinfo->value.enumerated.items = 4;
2112 if (uinfo->value.enumerated.item >= 4)
2113 uinfo->value.enumerated.item = 3;
2114 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2115 return 0;
2116}
2117
2118static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2119 struct snd_ctl_elem_value *ucontrol)
2120{
2121 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2122 unsigned int sel;
2123
bddcf541
TI
2124 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2125 AC_AMP_GET_INPUT);
2126 if (!(sel & 0x80))
2127 ucontrol->value.enumerated.item[0] = 0;
2128 else {
35b26722
TI
2129 sel = snd_hda_codec_read(codec, 0x0b, 0,
2130 AC_VERB_GET_CONNECT_SEL, 0);
2131 if (sel < 3)
fd66e0d0
TI
2132 sel++;
2133 else
2134 sel = 0;
bddcf541 2135 ucontrol->value.enumerated.item[0] = sel;
fd66e0d0 2136 }
fd66e0d0
TI
2137 return 0;
2138}
2139
2140static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2141 struct snd_ctl_elem_value *ucontrol)
2142{
2143 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
35b26722 2144 unsigned int val, sel;
fd66e0d0
TI
2145 int change;
2146
35b26722 2147 val = ucontrol->value.enumerated.item[0];
68ea7b2f
TI
2148 if (val > 3)
2149 return -EINVAL;
35b26722 2150 if (!val) {
bddcf541
TI
2151 sel = snd_hda_codec_read(codec, 0x1d, 0,
2152 AC_VERB_GET_AMP_GAIN_MUTE,
2153 AC_AMP_GET_INPUT);
2154 change = sel & 0x80;
82beb8fd
TI
2155 if (change) {
2156 snd_hda_codec_write_cache(codec, 0x1d, 0,
2157 AC_VERB_SET_AMP_GAIN_MUTE,
2158 AMP_IN_UNMUTE(0));
2159 snd_hda_codec_write_cache(codec, 0x1d, 0,
2160 AC_VERB_SET_AMP_GAIN_MUTE,
2161 AMP_IN_MUTE(1));
bddcf541 2162 }
fd66e0d0 2163 } else {
bddcf541
TI
2164 sel = snd_hda_codec_read(codec, 0x1d, 0,
2165 AC_VERB_GET_AMP_GAIN_MUTE,
2166 AC_AMP_GET_INPUT | 0x01);
2167 change = sel & 0x80;
82beb8fd
TI
2168 if (change) {
2169 snd_hda_codec_write_cache(codec, 0x1d, 0,
2170 AC_VERB_SET_AMP_GAIN_MUTE,
2171 AMP_IN_MUTE(0));
2172 snd_hda_codec_write_cache(codec, 0x1d, 0,
2173 AC_VERB_SET_AMP_GAIN_MUTE,
2174 AMP_IN_UNMUTE(1));
bddcf541 2175 }
35b26722
TI
2176 sel = snd_hda_codec_read(codec, 0x0b, 0,
2177 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2178 change |= sel != val;
82beb8fd
TI
2179 if (change)
2180 snd_hda_codec_write_cache(codec, 0x0b, 0,
2181 AC_VERB_SET_CONNECT_SEL,
2182 val - 1);
fd66e0d0
TI
2183 }
2184 return change;
2185}
2186
2187static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2188 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2189 {
2190 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2191 .name = "IEC958 Playback Source",
2192 .info = ad1988_spdif_playback_source_info,
2193 .get = ad1988_spdif_playback_source_get,
2194 .put = ad1988_spdif_playback_source_put,
2195 },
2196 { } /* end */
2197};
2198
2199static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2200 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2201 { } /* end */
2202};
2203
3adb8abc
TI
2204static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2205 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
9cae0c63 2206 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
3adb8abc
TI
2207 { } /* end */
2208};
fd66e0d0
TI
2209
2210/*
2211 * initialization verbs
2212 */
2213
2214/*
2215 * for 6-stack (+dig)
2216 */
2217static struct hda_verb ad1988_6stack_init_verbs[] = {
2e5b9567
TI
2218 /* Front, Surround, CLFE, side DAC; unmute as default */
2219 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2220 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2221 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2222 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2223 /* Port-A front headphon path */
2224 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2225 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2226 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2227 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2228 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2229 /* Port-D line-out path */
2230 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2231 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2232 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2233 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2234 /* Port-F surround path */
2235 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2236 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2237 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2238 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2239 /* Port-G CLFE path */
2240 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2241 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2242 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2243 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2244 /* Port-H side path */
2245 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2246 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2247 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2248 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2249 /* Mono out path */
2250 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2251 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2252 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2253 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2254 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2255 /* Port-B front mic-in path */
2256 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2257 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2258 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2259 /* Port-C line-in path */
2260 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2261 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2262 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2263 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2264 /* Port-E mic-in path */
2265 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2266 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2267 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2268 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
695005cf
JS
2269 /* Analog CD Input */
2270 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
db3da6c1
TI
2271 /* Analog Mix output amp */
2272 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2273
2274 { }
2275};
2276
2277static struct hda_verb ad1988_capture_init_verbs[] = {
2278 /* mute analog mix */
2279 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2280 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2281 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2282 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2283 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2284 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2285 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2286 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2287 /* select ADCs - front-mic */
2288 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2289 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2290 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2291 /* ADCs; muted */
2292 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2293 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2294 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2295
2296 { }
2297};
2298
2299static struct hda_verb ad1988_spdif_init_verbs[] = {
2300 /* SPDIF out sel */
2301 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2302 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2303 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
bddcf541 2304 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
fd66e0d0
TI
2305 /* SPDIF out pin */
2306 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
fd66e0d0
TI
2307
2308 { }
2309};
2310
3adb8abc
TI
2311/* AD1989 has no ADC -> SPDIF route */
2312static struct hda_verb ad1989_spdif_init_verbs[] = {
e8bfc6c1
RJ
2313 /* SPDIF-1 out pin */
2314 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3adb8abc 2315 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
e8bfc6c1
RJ
2316 /* SPDIF-2/HDMI out pin */
2317 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2318 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3adb8abc
TI
2319 { }
2320};
2321
fd66e0d0
TI
2322/*
2323 * verbs for 3stack (+dig)
2324 */
2325static struct hda_verb ad1988_3stack_ch2_init[] = {
2326 /* set port-C to line-in */
2327 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2328 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2329 /* set port-E to mic-in */
2330 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2331 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2332 { } /* end */
2333};
2334
2335static struct hda_verb ad1988_3stack_ch6_init[] = {
2336 /* set port-C to surround out */
fd66e0d0 2337 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2338 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0 2339 /* set port-E to CLFE out */
fd66e0d0 2340 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2341 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0
TI
2342 { } /* end */
2343};
2344
2345static struct hda_channel_mode ad1988_3stack_modes[2] = {
2346 { 2, ad1988_3stack_ch2_init },
2347 { 6, ad1988_3stack_ch6_init },
2348};
2349
2350static struct hda_verb ad1988_3stack_init_verbs[] = {
2e5b9567
TI
2351 /* Front, Surround, CLFE, side DAC; unmute as default */
2352 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2353 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2354 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2355 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2356 /* Port-A front headphon path */
2357 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2358 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2359 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2360 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2361 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2362 /* Port-D line-out path */
2363 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2364 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2365 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2366 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2367 /* Mono out path */
2368 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2369 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2370 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2371 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2372 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2373 /* Port-B front mic-in path */
2374 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2375 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2376 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1
TI
2377 /* Port-C line-in/surround path - 6ch mode as default */
2378 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2379 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2380 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1 2381 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
fd66e0d0 2382 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
d32410b1
TI
2383 /* Port-E mic-in/CLFE path - 6ch mode as default */
2384 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2385 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2386 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
f8c7c7b8 2387 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
fd66e0d0
TI
2388 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2389 /* mute analog mix */
2390 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2391 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2392 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2393 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2394 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2395 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2396 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2397 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2398 /* select ADCs - front-mic */
2399 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2400 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2401 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2402 /* ADCs; muted */
2403 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2404 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2405 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
db3da6c1
TI
2406 /* Analog Mix output amp */
2407 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2408 { }
2409};
2410
2411/*
2412 * verbs for laptop mode (+dig)
2413 */
2414static struct hda_verb ad1988_laptop_hp_on[] = {
2415 /* unmute port-A and mute port-D */
2416 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2417 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2418 { } /* end */
2419};
2420static struct hda_verb ad1988_laptop_hp_off[] = {
2421 /* mute port-A and unmute port-D */
2422 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2423 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2424 { } /* end */
2425};
2426
2427#define AD1988_HP_EVENT 0x01
2428
2429static struct hda_verb ad1988_laptop_init_verbs[] = {
2e5b9567
TI
2430 /* Front, Surround, CLFE, side DAC; unmute as default */
2431 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2432 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2433 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2434 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2435 /* Port-A front headphon path */
2436 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2437 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2438 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2439 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2440 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2441 /* unsolicited event for pin-sense */
2442 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2443 /* Port-D line-out path + EAPD */
2444 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2445 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2446 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2447 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2448 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2449 /* Mono out path */
2450 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2451 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2452 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2453 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2454 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2455 /* Port-B mic-in path */
2456 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2457 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2458 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2459 /* Port-C docking station - try to output */
2460 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2461 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2462 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2463 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2464 /* mute analog mix */
2465 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2466 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2467 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2468 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2469 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2470 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2471 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2472 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2473 /* select ADCs - mic */
2474 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2475 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2476 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2477 /* ADCs; muted */
2478 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2479 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2480 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
db3da6c1
TI
2481 /* Analog Mix output amp */
2482 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2483 { }
2484};
2485
2486static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2487{
2488 if ((res >> 26) != AD1988_HP_EVENT)
2489 return;
2490 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2491 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2492 else
2493 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2494}
2495
cb53c626
TI
2496#ifdef CONFIG_SND_HDA_POWER_SAVE
2497static struct hda_amp_list ad1988_loopbacks[] = {
2498 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2499 { 0x20, HDA_INPUT, 1 }, /* Line */
2500 { 0x20, HDA_INPUT, 4 }, /* Mic */
2501 { 0x20, HDA_INPUT, 6 }, /* CD */
2502 { } /* end */
2503};
2504#endif
fd66e0d0 2505
d32410b1
TI
2506/*
2507 * Automatic parse of I/O pins from the BIOS configuration
2508 */
2509
d32410b1
TI
2510enum {
2511 AD_CTL_WIDGET_VOL,
2512 AD_CTL_WIDGET_MUTE,
2513 AD_CTL_BIND_MUTE,
2514};
2515static struct snd_kcontrol_new ad1988_control_templates[] = {
2516 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2517 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2518 HDA_BIND_MUTE(NULL, 0, 0, 0),
2519};
2520
2521/* add dynamic controls */
2522static int add_control(struct ad198x_spec *spec, int type, const char *name,
2523 unsigned long val)
2524{
2525 struct snd_kcontrol_new *knew;
2526
603c4019
TI
2527 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2528 knew = snd_array_new(&spec->kctls);
2529 if (!knew)
2530 return -ENOMEM;
d32410b1
TI
2531 *knew = ad1988_control_templates[type];
2532 knew->name = kstrdup(name, GFP_KERNEL);
2533 if (! knew->name)
2534 return -ENOMEM;
2535 knew->private_value = val;
d32410b1
TI
2536 return 0;
2537}
2538
2539#define AD1988_PIN_CD_NID 0x18
2540#define AD1988_PIN_BEEP_NID 0x10
2541
2542static hda_nid_t ad1988_mixer_nids[8] = {
2543 /* A B C D E F G H */
2544 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2545};
2546
2547static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2548{
2549 static hda_nid_t idx_to_dac[8] = {
2550 /* A B C D E F G H */
f8c7c7b8 2551 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
d32410b1
TI
2552 };
2553 static hda_nid_t idx_to_dac_rev2[8] = {
2554 /* A B C D E F G H */
f8c7c7b8 2555 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
d32410b1 2556 };
1a806f48 2557 if (is_rev2(codec))
d32410b1
TI
2558 return idx_to_dac_rev2[idx];
2559 else
2560 return idx_to_dac[idx];
2561}
2562
2563static hda_nid_t ad1988_boost_nids[8] = {
2564 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2565};
2566
2567static int ad1988_pin_idx(hda_nid_t nid)
2568{
2569 static hda_nid_t ad1988_io_pins[8] = {
2570 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2571 };
2572 int i;
2573 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2574 if (ad1988_io_pins[i] == nid)
2575 return i;
2576 return 0; /* should be -1 */
2577}
2578
2579static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2580{
2581 static int loopback_idx[8] = {
2582 2, 0, 1, 3, 4, 5, 1, 4
2583 };
2584 switch (nid) {
2585 case AD1988_PIN_CD_NID:
2586 return 6;
2587 default:
2588 return loopback_idx[ad1988_pin_idx(nid)];
2589 }
2590}
2591
2592static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2593{
2594 static int adc_idx[8] = {
2595 0, 1, 2, 8, 4, 3, 6, 7
2596 };
2597 switch (nid) {
2598 case AD1988_PIN_CD_NID:
2599 return 5;
2600 default:
2601 return adc_idx[ad1988_pin_idx(nid)];
2602 }
2603}
2604
2605/* fill in the dac_nids table from the parsed pin configuration */
2606static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2607 const struct auto_pin_cfg *cfg)
2608{
2609 struct ad198x_spec *spec = codec->spec;
2610 int i, idx;
2611
2612 spec->multiout.dac_nids = spec->private_dac_nids;
2613
2614 /* check the pins hardwired to audio widget */
2615 for (i = 0; i < cfg->line_outs; i++) {
2616 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2617 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2618 }
2619 spec->multiout.num_dacs = cfg->line_outs;
2620 return 0;
2621}
2622
2623/* add playback controls from the parsed DAC table */
2624static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2625 const struct auto_pin_cfg *cfg)
2626{
2627 char name[32];
2628 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2629 hda_nid_t nid;
2630 int i, err;
2631
2632 for (i = 0; i < cfg->line_outs; i++) {
2633 hda_nid_t dac = spec->multiout.dac_nids[i];
2634 if (! dac)
2635 continue;
2636 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2637 if (i == 2) {
2638 /* Center/LFE */
2639 err = add_control(spec, AD_CTL_WIDGET_VOL,
2640 "Center Playback Volume",
2641 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2642 if (err < 0)
2643 return err;
2644 err = add_control(spec, AD_CTL_WIDGET_VOL,
2645 "LFE Playback Volume",
2646 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2647 if (err < 0)
2648 return err;
2649 err = add_control(spec, AD_CTL_BIND_MUTE,
2650 "Center Playback Switch",
2651 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2652 if (err < 0)
2653 return err;
2654 err = add_control(spec, AD_CTL_BIND_MUTE,
2655 "LFE Playback Switch",
2656 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2657 if (err < 0)
2658 return err;
2659 } else {
2660 sprintf(name, "%s Playback Volume", chname[i]);
2661 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2662 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2663 if (err < 0)
2664 return err;
2665 sprintf(name, "%s Playback Switch", chname[i]);
2666 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2667 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2668 if (err < 0)
2669 return err;
2670 }
2671 }
2672 return 0;
2673}
2674
2675/* add playback controls for speaker and HP outputs */
2676static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2677 const char *pfx)
2678{
2679 struct ad198x_spec *spec = codec->spec;
2680 hda_nid_t nid;
43785eae 2681 int i, idx, err;
d32410b1
TI
2682 char name[32];
2683
2684 if (! pin)
2685 return 0;
2686
2687 idx = ad1988_pin_idx(pin);
2688 nid = ad1988_idx_to_dac(codec, idx);
43785eae
TI
2689 /* check whether the corresponding DAC was already taken */
2690 for (i = 0; i < spec->autocfg.line_outs; i++) {
2691 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2692 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2693 if (dac == nid)
2694 break;
2695 }
2696 if (i >= spec->autocfg.line_outs) {
2697 /* specify the DAC as the extra output */
2698 if (!spec->multiout.hp_nid)
2699 spec->multiout.hp_nid = nid;
2700 else
2701 spec->multiout.extra_out_nid[0] = nid;
2702 /* control HP volume/switch on the output mixer amp */
2703 sprintf(name, "%s Playback Volume", pfx);
2704 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2705 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2706 if (err < 0)
2707 return err;
2708 }
d32410b1
TI
2709 nid = ad1988_mixer_nids[idx];
2710 sprintf(name, "%s Playback Switch", pfx);
2711 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2712 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2713 return err;
2714 return 0;
2715}
2716
2717/* create input playback/capture controls for the given pin */
2718static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2719 const char *ctlname, int boost)
2720{
2721 char name[32];
2722 int err, idx;
2723
2724 sprintf(name, "%s Playback Volume", ctlname);
2725 idx = ad1988_pin_to_loopback_idx(pin);
2726 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2727 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2728 return err;
2729 sprintf(name, "%s Playback Switch", ctlname);
2730 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2731 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2732 return err;
2733 if (boost) {
2734 hda_nid_t bnid;
2735 idx = ad1988_pin_idx(pin);
2736 bnid = ad1988_boost_nids[idx];
2737 if (bnid) {
2738 sprintf(name, "%s Boost", ctlname);
2739 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2740 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2741
2742 }
2743 }
2744 return 0;
2745}
2746
2747/* create playback/capture controls for input pins */
2748static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2749 const struct auto_pin_cfg *cfg)
2750{
d32410b1
TI
2751 struct hda_input_mux *imux = &spec->private_imux;
2752 int i, err;
2753
2754 for (i = 0; i < AUTO_PIN_LAST; i++) {
4a471b7d
TI
2755 err = new_analog_input(spec, cfg->input_pins[i],
2756 auto_pin_cfg_labels[i],
d32410b1
TI
2757 i <= AUTO_PIN_FRONT_MIC);
2758 if (err < 0)
2759 return err;
4a471b7d 2760 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
d32410b1
TI
2761 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2762 imux->num_items++;
2763 }
2764 imux->items[imux->num_items].label = "Mix";
2765 imux->items[imux->num_items].index = 9;
2766 imux->num_items++;
2767
2768 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2769 "Analog Mix Playback Volume",
2770 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2771 return err;
2772 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2773 "Analog Mix Playback Switch",
2774 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2775 return err;
2776
2777 return 0;
2778}
2779
2780static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2781 hda_nid_t nid, int pin_type,
2782 int dac_idx)
2783{
2784 /* set as output */
2785 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2786 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2787 switch (nid) {
2788 case 0x11: /* port-A - DAC 04 */
2789 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2790 break;
2791 case 0x14: /* port-B - DAC 06 */
2792 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2793 break;
2794 case 0x15: /* port-C - DAC 05 */
2795 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2796 break;
f8c7c7b8 2797 case 0x17: /* port-E - DAC 0a */
d32410b1
TI
2798 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2799 break;
2800 case 0x13: /* mono - DAC 04 */
2801 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2802 break;
2803 }
2804}
2805
2806static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2807{
2808 struct ad198x_spec *spec = codec->spec;
2809 int i;
2810
2811 for (i = 0; i < spec->autocfg.line_outs; i++) {
2812 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2813 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2814 }
2815}
2816
2817static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2818{
2819 struct ad198x_spec *spec = codec->spec;
2820 hda_nid_t pin;
2821
82bc955f 2822 pin = spec->autocfg.speaker_pins[0];
d32410b1
TI
2823 if (pin) /* connect to front */
2824 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
eb06ed8f 2825 pin = spec->autocfg.hp_pins[0];
d32410b1
TI
2826 if (pin) /* connect to front */
2827 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2828}
2829
2830static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2831{
2832 struct ad198x_spec *spec = codec->spec;
2833 int i, idx;
2834
2835 for (i = 0; i < AUTO_PIN_LAST; i++) {
2836 hda_nid_t nid = spec->autocfg.input_pins[i];
2837 if (! nid)
2838 continue;
2839 switch (nid) {
2840 case 0x15: /* port-C */
2841 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2842 break;
2843 case 0x17: /* port-E */
2844 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2845 break;
2846 }
2847 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2848 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2849 if (nid != AD1988_PIN_CD_NID)
2850 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2851 AMP_OUT_MUTE);
2852 idx = ad1988_pin_idx(nid);
2853 if (ad1988_boost_nids[idx])
2854 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2855 AC_VERB_SET_AMP_GAIN_MUTE,
2856 AMP_OUT_ZERO);
2857 }
2858}
2859
2860/* parse the BIOS configuration and set up the alc_spec */
2861/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2862static int ad1988_parse_auto_config(struct hda_codec *codec)
2863{
2864 struct ad198x_spec *spec = codec->spec;
2865 int err;
2866
df694daa 2867 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
d32410b1
TI
2868 return err;
2869 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2870 return err;
82bc955f 2871 if (! spec->autocfg.line_outs)
d32410b1
TI
2872 return 0; /* can't find valid BIOS pin config */
2873 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
82bc955f
TI
2874 (err = ad1988_auto_create_extra_out(codec,
2875 spec->autocfg.speaker_pins[0],
d32410b1 2876 "Speaker")) < 0 ||
eb06ed8f 2877 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
d32410b1
TI
2878 "Headphone")) < 0 ||
2879 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2880 return err;
2881
2882 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2883
2884 if (spec->autocfg.dig_out_pin)
2885 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2886 if (spec->autocfg.dig_in_pin)
2887 spec->dig_in_nid = AD1988_SPDIF_IN;
2888
603c4019
TI
2889 if (spec->kctls.list)
2890 spec->mixers[spec->num_mixers++] = spec->kctls.list;
d32410b1
TI
2891
2892 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2893
2894 spec->input_mux = &spec->private_imux;
2895
2896 return 1;
2897}
2898
2899/* init callback for auto-configuration model -- overriding the default init */
2900static int ad1988_auto_init(struct hda_codec *codec)
2901{
2902 ad198x_init(codec);
2903 ad1988_auto_init_multi_out(codec);
2904 ad1988_auto_init_extra_out(codec);
2905 ad1988_auto_init_analog_input(codec);
2906 return 0;
2907}
2908
2909
fd66e0d0
TI
2910/*
2911 */
2912
f5fcc13c
TI
2913static const char *ad1988_models[AD1988_MODEL_LAST] = {
2914 [AD1988_6STACK] = "6stack",
2915 [AD1988_6STACK_DIG] = "6stack-dig",
2916 [AD1988_3STACK] = "3stack",
2917 [AD1988_3STACK_DIG] = "3stack-dig",
2918 [AD1988_LAPTOP] = "laptop",
2919 [AD1988_LAPTOP_DIG] = "laptop-dig",
2920 [AD1988_AUTO] = "auto",
fd66e0d0
TI
2921};
2922
a64c8cd6 2923static struct snd_pci_quirk ad1988_cfg_tbl[] = {
18768991 2924 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
ac3e3741 2925 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
b9e16bc5 2926 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
f51ff993 2927 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
a64c8cd6
TD
2928 {}
2929};
2930
fd66e0d0
TI
2931static int patch_ad1988(struct hda_codec *codec)
2932{
2933 struct ad198x_spec *spec;
2934 int board_config;
2935
2936 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2937 if (spec == NULL)
2938 return -ENOMEM;
2939
fd66e0d0
TI
2940 codec->spec = spec;
2941
1a806f48 2942 if (is_rev2(codec))
f8c7c7b8
TI
2943 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2944
f5fcc13c 2945 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
a64c8cd6 2946 ad1988_models, ad1988_cfg_tbl);
f5fcc13c 2947 if (board_config < 0) {
d32410b1
TI
2948 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2949 board_config = AD1988_AUTO;
2950 }
2951
2952 if (board_config == AD1988_AUTO) {
2953 /* automatic parse from the BIOS config */
2954 int err = ad1988_parse_auto_config(codec);
2955 if (err < 0) {
2956 ad198x_free(codec);
2957 return err;
2958 } else if (! err) {
2959 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2960 board_config = AD1988_6STACK;
2961 }
fd66e0d0
TI
2962 }
2963
2964 switch (board_config) {
2965 case AD1988_6STACK:
2966 case AD1988_6STACK_DIG:
2967 spec->multiout.max_channels = 8;
2968 spec->multiout.num_dacs = 4;
1a806f48 2969 if (is_rev2(codec))
d32410b1
TI
2970 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2971 else
2972 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
fd66e0d0 2973 spec->input_mux = &ad1988_6stack_capture_source;
d32410b1 2974 spec->num_mixers = 2;
1a806f48 2975 if (is_rev2(codec))
d32410b1
TI
2976 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2977 else
2978 spec->mixers[0] = ad1988_6stack_mixers1;
2979 spec->mixers[1] = ad1988_6stack_mixers2;
fd66e0d0
TI
2980 spec->num_init_verbs = 1;
2981 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2982 if (board_config == AD1988_6STACK_DIG) {
2983 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2984 spec->dig_in_nid = AD1988_SPDIF_IN;
2985 }
2986 break;
2987 case AD1988_3STACK:
2988 case AD1988_3STACK_DIG:
2989 spec->multiout.max_channels = 6;
2990 spec->multiout.num_dacs = 3;
1a806f48 2991 if (is_rev2(codec))
d32410b1
TI
2992 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2993 else
2994 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
2995 spec->input_mux = &ad1988_6stack_capture_source;
2996 spec->channel_mode = ad1988_3stack_modes;
2997 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
d32410b1 2998 spec->num_mixers = 2;
1a806f48 2999 if (is_rev2(codec))
d32410b1
TI
3000 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3001 else
3002 spec->mixers[0] = ad1988_3stack_mixers1;
3003 spec->mixers[1] = ad1988_3stack_mixers2;
fd66e0d0
TI
3004 spec->num_init_verbs = 1;
3005 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3006 if (board_config == AD1988_3STACK_DIG)
3007 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3008 break;
3009 case AD1988_LAPTOP:
3010 case AD1988_LAPTOP_DIG:
3011 spec->multiout.max_channels = 2;
3012 spec->multiout.num_dacs = 1;
d32410b1 3013 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
3014 spec->input_mux = &ad1988_laptop_capture_source;
3015 spec->num_mixers = 1;
3016 spec->mixers[0] = ad1988_laptop_mixers;
3017 spec->num_init_verbs = 1;
3018 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3019 if (board_config == AD1988_LAPTOP_DIG)
3020 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3021 break;
3022 }
3023
d32410b1
TI
3024 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3025 spec->adc_nids = ad1988_adc_nids;
3026 spec->capsrc_nids = ad1988_capsrc_nids;
fd66e0d0
TI
3027 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3028 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3029 if (spec->multiout.dig_out_nid) {
3adb8abc
TI
3030 if (codec->vendor_id >= 0x11d4989a) {
3031 spec->mixers[spec->num_mixers++] =
3032 ad1989_spdif_out_mixers;
3033 spec->init_verbs[spec->num_init_verbs++] =
3034 ad1989_spdif_init_verbs;
9cae0c63 3035 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3adb8abc
TI
3036 } else {
3037 spec->mixers[spec->num_mixers++] =
3038 ad1988_spdif_out_mixers;
3039 spec->init_verbs[spec->num_init_verbs++] =
3040 ad1988_spdif_init_verbs;
3041 }
fd66e0d0 3042 }
3adb8abc 3043 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
fd66e0d0
TI
3044 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3045
3046 codec->patch_ops = ad198x_patch_ops;
3047 switch (board_config) {
d32410b1
TI
3048 case AD1988_AUTO:
3049 codec->patch_ops.init = ad1988_auto_init;
3050 break;
fd66e0d0
TI
3051 case AD1988_LAPTOP:
3052 case AD1988_LAPTOP_DIG:
3053 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3054 break;
3055 }
cb53c626
TI
3056#ifdef CONFIG_SND_HDA_POWER_SAVE
3057 spec->loopback.amplist = ad1988_loopbacks;
3058#endif
2134ea4f 3059 spec->vmaster_nid = 0x04;
fd66e0d0
TI
3060
3061 return 0;
3062}
3063
3064
2bac647c
TI
3065/*
3066 * AD1884 / AD1984
3067 *
3068 * port-B - front line/mic-in
3069 * port-E - aux in/out
3070 * port-F - aux in/out
3071 * port-C - rear line/mic-in
3072 * port-D - rear line/hp-out
3073 * port-A - front line/hp-out
3074 *
3075 * AD1984 = AD1884 + two digital mic-ins
3076 *
3077 * FIXME:
3078 * For simplicity, we share the single DAC for both HP and line-outs
3079 * right now. The inidividual playbacks could be easily implemented,
3080 * but no build-up framework is given, so far.
3081 */
3082
3083static hda_nid_t ad1884_dac_nids[1] = {
3084 0x04,
3085};
3086
3087static hda_nid_t ad1884_adc_nids[2] = {
3088 0x08, 0x09,
3089};
3090
3091static hda_nid_t ad1884_capsrc_nids[2] = {
3092 0x0c, 0x0d,
3093};
3094
3095#define AD1884_SPDIF_OUT 0x02
3096
3097static struct hda_input_mux ad1884_capture_source = {
3098 .num_items = 4,
3099 .items = {
3100 { "Front Mic", 0x0 },
3101 { "Mic", 0x1 },
3102 { "CD", 0x2 },
3103 { "Mix", 0x3 },
3104 },
3105};
3106
3107static struct snd_kcontrol_new ad1884_base_mixers[] = {
3108 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3109 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3110 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3111 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3112 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3113 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3114 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3115 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3116 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3117 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3118 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3119 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3120 /*
3121 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3122 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3123 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
3124 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3125 */
3126 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3127 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3128 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3129 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3130 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3131 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3132 {
3133 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3134 /* The multiple "Capture Source" controls confuse alsamixer
3135 * So call somewhat different..
2bac647c
TI
3136 */
3137 /* .name = "Capture Source", */
3138 .name = "Input Source",
3139 .count = 2,
3140 .info = ad198x_mux_enum_info,
3141 .get = ad198x_mux_enum_get,
3142 .put = ad198x_mux_enum_put,
3143 },
3144 /* SPDIF controls */
3145 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3146 {
3147 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3148 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3149 /* identical with ad1983 */
3150 .info = ad1983_spdif_route_info,
3151 .get = ad1983_spdif_route_get,
3152 .put = ad1983_spdif_route_put,
3153 },
3154 { } /* end */
3155};
3156
3157static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3158 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3159 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3160 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
538c49c4 3161 HDA_INPUT),
2bac647c 3162 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
538c49c4 3163 HDA_INPUT),
2bac647c
TI
3164 { } /* end */
3165};
3166
3167/*
3168 * initialization verbs
3169 */
3170static struct hda_verb ad1884_init_verbs[] = {
3171 /* DACs; mute as default */
3b194401
TI
3172 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3173 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2bac647c
TI
3174 /* Port-A (HP) mixer */
3175 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3176 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3177 /* Port-A pin */
3178 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3179 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3180 /* HP selector - select DAC2 */
3181 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3182 /* Port-D (Line-out) mixer */
3183 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3184 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3185 /* Port-D pin */
3186 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3187 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3188 /* Mono-out mixer */
3189 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3190 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3191 /* Mono-out pin */
3192 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3193 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3194 /* Mono selector */
3195 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3196 /* Port-B (front mic) pin */
3197 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3198 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3199 /* Port-C (rear mic) pin */
3200 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3201 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3202 /* Analog mixer; mute as default */
3203 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3204 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3205 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3206 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3207 /* Analog Mix output amp */
3208 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3209 /* SPDIF output selector */
3210 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3211 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3212 { } /* end */
3213};
3214
cb53c626
TI
3215#ifdef CONFIG_SND_HDA_POWER_SAVE
3216static struct hda_amp_list ad1884_loopbacks[] = {
3217 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3218 { 0x20, HDA_INPUT, 1 }, /* Mic */
3219 { 0x20, HDA_INPUT, 2 }, /* CD */
3220 { 0x20, HDA_INPUT, 4 }, /* Docking */
3221 { } /* end */
3222};
3223#endif
3224
2134ea4f
TI
3225static const char *ad1884_slave_vols[] = {
3226 "PCM Playback Volume",
3227 "Mic Playback Volume",
3228 "Mono Playback Volume",
3229 "Front Mic Playback Volume",
3230 "Mic Playback Volume",
3231 "CD Playback Volume",
3232 "Internal Mic Playback Volume",
3233 "Docking Mic Playback Volume"
3234 "Beep Playback Volume",
4806ef0c 3235 "IEC958 Playback Volume",
2134ea4f
TI
3236 NULL
3237};
3238
2bac647c
TI
3239static int patch_ad1884(struct hda_codec *codec)
3240{
3241 struct ad198x_spec *spec;
3242
3243 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3244 if (spec == NULL)
3245 return -ENOMEM;
3246
2bac647c
TI
3247 codec->spec = spec;
3248
3249 spec->multiout.max_channels = 2;
3250 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3251 spec->multiout.dac_nids = ad1884_dac_nids;
3252 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3253 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3254 spec->adc_nids = ad1884_adc_nids;
3255 spec->capsrc_nids = ad1884_capsrc_nids;
3256 spec->input_mux = &ad1884_capture_source;
3257 spec->num_mixers = 1;
3258 spec->mixers[0] = ad1884_base_mixers;
3259 spec->num_init_verbs = 1;
3260 spec->init_verbs[0] = ad1884_init_verbs;
3261 spec->spdif_route = 0;
cb53c626
TI
3262#ifdef CONFIG_SND_HDA_POWER_SAVE
3263 spec->loopback.amplist = ad1884_loopbacks;
3264#endif
2134ea4f
TI
3265 spec->vmaster_nid = 0x04;
3266 /* we need to cover all playback volumes */
3267 spec->slave_vols = ad1884_slave_vols;
2bac647c
TI
3268
3269 codec->patch_ops = ad198x_patch_ops;
3270
3271 return 0;
3272}
3273
3274/*
3275 * Lenovo Thinkpad T61/X61
3276 */
3277static struct hda_input_mux ad1984_thinkpad_capture_source = {
b26451c0 3278 .num_items = 4,
2bac647c
TI
3279 .items = {
3280 { "Mic", 0x0 },
3281 { "Internal Mic", 0x1 },
3282 { "Mix", 0x3 },
b26451c0 3283 { "Docking-Station", 0x4 },
2bac647c
TI
3284 },
3285};
3286
0aaa22e5
DK
3287
3288/*
3289 * Dell Precision T3400
3290 */
3291static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3292 .num_items = 3,
3293 .items = {
3294 { "Front Mic", 0x0 },
3295 { "Line-In", 0x1 },
3296 { "Mix", 0x3 },
3297 },
3298};
3299
3300
2bac647c
TI
3301static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3302 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3303 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3304 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3305 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3306 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3307 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3308 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3309 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3310 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3311 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
2bac647c
TI
3312 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3313 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
0ba7962b 3314 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
b959d1f8
TI
3315 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3316 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
2bac647c
TI
3317 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3318 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3319 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3320 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3321 {
3322 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3323 /* The multiple "Capture Source" controls confuse alsamixer
3324 * So call somewhat different..
2bac647c
TI
3325 */
3326 /* .name = "Capture Source", */
3327 .name = "Input Source",
3328 .count = 2,
3329 .info = ad198x_mux_enum_info,
3330 .get = ad198x_mux_enum_get,
3331 .put = ad198x_mux_enum_put,
3332 },
ebf00c54
JY
3333 /* SPDIF controls */
3334 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3335 {
3336 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3337 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3338 /* identical with ad1983 */
3339 .info = ad1983_spdif_route_info,
3340 .get = ad1983_spdif_route_get,
3341 .put = ad1983_spdif_route_put,
3342 },
2bac647c
TI
3343 { } /* end */
3344};
3345
3346/* additional verbs */
3347static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3348 /* Port-E (docking station mic) pin */
3349 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3350 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3351 /* docking mic boost */
3352 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3353 /* Analog mixer - docking mic; mute as default */
3354 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
b959d1f8
TI
3355 /* enable EAPD bit */
3356 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
2bac647c
TI
3357 { } /* end */
3358};
3359
0aaa22e5
DK
3360/*
3361 * Dell Precision T3400
3362 */
3363static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3364 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3365 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3366 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3367 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3368 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3369 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3370 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3371 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3372 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3373 /*
3374 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3375 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3376 */
3377 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3378 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3379 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3380 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3381 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3382 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3383 {
3384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3385 /* The multiple "Capture Source" controls confuse alsamixer
3386 * So call somewhat different..
3387 */
3388 /* .name = "Capture Source", */
3389 .name = "Input Source",
3390 .count = 2,
3391 .info = ad198x_mux_enum_info,
3392 .get = ad198x_mux_enum_get,
3393 .put = ad198x_mux_enum_put,
3394 },
3395 { } /* end */
3396};
3397
2bac647c
TI
3398/* Digial MIC ADC NID 0x05 + 0x06 */
3399static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3400 struct hda_codec *codec,
3401 unsigned int stream_tag,
3402 unsigned int format,
3403 struct snd_pcm_substream *substream)
3404{
3405 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3406 stream_tag, 0, format);
3407 return 0;
3408}
3409
3410static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3411 struct hda_codec *codec,
3412 struct snd_pcm_substream *substream)
3413{
888afa15 3414 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
2bac647c
TI
3415 return 0;
3416}
3417
3418static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3419 .substreams = 2,
3420 .channels_min = 2,
3421 .channels_max = 2,
3422 .nid = 0x05,
3423 .ops = {
3424 .prepare = ad1984_pcm_dmic_prepare,
3425 .cleanup = ad1984_pcm_dmic_cleanup
3426 },
3427};
3428
3429static int ad1984_build_pcms(struct hda_codec *codec)
3430{
3431 struct ad198x_spec *spec = codec->spec;
3432 struct hda_pcm *info;
3433 int err;
3434
3435 err = ad198x_build_pcms(codec);
3436 if (err < 0)
3437 return err;
3438
3439 info = spec->pcm_rec + codec->num_pcms;
3440 codec->num_pcms++;
3441 info->name = "AD1984 Digital Mic";
3442 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3443 return 0;
3444}
3445
3446/* models */
3447enum {
3448 AD1984_BASIC,
3449 AD1984_THINKPAD,
0aaa22e5 3450 AD1984_DELL_DESKTOP,
2bac647c
TI
3451 AD1984_MODELS
3452};
3453
3454static const char *ad1984_models[AD1984_MODELS] = {
3455 [AD1984_BASIC] = "basic",
3456 [AD1984_THINKPAD] = "thinkpad",
0aaa22e5 3457 [AD1984_DELL_DESKTOP] = "dell_desktop",
2bac647c
TI
3458};
3459
3460static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3461 /* Lenovo Thinkpad T61/X61 */
3462 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
0aaa22e5 3463 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
2bac647c
TI
3464 {}
3465};
3466
3467static int patch_ad1984(struct hda_codec *codec)
3468{
3469 struct ad198x_spec *spec;
3470 int board_config, err;
3471
3472 err = patch_ad1884(codec);
3473 if (err < 0)
3474 return err;
3475 spec = codec->spec;
3476 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3477 ad1984_models, ad1984_cfg_tbl);
3478 switch (board_config) {
3479 case AD1984_BASIC:
3480 /* additional digital mics */
3481 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3482 codec->patch_ops.build_pcms = ad1984_build_pcms;
3483 break;
3484 case AD1984_THINKPAD:
ebf00c54 3485 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
2bac647c
TI
3486 spec->input_mux = &ad1984_thinkpad_capture_source;
3487 spec->mixers[0] = ad1984_thinkpad_mixers;
3488 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3489 break;
0aaa22e5
DK
3490 case AD1984_DELL_DESKTOP:
3491 spec->multiout.dig_out_nid = 0;
3492 spec->input_mux = &ad1984_dell_desktop_capture_source;
3493 spec->mixers[0] = ad1984_dell_desktop_mixers;
3494 break;
2bac647c
TI
3495 }
3496 return 0;
3497}
3498
3499
c5059259
TI
3500/*
3501 * AD1883 / AD1884A / AD1984A / AD1984B
3502 *
3503 * port-B (0x14) - front mic-in
3504 * port-E (0x1c) - rear mic-in
3505 * port-F (0x16) - CD / ext out
3506 * port-C (0x15) - rear line-in
3507 * port-D (0x12) - rear line-out
3508 * port-A (0x11) - front hp-out
3509 *
3510 * AD1984A = AD1884A + digital-mic
3511 * AD1883 = equivalent with AD1984A
3512 * AD1984B = AD1984A + extra SPDIF-out
3513 *
3514 * FIXME:
3515 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3516 */
3517
3518static hda_nid_t ad1884a_dac_nids[1] = {
3519 0x03,
3520};
3521
3522#define ad1884a_adc_nids ad1884_adc_nids
3523#define ad1884a_capsrc_nids ad1884_capsrc_nids
3524
3525#define AD1884A_SPDIF_OUT 0x02
3526
3527static struct hda_input_mux ad1884a_capture_source = {
3528 .num_items = 5,
3529 .items = {
3530 { "Front Mic", 0x0 },
3531 { "Mic", 0x4 },
3532 { "Line", 0x1 },
3533 { "CD", 0x2 },
3534 { "Mix", 0x3 },
3535 },
3536};
3537
3538static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3539 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3540 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3541 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3542 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3543 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3544 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3545 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3546 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3547 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3548 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3549 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3550 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3551 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3552 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3553 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3554 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3555 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3556 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3557 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3558 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3559 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3560 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3561 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3562 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3563 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3564 {
3565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3566 /* The multiple "Capture Source" controls confuse alsamixer
3567 * So call somewhat different..
3568 */
3569 /* .name = "Capture Source", */
3570 .name = "Input Source",
3571 .count = 2,
3572 .info = ad198x_mux_enum_info,
3573 .get = ad198x_mux_enum_get,
3574 .put = ad198x_mux_enum_put,
3575 },
3576 /* SPDIF controls */
3577 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3578 {
3579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3580 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3581 /* identical with ad1983 */
3582 .info = ad1983_spdif_route_info,
3583 .get = ad1983_spdif_route_get,
3584 .put = ad1983_spdif_route_put,
3585 },
3586 { } /* end */
3587};
3588
3589/*
3590 * initialization verbs
3591 */
3592static struct hda_verb ad1884a_init_verbs[] = {
3593 /* DACs; unmute as default */
3594 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3595 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3596 /* Port-A (HP) mixer - route only from analog mixer */
3597 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3598 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3599 /* Port-A pin */
3600 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3601 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3602 /* Port-D (Line-out) mixer - route only from analog mixer */
3603 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3604 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3605 /* Port-D pin */
3606 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3607 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3608 /* Mono-out mixer - route only from analog mixer */
3609 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3610 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3611 /* Mono-out pin */
3612 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3613 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3614 /* Port-B (front mic) pin */
3615 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3616 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3617 /* Port-C (rear line-in) pin */
3618 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3619 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3620 /* Port-E (rear mic) pin */
3621 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3622 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3623 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3624 /* Port-F (CD) pin */
3625 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3626 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3627 /* Analog mixer; mute as default */
3628 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3634 /* Analog Mix output amp */
3635 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3636 /* capture sources */
3637 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3638 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3639 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3640 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3641 /* SPDIF output amp */
3642 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3643 { } /* end */
3644};
3645
3646#ifdef CONFIG_SND_HDA_POWER_SAVE
3647static struct hda_amp_list ad1884a_loopbacks[] = {
3648 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3649 { 0x20, HDA_INPUT, 1 }, /* Mic */
3650 { 0x20, HDA_INPUT, 2 }, /* CD */
3651 { 0x20, HDA_INPUT, 4 }, /* Docking */
3652 { } /* end */
3653};
3654#endif
3655
3656/*
3657 * Laptop model
3658 *
3659 * Port A: Headphone jack
3660 * Port B: MIC jack
3661 * Port C: Internal MIC
3662 * Port D: Dock Line Out (if enabled)
3663 * Port E: Dock Line In (if enabled)
3664 * Port F: Internal speakers
3665 */
3666
3667static struct hda_input_mux ad1884a_laptop_capture_source = {
3668 .num_items = 4,
3669 .items = {
3670 { "Mic", 0x0 }, /* port-B */
3671 { "Internal Mic", 0x1 }, /* port-C */
3672 { "Dock Mic", 0x4 }, /* port-E */
3673 { "Mix", 0x3 },
3674 },
3675};
3676
3677static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3678 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3679 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3680 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3681 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3682 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3683 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3684 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3685 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3686 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3687 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3688 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3689 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3690 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3691 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3692 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3693 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3694 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3695 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3696 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3697 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3698 {
3699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3700 /* The multiple "Capture Source" controls confuse alsamixer
3701 * So call somewhat different..
3702 */
3703 /* .name = "Capture Source", */
3704 .name = "Input Source",
3705 .count = 2,
3706 .info = ad198x_mux_enum_info,
3707 .get = ad198x_mux_enum_get,
3708 .put = ad198x_mux_enum_put,
3709 },
3710 { } /* end */
3711};
3712
b40b04ad
TI
3713static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3714 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3715 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3716 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3717 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
b40b04ad
TI
3718 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3719 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
269ef19c
TI
3720 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3721 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
b40b04ad
TI
3722 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3723 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
b40b04ad
TI
3724 { } /* end */
3725};
3726
c5059259
TI
3727/* mute internal speaker if HP is plugged */
3728static void ad1884a_hp_automute(struct hda_codec *codec)
3729{
3730 unsigned int present;
3731
3732 present = snd_hda_codec_read(codec, 0x11, 0,
3733 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3734 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3735 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3736 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3737 present ? 0x00 : 0x02);
3738}
3739
269ef19c
TI
3740/* switch to external mic if plugged */
3741static void ad1884a_hp_automic(struct hda_codec *codec)
3742{
3743 unsigned int present;
3744
3745 present = snd_hda_codec_read(codec, 0x14, 0,
3746 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3747 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3748 present ? 0 : 1);
3749}
3750
c5059259 3751#define AD1884A_HP_EVENT 0x37
269ef19c 3752#define AD1884A_MIC_EVENT 0x36
c5059259
TI
3753
3754/* unsolicited event for HP jack sensing */
3755static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3756{
269ef19c
TI
3757 switch (res >> 26) {
3758 case AD1884A_HP_EVENT:
3759 ad1884a_hp_automute(codec);
3760 break;
3761 case AD1884A_MIC_EVENT:
3762 ad1884a_hp_automic(codec);
3763 break;
3764 }
c5059259
TI
3765}
3766
3767/* initialize jack-sensing, too */
3768static int ad1884a_hp_init(struct hda_codec *codec)
3769{
3770 ad198x_init(codec);
3771 ad1884a_hp_automute(codec);
269ef19c 3772 ad1884a_hp_automic(codec);
c5059259
TI
3773 return 0;
3774}
3775
3776/* additional verbs for laptop model */
3777static struct hda_verb ad1884a_laptop_verbs[] = {
3778 /* Port-A (HP) pin - always unmuted */
3779 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3780 /* Port-F (int speaker) mixer - route only from analog mixer */
3781 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3782 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3783 /* Port-F pin */
3784 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3785 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
269ef19c
TI
3786 /* Port-C pin - internal mic-in */
3787 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3788 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3789 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
c5059259
TI
3790 /* analog mix */
3791 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3792 /* unsolicited event for pin-sense */
3793 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
269ef19c 3794 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
c5059259
TI
3795 { } /* end */
3796};
3797
f081374b
TI
3798/*
3799 * Thinkpad X300
3800 * 0x11 - HP
3801 * 0x12 - speaker
3802 * 0x14 - mic-in
3803 * 0x17 - built-in mic
3804 */
3805
3806static struct hda_verb ad1984a_thinkpad_verbs[] = {
3807 /* HP unmute */
3808 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3809 /* analog mix */
3810 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3811 /* turn on EAPD */
3812 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3813 /* unsolicited event for pin-sense */
3814 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3815 /* internal mic - dmic */
3816 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
05808ecc
TI
3817 /* set magic COEFs for dmic */
3818 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3819 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
f081374b
TI
3820 { } /* end */
3821};
3822
3823static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3824 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3825 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3826 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3827 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3828 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3829 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3830 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3831 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3832 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3833 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3834 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3835 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3836 {
3837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3838 .name = "Capture Source",
3839 .info = ad198x_mux_enum_info,
3840 .get = ad198x_mux_enum_get,
3841 .put = ad198x_mux_enum_put,
3842 },
3843 { } /* end */
3844};
3845
3846static struct hda_input_mux ad1984a_thinkpad_capture_source = {
3847 .num_items = 3,
3848 .items = {
3849 { "Mic", 0x0 },
3850 { "Internal Mic", 0x5 },
3851 { "Mix", 0x3 },
3852 },
3853};
3854
3855/* mute internal speaker if HP is plugged */
3856static void ad1984a_thinkpad_automute(struct hda_codec *codec)
3857{
3858 unsigned int present;
3859
3860 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
3861 & AC_PINSENSE_PRESENCE;
3862 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
3863 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3864}
3865
3866/* unsolicited event for HP jack sensing */
3867static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
3868 unsigned int res)
3869{
3870 if ((res >> 26) != AD1884A_HP_EVENT)
3871 return;
3872 ad1984a_thinkpad_automute(codec);
3873}
3874
3875/* initialize jack-sensing, too */
3876static int ad1984a_thinkpad_init(struct hda_codec *codec)
3877{
3878 ad198x_init(codec);
3879 ad1984a_thinkpad_automute(codec);
3880 return 0;
3881}
3882
c5059259
TI
3883/*
3884 */
3885
3886enum {
3887 AD1884A_DESKTOP,
3888 AD1884A_LAPTOP,
b40b04ad 3889 AD1884A_MOBILE,
f081374b 3890 AD1884A_THINKPAD,
c5059259
TI
3891 AD1884A_MODELS
3892};
3893
3894static const char *ad1884a_models[AD1884A_MODELS] = {
3895 [AD1884A_DESKTOP] = "desktop",
3896 [AD1884A_LAPTOP] = "laptop",
b40b04ad 3897 [AD1884A_MOBILE] = "mobile",
f081374b 3898 [AD1884A_THINKPAD] = "thinkpad",
b40b04ad
TI
3899};
3900
3901static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3902 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
5695ff44 3903 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
25424831 3904 SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
65b92e5c 3905 SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
f081374b 3906 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
b40b04ad 3907 {}
c5059259
TI
3908};
3909
3910static int patch_ad1884a(struct hda_codec *codec)
3911{
3912 struct ad198x_spec *spec;
3913 int board_config;
3914
3915 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3916 if (spec == NULL)
3917 return -ENOMEM;
3918
c5059259
TI
3919 codec->spec = spec;
3920
3921 spec->multiout.max_channels = 2;
3922 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3923 spec->multiout.dac_nids = ad1884a_dac_nids;
3924 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3925 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3926 spec->adc_nids = ad1884a_adc_nids;
3927 spec->capsrc_nids = ad1884a_capsrc_nids;
3928 spec->input_mux = &ad1884a_capture_source;
3929 spec->num_mixers = 1;
3930 spec->mixers[0] = ad1884a_base_mixers;
3931 spec->num_init_verbs = 1;
3932 spec->init_verbs[0] = ad1884a_init_verbs;
3933 spec->spdif_route = 0;
3934#ifdef CONFIG_SND_HDA_POWER_SAVE
3935 spec->loopback.amplist = ad1884a_loopbacks;
3936#endif
3937 codec->patch_ops = ad198x_patch_ops;
3938
3939 /* override some parameters */
3940 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
b40b04ad
TI
3941 ad1884a_models,
3942 ad1884a_cfg_tbl);
c5059259
TI
3943 switch (board_config) {
3944 case AD1884A_LAPTOP:
3945 spec->mixers[0] = ad1884a_laptop_mixers;
3946 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3947 spec->multiout.dig_out_nid = 0;
3948 spec->input_mux = &ad1884a_laptop_capture_source;
3949 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3950 codec->patch_ops.init = ad1884a_hp_init;
3951 break;
b40b04ad
TI
3952 case AD1884A_MOBILE:
3953 spec->mixers[0] = ad1884a_mobile_mixers;
3954 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3955 spec->multiout.dig_out_nid = 0;
b40b04ad
TI
3956 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3957 codec->patch_ops.init = ad1884a_hp_init;
3958 break;
f081374b
TI
3959 case AD1884A_THINKPAD:
3960 spec->mixers[0] = ad1984a_thinkpad_mixers;
3961 spec->init_verbs[spec->num_init_verbs++] =
3962 ad1984a_thinkpad_verbs;
3963 spec->multiout.dig_out_nid = 0;
3964 spec->input_mux = &ad1984a_thinkpad_capture_source;
3965 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
3966 codec->patch_ops.init = ad1984a_thinkpad_init;
3967 break;
c5059259
TI
3968 }
3969
3970 return 0;
3971}
3972
3973
0ac8551e 3974/*
9e44c6e4 3975 * AD1882 / AD1882A
0ac8551e
TI
3976 *
3977 * port-A - front hp-out
3978 * port-B - front mic-in
3979 * port-C - rear line-in, shared surr-out (3stack)
3980 * port-D - rear line-out
3981 * port-E - rear mic-in, shared clfe-out (3stack)
3982 * port-F - rear surr-out (6stack)
3983 * port-G - rear clfe-out (6stack)
3984 */
3985
3986static hda_nid_t ad1882_dac_nids[3] = {
3987 0x04, 0x03, 0x05
3988};
3989
3990static hda_nid_t ad1882_adc_nids[2] = {
3991 0x08, 0x09,
3992};
3993
3994static hda_nid_t ad1882_capsrc_nids[2] = {
3995 0x0c, 0x0d,
3996};
3997
3998#define AD1882_SPDIF_OUT 0x02
3999
4000/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4001static struct hda_input_mux ad1882_capture_source = {
4002 .num_items = 5,
4003 .items = {
4004 { "Front Mic", 0x1 },
4005 { "Mic", 0x4 },
4006 { "Line", 0x2 },
4007 { "CD", 0x3 },
4008 { "Mix", 0x7 },
4009 },
4010};
4011
9e44c6e4
TI
4012/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4013static struct hda_input_mux ad1882a_capture_source = {
4014 .num_items = 5,
4015 .items = {
4016 { "Front Mic", 0x1 },
4017 { "Mic", 0x4},
4018 { "Line", 0x2 },
4019 { "Digital Mic", 0x06 },
4020 { "Mix", 0x7 },
4021 },
4022};
4023
0ac8551e
TI
4024static struct snd_kcontrol_new ad1882_base_mixers[] = {
4025 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4026 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4027 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4028 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4029 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4030 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4031 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4032 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
9e44c6e4 4033
0ac8551e
TI
4034 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4035 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4036 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4037 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4038 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4039 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4040 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4041 {
4042 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4043 /* The multiple "Capture Source" controls confuse alsamixer
4044 * So call somewhat different..
0ac8551e
TI
4045 */
4046 /* .name = "Capture Source", */
4047 .name = "Input Source",
4048 .count = 2,
4049 .info = ad198x_mux_enum_info,
4050 .get = ad198x_mux_enum_get,
4051 .put = ad198x_mux_enum_put,
4052 },
4053 /* SPDIF controls */
4054 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4055 {
4056 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4057 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4058 /* identical with ad1983 */
4059 .info = ad1983_spdif_route_info,
4060 .get = ad1983_spdif_route_get,
4061 .put = ad1983_spdif_route_put,
4062 },
4063 { } /* end */
4064};
4065
9e44c6e4
TI
4066static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4067 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4068 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4069 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4070 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4071 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4072 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4073 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4074 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4075 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4076 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4077 { } /* end */
4078};
4079
4080static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4081 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4082 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4083 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4084 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4085 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4086 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4087 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4088 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4089 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4090 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4091 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4092 { } /* end */
4093};
4094
0ac8551e
TI
4095static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4096 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4097 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4098 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4099 {
4100 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4101 .name = "Channel Mode",
4102 .info = ad198x_ch_mode_info,
4103 .get = ad198x_ch_mode_get,
4104 .put = ad198x_ch_mode_put,
4105 },
4106 { } /* end */
4107};
4108
4109static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4110 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4111 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4112 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4113 { } /* end */
4114};
4115
4116static struct hda_verb ad1882_ch2_init[] = {
4117 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4118 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4119 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4120 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4121 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4122 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4123 { } /* end */
4124};
4125
4126static struct hda_verb ad1882_ch4_init[] = {
4127 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4128 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4129 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4130 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4131 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4132 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4133 { } /* end */
4134};
4135
4136static struct hda_verb ad1882_ch6_init[] = {
4137 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4138 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4139 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4140 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4141 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4142 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4143 { } /* end */
4144};
4145
4146static struct hda_channel_mode ad1882_modes[3] = {
4147 { 2, ad1882_ch2_init },
4148 { 4, ad1882_ch4_init },
4149 { 6, ad1882_ch6_init },
4150};
4151
4152/*
4153 * initialization verbs
4154 */
4155static struct hda_verb ad1882_init_verbs[] = {
4156 /* DACs; mute as default */
4157 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4158 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4159 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4160 /* Port-A (HP) mixer */
4161 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4162 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4163 /* Port-A pin */
4164 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4165 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4166 /* HP selector - select DAC2 */
4167 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4168 /* Port-D (Line-out) mixer */
4169 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4170 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4171 /* Port-D pin */
4172 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4173 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4174 /* Mono-out mixer */
4175 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4176 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4177 /* Mono-out pin */
4178 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4179 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4180 /* Port-B (front mic) pin */
4181 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4182 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4183 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4184 /* Port-C (line-in) pin */
4185 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4186 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4187 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4188 /* Port-C mixer - mute as input */
4189 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4190 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4191 /* Port-E (mic-in) pin */
4192 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4193 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4194 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4195 /* Port-E mixer - mute as input */
4196 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4197 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4198 /* Port-F (surround) */
4199 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4200 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4201 /* Port-G (CLFE) */
4202 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4203 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4204 /* Analog mixer; mute as default */
4205 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4206 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4207 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4208 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4209 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4210 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4211 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4212 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4213 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4214 /* Analog Mix output amp */
4215 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4216 /* SPDIF output selector */
4217 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4218 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4219 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4220 { } /* end */
4221};
4222
cb53c626
TI
4223#ifdef CONFIG_SND_HDA_POWER_SAVE
4224static struct hda_amp_list ad1882_loopbacks[] = {
4225 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4226 { 0x20, HDA_INPUT, 1 }, /* Mic */
4227 { 0x20, HDA_INPUT, 4 }, /* Line */
4228 { 0x20, HDA_INPUT, 6 }, /* CD */
4229 { } /* end */
4230};
4231#endif
4232
0ac8551e
TI
4233/* models */
4234enum {
4235 AD1882_3STACK,
4236 AD1882_6STACK,
4237 AD1882_MODELS
4238};
4239
4240static const char *ad1882_models[AD1986A_MODELS] = {
4241 [AD1882_3STACK] = "3stack",
4242 [AD1882_6STACK] = "6stack",
4243};
4244
4245
4246static int patch_ad1882(struct hda_codec *codec)
4247{
4248 struct ad198x_spec *spec;
4249 int board_config;
4250
4251 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4252 if (spec == NULL)
4253 return -ENOMEM;
4254
0ac8551e
TI
4255 codec->spec = spec;
4256
4257 spec->multiout.max_channels = 6;
4258 spec->multiout.num_dacs = 3;
4259 spec->multiout.dac_nids = ad1882_dac_nids;
4260 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4261 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4262 spec->adc_nids = ad1882_adc_nids;
4263 spec->capsrc_nids = ad1882_capsrc_nids;
9e44c6e4
TI
4264 if (codec->vendor_id == 0x11d1882)
4265 spec->input_mux = &ad1882_capture_source;
4266 else
4267 spec->input_mux = &ad1882a_capture_source;
4268 spec->num_mixers = 2;
0ac8551e 4269 spec->mixers[0] = ad1882_base_mixers;
9e44c6e4
TI
4270 if (codec->vendor_id == 0x11d1882)
4271 spec->mixers[1] = ad1882_loopback_mixers;
4272 else
4273 spec->mixers[1] = ad1882a_loopback_mixers;
0ac8551e
TI
4274 spec->num_init_verbs = 1;
4275 spec->init_verbs[0] = ad1882_init_verbs;
4276 spec->spdif_route = 0;
cb53c626
TI
4277#ifdef CONFIG_SND_HDA_POWER_SAVE
4278 spec->loopback.amplist = ad1882_loopbacks;
4279#endif
2134ea4f 4280 spec->vmaster_nid = 0x04;
0ac8551e
TI
4281
4282 codec->patch_ops = ad198x_patch_ops;
4283
4284 /* override some parameters */
4285 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4286 ad1882_models, NULL);
4287 switch (board_config) {
4288 default:
4289 case AD1882_3STACK:
9e44c6e4
TI
4290 spec->num_mixers = 3;
4291 spec->mixers[2] = ad1882_3stack_mixers;
0ac8551e
TI
4292 spec->channel_mode = ad1882_modes;
4293 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4294 spec->need_dac_fix = 1;
4295 spec->multiout.max_channels = 2;
4296 spec->multiout.num_dacs = 1;
4297 break;
4298 case AD1882_6STACK:
9e44c6e4
TI
4299 spec->num_mixers = 3;
4300 spec->mixers[2] = ad1882_6stack_mixers;
0ac8551e
TI
4301 break;
4302 }
4303 return 0;
4304}
4305
4306
1da177e4
LT
4307/*
4308 * patch entries
4309 */
1289e9e8 4310static struct hda_codec_preset snd_hda_preset_analog[] = {
c5059259 4311 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
0ac8551e 4312 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
c5059259 4313 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
2bac647c 4314 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
c5059259
TI
4315 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4316 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4a3fdf3d
TI
4317 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4318 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
2bac647c 4319 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
1da177e4 4320 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
fd66e0d0 4321 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
71b2ccc3 4322 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
9e44c6e4 4323 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
3adb8abc
TI
4324 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4325 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
1da177e4
LT
4326 {} /* terminator */
4327};
1289e9e8
TI
4328
4329MODULE_ALIAS("snd-hda-codec-id:11d4*");
4330
4331MODULE_LICENSE("GPL");
4332MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4333
4334static struct hda_codec_preset_list analog_list = {
4335 .preset = snd_hda_preset_analog,
4336 .owner = THIS_MODULE,
4337};
4338
4339static int __init patch_analog_init(void)
4340{
4341 return snd_hda_add_codec_preset(&analog_list);
4342}
4343
4344static void __exit patch_analog_exit(void)
4345{
4346 snd_hda_delete_codec_preset(&analog_list);
4347}
4348
4349module_init(patch_analog_init)
4350module_exit(patch_analog_exit)
This page took 0.675046 seconds and 5 git commands to generate.