ALSA: hda - Fix invalid amp init for ALC268 codec
[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 */
6d6e17de
TI
1410 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1411 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4a3fdf3d
TI
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},
fd66e0d0
TI
2291
2292 { }
2293};
2294
2295static struct hda_verb ad1988_spdif_init_verbs[] = {
2296 /* SPDIF out sel */
2297 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2298 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2299 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
bddcf541 2300 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
fd66e0d0
TI
2301 /* SPDIF out pin */
2302 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
fd66e0d0
TI
2303
2304 { }
2305};
2306
3adb8abc
TI
2307/* AD1989 has no ADC -> SPDIF route */
2308static struct hda_verb ad1989_spdif_init_verbs[] = {
e8bfc6c1
RJ
2309 /* SPDIF-1 out pin */
2310 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3adb8abc 2311 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
e8bfc6c1
RJ
2312 /* SPDIF-2/HDMI out pin */
2313 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2314 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3adb8abc
TI
2315 { }
2316};
2317
fd66e0d0
TI
2318/*
2319 * verbs for 3stack (+dig)
2320 */
2321static struct hda_verb ad1988_3stack_ch2_init[] = {
2322 /* set port-C to line-in */
2323 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2324 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2325 /* set port-E to mic-in */
2326 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2327 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2328 { } /* end */
2329};
2330
2331static struct hda_verb ad1988_3stack_ch6_init[] = {
2332 /* set port-C to surround out */
fd66e0d0 2333 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2334 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0 2335 /* set port-E to CLFE out */
fd66e0d0 2336 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2337 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0
TI
2338 { } /* end */
2339};
2340
2341static struct hda_channel_mode ad1988_3stack_modes[2] = {
2342 { 2, ad1988_3stack_ch2_init },
2343 { 6, ad1988_3stack_ch6_init },
2344};
2345
2346static struct hda_verb ad1988_3stack_init_verbs[] = {
2e5b9567
TI
2347 /* Front, Surround, CLFE, side DAC; unmute as default */
2348 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2349 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2350 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2351 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2352 /* Port-A front headphon path */
2353 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2354 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2355 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2356 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2357 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2358 /* Port-D line-out path */
2359 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2360 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2361 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2362 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2363 /* Mono out path */
2364 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2365 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2366 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2367 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2368 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2369 /* Port-B front mic-in path */
2370 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2371 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2372 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1
TI
2373 /* Port-C line-in/surround path - 6ch mode as default */
2374 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2375 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2376 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1 2377 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
fd66e0d0 2378 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
d32410b1
TI
2379 /* Port-E mic-in/CLFE path - 6ch mode as default */
2380 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2381 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2382 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
f8c7c7b8 2383 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
fd66e0d0
TI
2384 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2385 /* mute analog mix */
2386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2388 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2389 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2390 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2391 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2392 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2393 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2394 /* select ADCs - front-mic */
2395 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2396 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2397 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
db3da6c1
TI
2398 /* Analog Mix output amp */
2399 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2400 { }
2401};
2402
2403/*
2404 * verbs for laptop mode (+dig)
2405 */
2406static struct hda_verb ad1988_laptop_hp_on[] = {
2407 /* unmute port-A and mute port-D */
2408 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2409 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2410 { } /* end */
2411};
2412static struct hda_verb ad1988_laptop_hp_off[] = {
2413 /* mute port-A and unmute port-D */
2414 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2415 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2416 { } /* end */
2417};
2418
2419#define AD1988_HP_EVENT 0x01
2420
2421static struct hda_verb ad1988_laptop_init_verbs[] = {
2e5b9567
TI
2422 /* Front, Surround, CLFE, side DAC; unmute as default */
2423 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2424 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2425 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2426 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2427 /* Port-A front headphon path */
2428 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2429 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2430 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2431 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2432 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2433 /* unsolicited event for pin-sense */
2434 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2435 /* Port-D line-out path + EAPD */
2436 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2437 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2438 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2439 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2440 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2441 /* Mono out path */
2442 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2443 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2444 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2445 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2446 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2447 /* Port-B mic-in path */
2448 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2449 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2450 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2451 /* Port-C docking station - try to output */
2452 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2453 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2454 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2455 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2456 /* mute analog mix */
2457 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2458 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2459 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2460 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2461 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2462 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2463 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2464 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2465 /* select ADCs - mic */
2466 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2467 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2468 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
db3da6c1
TI
2469 /* Analog Mix output amp */
2470 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2471 { }
2472};
2473
2474static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2475{
2476 if ((res >> 26) != AD1988_HP_EVENT)
2477 return;
2478 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2479 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2480 else
2481 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2482}
2483
cb53c626
TI
2484#ifdef CONFIG_SND_HDA_POWER_SAVE
2485static struct hda_amp_list ad1988_loopbacks[] = {
2486 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2487 { 0x20, HDA_INPUT, 1 }, /* Line */
2488 { 0x20, HDA_INPUT, 4 }, /* Mic */
2489 { 0x20, HDA_INPUT, 6 }, /* CD */
2490 { } /* end */
2491};
2492#endif
fd66e0d0 2493
d32410b1
TI
2494/*
2495 * Automatic parse of I/O pins from the BIOS configuration
2496 */
2497
d32410b1
TI
2498enum {
2499 AD_CTL_WIDGET_VOL,
2500 AD_CTL_WIDGET_MUTE,
2501 AD_CTL_BIND_MUTE,
2502};
2503static struct snd_kcontrol_new ad1988_control_templates[] = {
2504 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2505 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2506 HDA_BIND_MUTE(NULL, 0, 0, 0),
2507};
2508
2509/* add dynamic controls */
2510static int add_control(struct ad198x_spec *spec, int type, const char *name,
2511 unsigned long val)
2512{
2513 struct snd_kcontrol_new *knew;
2514
603c4019
TI
2515 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2516 knew = snd_array_new(&spec->kctls);
2517 if (!knew)
2518 return -ENOMEM;
d32410b1
TI
2519 *knew = ad1988_control_templates[type];
2520 knew->name = kstrdup(name, GFP_KERNEL);
2521 if (! knew->name)
2522 return -ENOMEM;
2523 knew->private_value = val;
d32410b1
TI
2524 return 0;
2525}
2526
2527#define AD1988_PIN_CD_NID 0x18
2528#define AD1988_PIN_BEEP_NID 0x10
2529
2530static hda_nid_t ad1988_mixer_nids[8] = {
2531 /* A B C D E F G H */
2532 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2533};
2534
2535static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2536{
2537 static hda_nid_t idx_to_dac[8] = {
2538 /* A B C D E F G H */
f8c7c7b8 2539 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
d32410b1
TI
2540 };
2541 static hda_nid_t idx_to_dac_rev2[8] = {
2542 /* A B C D E F G H */
f8c7c7b8 2543 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
d32410b1 2544 };
1a806f48 2545 if (is_rev2(codec))
d32410b1
TI
2546 return idx_to_dac_rev2[idx];
2547 else
2548 return idx_to_dac[idx];
2549}
2550
2551static hda_nid_t ad1988_boost_nids[8] = {
2552 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2553};
2554
2555static int ad1988_pin_idx(hda_nid_t nid)
2556{
2557 static hda_nid_t ad1988_io_pins[8] = {
2558 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2559 };
2560 int i;
2561 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2562 if (ad1988_io_pins[i] == nid)
2563 return i;
2564 return 0; /* should be -1 */
2565}
2566
2567static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2568{
2569 static int loopback_idx[8] = {
2570 2, 0, 1, 3, 4, 5, 1, 4
2571 };
2572 switch (nid) {
2573 case AD1988_PIN_CD_NID:
2574 return 6;
2575 default:
2576 return loopback_idx[ad1988_pin_idx(nid)];
2577 }
2578}
2579
2580static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2581{
2582 static int adc_idx[8] = {
2583 0, 1, 2, 8, 4, 3, 6, 7
2584 };
2585 switch (nid) {
2586 case AD1988_PIN_CD_NID:
2587 return 5;
2588 default:
2589 return adc_idx[ad1988_pin_idx(nid)];
2590 }
2591}
2592
2593/* fill in the dac_nids table from the parsed pin configuration */
2594static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2595 const struct auto_pin_cfg *cfg)
2596{
2597 struct ad198x_spec *spec = codec->spec;
2598 int i, idx;
2599
2600 spec->multiout.dac_nids = spec->private_dac_nids;
2601
2602 /* check the pins hardwired to audio widget */
2603 for (i = 0; i < cfg->line_outs; i++) {
2604 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2605 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2606 }
2607 spec->multiout.num_dacs = cfg->line_outs;
2608 return 0;
2609}
2610
2611/* add playback controls from the parsed DAC table */
2612static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2613 const struct auto_pin_cfg *cfg)
2614{
2615 char name[32];
2616 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2617 hda_nid_t nid;
2618 int i, err;
2619
2620 for (i = 0; i < cfg->line_outs; i++) {
2621 hda_nid_t dac = spec->multiout.dac_nids[i];
2622 if (! dac)
2623 continue;
2624 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2625 if (i == 2) {
2626 /* Center/LFE */
2627 err = add_control(spec, AD_CTL_WIDGET_VOL,
2628 "Center Playback Volume",
2629 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2630 if (err < 0)
2631 return err;
2632 err = add_control(spec, AD_CTL_WIDGET_VOL,
2633 "LFE Playback Volume",
2634 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2635 if (err < 0)
2636 return err;
2637 err = add_control(spec, AD_CTL_BIND_MUTE,
2638 "Center Playback Switch",
2639 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2640 if (err < 0)
2641 return err;
2642 err = add_control(spec, AD_CTL_BIND_MUTE,
2643 "LFE Playback Switch",
2644 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2645 if (err < 0)
2646 return err;
2647 } else {
2648 sprintf(name, "%s Playback Volume", chname[i]);
2649 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2650 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2651 if (err < 0)
2652 return err;
2653 sprintf(name, "%s Playback Switch", chname[i]);
2654 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2655 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2656 if (err < 0)
2657 return err;
2658 }
2659 }
2660 return 0;
2661}
2662
2663/* add playback controls for speaker and HP outputs */
2664static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2665 const char *pfx)
2666{
2667 struct ad198x_spec *spec = codec->spec;
2668 hda_nid_t nid;
43785eae 2669 int i, idx, err;
d32410b1
TI
2670 char name[32];
2671
2672 if (! pin)
2673 return 0;
2674
2675 idx = ad1988_pin_idx(pin);
2676 nid = ad1988_idx_to_dac(codec, idx);
43785eae
TI
2677 /* check whether the corresponding DAC was already taken */
2678 for (i = 0; i < spec->autocfg.line_outs; i++) {
2679 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2680 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2681 if (dac == nid)
2682 break;
2683 }
2684 if (i >= spec->autocfg.line_outs) {
2685 /* specify the DAC as the extra output */
2686 if (!spec->multiout.hp_nid)
2687 spec->multiout.hp_nid = nid;
2688 else
2689 spec->multiout.extra_out_nid[0] = nid;
2690 /* control HP volume/switch on the output mixer amp */
2691 sprintf(name, "%s Playback Volume", pfx);
2692 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2693 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2694 if (err < 0)
2695 return err;
2696 }
d32410b1
TI
2697 nid = ad1988_mixer_nids[idx];
2698 sprintf(name, "%s Playback Switch", pfx);
2699 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2700 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2701 return err;
2702 return 0;
2703}
2704
2705/* create input playback/capture controls for the given pin */
2706static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2707 const char *ctlname, int boost)
2708{
2709 char name[32];
2710 int err, idx;
2711
2712 sprintf(name, "%s Playback Volume", ctlname);
2713 idx = ad1988_pin_to_loopback_idx(pin);
2714 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2715 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2716 return err;
2717 sprintf(name, "%s Playback Switch", ctlname);
2718 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2719 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2720 return err;
2721 if (boost) {
2722 hda_nid_t bnid;
2723 idx = ad1988_pin_idx(pin);
2724 bnid = ad1988_boost_nids[idx];
2725 if (bnid) {
2726 sprintf(name, "%s Boost", ctlname);
2727 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2728 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2729
2730 }
2731 }
2732 return 0;
2733}
2734
2735/* create playback/capture controls for input pins */
2736static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2737 const struct auto_pin_cfg *cfg)
2738{
d32410b1
TI
2739 struct hda_input_mux *imux = &spec->private_imux;
2740 int i, err;
2741
2742 for (i = 0; i < AUTO_PIN_LAST; i++) {
4a471b7d
TI
2743 err = new_analog_input(spec, cfg->input_pins[i],
2744 auto_pin_cfg_labels[i],
d32410b1
TI
2745 i <= AUTO_PIN_FRONT_MIC);
2746 if (err < 0)
2747 return err;
4a471b7d 2748 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
d32410b1
TI
2749 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2750 imux->num_items++;
2751 }
2752 imux->items[imux->num_items].label = "Mix";
2753 imux->items[imux->num_items].index = 9;
2754 imux->num_items++;
2755
2756 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2757 "Analog Mix Playback Volume",
2758 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2759 return err;
2760 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2761 "Analog Mix Playback Switch",
2762 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2763 return err;
2764
2765 return 0;
2766}
2767
2768static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2769 hda_nid_t nid, int pin_type,
2770 int dac_idx)
2771{
2772 /* set as output */
2773 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2774 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2775 switch (nid) {
2776 case 0x11: /* port-A - DAC 04 */
2777 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2778 break;
2779 case 0x14: /* port-B - DAC 06 */
2780 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2781 break;
2782 case 0x15: /* port-C - DAC 05 */
2783 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2784 break;
f8c7c7b8 2785 case 0x17: /* port-E - DAC 0a */
d32410b1
TI
2786 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2787 break;
2788 case 0x13: /* mono - DAC 04 */
2789 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2790 break;
2791 }
2792}
2793
2794static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2795{
2796 struct ad198x_spec *spec = codec->spec;
2797 int i;
2798
2799 for (i = 0; i < spec->autocfg.line_outs; i++) {
2800 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2801 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2802 }
2803}
2804
2805static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2806{
2807 struct ad198x_spec *spec = codec->spec;
2808 hda_nid_t pin;
2809
82bc955f 2810 pin = spec->autocfg.speaker_pins[0];
d32410b1
TI
2811 if (pin) /* connect to front */
2812 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
eb06ed8f 2813 pin = spec->autocfg.hp_pins[0];
d32410b1
TI
2814 if (pin) /* connect to front */
2815 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2816}
2817
2818static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2819{
2820 struct ad198x_spec *spec = codec->spec;
2821 int i, idx;
2822
2823 for (i = 0; i < AUTO_PIN_LAST; i++) {
2824 hda_nid_t nid = spec->autocfg.input_pins[i];
2825 if (! nid)
2826 continue;
2827 switch (nid) {
2828 case 0x15: /* port-C */
2829 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2830 break;
2831 case 0x17: /* port-E */
2832 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2833 break;
2834 }
2835 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2836 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2837 if (nid != AD1988_PIN_CD_NID)
2838 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2839 AMP_OUT_MUTE);
2840 idx = ad1988_pin_idx(nid);
2841 if (ad1988_boost_nids[idx])
2842 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2843 AC_VERB_SET_AMP_GAIN_MUTE,
2844 AMP_OUT_ZERO);
2845 }
2846}
2847
2848/* parse the BIOS configuration and set up the alc_spec */
2849/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2850static int ad1988_parse_auto_config(struct hda_codec *codec)
2851{
2852 struct ad198x_spec *spec = codec->spec;
2853 int err;
2854
df694daa 2855 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
d32410b1
TI
2856 return err;
2857 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2858 return err;
82bc955f 2859 if (! spec->autocfg.line_outs)
d32410b1
TI
2860 return 0; /* can't find valid BIOS pin config */
2861 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
82bc955f
TI
2862 (err = ad1988_auto_create_extra_out(codec,
2863 spec->autocfg.speaker_pins[0],
d32410b1 2864 "Speaker")) < 0 ||
eb06ed8f 2865 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
d32410b1
TI
2866 "Headphone")) < 0 ||
2867 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2868 return err;
2869
2870 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2871
2872 if (spec->autocfg.dig_out_pin)
2873 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2874 if (spec->autocfg.dig_in_pin)
2875 spec->dig_in_nid = AD1988_SPDIF_IN;
2876
603c4019
TI
2877 if (spec->kctls.list)
2878 spec->mixers[spec->num_mixers++] = spec->kctls.list;
d32410b1
TI
2879
2880 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2881
2882 spec->input_mux = &spec->private_imux;
2883
2884 return 1;
2885}
2886
2887/* init callback for auto-configuration model -- overriding the default init */
2888static int ad1988_auto_init(struct hda_codec *codec)
2889{
2890 ad198x_init(codec);
2891 ad1988_auto_init_multi_out(codec);
2892 ad1988_auto_init_extra_out(codec);
2893 ad1988_auto_init_analog_input(codec);
2894 return 0;
2895}
2896
2897
fd66e0d0
TI
2898/*
2899 */
2900
f5fcc13c
TI
2901static const char *ad1988_models[AD1988_MODEL_LAST] = {
2902 [AD1988_6STACK] = "6stack",
2903 [AD1988_6STACK_DIG] = "6stack-dig",
2904 [AD1988_3STACK] = "3stack",
2905 [AD1988_3STACK_DIG] = "3stack-dig",
2906 [AD1988_LAPTOP] = "laptop",
2907 [AD1988_LAPTOP_DIG] = "laptop-dig",
2908 [AD1988_AUTO] = "auto",
fd66e0d0
TI
2909};
2910
a64c8cd6 2911static struct snd_pci_quirk ad1988_cfg_tbl[] = {
18768991 2912 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
ac3e3741 2913 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
b9e16bc5 2914 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
f51ff993 2915 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
a64c8cd6
TD
2916 {}
2917};
2918
fd66e0d0
TI
2919static int patch_ad1988(struct hda_codec *codec)
2920{
2921 struct ad198x_spec *spec;
2922 int board_config;
2923
2924 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2925 if (spec == NULL)
2926 return -ENOMEM;
2927
fd66e0d0
TI
2928 codec->spec = spec;
2929
1a806f48 2930 if (is_rev2(codec))
f8c7c7b8
TI
2931 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2932
f5fcc13c 2933 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
a64c8cd6 2934 ad1988_models, ad1988_cfg_tbl);
f5fcc13c 2935 if (board_config < 0) {
d32410b1
TI
2936 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2937 board_config = AD1988_AUTO;
2938 }
2939
2940 if (board_config == AD1988_AUTO) {
2941 /* automatic parse from the BIOS config */
2942 int err = ad1988_parse_auto_config(codec);
2943 if (err < 0) {
2944 ad198x_free(codec);
2945 return err;
2946 } else if (! err) {
2947 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2948 board_config = AD1988_6STACK;
2949 }
fd66e0d0
TI
2950 }
2951
2952 switch (board_config) {
2953 case AD1988_6STACK:
2954 case AD1988_6STACK_DIG:
2955 spec->multiout.max_channels = 8;
2956 spec->multiout.num_dacs = 4;
1a806f48 2957 if (is_rev2(codec))
d32410b1
TI
2958 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2959 else
2960 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
fd66e0d0 2961 spec->input_mux = &ad1988_6stack_capture_source;
d32410b1 2962 spec->num_mixers = 2;
1a806f48 2963 if (is_rev2(codec))
d32410b1
TI
2964 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2965 else
2966 spec->mixers[0] = ad1988_6stack_mixers1;
2967 spec->mixers[1] = ad1988_6stack_mixers2;
fd66e0d0
TI
2968 spec->num_init_verbs = 1;
2969 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2970 if (board_config == AD1988_6STACK_DIG) {
2971 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2972 spec->dig_in_nid = AD1988_SPDIF_IN;
2973 }
2974 break;
2975 case AD1988_3STACK:
2976 case AD1988_3STACK_DIG:
2977 spec->multiout.max_channels = 6;
2978 spec->multiout.num_dacs = 3;
1a806f48 2979 if (is_rev2(codec))
d32410b1
TI
2980 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2981 else
2982 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
2983 spec->input_mux = &ad1988_6stack_capture_source;
2984 spec->channel_mode = ad1988_3stack_modes;
2985 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
d32410b1 2986 spec->num_mixers = 2;
1a806f48 2987 if (is_rev2(codec))
d32410b1
TI
2988 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
2989 else
2990 spec->mixers[0] = ad1988_3stack_mixers1;
2991 spec->mixers[1] = ad1988_3stack_mixers2;
fd66e0d0
TI
2992 spec->num_init_verbs = 1;
2993 spec->init_verbs[0] = ad1988_3stack_init_verbs;
2994 if (board_config == AD1988_3STACK_DIG)
2995 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2996 break;
2997 case AD1988_LAPTOP:
2998 case AD1988_LAPTOP_DIG:
2999 spec->multiout.max_channels = 2;
3000 spec->multiout.num_dacs = 1;
d32410b1 3001 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
3002 spec->input_mux = &ad1988_laptop_capture_source;
3003 spec->num_mixers = 1;
3004 spec->mixers[0] = ad1988_laptop_mixers;
3005 spec->num_init_verbs = 1;
3006 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3007 if (board_config == AD1988_LAPTOP_DIG)
3008 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3009 break;
3010 }
3011
d32410b1
TI
3012 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3013 spec->adc_nids = ad1988_adc_nids;
3014 spec->capsrc_nids = ad1988_capsrc_nids;
fd66e0d0
TI
3015 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3016 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3017 if (spec->multiout.dig_out_nid) {
3adb8abc
TI
3018 if (codec->vendor_id >= 0x11d4989a) {
3019 spec->mixers[spec->num_mixers++] =
3020 ad1989_spdif_out_mixers;
3021 spec->init_verbs[spec->num_init_verbs++] =
3022 ad1989_spdif_init_verbs;
9cae0c63 3023 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3adb8abc
TI
3024 } else {
3025 spec->mixers[spec->num_mixers++] =
3026 ad1988_spdif_out_mixers;
3027 spec->init_verbs[spec->num_init_verbs++] =
3028 ad1988_spdif_init_verbs;
3029 }
fd66e0d0 3030 }
3adb8abc 3031 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
fd66e0d0
TI
3032 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3033
3034 codec->patch_ops = ad198x_patch_ops;
3035 switch (board_config) {
d32410b1
TI
3036 case AD1988_AUTO:
3037 codec->patch_ops.init = ad1988_auto_init;
3038 break;
fd66e0d0
TI
3039 case AD1988_LAPTOP:
3040 case AD1988_LAPTOP_DIG:
3041 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3042 break;
3043 }
cb53c626
TI
3044#ifdef CONFIG_SND_HDA_POWER_SAVE
3045 spec->loopback.amplist = ad1988_loopbacks;
3046#endif
2134ea4f 3047 spec->vmaster_nid = 0x04;
fd66e0d0
TI
3048
3049 return 0;
3050}
3051
3052
2bac647c
TI
3053/*
3054 * AD1884 / AD1984
3055 *
3056 * port-B - front line/mic-in
3057 * port-E - aux in/out
3058 * port-F - aux in/out
3059 * port-C - rear line/mic-in
3060 * port-D - rear line/hp-out
3061 * port-A - front line/hp-out
3062 *
3063 * AD1984 = AD1884 + two digital mic-ins
3064 *
3065 * FIXME:
3066 * For simplicity, we share the single DAC for both HP and line-outs
3067 * right now. The inidividual playbacks could be easily implemented,
3068 * but no build-up framework is given, so far.
3069 */
3070
3071static hda_nid_t ad1884_dac_nids[1] = {
3072 0x04,
3073};
3074
3075static hda_nid_t ad1884_adc_nids[2] = {
3076 0x08, 0x09,
3077};
3078
3079static hda_nid_t ad1884_capsrc_nids[2] = {
3080 0x0c, 0x0d,
3081};
3082
3083#define AD1884_SPDIF_OUT 0x02
3084
3085static struct hda_input_mux ad1884_capture_source = {
3086 .num_items = 4,
3087 .items = {
3088 { "Front Mic", 0x0 },
3089 { "Mic", 0x1 },
3090 { "CD", 0x2 },
3091 { "Mix", 0x3 },
3092 },
3093};
3094
3095static struct snd_kcontrol_new ad1884_base_mixers[] = {
3096 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3097 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3098 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3099 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3100 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3101 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3102 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3103 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3104 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3105 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3106 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3107 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3108 /*
3109 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3110 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3111 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
3112 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3113 */
3114 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3115 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3116 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3117 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3118 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3119 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3120 {
3121 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3122 /* The multiple "Capture Source" controls confuse alsamixer
3123 * So call somewhat different..
2bac647c
TI
3124 */
3125 /* .name = "Capture Source", */
3126 .name = "Input Source",
3127 .count = 2,
3128 .info = ad198x_mux_enum_info,
3129 .get = ad198x_mux_enum_get,
3130 .put = ad198x_mux_enum_put,
3131 },
3132 /* SPDIF controls */
3133 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3134 {
3135 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3136 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3137 /* identical with ad1983 */
3138 .info = ad1983_spdif_route_info,
3139 .get = ad1983_spdif_route_get,
3140 .put = ad1983_spdif_route_put,
3141 },
3142 { } /* end */
3143};
3144
3145static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3146 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3147 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3148 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
538c49c4 3149 HDA_INPUT),
2bac647c 3150 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
538c49c4 3151 HDA_INPUT),
2bac647c
TI
3152 { } /* end */
3153};
3154
3155/*
3156 * initialization verbs
3157 */
3158static struct hda_verb ad1884_init_verbs[] = {
3159 /* DACs; mute as default */
3b194401
TI
3160 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3161 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2bac647c
TI
3162 /* Port-A (HP) mixer */
3163 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3164 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3165 /* Port-A pin */
3166 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3167 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3168 /* HP selector - select DAC2 */
3169 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3170 /* Port-D (Line-out) mixer */
3171 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3172 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3173 /* Port-D pin */
3174 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3175 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3176 /* Mono-out mixer */
3177 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3178 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3179 /* Mono-out pin */
3180 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3181 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3182 /* Mono selector */
3183 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3184 /* Port-B (front mic) pin */
3185 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3186 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2bac647c
TI
3187 /* Port-C (rear mic) pin */
3188 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3189 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2bac647c
TI
3190 /* Analog mixer; mute as default */
3191 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3192 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3193 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3194 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3195 /* Analog Mix output amp */
3196 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3197 /* SPDIF output selector */
3198 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3199 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3200 { } /* end */
3201};
3202
cb53c626
TI
3203#ifdef CONFIG_SND_HDA_POWER_SAVE
3204static struct hda_amp_list ad1884_loopbacks[] = {
3205 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3206 { 0x20, HDA_INPUT, 1 }, /* Mic */
3207 { 0x20, HDA_INPUT, 2 }, /* CD */
3208 { 0x20, HDA_INPUT, 4 }, /* Docking */
3209 { } /* end */
3210};
3211#endif
3212
2134ea4f
TI
3213static const char *ad1884_slave_vols[] = {
3214 "PCM Playback Volume",
3215 "Mic Playback Volume",
3216 "Mono Playback Volume",
3217 "Front Mic Playback Volume",
3218 "Mic Playback Volume",
3219 "CD Playback Volume",
3220 "Internal Mic Playback Volume",
3221 "Docking Mic Playback Volume"
3222 "Beep Playback Volume",
4806ef0c 3223 "IEC958 Playback Volume",
2134ea4f
TI
3224 NULL
3225};
3226
2bac647c
TI
3227static int patch_ad1884(struct hda_codec *codec)
3228{
3229 struct ad198x_spec *spec;
3230
3231 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3232 if (spec == NULL)
3233 return -ENOMEM;
3234
2bac647c
TI
3235 codec->spec = spec;
3236
3237 spec->multiout.max_channels = 2;
3238 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3239 spec->multiout.dac_nids = ad1884_dac_nids;
3240 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3241 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3242 spec->adc_nids = ad1884_adc_nids;
3243 spec->capsrc_nids = ad1884_capsrc_nids;
3244 spec->input_mux = &ad1884_capture_source;
3245 spec->num_mixers = 1;
3246 spec->mixers[0] = ad1884_base_mixers;
3247 spec->num_init_verbs = 1;
3248 spec->init_verbs[0] = ad1884_init_verbs;
3249 spec->spdif_route = 0;
cb53c626
TI
3250#ifdef CONFIG_SND_HDA_POWER_SAVE
3251 spec->loopback.amplist = ad1884_loopbacks;
3252#endif
2134ea4f
TI
3253 spec->vmaster_nid = 0x04;
3254 /* we need to cover all playback volumes */
3255 spec->slave_vols = ad1884_slave_vols;
2bac647c
TI
3256
3257 codec->patch_ops = ad198x_patch_ops;
3258
3259 return 0;
3260}
3261
3262/*
3263 * Lenovo Thinkpad T61/X61
3264 */
3265static struct hda_input_mux ad1984_thinkpad_capture_source = {
b26451c0 3266 .num_items = 4,
2bac647c
TI
3267 .items = {
3268 { "Mic", 0x0 },
3269 { "Internal Mic", 0x1 },
3270 { "Mix", 0x3 },
b26451c0 3271 { "Docking-Station", 0x4 },
2bac647c
TI
3272 },
3273};
3274
0aaa22e5
DK
3275
3276/*
3277 * Dell Precision T3400
3278 */
3279static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3280 .num_items = 3,
3281 .items = {
3282 { "Front Mic", 0x0 },
3283 { "Line-In", 0x1 },
3284 { "Mix", 0x3 },
3285 },
3286};
3287
3288
2bac647c
TI
3289static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3290 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3291 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3292 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3293 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3294 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3295 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3296 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3297 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3298 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3299 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
2bac647c
TI
3300 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3301 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
0ba7962b 3302 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
b959d1f8
TI
3303 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3304 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
2bac647c
TI
3305 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3306 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3307 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3308 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3309 {
3310 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3311 /* The multiple "Capture Source" controls confuse alsamixer
3312 * So call somewhat different..
2bac647c
TI
3313 */
3314 /* .name = "Capture Source", */
3315 .name = "Input Source",
3316 .count = 2,
3317 .info = ad198x_mux_enum_info,
3318 .get = ad198x_mux_enum_get,
3319 .put = ad198x_mux_enum_put,
3320 },
ebf00c54
JY
3321 /* SPDIF controls */
3322 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3323 {
3324 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3325 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3326 /* identical with ad1983 */
3327 .info = ad1983_spdif_route_info,
3328 .get = ad1983_spdif_route_get,
3329 .put = ad1983_spdif_route_put,
3330 },
2bac647c
TI
3331 { } /* end */
3332};
3333
3334/* additional verbs */
3335static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3336 /* Port-E (docking station mic) pin */
3337 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3338 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3339 /* docking mic boost */
3340 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3341 /* Analog mixer - docking mic; mute as default */
3342 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
b959d1f8
TI
3343 /* enable EAPD bit */
3344 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
2bac647c
TI
3345 { } /* end */
3346};
3347
0aaa22e5
DK
3348/*
3349 * Dell Precision T3400
3350 */
3351static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3352 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3353 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3354 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3355 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3356 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3357 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3358 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3359 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3360 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3361 /*
3362 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3363 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3364 */
3365 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3366 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3367 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3368 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3369 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3370 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3371 {
3372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3373 /* The multiple "Capture Source" controls confuse alsamixer
3374 * So call somewhat different..
3375 */
3376 /* .name = "Capture Source", */
3377 .name = "Input Source",
3378 .count = 2,
3379 .info = ad198x_mux_enum_info,
3380 .get = ad198x_mux_enum_get,
3381 .put = ad198x_mux_enum_put,
3382 },
3383 { } /* end */
3384};
3385
2bac647c
TI
3386/* Digial MIC ADC NID 0x05 + 0x06 */
3387static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3388 struct hda_codec *codec,
3389 unsigned int stream_tag,
3390 unsigned int format,
3391 struct snd_pcm_substream *substream)
3392{
3393 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3394 stream_tag, 0, format);
3395 return 0;
3396}
3397
3398static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3399 struct hda_codec *codec,
3400 struct snd_pcm_substream *substream)
3401{
888afa15 3402 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
2bac647c
TI
3403 return 0;
3404}
3405
3406static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3407 .substreams = 2,
3408 .channels_min = 2,
3409 .channels_max = 2,
3410 .nid = 0x05,
3411 .ops = {
3412 .prepare = ad1984_pcm_dmic_prepare,
3413 .cleanup = ad1984_pcm_dmic_cleanup
3414 },
3415};
3416
3417static int ad1984_build_pcms(struct hda_codec *codec)
3418{
3419 struct ad198x_spec *spec = codec->spec;
3420 struct hda_pcm *info;
3421 int err;
3422
3423 err = ad198x_build_pcms(codec);
3424 if (err < 0)
3425 return err;
3426
3427 info = spec->pcm_rec + codec->num_pcms;
3428 codec->num_pcms++;
3429 info->name = "AD1984 Digital Mic";
3430 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3431 return 0;
3432}
3433
3434/* models */
3435enum {
3436 AD1984_BASIC,
3437 AD1984_THINKPAD,
0aaa22e5 3438 AD1984_DELL_DESKTOP,
2bac647c
TI
3439 AD1984_MODELS
3440};
3441
3442static const char *ad1984_models[AD1984_MODELS] = {
3443 [AD1984_BASIC] = "basic",
3444 [AD1984_THINKPAD] = "thinkpad",
0aaa22e5 3445 [AD1984_DELL_DESKTOP] = "dell_desktop",
2bac647c
TI
3446};
3447
3448static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3449 /* Lenovo Thinkpad T61/X61 */
3450 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
0aaa22e5 3451 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
2bac647c
TI
3452 {}
3453};
3454
3455static int patch_ad1984(struct hda_codec *codec)
3456{
3457 struct ad198x_spec *spec;
3458 int board_config, err;
3459
3460 err = patch_ad1884(codec);
3461 if (err < 0)
3462 return err;
3463 spec = codec->spec;
3464 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3465 ad1984_models, ad1984_cfg_tbl);
3466 switch (board_config) {
3467 case AD1984_BASIC:
3468 /* additional digital mics */
3469 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3470 codec->patch_ops.build_pcms = ad1984_build_pcms;
3471 break;
3472 case AD1984_THINKPAD:
ebf00c54 3473 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
2bac647c
TI
3474 spec->input_mux = &ad1984_thinkpad_capture_source;
3475 spec->mixers[0] = ad1984_thinkpad_mixers;
3476 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3477 break;
0aaa22e5
DK
3478 case AD1984_DELL_DESKTOP:
3479 spec->multiout.dig_out_nid = 0;
3480 spec->input_mux = &ad1984_dell_desktop_capture_source;
3481 spec->mixers[0] = ad1984_dell_desktop_mixers;
3482 break;
2bac647c
TI
3483 }
3484 return 0;
3485}
3486
3487
c5059259
TI
3488/*
3489 * AD1883 / AD1884A / AD1984A / AD1984B
3490 *
3491 * port-B (0x14) - front mic-in
3492 * port-E (0x1c) - rear mic-in
3493 * port-F (0x16) - CD / ext out
3494 * port-C (0x15) - rear line-in
3495 * port-D (0x12) - rear line-out
3496 * port-A (0x11) - front hp-out
3497 *
3498 * AD1984A = AD1884A + digital-mic
3499 * AD1883 = equivalent with AD1984A
3500 * AD1984B = AD1984A + extra SPDIF-out
3501 *
3502 * FIXME:
3503 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3504 */
3505
3506static hda_nid_t ad1884a_dac_nids[1] = {
3507 0x03,
3508};
3509
3510#define ad1884a_adc_nids ad1884_adc_nids
3511#define ad1884a_capsrc_nids ad1884_capsrc_nids
3512
3513#define AD1884A_SPDIF_OUT 0x02
3514
3515static struct hda_input_mux ad1884a_capture_source = {
3516 .num_items = 5,
3517 .items = {
3518 { "Front Mic", 0x0 },
3519 { "Mic", 0x4 },
3520 { "Line", 0x1 },
3521 { "CD", 0x2 },
3522 { "Mix", 0x3 },
3523 },
3524};
3525
3526static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3527 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3528 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3529 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3530 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3531 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3532 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3533 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3534 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3535 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3536 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3537 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3538 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3539 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3540 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3541 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3542 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3543 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3544 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3545 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3546 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3547 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3548 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3549 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3550 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3551 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3552 {
3553 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3554 /* The multiple "Capture Source" controls confuse alsamixer
3555 * So call somewhat different..
3556 */
3557 /* .name = "Capture Source", */
3558 .name = "Input Source",
3559 .count = 2,
3560 .info = ad198x_mux_enum_info,
3561 .get = ad198x_mux_enum_get,
3562 .put = ad198x_mux_enum_put,
3563 },
3564 /* SPDIF controls */
3565 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3566 {
3567 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3568 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3569 /* identical with ad1983 */
3570 .info = ad1983_spdif_route_info,
3571 .get = ad1983_spdif_route_get,
3572 .put = ad1983_spdif_route_put,
3573 },
3574 { } /* end */
3575};
3576
3577/*
3578 * initialization verbs
3579 */
3580static struct hda_verb ad1884a_init_verbs[] = {
3581 /* DACs; unmute as default */
3582 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3583 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3584 /* Port-A (HP) mixer - route only from analog mixer */
3585 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3586 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3587 /* Port-A pin */
3588 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3589 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3590 /* Port-D (Line-out) mixer - route only from analog mixer */
3591 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3592 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3593 /* Port-D pin */
3594 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3595 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3596 /* Mono-out mixer - route only from analog mixer */
3597 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3598 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3599 /* Mono-out pin */
3600 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3601 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3602 /* Port-B (front mic) pin */
3603 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3604 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
c5059259
TI
3605 /* Port-C (rear line-in) pin */
3606 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
60e388e8 3607 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
c5059259
TI
3608 /* Port-E (rear mic) pin */
3609 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3610 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3611 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3612 /* Port-F (CD) pin */
3613 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3614 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3615 /* Analog mixer; mute as default */
3616 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3617 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3618 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3619 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3620 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3621 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3622 /* Analog Mix output amp */
3623 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3624 /* capture sources */
3625 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3626 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3627 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3628 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3629 /* SPDIF output amp */
3630 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3631 { } /* end */
3632};
3633
3634#ifdef CONFIG_SND_HDA_POWER_SAVE
3635static struct hda_amp_list ad1884a_loopbacks[] = {
3636 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3637 { 0x20, HDA_INPUT, 1 }, /* Mic */
3638 { 0x20, HDA_INPUT, 2 }, /* CD */
3639 { 0x20, HDA_INPUT, 4 }, /* Docking */
3640 { } /* end */
3641};
3642#endif
3643
3644/*
3645 * Laptop model
3646 *
3647 * Port A: Headphone jack
3648 * Port B: MIC jack
3649 * Port C: Internal MIC
3650 * Port D: Dock Line Out (if enabled)
3651 * Port E: Dock Line In (if enabled)
3652 * Port F: Internal speakers
3653 */
3654
3655static struct hda_input_mux ad1884a_laptop_capture_source = {
3656 .num_items = 4,
3657 .items = {
3658 { "Mic", 0x0 }, /* port-B */
3659 { "Internal Mic", 0x1 }, /* port-C */
3660 { "Dock Mic", 0x4 }, /* port-E */
3661 { "Mix", 0x3 },
3662 },
3663};
3664
3665static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3666 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3667 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3668 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3669 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3670 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3671 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3672 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3673 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3674 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3675 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3676 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3677 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3678 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3679 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3680 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3681 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3682 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3683 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3684 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3685 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3686 {
3687 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3688 /* The multiple "Capture Source" controls confuse alsamixer
3689 * So call somewhat different..
3690 */
3691 /* .name = "Capture Source", */
3692 .name = "Input Source",
3693 .count = 2,
3694 .info = ad198x_mux_enum_info,
3695 .get = ad198x_mux_enum_get,
3696 .put = ad198x_mux_enum_put,
3697 },
3698 { } /* end */
3699};
3700
b40b04ad
TI
3701static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3702 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3703 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3704 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3705 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
b40b04ad
TI
3706 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3707 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
269ef19c
TI
3708 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3709 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
b40b04ad
TI
3710 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3711 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
b40b04ad
TI
3712 { } /* end */
3713};
3714
c5059259
TI
3715/* mute internal speaker if HP is plugged */
3716static void ad1884a_hp_automute(struct hda_codec *codec)
3717{
3718 unsigned int present;
3719
3720 present = snd_hda_codec_read(codec, 0x11, 0,
3721 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3722 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3723 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3724 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3725 present ? 0x00 : 0x02);
3726}
3727
269ef19c
TI
3728/* switch to external mic if plugged */
3729static void ad1884a_hp_automic(struct hda_codec *codec)
3730{
3731 unsigned int present;
3732
3733 present = snd_hda_codec_read(codec, 0x14, 0,
3734 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3735 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3736 present ? 0 : 1);
3737}
3738
c5059259 3739#define AD1884A_HP_EVENT 0x37
269ef19c 3740#define AD1884A_MIC_EVENT 0x36
c5059259
TI
3741
3742/* unsolicited event for HP jack sensing */
3743static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3744{
269ef19c
TI
3745 switch (res >> 26) {
3746 case AD1884A_HP_EVENT:
3747 ad1884a_hp_automute(codec);
3748 break;
3749 case AD1884A_MIC_EVENT:
3750 ad1884a_hp_automic(codec);
3751 break;
3752 }
c5059259
TI
3753}
3754
3755/* initialize jack-sensing, too */
3756static int ad1884a_hp_init(struct hda_codec *codec)
3757{
3758 ad198x_init(codec);
3759 ad1884a_hp_automute(codec);
269ef19c 3760 ad1884a_hp_automic(codec);
c5059259
TI
3761 return 0;
3762}
3763
3764/* additional verbs for laptop model */
3765static struct hda_verb ad1884a_laptop_verbs[] = {
3766 /* Port-A (HP) pin - always unmuted */
3767 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3768 /* Port-F (int speaker) mixer - route only from analog mixer */
3769 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3770 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3771 /* Port-F pin */
3772 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3773 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
269ef19c
TI
3774 /* Port-C pin - internal mic-in */
3775 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3776 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3777 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
c5059259
TI
3778 /* analog mix */
3779 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3780 /* unsolicited event for pin-sense */
3781 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
269ef19c 3782 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
c5059259
TI
3783 { } /* end */
3784};
3785
f081374b
TI
3786/*
3787 * Thinkpad X300
3788 * 0x11 - HP
3789 * 0x12 - speaker
3790 * 0x14 - mic-in
3791 * 0x17 - built-in mic
3792 */
3793
3794static struct hda_verb ad1984a_thinkpad_verbs[] = {
3795 /* HP unmute */
3796 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3797 /* analog mix */
3798 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3799 /* turn on EAPD */
3800 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3801 /* unsolicited event for pin-sense */
3802 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3803 /* internal mic - dmic */
3804 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
05808ecc
TI
3805 /* set magic COEFs for dmic */
3806 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3807 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
f081374b
TI
3808 { } /* end */
3809};
3810
3811static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3812 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3813 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3814 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3815 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3816 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3817 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3818 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3819 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3820 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3821 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3822 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3823 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3824 {
3825 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3826 .name = "Capture Source",
3827 .info = ad198x_mux_enum_info,
3828 .get = ad198x_mux_enum_get,
3829 .put = ad198x_mux_enum_put,
3830 },
3831 { } /* end */
3832};
3833
3834static struct hda_input_mux ad1984a_thinkpad_capture_source = {
3835 .num_items = 3,
3836 .items = {
3837 { "Mic", 0x0 },
3838 { "Internal Mic", 0x5 },
3839 { "Mix", 0x3 },
3840 },
3841};
3842
3843/* mute internal speaker if HP is plugged */
3844static void ad1984a_thinkpad_automute(struct hda_codec *codec)
3845{
3846 unsigned int present;
3847
3848 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
3849 & AC_PINSENSE_PRESENCE;
3850 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
3851 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3852}
3853
3854/* unsolicited event for HP jack sensing */
3855static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
3856 unsigned int res)
3857{
3858 if ((res >> 26) != AD1884A_HP_EVENT)
3859 return;
3860 ad1984a_thinkpad_automute(codec);
3861}
3862
3863/* initialize jack-sensing, too */
3864static int ad1984a_thinkpad_init(struct hda_codec *codec)
3865{
3866 ad198x_init(codec);
3867 ad1984a_thinkpad_automute(codec);
3868 return 0;
3869}
3870
c5059259
TI
3871/*
3872 */
3873
3874enum {
3875 AD1884A_DESKTOP,
3876 AD1884A_LAPTOP,
b40b04ad 3877 AD1884A_MOBILE,
f081374b 3878 AD1884A_THINKPAD,
c5059259
TI
3879 AD1884A_MODELS
3880};
3881
3882static const char *ad1884a_models[AD1884A_MODELS] = {
3883 [AD1884A_DESKTOP] = "desktop",
3884 [AD1884A_LAPTOP] = "laptop",
b40b04ad 3885 [AD1884A_MOBILE] = "mobile",
f081374b 3886 [AD1884A_THINKPAD] = "thinkpad",
b40b04ad
TI
3887};
3888
3889static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3890 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
d5337deb 3891 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
5695ff44 3892 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
11d518e0 3893 SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
25424831 3894 SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
65b92e5c 3895 SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
f081374b 3896 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
b40b04ad 3897 {}
c5059259
TI
3898};
3899
3900static int patch_ad1884a(struct hda_codec *codec)
3901{
3902 struct ad198x_spec *spec;
3903 int board_config;
3904
3905 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3906 if (spec == NULL)
3907 return -ENOMEM;
3908
c5059259
TI
3909 codec->spec = spec;
3910
3911 spec->multiout.max_channels = 2;
3912 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3913 spec->multiout.dac_nids = ad1884a_dac_nids;
3914 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3915 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3916 spec->adc_nids = ad1884a_adc_nids;
3917 spec->capsrc_nids = ad1884a_capsrc_nids;
3918 spec->input_mux = &ad1884a_capture_source;
3919 spec->num_mixers = 1;
3920 spec->mixers[0] = ad1884a_base_mixers;
3921 spec->num_init_verbs = 1;
3922 spec->init_verbs[0] = ad1884a_init_verbs;
3923 spec->spdif_route = 0;
3924#ifdef CONFIG_SND_HDA_POWER_SAVE
3925 spec->loopback.amplist = ad1884a_loopbacks;
3926#endif
3927 codec->patch_ops = ad198x_patch_ops;
3928
3929 /* override some parameters */
3930 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
b40b04ad
TI
3931 ad1884a_models,
3932 ad1884a_cfg_tbl);
c5059259
TI
3933 switch (board_config) {
3934 case AD1884A_LAPTOP:
3935 spec->mixers[0] = ad1884a_laptop_mixers;
3936 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3937 spec->multiout.dig_out_nid = 0;
3938 spec->input_mux = &ad1884a_laptop_capture_source;
3939 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3940 codec->patch_ops.init = ad1884a_hp_init;
3941 break;
b40b04ad
TI
3942 case AD1884A_MOBILE:
3943 spec->mixers[0] = ad1884a_mobile_mixers;
3944 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3945 spec->multiout.dig_out_nid = 0;
b40b04ad
TI
3946 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3947 codec->patch_ops.init = ad1884a_hp_init;
3948 break;
f081374b
TI
3949 case AD1884A_THINKPAD:
3950 spec->mixers[0] = ad1984a_thinkpad_mixers;
3951 spec->init_verbs[spec->num_init_verbs++] =
3952 ad1984a_thinkpad_verbs;
3953 spec->multiout.dig_out_nid = 0;
3954 spec->input_mux = &ad1984a_thinkpad_capture_source;
3955 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
3956 codec->patch_ops.init = ad1984a_thinkpad_init;
3957 break;
c5059259
TI
3958 }
3959
3960 return 0;
3961}
3962
3963
0ac8551e 3964/*
9e44c6e4 3965 * AD1882 / AD1882A
0ac8551e
TI
3966 *
3967 * port-A - front hp-out
3968 * port-B - front mic-in
3969 * port-C - rear line-in, shared surr-out (3stack)
3970 * port-D - rear line-out
3971 * port-E - rear mic-in, shared clfe-out (3stack)
3972 * port-F - rear surr-out (6stack)
3973 * port-G - rear clfe-out (6stack)
3974 */
3975
3976static hda_nid_t ad1882_dac_nids[3] = {
3977 0x04, 0x03, 0x05
3978};
3979
3980static hda_nid_t ad1882_adc_nids[2] = {
3981 0x08, 0x09,
3982};
3983
3984static hda_nid_t ad1882_capsrc_nids[2] = {
3985 0x0c, 0x0d,
3986};
3987
3988#define AD1882_SPDIF_OUT 0x02
3989
3990/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
3991static struct hda_input_mux ad1882_capture_source = {
3992 .num_items = 5,
3993 .items = {
3994 { "Front Mic", 0x1 },
3995 { "Mic", 0x4 },
3996 { "Line", 0x2 },
3997 { "CD", 0x3 },
3998 { "Mix", 0x7 },
3999 },
4000};
4001
9e44c6e4
TI
4002/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4003static struct hda_input_mux ad1882a_capture_source = {
4004 .num_items = 5,
4005 .items = {
4006 { "Front Mic", 0x1 },
4007 { "Mic", 0x4},
4008 { "Line", 0x2 },
4009 { "Digital Mic", 0x06 },
4010 { "Mix", 0x7 },
4011 },
4012};
4013
0ac8551e
TI
4014static struct snd_kcontrol_new ad1882_base_mixers[] = {
4015 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4016 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4017 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4018 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4019 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4020 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4021 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4022 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
9e44c6e4 4023
0ac8551e
TI
4024 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4025 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4026 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4027 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4028 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4029 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4030 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4031 {
4032 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4033 /* The multiple "Capture Source" controls confuse alsamixer
4034 * So call somewhat different..
0ac8551e
TI
4035 */
4036 /* .name = "Capture Source", */
4037 .name = "Input Source",
4038 .count = 2,
4039 .info = ad198x_mux_enum_info,
4040 .get = ad198x_mux_enum_get,
4041 .put = ad198x_mux_enum_put,
4042 },
4043 /* SPDIF controls */
4044 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4045 {
4046 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4047 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4048 /* identical with ad1983 */
4049 .info = ad1983_spdif_route_info,
4050 .get = ad1983_spdif_route_get,
4051 .put = ad1983_spdif_route_put,
4052 },
4053 { } /* end */
4054};
4055
9e44c6e4
TI
4056static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4057 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4058 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4059 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4060 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4061 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4062 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4063 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4064 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4065 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4066 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4067 { } /* end */
4068};
4069
4070static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4071 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4072 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4073 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4074 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4075 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4076 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4077 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4078 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4079 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4080 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4081 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4082 { } /* end */
4083};
4084
0ac8551e
TI
4085static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4086 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4087 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4088 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4089 {
4090 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4091 .name = "Channel Mode",
4092 .info = ad198x_ch_mode_info,
4093 .get = ad198x_ch_mode_get,
4094 .put = ad198x_ch_mode_put,
4095 },
4096 { } /* end */
4097};
4098
4099static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4100 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4101 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4102 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4103 { } /* end */
4104};
4105
4106static struct hda_verb ad1882_ch2_init[] = {
4107 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4108 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4109 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4110 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4111 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4112 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4113 { } /* end */
4114};
4115
4116static struct hda_verb ad1882_ch4_init[] = {
4117 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4118 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4119 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(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_ch6_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_OUT},
4131 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4132 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4133 { } /* end */
4134};
4135
4136static struct hda_channel_mode ad1882_modes[3] = {
4137 { 2, ad1882_ch2_init },
4138 { 4, ad1882_ch4_init },
4139 { 6, ad1882_ch6_init },
4140};
4141
4142/*
4143 * initialization verbs
4144 */
4145static struct hda_verb ad1882_init_verbs[] = {
4146 /* DACs; mute as default */
4147 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4148 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4149 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4150 /* Port-A (HP) mixer */
4151 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4152 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4153 /* Port-A pin */
4154 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4155 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4156 /* HP selector - select DAC2 */
4157 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4158 /* Port-D (Line-out) mixer */
4159 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4160 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4161 /* Port-D pin */
4162 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4163 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4164 /* Mono-out mixer */
4165 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4166 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4167 /* Mono-out pin */
4168 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4169 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4170 /* Port-B (front mic) pin */
4171 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4172 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4173 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4174 /* Port-C (line-in) pin */
4175 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4176 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4177 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4178 /* Port-C mixer - mute as input */
4179 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4180 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4181 /* Port-E (mic-in) pin */
4182 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4183 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4184 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4185 /* Port-E mixer - mute as input */
4186 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4187 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4188 /* Port-F (surround) */
4189 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4190 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4191 /* Port-G (CLFE) */
4192 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4193 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4194 /* Analog mixer; mute as default */
4195 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4196 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4197 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4198 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4199 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4200 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4201 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4202 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4203 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4204 /* Analog Mix output amp */
4205 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4206 /* SPDIF output selector */
4207 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4208 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4209 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4210 { } /* end */
4211};
4212
cb53c626
TI
4213#ifdef CONFIG_SND_HDA_POWER_SAVE
4214static struct hda_amp_list ad1882_loopbacks[] = {
4215 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4216 { 0x20, HDA_INPUT, 1 }, /* Mic */
4217 { 0x20, HDA_INPUT, 4 }, /* Line */
4218 { 0x20, HDA_INPUT, 6 }, /* CD */
4219 { } /* end */
4220};
4221#endif
4222
0ac8551e
TI
4223/* models */
4224enum {
4225 AD1882_3STACK,
4226 AD1882_6STACK,
4227 AD1882_MODELS
4228};
4229
4230static const char *ad1882_models[AD1986A_MODELS] = {
4231 [AD1882_3STACK] = "3stack",
4232 [AD1882_6STACK] = "6stack",
4233};
4234
4235
4236static int patch_ad1882(struct hda_codec *codec)
4237{
4238 struct ad198x_spec *spec;
4239 int board_config;
4240
4241 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4242 if (spec == NULL)
4243 return -ENOMEM;
4244
0ac8551e
TI
4245 codec->spec = spec;
4246
4247 spec->multiout.max_channels = 6;
4248 spec->multiout.num_dacs = 3;
4249 spec->multiout.dac_nids = ad1882_dac_nids;
4250 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4251 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4252 spec->adc_nids = ad1882_adc_nids;
4253 spec->capsrc_nids = ad1882_capsrc_nids;
c247ed6f 4254 if (codec->vendor_id == 0x11d41882)
9e44c6e4
TI
4255 spec->input_mux = &ad1882_capture_source;
4256 else
4257 spec->input_mux = &ad1882a_capture_source;
4258 spec->num_mixers = 2;
0ac8551e 4259 spec->mixers[0] = ad1882_base_mixers;
c247ed6f 4260 if (codec->vendor_id == 0x11d41882)
9e44c6e4
TI
4261 spec->mixers[1] = ad1882_loopback_mixers;
4262 else
4263 spec->mixers[1] = ad1882a_loopback_mixers;
0ac8551e
TI
4264 spec->num_init_verbs = 1;
4265 spec->init_verbs[0] = ad1882_init_verbs;
4266 spec->spdif_route = 0;
cb53c626
TI
4267#ifdef CONFIG_SND_HDA_POWER_SAVE
4268 spec->loopback.amplist = ad1882_loopbacks;
4269#endif
2134ea4f 4270 spec->vmaster_nid = 0x04;
0ac8551e
TI
4271
4272 codec->patch_ops = ad198x_patch_ops;
4273
4274 /* override some parameters */
4275 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4276 ad1882_models, NULL);
4277 switch (board_config) {
4278 default:
4279 case AD1882_3STACK:
9e44c6e4
TI
4280 spec->num_mixers = 3;
4281 spec->mixers[2] = ad1882_3stack_mixers;
0ac8551e
TI
4282 spec->channel_mode = ad1882_modes;
4283 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4284 spec->need_dac_fix = 1;
4285 spec->multiout.max_channels = 2;
4286 spec->multiout.num_dacs = 1;
4287 break;
4288 case AD1882_6STACK:
9e44c6e4
TI
4289 spec->num_mixers = 3;
4290 spec->mixers[2] = ad1882_6stack_mixers;
0ac8551e
TI
4291 break;
4292 }
4293 return 0;
4294}
4295
4296
1da177e4
LT
4297/*
4298 * patch entries
4299 */
1289e9e8 4300static struct hda_codec_preset snd_hda_preset_analog[] = {
c5059259 4301 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
0ac8551e 4302 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
c5059259 4303 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
2bac647c 4304 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
c5059259
TI
4305 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4306 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4a3fdf3d
TI
4307 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4308 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
2bac647c 4309 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
1da177e4 4310 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
fd66e0d0 4311 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
71b2ccc3 4312 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
9e44c6e4 4313 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
3adb8abc
TI
4314 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4315 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
1da177e4
LT
4316 {} /* terminator */
4317};
1289e9e8
TI
4318
4319MODULE_ALIAS("snd-hda-codec-id:11d4*");
4320
4321MODULE_LICENSE("GPL");
4322MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4323
4324static struct hda_codec_preset_list analog_list = {
4325 .preset = snd_hda_preset_analog,
4326 .owner = THIS_MODULE,
4327};
4328
4329static int __init patch_analog_init(void)
4330{
4331 return snd_hda_add_codec_preset(&analog_list);
4332}
4333
4334static void __exit patch_analog_exit(void)
4335{
4336 snd_hda_delete_codec_preset(&analog_list);
4337}
4338
4339module_init(patch_analog_init)
4340module_exit(patch_analog_exit)
This page took 0.741979 seconds and 5 git commands to generate.