2 * HD audio interface patch for AD1981HD, AD1983, AD1986A, AD1988
4 * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This driver is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
31 struct snd_kcontrol_new
*mixers
[5];
34 const struct hda_verb
*init_verbs
[5]; /* initialization verbs
35 * don't forget NULL termination!
37 unsigned int num_init_verbs
;
40 struct hda_multi_out multiout
; /* playback set-up
41 * max_channels, dacs must be set
42 * dig_out_nid and hp_nid are optional
44 unsigned int cur_eapd
;
47 unsigned int num_adc_nids
;
49 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
52 const struct hda_input_mux
*input_mux
;
53 hda_nid_t
*capsrc_nids
;
54 unsigned int cur_mux
[3];
57 const struct hda_channel_mode
*channel_mode
;
61 struct hda_pcm pcm_rec
[2]; /* used in alc_build_pcms() */
63 struct semaphore amp_mutex
; /* PCM volume/mute control mutex */
64 unsigned int spdif_route
;
66 /* dynamic controls, init_verbs and input_mux */
67 struct auto_pin_cfg autocfg
;
68 unsigned int num_kctl_alloc
, num_kctl_used
;
69 struct snd_kcontrol_new
*kctl_alloc
;
70 struct hda_input_mux private_imux
;
71 hda_nid_t private_dac_nids
[4];
75 * input MUX handling (common part)
77 static int ad198x_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
79 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
80 struct ad198x_spec
*spec
= codec
->spec
;
82 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
85 static int ad198x_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
87 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
88 struct ad198x_spec
*spec
= codec
->spec
;
89 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
91 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
95 static int ad198x_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
97 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
98 struct ad198x_spec
*spec
= codec
->spec
;
99 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
101 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
102 spec
->capsrc_nids
[adc_idx
],
103 &spec
->cur_mux
[adc_idx
]);
107 * initialization (common callbacks)
109 static int ad198x_init(struct hda_codec
*codec
)
111 struct ad198x_spec
*spec
= codec
->spec
;
114 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
115 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
119 static int ad198x_build_controls(struct hda_codec
*codec
)
121 struct ad198x_spec
*spec
= codec
->spec
;
125 for (i
= 0; i
< spec
->num_mixers
; i
++) {
126 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
130 if (spec
->multiout
.dig_out_nid
) {
131 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
135 if (spec
->dig_in_nid
) {
136 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
144 * Analog playback callbacks
146 static int ad198x_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
147 struct hda_codec
*codec
,
148 struct snd_pcm_substream
*substream
)
150 struct ad198x_spec
*spec
= codec
->spec
;
151 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
154 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
155 struct hda_codec
*codec
,
156 unsigned int stream_tag
,
158 struct snd_pcm_substream
*substream
)
160 struct ad198x_spec
*spec
= codec
->spec
;
161 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
165 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
166 struct hda_codec
*codec
,
167 struct snd_pcm_substream
*substream
)
169 struct ad198x_spec
*spec
= codec
->spec
;
170 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
176 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
177 struct hda_codec
*codec
,
178 struct snd_pcm_substream
*substream
)
180 struct ad198x_spec
*spec
= codec
->spec
;
181 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
184 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
185 struct hda_codec
*codec
,
186 struct snd_pcm_substream
*substream
)
188 struct ad198x_spec
*spec
= codec
->spec
;
189 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
195 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
196 struct hda_codec
*codec
,
197 unsigned int stream_tag
,
199 struct snd_pcm_substream
*substream
)
201 struct ad198x_spec
*spec
= codec
->spec
;
202 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
203 stream_tag
, 0, format
);
207 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
208 struct hda_codec
*codec
,
209 struct snd_pcm_substream
*substream
)
211 struct ad198x_spec
*spec
= codec
->spec
;
212 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
220 static struct hda_pcm_stream ad198x_pcm_analog_playback
= {
223 .channels_max
= 6, /* changed later */
224 .nid
= 0, /* fill later */
226 .open
= ad198x_playback_pcm_open
,
227 .prepare
= ad198x_playback_pcm_prepare
,
228 .cleanup
= ad198x_playback_pcm_cleanup
232 static struct hda_pcm_stream ad198x_pcm_analog_capture
= {
236 .nid
= 0, /* fill later */
238 .prepare
= ad198x_capture_pcm_prepare
,
239 .cleanup
= ad198x_capture_pcm_cleanup
243 static struct hda_pcm_stream ad198x_pcm_digital_playback
= {
247 .nid
= 0, /* fill later */
249 .open
= ad198x_dig_playback_pcm_open
,
250 .close
= ad198x_dig_playback_pcm_close
254 static struct hda_pcm_stream ad198x_pcm_digital_capture
= {
258 /* NID is set in alc_build_pcms */
261 static int ad198x_build_pcms(struct hda_codec
*codec
)
263 struct ad198x_spec
*spec
= codec
->spec
;
264 struct hda_pcm
*info
= spec
->pcm_rec
;
267 codec
->pcm_info
= info
;
269 info
->name
= "AD198x Analog";
270 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_analog_playback
;
271 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->multiout
.max_channels
;
272 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
273 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_analog_capture
;
274 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_adc_nids
;
275 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
277 if (spec
->multiout
.dig_out_nid
) {
280 info
->name
= "AD198x Digital";
281 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_digital_playback
;
282 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
283 if (spec
->dig_in_nid
) {
284 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_digital_capture
;
285 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
292 static void ad198x_free(struct hda_codec
*codec
)
294 struct ad198x_spec
*spec
= codec
->spec
;
297 if (spec
->kctl_alloc
) {
298 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
299 kfree(spec
->kctl_alloc
[i
].name
);
300 kfree(spec
->kctl_alloc
);
306 static int ad198x_resume(struct hda_codec
*codec
)
308 struct ad198x_spec
*spec
= codec
->spec
;
312 for (i
= 0; i
< spec
->num_mixers
; i
++)
313 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
314 if (spec
->multiout
.dig_out_nid
)
315 snd_hda_resume_spdif_out(codec
);
316 if (spec
->dig_in_nid
)
317 snd_hda_resume_spdif_in(codec
);
322 static struct hda_codec_ops ad198x_patch_ops
= {
323 .build_controls
= ad198x_build_controls
,
324 .build_pcms
= ad198x_build_pcms
,
328 .resume
= ad198x_resume
,
337 #define AD1986A_SPDIF_OUT 0x02
338 #define AD1986A_FRONT_DAC 0x03
339 #define AD1986A_SURR_DAC 0x04
340 #define AD1986A_CLFE_DAC 0x05
341 #define AD1986A_ADC 0x06
343 static hda_nid_t ad1986a_dac_nids
[3] = {
344 AD1986A_FRONT_DAC
, AD1986A_SURR_DAC
, AD1986A_CLFE_DAC
346 static hda_nid_t ad1986a_adc_nids
[1] = { AD1986A_ADC
};
348 static struct hda_input_mux ad1986a_capture_source
= {
364 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
367 #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
369 static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
371 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
372 struct ad198x_spec
*ad
= codec
->spec
;
374 down(&ad
->amp_mutex
);
375 snd_hda_mixer_amp_volume_get(kcontrol
, ucontrol
);
380 static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
382 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
383 struct ad198x_spec
*ad
= codec
->spec
;
386 down(&ad
->amp_mutex
);
387 for (i
= 0; i
< ARRAY_SIZE(ad1986a_dac_nids
); i
++) {
388 kcontrol
->private_value
= HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids
[i
], 3, 0, HDA_OUTPUT
);
389 change
|= snd_hda_mixer_amp_volume_put(kcontrol
, ucontrol
);
391 kcontrol
->private_value
= HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
);
396 #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
398 static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
400 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
401 struct ad198x_spec
*ad
= codec
->spec
;
403 down(&ad
->amp_mutex
);
404 snd_hda_mixer_amp_switch_get(kcontrol
, ucontrol
);
409 static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
411 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
412 struct ad198x_spec
*ad
= codec
->spec
;
415 down(&ad
->amp_mutex
);
416 for (i
= 0; i
< ARRAY_SIZE(ad1986a_dac_nids
); i
++) {
417 kcontrol
->private_value
= HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids
[i
], 3, 0, HDA_OUTPUT
);
418 change
|= snd_hda_mixer_amp_switch_put(kcontrol
, ucontrol
);
420 kcontrol
->private_value
= HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
);
428 static struct snd_kcontrol_new ad1986a_mixers
[] = {
430 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
431 .name
= "PCM Playback Volume",
432 .info
= ad1986a_pcm_amp_vol_info
,
433 .get
= ad1986a_pcm_amp_vol_get
,
434 .put
= ad1986a_pcm_amp_vol_put
,
435 .private_value
= HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
)
438 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
439 .name
= "PCM Playback Switch",
440 .info
= ad1986a_pcm_amp_sw_info
,
441 .get
= ad1986a_pcm_amp_sw_get
,
442 .put
= ad1986a_pcm_amp_sw_put
,
443 .private_value
= HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
)
445 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
446 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
447 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
448 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
449 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT
),
450 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT
),
451 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT
),
452 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT
),
453 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT
),
454 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT
),
455 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
456 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
457 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
458 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
459 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
460 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
461 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
462 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
463 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT
),
464 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT
),
465 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT
),
466 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT
),
467 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
468 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
470 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
471 .name
= "Capture Source",
472 .info
= ad198x_mux_enum_info
,
473 .get
= ad198x_mux_enum_get
,
474 .put
= ad198x_mux_enum_put
,
476 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT
),
481 * initialization verbs
483 static struct hda_verb ad1986a_init_verbs
[] = {
484 /* Front, Surround, CLFE DAC; mute as default */
485 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
486 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
487 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
489 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
490 /* HP, Line-Out, Surround, CLFE selectors */
491 {0x0a, AC_VERB_SET_CONNECT_SEL
, 0x0},
492 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0},
493 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
494 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
496 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x0},
497 /* Mic selector: Mic 1/2 pin */
498 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
499 /* Line-in selector: Line-in */
500 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x0},
502 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x0},
503 /* Record selector: mic */
504 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x0},
505 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
506 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
507 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
508 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
509 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
510 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
512 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x0},
513 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
514 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
515 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
516 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
517 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
518 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
520 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
521 /* Front, Surround, CLFE Pins */
522 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
523 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
524 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
526 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
528 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
529 /* Line, Aux, CD, Beep-In Pin */
530 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
531 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
532 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
533 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
534 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
539 static int patch_ad1986a(struct hda_codec
*codec
)
541 struct ad198x_spec
*spec
;
543 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
547 init_MUTEX(&spec
->amp_mutex
);
550 spec
->multiout
.max_channels
= 6;
551 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1986a_dac_nids
);
552 spec
->multiout
.dac_nids
= ad1986a_dac_nids
;
553 spec
->multiout
.dig_out_nid
= AD1986A_SPDIF_OUT
;
554 spec
->num_adc_nids
= 1;
555 spec
->adc_nids
= ad1986a_adc_nids
;
556 spec
->capsrc_nids
= ad1986a_adc_nids
;
557 spec
->input_mux
= &ad1986a_capture_source
;
558 spec
->num_mixers
= 1;
559 spec
->mixers
[0] = ad1986a_mixers
;
560 spec
->num_init_verbs
= 1;
561 spec
->init_verbs
[0] = ad1986a_init_verbs
;
563 codec
->patch_ops
= ad198x_patch_ops
;
572 #define AD1983_SPDIF_OUT 0x02
573 #define AD1983_DAC 0x03
574 #define AD1983_ADC 0x04
576 static hda_nid_t ad1983_dac_nids
[1] = { AD1983_DAC
};
577 static hda_nid_t ad1983_adc_nids
[1] = { AD1983_ADC
};
579 static struct hda_input_mux ad1983_capture_source
= {
590 * SPDIF playback route
592 static int ad1983_spdif_route_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
594 static char *texts
[] = { "PCM", "ADC" };
596 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
598 uinfo
->value
.enumerated
.items
= 2;
599 if (uinfo
->value
.enumerated
.item
> 1)
600 uinfo
->value
.enumerated
.item
= 1;
601 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
605 static int ad1983_spdif_route_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
607 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
608 struct ad198x_spec
*spec
= codec
->spec
;
610 ucontrol
->value
.enumerated
.item
[0] = spec
->spdif_route
;
614 static int ad1983_spdif_route_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
616 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
617 struct ad198x_spec
*spec
= codec
->spec
;
619 if (spec
->spdif_route
!= ucontrol
->value
.enumerated
.item
[0]) {
620 spec
->spdif_route
= ucontrol
->value
.enumerated
.item
[0];
621 snd_hda_codec_write(codec
, spec
->multiout
.dig_out_nid
, 0,
622 AC_VERB_SET_CONNECT_SEL
, spec
->spdif_route
);
628 static struct snd_kcontrol_new ad1983_mixers
[] = {
629 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
630 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
631 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
632 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
633 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
634 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
635 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
636 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
637 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
638 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
639 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
640 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
641 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT
),
642 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT
),
643 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT
),
644 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
645 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
647 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
648 .name
= "Capture Source",
649 .info
= ad198x_mux_enum_info
,
650 .get
= ad198x_mux_enum_get
,
651 .put
= ad198x_mux_enum_put
,
654 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
655 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Route",
656 .info
= ad1983_spdif_route_info
,
657 .get
= ad1983_spdif_route_get
,
658 .put
= ad1983_spdif_route_put
,
663 static struct hda_verb ad1983_init_verbs
[] = {
664 /* Front, HP, Mono; mute as default */
665 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
666 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
667 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
668 /* Beep, PCM, Mic, Line-In: mute */
669 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
670 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
671 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
672 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
673 /* Front, HP selectors; from Mix */
674 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
675 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
676 /* Mono selector; from Mix */
677 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
678 /* Mic selector; Mic */
679 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
680 /* Line-in selector: Line-in */
681 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
683 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
684 /* Record selector: mic */
685 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
686 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
687 /* SPDIF route: PCM */
688 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
690 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
692 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
694 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
696 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
698 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
703 static int patch_ad1983(struct hda_codec
*codec
)
705 struct ad198x_spec
*spec
;
707 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
711 init_MUTEX(&spec
->amp_mutex
);
714 spec
->multiout
.max_channels
= 2;
715 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1983_dac_nids
);
716 spec
->multiout
.dac_nids
= ad1983_dac_nids
;
717 spec
->multiout
.dig_out_nid
= AD1983_SPDIF_OUT
;
718 spec
->num_adc_nids
= 1;
719 spec
->adc_nids
= ad1983_adc_nids
;
720 spec
->capsrc_nids
= ad1983_adc_nids
;
721 spec
->input_mux
= &ad1983_capture_source
;
722 spec
->num_mixers
= 1;
723 spec
->mixers
[0] = ad1983_mixers
;
724 spec
->num_init_verbs
= 1;
725 spec
->init_verbs
[0] = ad1983_init_verbs
;
726 spec
->spdif_route
= 0;
728 codec
->patch_ops
= ad198x_patch_ops
;
738 #define AD1981_SPDIF_OUT 0x02
739 #define AD1981_DAC 0x03
740 #define AD1981_ADC 0x04
742 static hda_nid_t ad1981_dac_nids
[1] = { AD1981_DAC
};
743 static hda_nid_t ad1981_adc_nids
[1] = { AD1981_ADC
};
745 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
746 static struct hda_input_mux ad1981_capture_source
= {
749 { "Front Mic", 0x0 },
759 static struct snd_kcontrol_new ad1981_mixers
[] = {
760 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
761 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
762 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
763 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
764 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
765 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
766 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
767 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
768 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
769 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
770 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
771 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
772 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
773 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
774 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
775 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
776 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
777 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
778 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT
),
779 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT
),
780 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT
),
781 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT
),
782 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
783 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
785 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
786 .name
= "Capture Source",
787 .info
= ad198x_mux_enum_info
,
788 .get
= ad198x_mux_enum_get
,
789 .put
= ad198x_mux_enum_put
,
791 /* identical with AD1983 */
793 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
794 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Route",
795 .info
= ad1983_spdif_route_info
,
796 .get
= ad1983_spdif_route_get
,
797 .put
= ad1983_spdif_route_put
,
802 static struct hda_verb ad1981_init_verbs
[] = {
803 /* Front, HP, Mono; mute as default */
804 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
805 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
806 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
807 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
808 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
809 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
810 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
811 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
812 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
813 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
814 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
815 /* Front, HP selectors; from Mix */
816 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
817 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
818 /* Mono selector; from Mix */
819 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
820 /* Mic Mixer; select Front Mic */
821 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
822 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
824 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
825 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
826 /* Record selector: Front mic */
827 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
828 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
829 /* SPDIF route: PCM */
830 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
832 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
834 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
836 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
837 /* Front & Rear Mic Pins */
838 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
839 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
841 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
843 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00},
844 /* Line-Out as Input: disabled */
845 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
849 static int patch_ad1981(struct hda_codec
*codec
)
851 struct ad198x_spec
*spec
;
853 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
857 init_MUTEX(&spec
->amp_mutex
);
860 spec
->multiout
.max_channels
= 2;
861 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1981_dac_nids
);
862 spec
->multiout
.dac_nids
= ad1981_dac_nids
;
863 spec
->multiout
.dig_out_nid
= AD1981_SPDIF_OUT
;
864 spec
->num_adc_nids
= 1;
865 spec
->adc_nids
= ad1981_adc_nids
;
866 spec
->capsrc_nids
= ad1981_adc_nids
;
867 spec
->input_mux
= &ad1981_capture_source
;
868 spec
->num_mixers
= 1;
869 spec
->mixers
[0] = ad1981_mixers
;
870 spec
->num_init_verbs
= 1;
871 spec
->init_verbs
[0] = ad1981_init_verbs
;
872 spec
->spdif_route
= 0;
874 codec
->patch_ops
= ad198x_patch_ops
;
883 * Output pins and routes
885 * Pin Mix Sel DAC (*)
886 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
887 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
888 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
889 * port-D 0x12 (mute/hp) <- 0x29 <- 04
890 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
891 * port-F 0x16 (mute) <- 0x2a <- 06
892 * port-G 0x24 (mute) <- 0x27 <- 05
893 * port-H 0x25 (mute) <- 0x28 <- 0a
894 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
896 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
897 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
899 * Input pins and routes
901 * pin boost mix input # / adc input #
902 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
903 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
904 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
905 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
906 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
907 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
908 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
909 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
913 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
914 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
916 * Inputs of Analog Mix (0x20)
917 * 0:Port-B (front mic)
918 * 1:Port-C/G/H (line-in)
920 * 3:Port-D (line-in/2)
921 * 4:Port-E/G/H (mic-in)
928 * 1:Port-B (front mic-in)
935 * 8:Port-D (line-in/2)
938 * Proposed pin assignments by the datasheet
941 * Port-A front headphone
951 * Port-A front headphone
953 * C rear line-in/surround
961 * D internal speaker (with EAPD)
978 /* reivision id to check workarounds */
979 #define AD1988A_REV2 0x100200
986 static hda_nid_t ad1988_6stack_dac_nids
[4] = {
987 0x04, 0x06, 0x05, 0x0a
990 static hda_nid_t ad1988_3stack_dac_nids
[3] = {
994 /* for AD1988A revision-2, DAC2-4 are swapped */
995 static hda_nid_t ad1988_6stack_dac_nids_rev2
[4] = {
996 0x04, 0x05, 0x0a, 0x06
999 static hda_nid_t ad1988_3stack_dac_nids_rev2
[3] = {
1003 static hda_nid_t ad1988_adc_nids
[3] = {
1007 static hda_nid_t ad1988_capsrc_nids
[3] = {
1011 #define AD1988_SPDIF_OUT 0x02
1012 #define AD1988_SPDIF_IN 0x07
1014 static struct hda_input_mux ad1988_6stack_capture_source
= {
1017 { "Front Mic", 0x0 },
1025 static struct hda_input_mux ad1988_laptop_capture_source
= {
1028 { "Mic/Line", 0x0 },
1036 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
1037 struct snd_ctl_elem_info
*uinfo
)
1039 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1040 struct ad198x_spec
*spec
= codec
->spec
;
1041 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
1042 spec
->num_channel_mode
);
1045 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
1046 struct snd_ctl_elem_value
*ucontrol
)
1048 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1049 struct ad198x_spec
*spec
= codec
->spec
;
1050 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
1051 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
1054 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
1055 struct snd_ctl_elem_value
*ucontrol
)
1057 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1058 struct ad198x_spec
*spec
= codec
->spec
;
1059 return snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
1060 spec
->num_channel_mode
, &spec
->multiout
.max_channels
);
1066 static int ad1988_eapd_info(struct snd_kcontrol
*kcontrol
,
1067 struct snd_ctl_elem_info
*uinfo
)
1069 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
1071 uinfo
->value
.integer
.min
= 0;
1072 uinfo
->value
.integer
.max
= 1;
1076 static int ad1988_eapd_get(struct snd_kcontrol
*kcontrol
,
1077 struct snd_ctl_elem_value
*ucontrol
)
1079 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1080 struct ad198x_spec
*spec
= codec
->spec
;
1081 ucontrol
->value
.enumerated
.item
[0] = ! spec
->cur_eapd
;
1085 static int ad1988_eapd_put(struct snd_kcontrol
*kcontrol
,
1086 struct snd_ctl_elem_value
*ucontrol
)
1088 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1089 struct ad198x_spec
*spec
= codec
->spec
;
1091 eapd
= ! ucontrol
->value
.enumerated
.item
[0];
1092 if (eapd
== spec
->cur_eapd
&& ! codec
->in_resume
)
1094 spec
->cur_eapd
= eapd
;
1095 snd_hda_codec_write(codec
, 0x12 /* port-D */,
1096 0, AC_VERB_SET_EAPD_BTLENABLE
,
1097 eapd
? 0x02 : 0x00);
1102 static struct snd_kcontrol_new ad1988_6stack_mixers1
[] = {
1103 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
1104 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1105 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
1106 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
1107 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
1110 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2
[] = {
1111 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
1112 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1113 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
1114 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT
),
1115 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1118 static struct snd_kcontrol_new ad1988_6stack_mixers2
[] = {
1119 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
1120 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT
),
1121 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT
),
1122 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT
),
1123 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT
),
1124 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
1125 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
1127 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
1128 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
1129 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
1130 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
1131 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
1132 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
1133 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
1134 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
1136 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT
),
1137 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT
),
1139 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
1140 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
1142 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
1143 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT
),
1149 static struct snd_kcontrol_new ad1988_3stack_mixers1
[] = {
1150 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
1151 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
1152 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
1153 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
1156 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2
[] = {
1157 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
1158 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
1159 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT
),
1160 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT
),
1163 static struct snd_kcontrol_new ad1988_3stack_mixers2
[] = {
1164 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
1165 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT
),
1166 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT
),
1167 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT
),
1168 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
1169 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
1171 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
1172 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
1173 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
1174 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
1175 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
1176 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
1177 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
1178 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
1180 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT
),
1181 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT
),
1183 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
1184 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
1186 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
1187 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT
),
1189 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1190 .name
= "Channel Mode",
1191 .info
= ad198x_ch_mode_info
,
1192 .get
= ad198x_ch_mode_get
,
1193 .put
= ad198x_ch_mode_put
,
1200 static struct snd_kcontrol_new ad1988_laptop_mixers
[] = {
1201 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
1202 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT
),
1203 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
1205 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
1206 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
1207 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
1208 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
1209 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
1210 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
1212 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT
),
1213 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT
),
1215 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
1216 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
1218 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
1221 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1222 .name
= "External Amplifier",
1223 .info
= ad1988_eapd_info
,
1224 .get
= ad1988_eapd_get
,
1225 .put
= ad1988_eapd_put
,
1232 static struct snd_kcontrol_new ad1988_capture_mixers
[] = {
1233 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
1234 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
1235 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
1236 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
1237 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT
),
1238 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT
),
1240 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1241 /* The multiple "Capture Source" controls confuse alsamixer
1242 * So call somewhat different..
1243 * FIXME: the controls appear in the "playback" view!
1245 /* .name = "Capture Source", */
1246 .name
= "Input Source",
1248 .info
= ad198x_mux_enum_info
,
1249 .get
= ad198x_mux_enum_get
,
1250 .put
= ad198x_mux_enum_put
,
1255 static int ad1988_spdif_playback_source_info(struct snd_kcontrol
*kcontrol
,
1256 struct snd_ctl_elem_info
*uinfo
)
1258 static char *texts
[] = {
1259 "PCM", "ADC1", "ADC2", "ADC3"
1261 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1263 uinfo
->value
.enumerated
.items
= 4;
1264 if (uinfo
->value
.enumerated
.item
>= 4)
1265 uinfo
->value
.enumerated
.item
= 3;
1266 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1270 static int ad1988_spdif_playback_source_get(struct snd_kcontrol
*kcontrol
,
1271 struct snd_ctl_elem_value
*ucontrol
)
1273 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1276 sel
= snd_hda_codec_read(codec
, 0x02, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1278 sel
= snd_hda_codec_read(codec
, 0x0b, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1284 ucontrol
->value
.enumerated
.item
[0] = sel
;
1288 static int ad1988_spdif_playback_source_put(struct snd_kcontrol
*kcontrol
,
1289 struct snd_ctl_elem_value
*ucontrol
)
1291 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1295 sel
= snd_hda_codec_read(codec
, 0x02, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1296 if (! ucontrol
->value
.enumerated
.item
[0]) {
1299 snd_hda_codec_write(codec
, 0x02, 0, AC_VERB_SET_CONNECT_SEL
, 0);
1303 snd_hda_codec_write(codec
, 0x02, 0, AC_VERB_SET_CONNECT_SEL
, 1);
1304 sel
= snd_hda_codec_read(codec
, 0x0b, 0, AC_VERB_GET_CONNECT_SEL
, 0) + 1;
1305 change
|= sel
== ucontrol
->value
.enumerated
.item
[0];
1307 snd_hda_codec_write(codec
, 0x02, 0, AC_VERB_SET_CONNECT_SEL
,
1308 ucontrol
->value
.enumerated
.item
[0] - 1);
1313 static struct snd_kcontrol_new ad1988_spdif_out_mixers
[] = {
1314 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
1316 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1317 .name
= "IEC958 Playback Source",
1318 .info
= ad1988_spdif_playback_source_info
,
1319 .get
= ad1988_spdif_playback_source_get
,
1320 .put
= ad1988_spdif_playback_source_put
,
1325 static struct snd_kcontrol_new ad1988_spdif_in_mixers
[] = {
1326 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT
),
1332 * initialization verbs
1336 * for 6-stack (+dig)
1338 static struct hda_verb ad1988_6stack_init_verbs
[] = {
1339 /* Front, Surround, CLFE, side DAC; unmute as default */
1340 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1341 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1342 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1343 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1344 /* Port-A front headphon path */
1345 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
1346 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1347 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1348 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1349 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1350 /* Port-D line-out path */
1351 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1352 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1353 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1354 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1355 /* Port-F surround path */
1356 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1357 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1358 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1359 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1360 /* Port-G CLFE path */
1361 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1362 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1363 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1364 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1365 /* Port-H side path */
1366 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1367 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1368 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1369 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1371 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
1372 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1373 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1374 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1375 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
1376 /* Port-B front mic-in path */
1377 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1378 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1379 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1380 /* Port-C line-in path */
1381 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1382 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1383 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1384 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
1385 /* Port-E mic-in path */
1386 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1387 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1388 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1389 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
1394 static struct hda_verb ad1988_capture_init_verbs
[] = {
1395 /* mute analog mix */
1396 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1397 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1398 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1399 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1400 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1401 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
1402 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
1403 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
1404 /* select ADCs - front-mic */
1405 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
1406 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1407 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
1409 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1410 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1411 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1416 static struct hda_verb ad1988_spdif_init_verbs
[] = {
1418 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
1419 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* ADC1 */
1420 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1421 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1423 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
1424 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
1430 * verbs for 3stack (+dig)
1432 static struct hda_verb ad1988_3stack_ch2_init
[] = {
1433 /* set port-C to line-in */
1434 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1435 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1436 /* set port-E to mic-in */
1437 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1438 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1442 static struct hda_verb ad1988_3stack_ch6_init
[] = {
1443 /* set port-C to surround out */
1444 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1445 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1446 /* set port-E to CLFE out */
1447 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1448 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1452 static struct hda_channel_mode ad1988_3stack_modes
[2] = {
1453 { 2, ad1988_3stack_ch2_init
},
1454 { 6, ad1988_3stack_ch6_init
},
1457 static struct hda_verb ad1988_3stack_init_verbs
[] = {
1458 /* Front, Surround, CLFE, side DAC; unmute as default */
1459 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1460 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1461 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1462 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1463 /* Port-A front headphon path */
1464 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
1465 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1466 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1467 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1468 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1469 /* Port-D line-out path */
1470 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1471 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1472 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1473 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1475 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
1476 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1477 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1478 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1479 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
1480 /* Port-B front mic-in path */
1481 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1482 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1483 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1484 /* Port-C line-in/surround path - 6ch mode as default */
1485 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1486 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1487 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1488 {0x31, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* output sel: DAC 0x05 */
1489 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
1490 /* Port-E mic-in/CLFE path - 6ch mode as default */
1491 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1492 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1493 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1494 {0x32, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* output sel: DAC 0x0a */
1495 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
1496 /* mute analog mix */
1497 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1498 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1499 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1500 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1501 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1502 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
1503 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
1504 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
1505 /* select ADCs - front-mic */
1506 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
1507 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1508 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
1510 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1511 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1512 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1517 * verbs for laptop mode (+dig)
1519 static struct hda_verb ad1988_laptop_hp_on
[] = {
1520 /* unmute port-A and mute port-D */
1521 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1522 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1525 static struct hda_verb ad1988_laptop_hp_off
[] = {
1526 /* mute port-A and unmute port-D */
1527 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1528 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1532 #define AD1988_HP_EVENT 0x01
1534 static struct hda_verb ad1988_laptop_init_verbs
[] = {
1535 /* Front, Surround, CLFE, side DAC; unmute as default */
1536 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1537 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1538 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1539 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1540 /* Port-A front headphon path */
1541 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
1542 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1543 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1544 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1545 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1546 /* unsolicited event for pin-sense */
1547 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1988_HP_EVENT
},
1548 /* Port-D line-out path + EAPD */
1549 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1550 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1551 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1552 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1553 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x00}, /* EAPD-off */
1555 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
1556 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1557 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1558 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1559 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
1560 /* Port-B mic-in path */
1561 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1562 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1563 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1564 /* Port-C docking station - try to output */
1565 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1566 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1567 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1568 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
1569 /* mute analog mix */
1570 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1571 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1572 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1573 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1574 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1575 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
1576 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
1577 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
1578 /* select ADCs - mic */
1579 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
1580 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1581 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
1583 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1584 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1585 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1589 static void ad1988_laptop_unsol_event(struct hda_codec
*codec
, unsigned int res
)
1591 if ((res
>> 26) != AD1988_HP_EVENT
)
1593 if (snd_hda_codec_read(codec
, 0x11, 0, AC_VERB_GET_PIN_SENSE
, 0) & (1 << 31))
1594 snd_hda_sequence_write(codec
, ad1988_laptop_hp_on
);
1596 snd_hda_sequence_write(codec
, ad1988_laptop_hp_off
);
1601 * Automatic parse of I/O pins from the BIOS configuration
1604 #define NUM_CONTROL_ALLOC 32
1605 #define NUM_VERB_ALLOC 32
1612 static struct snd_kcontrol_new ad1988_control_templates
[] = {
1613 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
1614 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
1615 HDA_BIND_MUTE(NULL
, 0, 0, 0),
1618 /* add dynamic controls */
1619 static int add_control(struct ad198x_spec
*spec
, int type
, const char *name
,
1622 struct snd_kcontrol_new
*knew
;
1624 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
1625 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
1627 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
); /* array + terminator */
1630 if (spec
->kctl_alloc
) {
1631 memcpy(knew
, spec
->kctl_alloc
, sizeof(*knew
) * spec
->num_kctl_alloc
);
1632 kfree(spec
->kctl_alloc
);
1634 spec
->kctl_alloc
= knew
;
1635 spec
->num_kctl_alloc
= num
;
1638 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
1639 *knew
= ad1988_control_templates
[type
];
1640 knew
->name
= kstrdup(name
, GFP_KERNEL
);
1643 knew
->private_value
= val
;
1644 spec
->num_kctl_used
++;
1648 #define AD1988_PIN_CD_NID 0x18
1649 #define AD1988_PIN_BEEP_NID 0x10
1651 static hda_nid_t ad1988_mixer_nids
[8] = {
1652 /* A B C D E F G H */
1653 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
1656 static inline hda_nid_t
ad1988_idx_to_dac(struct hda_codec
*codec
, int idx
)
1658 static hda_nid_t idx_to_dac
[8] = {
1659 /* A B C D E F G H */
1660 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
1662 static hda_nid_t idx_to_dac_rev2
[8] = {
1663 /* A B C D E F G H */
1664 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
1666 if (codec
->revision_id
== AD1988A_REV2
)
1667 return idx_to_dac_rev2
[idx
];
1669 return idx_to_dac
[idx
];
1672 static hda_nid_t ad1988_boost_nids
[8] = {
1673 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
1676 static int ad1988_pin_idx(hda_nid_t nid
)
1678 static hda_nid_t ad1988_io_pins
[8] = {
1679 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
1682 for (i
= 0; i
< ARRAY_SIZE(ad1988_io_pins
); i
++)
1683 if (ad1988_io_pins
[i
] == nid
)
1685 return 0; /* should be -1 */
1688 static int ad1988_pin_to_loopback_idx(hda_nid_t nid
)
1690 static int loopback_idx
[8] = {
1691 2, 0, 1, 3, 4, 5, 1, 4
1694 case AD1988_PIN_CD_NID
:
1697 return loopback_idx
[ad1988_pin_idx(nid
)];
1701 static int ad1988_pin_to_adc_idx(hda_nid_t nid
)
1703 static int adc_idx
[8] = {
1704 0, 1, 2, 8, 4, 3, 6, 7
1707 case AD1988_PIN_CD_NID
:
1710 return adc_idx
[ad1988_pin_idx(nid
)];
1714 /* fill in the dac_nids table from the parsed pin configuration */
1715 static int ad1988_auto_fill_dac_nids(struct hda_codec
*codec
,
1716 const struct auto_pin_cfg
*cfg
)
1718 struct ad198x_spec
*spec
= codec
->spec
;
1721 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1723 /* check the pins hardwired to audio widget */
1724 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1725 idx
= ad1988_pin_idx(cfg
->line_out_pins
[i
]);
1726 spec
->multiout
.dac_nids
[i
] = ad1988_idx_to_dac(codec
, idx
);
1728 spec
->multiout
.num_dacs
= cfg
->line_outs
;
1732 /* add playback controls from the parsed DAC table */
1733 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec
*spec
,
1734 const struct auto_pin_cfg
*cfg
)
1737 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
1741 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1742 hda_nid_t dac
= spec
->multiout
.dac_nids
[i
];
1745 nid
= ad1988_mixer_nids
[ad1988_pin_idx(cfg
->line_out_pins
[i
])];
1748 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
1749 "Center Playback Volume",
1750 HDA_COMPOSE_AMP_VAL(dac
, 1, 0, HDA_OUTPUT
));
1753 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
1754 "LFE Playback Volume",
1755 HDA_COMPOSE_AMP_VAL(dac
, 2, 0, HDA_OUTPUT
));
1758 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
1759 "Center Playback Switch",
1760 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
));
1763 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
1764 "LFE Playback Switch",
1765 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
));
1769 sprintf(name
, "%s Playback Volume", chname
[i
]);
1770 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
1771 HDA_COMPOSE_AMP_VAL(dac
, 3, 0, HDA_OUTPUT
));
1774 sprintf(name
, "%s Playback Switch", chname
[i
]);
1775 err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
1776 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
));
1784 /* add playback controls for speaker and HP outputs */
1785 static int ad1988_auto_create_extra_out(struct hda_codec
*codec
, hda_nid_t pin
,
1788 struct ad198x_spec
*spec
= codec
->spec
;
1796 idx
= ad1988_pin_idx(pin
);
1797 nid
= ad1988_idx_to_dac(codec
, idx
);
1798 if (! spec
->multiout
.dac_nids
[0]) {
1799 /* use this as the primary output */
1800 spec
->multiout
.dac_nids
[0] = nid
;
1801 if (! spec
->multiout
.num_dacs
)
1802 spec
->multiout
.num_dacs
= 1;
1804 /* specify the DAC as the extra output */
1805 spec
->multiout
.hp_nid
= nid
;
1806 /* control HP volume/switch on the output mixer amp */
1807 sprintf(name
, "%s Playback Volume", pfx
);
1808 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
1809 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
1811 nid
= ad1988_mixer_nids
[idx
];
1812 sprintf(name
, "%s Playback Switch", pfx
);
1813 if ((err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
1814 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
1819 /* create input playback/capture controls for the given pin */
1820 static int new_analog_input(struct ad198x_spec
*spec
, hda_nid_t pin
,
1821 const char *ctlname
, int boost
)
1826 sprintf(name
, "%s Playback Volume", ctlname
);
1827 idx
= ad1988_pin_to_loopback_idx(pin
);
1828 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
1829 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
1831 sprintf(name
, "%s Playback Switch", ctlname
);
1832 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
, name
,
1833 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
1837 idx
= ad1988_pin_idx(pin
);
1838 bnid
= ad1988_boost_nids
[idx
];
1840 sprintf(name
, "%s Boost", ctlname
);
1841 return add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
1842 HDA_COMPOSE_AMP_VAL(bnid
, 3, idx
, HDA_OUTPUT
));
1849 /* create playback/capture controls for input pins */
1850 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec
*spec
,
1851 const struct auto_pin_cfg
*cfg
)
1853 static char *labels
[AUTO_PIN_LAST
] = {
1854 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
1856 struct hda_input_mux
*imux
= &spec
->private_imux
;
1859 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1860 err
= new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1861 i
<= AUTO_PIN_FRONT_MIC
);
1864 imux
->items
[imux
->num_items
].label
= labels
[i
];
1865 imux
->items
[imux
->num_items
].index
= ad1988_pin_to_adc_idx(cfg
->input_pins
[i
]);
1868 imux
->items
[imux
->num_items
].label
= "Mix";
1869 imux
->items
[imux
->num_items
].index
= 9;
1872 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
1873 "Analog Mix Playback Volume",
1874 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
1876 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
,
1877 "Analog Mix Playback Switch",
1878 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
1884 static void ad1988_auto_set_output_and_unmute(struct hda_codec
*codec
,
1885 hda_nid_t nid
, int pin_type
,
1889 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
1890 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
1892 case 0x11: /* port-A - DAC 04 */
1893 snd_hda_codec_write(codec
, 0x37, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
1895 case 0x14: /* port-B - DAC 06 */
1896 snd_hda_codec_write(codec
, 0x30, 0, AC_VERB_SET_CONNECT_SEL
, 0x02);
1898 case 0x15: /* port-C - DAC 05 */
1899 snd_hda_codec_write(codec
, 0x31, 0, AC_VERB_SET_CONNECT_SEL
, 0x00);
1901 case 0x17: /* port-E - DAC 0a */
1902 snd_hda_codec_write(codec
, 0x32, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
1904 case 0x13: /* mono - DAC 04 */
1905 snd_hda_codec_write(codec
, 0x36, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
1910 static void ad1988_auto_init_multi_out(struct hda_codec
*codec
)
1912 struct ad198x_spec
*spec
= codec
->spec
;
1915 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
1916 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
1917 ad1988_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
1921 static void ad1988_auto_init_extra_out(struct hda_codec
*codec
)
1923 struct ad198x_spec
*spec
= codec
->spec
;
1926 pin
= spec
->autocfg
.speaker_pin
;
1927 if (pin
) /* connect to front */
1928 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
1929 pin
= spec
->autocfg
.hp_pin
;
1930 if (pin
) /* connect to front */
1931 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
1934 static void ad1988_auto_init_analog_input(struct hda_codec
*codec
)
1936 struct ad198x_spec
*spec
= codec
->spec
;
1939 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1940 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
1944 case 0x15: /* port-C */
1945 snd_hda_codec_write(codec
, 0x33, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
1947 case 0x17: /* port-E */
1948 snd_hda_codec_write(codec
, 0x34, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
1951 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
1952 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
1953 if (nid
!= AD1988_PIN_CD_NID
)
1954 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
1956 idx
= ad1988_pin_idx(nid
);
1957 if (ad1988_boost_nids
[idx
])
1958 snd_hda_codec_write(codec
, ad1988_boost_nids
[idx
], 0,
1959 AC_VERB_SET_AMP_GAIN_MUTE
,
1964 /* parse the BIOS configuration and set up the alc_spec */
1965 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
1966 static int ad1988_parse_auto_config(struct hda_codec
*codec
)
1968 struct ad198x_spec
*spec
= codec
->spec
;
1971 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
1973 if ((err
= ad1988_auto_fill_dac_nids(codec
, &spec
->autocfg
)) < 0)
1975 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
1976 ! spec
->autocfg
.hp_pin
)
1977 return 0; /* can't find valid BIOS pin config */
1978 if ((err
= ad1988_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
1979 (err
= ad1988_auto_create_extra_out(codec
, spec
->autocfg
.speaker_pin
,
1981 (err
= ad1988_auto_create_extra_out(codec
, spec
->autocfg
.speaker_pin
,
1982 "Headphone")) < 0 ||
1983 (err
= ad1988_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
1986 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1988 if (spec
->autocfg
.dig_out_pin
)
1989 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
1990 if (spec
->autocfg
.dig_in_pin
)
1991 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
1993 if (spec
->kctl_alloc
)
1994 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1996 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_6stack_init_verbs
;
1998 spec
->input_mux
= &spec
->private_imux
;
2003 /* init callback for auto-configuration model -- overriding the default init */
2004 static int ad1988_auto_init(struct hda_codec
*codec
)
2007 ad1988_auto_init_multi_out(codec
);
2008 ad1988_auto_init_extra_out(codec
);
2009 ad1988_auto_init_analog_input(codec
);
2017 static struct hda_board_config ad1988_cfg_tbl
[] = {
2018 { .modelname
= "6stack", .config
= AD1988_6STACK
},
2019 { .modelname
= "6stack-dig", .config
= AD1988_6STACK_DIG
},
2020 { .modelname
= "3stack", .config
= AD1988_3STACK
},
2021 { .modelname
= "3stack-dig", .config
= AD1988_3STACK_DIG
},
2022 { .modelname
= "laptop", .config
= AD1988_LAPTOP
},
2023 { .modelname
= "laptop-dig", .config
= AD1988_LAPTOP_DIG
},
2024 { .modelname
= "auto", .config
= AD1988_AUTO
},
2028 static int patch_ad1988(struct hda_codec
*codec
)
2030 struct ad198x_spec
*spec
;
2033 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
2037 init_MUTEX(&spec
->amp_mutex
);
2040 if (codec
->revision_id
== AD1988A_REV2
)
2041 snd_printk(KERN_INFO
"patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2043 board_config
= snd_hda_check_board_config(codec
, ad1988_cfg_tbl
);
2044 if (board_config
< 0 || board_config
>= AD1988_MODEL_LAST
) {
2045 printk(KERN_INFO
"hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2046 board_config
= AD1988_AUTO
;
2049 if (board_config
== AD1988_AUTO
) {
2050 /* automatic parse from the BIOS config */
2051 int err
= ad1988_parse_auto_config(codec
);
2056 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2057 board_config
= AD1988_6STACK
;
2061 switch (board_config
) {
2063 case AD1988_6STACK_DIG
:
2064 spec
->multiout
.max_channels
= 8;
2065 spec
->multiout
.num_dacs
= 4;
2066 if (codec
->revision_id
== AD1988A_REV2
)
2067 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids_rev2
;
2069 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids
;
2070 spec
->input_mux
= &ad1988_6stack_capture_source
;
2071 spec
->num_mixers
= 2;
2072 if (codec
->revision_id
== AD1988A_REV2
)
2073 spec
->mixers
[0] = ad1988_6stack_mixers1_rev2
;
2075 spec
->mixers
[0] = ad1988_6stack_mixers1
;
2076 spec
->mixers
[1] = ad1988_6stack_mixers2
;
2077 spec
->num_init_verbs
= 1;
2078 spec
->init_verbs
[0] = ad1988_6stack_init_verbs
;
2079 if (board_config
== AD1988_6STACK_DIG
) {
2080 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
2081 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
2085 case AD1988_3STACK_DIG
:
2086 spec
->multiout
.max_channels
= 6;
2087 spec
->multiout
.num_dacs
= 3;
2088 if (codec
->revision_id
== AD1988A_REV2
)
2089 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids_rev2
;
2091 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
2092 spec
->input_mux
= &ad1988_6stack_capture_source
;
2093 spec
->channel_mode
= ad1988_3stack_modes
;
2094 spec
->num_channel_mode
= ARRAY_SIZE(ad1988_3stack_modes
);
2095 spec
->num_mixers
= 2;
2096 if (codec
->revision_id
== AD1988A_REV2
)
2097 spec
->mixers
[0] = ad1988_3stack_mixers1_rev2
;
2099 spec
->mixers
[0] = ad1988_3stack_mixers1
;
2100 spec
->mixers
[1] = ad1988_3stack_mixers2
;
2101 spec
->num_init_verbs
= 1;
2102 spec
->init_verbs
[0] = ad1988_3stack_init_verbs
;
2103 if (board_config
== AD1988_3STACK_DIG
)
2104 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
2107 case AD1988_LAPTOP_DIG
:
2108 spec
->multiout
.max_channels
= 2;
2109 spec
->multiout
.num_dacs
= 1;
2110 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
2111 spec
->input_mux
= &ad1988_laptop_capture_source
;
2112 spec
->num_mixers
= 1;
2113 spec
->mixers
[0] = ad1988_laptop_mixers
;
2114 spec
->num_init_verbs
= 1;
2115 spec
->init_verbs
[0] = ad1988_laptop_init_verbs
;
2116 if (board_config
== AD1988_LAPTOP_DIG
)
2117 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
2121 spec
->num_adc_nids
= ARRAY_SIZE(ad1988_adc_nids
);
2122 spec
->adc_nids
= ad1988_adc_nids
;
2123 spec
->capsrc_nids
= ad1988_capsrc_nids
;
2124 spec
->mixers
[spec
->num_mixers
++] = ad1988_capture_mixers
;
2125 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_capture_init_verbs
;
2126 if (spec
->multiout
.dig_out_nid
) {
2127 spec
->mixers
[spec
->num_mixers
++] = ad1988_spdif_out_mixers
;
2128 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_spdif_init_verbs
;
2130 if (spec
->dig_in_nid
)
2131 spec
->mixers
[spec
->num_mixers
++] = ad1988_spdif_in_mixers
;
2133 codec
->patch_ops
= ad198x_patch_ops
;
2134 switch (board_config
) {
2136 codec
->patch_ops
.init
= ad1988_auto_init
;
2139 case AD1988_LAPTOP_DIG
:
2140 codec
->patch_ops
.unsol_event
= ad1988_laptop_unsol_event
;
2151 struct hda_codec_preset snd_hda_preset_analog
[] = {
2152 { .id
= 0x11d41981, .name
= "AD1981", .patch
= patch_ad1981
},
2153 { .id
= 0x11d41983, .name
= "AD1983", .patch
= patch_ad1983
},
2154 { .id
= 0x11d41986, .name
= "AD1986A", .patch
= patch_ad1986a
},
2155 { .id
= 0x11d41988, .name
= "AD1988", .patch
= patch_ad1988
},