2 * HD audio interface patch for Conexant HDA audio codec
4 * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
5 * Takashi Iwai <tiwai@suse.de>
6 * Tobin Davis <tdavis@dsl-only.net>
8 * This driver is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This driver is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include <sound/jack.h>
30 #include "hda_codec.h"
31 #include "hda_local.h"
34 #define CXT_PIN_DIR_IN 0x00
35 #define CXT_PIN_DIR_OUT 0x01
36 #define CXT_PIN_DIR_INOUT 0x02
37 #define CXT_PIN_DIR_IN_NOMICBIAS 0x03
38 #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
40 #define CONEXANT_HP_EVENT 0x37
41 #define CONEXANT_MIC_EVENT 0x38
43 /* Conexant 5051 specific */
45 #define CXT5051_SPDIF_OUT 0x1C
46 #define CXT5051_PORTB_EVENT 0x38
47 #define CXT5051_PORTC_EVENT 0x39
50 struct conexant_jack {
54 struct snd_jack *jack;
58 struct conexant_spec {
60 struct snd_kcontrol_new *mixers[5];
62 hda_nid_t vmaster_nid;
64 const struct hda_verb *init_verbs[5]; /* initialization verbs
68 unsigned int num_init_verbs;
71 struct hda_multi_out multiout; /* playback set-up
72 * max_channels, dacs must be set
73 * dig_out_nid and hp_nid are optional
75 unsigned int cur_eapd;
76 unsigned int hp_present;
77 unsigned int no_auto_mic;
78 unsigned int need_dac_fix;
81 unsigned int num_adc_nids;
83 hda_nid_t dig_in_nid; /* digital-in NID; optional */
85 unsigned int cur_adc_idx;
87 unsigned int cur_adc_stream_tag;
88 unsigned int cur_adc_format;
91 const struct hda_input_mux *input_mux;
92 hda_nid_t *capsrc_nids;
93 unsigned int cur_mux[3];
96 const struct hda_channel_mode *channel_mode;
100 struct hda_pcm pcm_rec[2]; /* used in build_pcms() */
102 unsigned int spdif_route;
105 struct snd_array jacks;
107 /* dynamic controls, init_verbs and input_mux */
108 struct auto_pin_cfg autocfg;
109 struct hda_input_mux private_imux;
110 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
112 unsigned int dell_automute;
113 unsigned int port_d_mode;
114 unsigned int dell_vostro;
116 unsigned int ext_mic_present;
117 unsigned int recording;
118 void (*capture_prepare)(struct hda_codec *codec);
119 void (*capture_cleanup)(struct hda_codec *codec);
122 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
123 struct hda_codec *codec,
124 struct snd_pcm_substream *substream)
126 struct conexant_spec *spec = codec->spec;
127 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
131 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
132 struct hda_codec *codec,
133 unsigned int stream_tag,
135 struct snd_pcm_substream *substream)
137 struct conexant_spec *spec = codec->spec;
138 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
143 static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
144 struct hda_codec *codec,
145 struct snd_pcm_substream *substream)
147 struct conexant_spec *spec = codec->spec;
148 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
154 static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
155 struct hda_codec *codec,
156 struct snd_pcm_substream *substream)
158 struct conexant_spec *spec = codec->spec;
159 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
162 static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
163 struct hda_codec *codec,
164 struct snd_pcm_substream *substream)
166 struct conexant_spec *spec = codec->spec;
167 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
170 static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
171 struct hda_codec *codec,
172 unsigned int stream_tag,
174 struct snd_pcm_substream *substream)
176 struct conexant_spec *spec = codec->spec;
177 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
185 static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
186 struct hda_codec *codec,
187 unsigned int stream_tag,
189 struct snd_pcm_substream *substream)
191 struct conexant_spec *spec = codec->spec;
192 if (spec->capture_prepare)
193 spec->capture_prepare(codec);
194 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
195 stream_tag, 0, format);
199 static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
200 struct hda_codec *codec,
201 struct snd_pcm_substream *substream)
203 struct conexant_spec *spec = codec->spec;
204 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
205 if (spec->capture_cleanup)
206 spec->capture_cleanup(codec);
212 static struct hda_pcm_stream conexant_pcm_analog_playback = {
216 .nid = 0, /* fill later */
218 .open = conexant_playback_pcm_open,
219 .prepare = conexant_playback_pcm_prepare,
220 .cleanup = conexant_playback_pcm_cleanup
224 static struct hda_pcm_stream conexant_pcm_analog_capture = {
228 .nid = 0, /* fill later */
230 .prepare = conexant_capture_pcm_prepare,
231 .cleanup = conexant_capture_pcm_cleanup
236 static struct hda_pcm_stream conexant_pcm_digital_playback = {
240 .nid = 0, /* fill later */
242 .open = conexant_dig_playback_pcm_open,
243 .close = conexant_dig_playback_pcm_close,
244 .prepare = conexant_dig_playback_pcm_prepare
248 static struct hda_pcm_stream conexant_pcm_digital_capture = {
252 /* NID is set in alc_build_pcms */
255 static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
256 struct hda_codec *codec,
257 unsigned int stream_tag,
259 struct snd_pcm_substream *substream)
261 struct conexant_spec *spec = codec->spec;
262 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
263 spec->cur_adc_stream_tag = stream_tag;
264 spec->cur_adc_format = format;
265 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
269 static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
270 struct hda_codec *codec,
271 struct snd_pcm_substream *substream)
273 struct conexant_spec *spec = codec->spec;
274 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
279 static struct hda_pcm_stream cx5051_pcm_analog_capture = {
283 .nid = 0, /* fill later */
285 .prepare = cx5051_capture_pcm_prepare,
286 .cleanup = cx5051_capture_pcm_cleanup
290 static int conexant_build_pcms(struct hda_codec *codec)
292 struct conexant_spec *spec = codec->spec;
293 struct hda_pcm *info = spec->pcm_rec;
296 codec->pcm_info = info;
298 info->name = "CONEXANT Analog";
299 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
300 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
301 spec->multiout.max_channels;
302 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
303 spec->multiout.dac_nids[0];
304 if (codec->vendor_id == 0x14f15051)
305 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
306 cx5051_pcm_analog_capture;
308 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
309 conexant_pcm_analog_capture;
310 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
311 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
313 if (spec->multiout.dig_out_nid) {
316 info->name = "Conexant Digital";
317 info->pcm_type = HDA_PCM_TYPE_SPDIF;
318 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
319 conexant_pcm_digital_playback;
320 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
321 spec->multiout.dig_out_nid;
322 if (spec->dig_in_nid) {
323 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
324 conexant_pcm_digital_capture;
325 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
333 static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
334 struct snd_ctl_elem_info *uinfo)
336 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
337 struct conexant_spec *spec = codec->spec;
339 return snd_hda_input_mux_info(spec->input_mux, uinfo);
342 static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
343 struct snd_ctl_elem_value *ucontrol)
345 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
346 struct conexant_spec *spec = codec->spec;
347 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
349 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
353 static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
354 struct snd_ctl_elem_value *ucontrol)
356 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
357 struct conexant_spec *spec = codec->spec;
358 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
360 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
361 spec->capsrc_nids[adc_idx],
362 &spec->cur_mux[adc_idx]);
365 #ifdef CONFIG_SND_HDA_INPUT_JACK
366 static void conexant_free_jack_priv(struct snd_jack *jack)
368 struct conexant_jack *jacks = jack->private_data;
373 static int conexant_add_jack(struct hda_codec *codec,
374 hda_nid_t nid, int type)
376 struct conexant_spec *spec;
377 struct conexant_jack *jack;
382 snd_array_init(&spec->jacks, sizeof(*jack), 32);
383 jack = snd_array_new(&spec->jacks);
384 name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
392 err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
395 jack->jack->private_data = jack;
396 jack->jack->private_free = conexant_free_jack_priv;
400 static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
402 struct conexant_spec *spec = codec->spec;
403 struct conexant_jack *jacks = spec->jacks.list;
407 for (i = 0; i < spec->jacks.used; i++) {
408 if (jacks->nid == nid) {
409 unsigned int present;
410 present = snd_hda_jack_detect(codec, nid);
412 present = (present) ? jacks->type : 0 ;
414 snd_jack_report(jacks->jack,
422 static int conexant_init_jacks(struct hda_codec *codec)
424 struct conexant_spec *spec = codec->spec;
427 for (i = 0; i < spec->num_init_verbs; i++) {
428 const struct hda_verb *hv;
430 hv = spec->init_verbs[i];
433 switch (hv->param ^ AC_USRSP_EN) {
434 case CONEXANT_HP_EVENT:
435 err = conexant_add_jack(codec, hv->nid,
437 conexant_report_jack(codec, hv->nid);
439 case CXT5051_PORTC_EVENT:
440 case CONEXANT_MIC_EVENT:
441 err = conexant_add_jack(codec, hv->nid,
442 SND_JACK_MICROPHONE);
443 conexant_report_jack(codec, hv->nid);
455 static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
459 static inline int conexant_init_jacks(struct hda_codec *codec)
465 static int conexant_init(struct hda_codec *codec)
467 struct conexant_spec *spec = codec->spec;
470 for (i = 0; i < spec->num_init_verbs; i++)
471 snd_hda_sequence_write(codec, spec->init_verbs[i]);
475 static void conexant_free(struct hda_codec *codec)
477 #ifdef CONFIG_SND_HDA_INPUT_JACK
478 struct conexant_spec *spec = codec->spec;
479 if (spec->jacks.list) {
480 struct conexant_jack *jacks = spec->jacks.list;
482 for (i = 0; i < spec->jacks.used; i++, jacks++) {
484 snd_device_free(codec->bus->card, jacks->jack);
486 snd_array_free(&spec->jacks);
489 snd_hda_detach_beep_device(codec);
493 static struct snd_kcontrol_new cxt_capture_mixers[] = {
495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
496 .name = "Capture Source",
497 .info = conexant_mux_enum_info,
498 .get = conexant_mux_enum_get,
499 .put = conexant_mux_enum_put
504 static const char *slave_vols[] = {
505 "Headphone Playback Volume",
506 "Speaker Playback Volume",
510 static const char *slave_sws[] = {
511 "Headphone Playback Switch",
512 "Speaker Playback Switch",
516 static int conexant_build_controls(struct hda_codec *codec)
518 struct conexant_spec *spec = codec->spec;
522 for (i = 0; i < spec->num_mixers; i++) {
523 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
527 if (spec->multiout.dig_out_nid) {
528 err = snd_hda_create_spdif_out_ctls(codec,
529 spec->multiout.dig_out_nid);
532 err = snd_hda_create_spdif_share_sw(codec,
536 spec->multiout.share_spdif = 1;
538 if (spec->dig_in_nid) {
539 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
544 /* if we have no master control, let's create it */
545 if (spec->vmaster_nid &&
546 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
547 unsigned int vmaster_tlv[4];
548 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
549 HDA_OUTPUT, vmaster_tlv);
550 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
551 vmaster_tlv, slave_vols);
555 if (spec->vmaster_nid &&
556 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
557 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
563 if (spec->input_mux) {
564 err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
572 static struct hda_codec_ops conexant_patch_ops = {
573 .build_controls = conexant_build_controls,
574 .build_pcms = conexant_build_pcms,
575 .init = conexant_init,
576 .free = conexant_free,
581 * the private value = nid | (invert << 8)
584 #define cxt_eapd_info snd_ctl_boolean_mono_info
586 static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
587 struct snd_ctl_elem_value *ucontrol)
589 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
590 struct conexant_spec *spec = codec->spec;
591 int invert = (kcontrol->private_value >> 8) & 1;
593 ucontrol->value.integer.value[0] = !spec->cur_eapd;
595 ucontrol->value.integer.value[0] = spec->cur_eapd;
600 static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
603 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
604 struct conexant_spec *spec = codec->spec;
605 int invert = (kcontrol->private_value >> 8) & 1;
606 hda_nid_t nid = kcontrol->private_value & 0xff;
609 eapd = !!ucontrol->value.integer.value[0];
612 if (eapd == spec->cur_eapd)
615 spec->cur_eapd = eapd;
616 snd_hda_codec_write_cache(codec, nid,
617 0, AC_VERB_SET_EAPD_BTLENABLE,
622 /* controls for test mode */
623 #ifdef CONFIG_SND_DEBUG
625 #define CXT_EAPD_SWITCH(xname, nid, mask) \
626 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
627 .info = cxt_eapd_info, \
628 .get = cxt_eapd_get, \
629 .put = cxt_eapd_put, \
630 .private_value = nid | (mask<<16) }
634 static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
635 struct snd_ctl_elem_info *uinfo)
637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
638 struct conexant_spec *spec = codec->spec;
639 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
640 spec->num_channel_mode);
643 static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
644 struct snd_ctl_elem_value *ucontrol)
646 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
647 struct conexant_spec *spec = codec->spec;
648 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
649 spec->num_channel_mode,
650 spec->multiout.max_channels);
653 static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
654 struct snd_ctl_elem_value *ucontrol)
656 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
657 struct conexant_spec *spec = codec->spec;
658 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
659 spec->num_channel_mode,
660 &spec->multiout.max_channels);
661 if (err >= 0 && spec->need_dac_fix)
662 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
666 #define CXT_PIN_MODE(xname, nid, dir) \
667 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
668 .info = conexant_ch_mode_info, \
669 .get = conexant_ch_mode_get, \
670 .put = conexant_ch_mode_put, \
671 .private_value = nid | (dir<<16) }
673 #endif /* CONFIG_SND_DEBUG */
675 /* Conexant 5045 specific */
677 static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
678 static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
679 static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
680 #define CXT5045_SPDIF_OUT 0x18
682 static struct hda_channel_mode cxt5045_modes[1] = {
686 static struct hda_input_mux cxt5045_capture_source = {
694 static struct hda_input_mux cxt5045_capture_source_benq = {
705 static struct hda_input_mux cxt5045_capture_source_hp530 = {
713 /* turn on/off EAPD (+ mute HP) as a master switch */
714 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
715 struct snd_ctl_elem_value *ucontrol)
717 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
718 struct conexant_spec *spec = codec->spec;
721 if (!cxt_eapd_put(kcontrol, ucontrol))
724 /* toggle internal speakers mute depending of presence of
727 bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
728 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
731 bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
732 snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
737 /* bind volumes of both NID 0x10 and 0x11 */
738 static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
739 .ops = &snd_hda_bind_vol,
741 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
742 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
747 /* toggle input of built-in and mic jack appropriately */
748 static void cxt5045_hp_automic(struct hda_codec *codec)
750 static struct hda_verb mic_jack_on[] = {
751 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
752 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
755 static struct hda_verb mic_jack_off[] = {
756 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
757 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
760 unsigned int present;
762 present = snd_hda_jack_detect(codec, 0x12);
764 snd_hda_sequence_write(codec, mic_jack_on);
766 snd_hda_sequence_write(codec, mic_jack_off);
770 /* mute internal speaker if HP is plugged */
771 static void cxt5045_hp_automute(struct hda_codec *codec)
773 struct conexant_spec *spec = codec->spec;
776 spec->hp_present = snd_hda_jack_detect(codec, 0x11);
778 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
779 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
783 /* unsolicited event for HP jack sensing */
784 static void cxt5045_hp_unsol_event(struct hda_codec *codec,
789 case CONEXANT_HP_EVENT:
790 cxt5045_hp_automute(codec);
792 case CONEXANT_MIC_EVENT:
793 cxt5045_hp_automic(codec);
799 static struct snd_kcontrol_new cxt5045_mixers[] = {
800 HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
801 HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
802 HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
803 HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
804 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
805 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
806 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
807 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
808 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
809 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
810 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
813 .name = "Master Playback Switch",
814 .info = cxt_eapd_info,
816 .put = cxt5045_hp_master_sw_put,
817 .private_value = 0x10,
823 static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
824 HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
825 HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
826 HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
827 HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT),
829 HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT),
830 HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT),
831 HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT),
832 HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT),
834 HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT),
835 HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT),
840 static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
841 HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
842 HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
843 HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
844 HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
845 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
846 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
847 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
848 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
849 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
850 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
851 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
854 .name = "Master Playback Switch",
855 .info = cxt_eapd_info,
857 .put = cxt5045_hp_master_sw_put,
858 .private_value = 0x10,
864 static struct hda_verb cxt5045_init_verbs[] = {
866 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
867 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
869 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
870 {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
871 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
872 {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
873 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
874 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
875 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
876 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
877 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
878 /* Record selector: Int mic */
879 {0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
880 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
881 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
882 /* SPDIF route: PCM */
883 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
884 { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
886 {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */
890 static struct hda_verb cxt5045_benq_init_verbs[] = {
892 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
893 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
894 /* Line In,HP, Amp */
895 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
896 {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
897 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
898 {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
899 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
900 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
901 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
902 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
903 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
904 /* Record selector: Int mic */
905 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
906 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
907 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
908 /* SPDIF route: PCM */
909 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
910 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
912 {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
916 static struct hda_verb cxt5045_hp_sense_init_verbs[] = {
917 /* pin sensing on HP jack */
918 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
922 static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
923 /* pin sensing on HP jack */
924 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
928 #ifdef CONFIG_SND_DEBUG
929 /* Test configuration for debugging, modelled after the ALC260 test
932 static struct hda_input_mux cxt5045_test_capture_source = {
937 { "LINE1 pin", 0x2 },
938 { "HP-OUT pin", 0x3 },
943 static struct snd_kcontrol_new cxt5045_test_mixer[] = {
945 /* Output controls */
946 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
947 HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
948 HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT),
949 HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT),
950 HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
951 HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
953 /* Modes for retasking pin widgets */
954 CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
955 CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
957 /* EAPD Switch Control */
958 CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
960 /* Loopback mixer controls */
962 HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT),
963 HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT),
964 HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT),
965 HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT),
966 HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT),
967 HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT),
968 HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT),
969 HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT),
970 HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT),
971 HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT),
973 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
974 .name = "Input Source",
975 .info = conexant_mux_enum_info,
976 .get = conexant_mux_enum_get,
977 .put = conexant_mux_enum_put,
979 /* Audio input controls */
980 HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
981 HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
982 HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
983 HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
984 HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
985 HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
986 HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
987 HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
988 HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
989 HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
993 static struct hda_verb cxt5045_test_init_verbs[] = {
994 /* Set connections */
995 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
996 { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
997 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
998 /* Enable retasking pins as output, initially without power amp */
999 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1000 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1002 /* Disable digital (SPDIF) pins initially, but users can enable
1003 * them via a mixer switch. In the case of SPDIF-out, this initverb
1004 * payload also sets the generation to 0, output to be in "consumer"
1005 * PCM format, copyright asserted, no pre-emphasis and no validity
1008 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1009 {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
1011 /* Start with output sum widgets muted and their output gains at min */
1012 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1013 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1015 /* Unmute retasking pin widget output buffers since the default
1016 * state appears to be output. As the pin mode is changed by the
1017 * user the pin mode control will take care of enabling the pin's
1018 * input/output buffers as needed.
1020 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1021 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1023 /* Mute capture amp left and right */
1024 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1026 /* Set ADC connection select to match default mixer setting (mic1
1029 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1030 {0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1032 /* Mute all inputs to mixer widget (even unconnected ones) */
1033 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
1034 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
1035 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
1036 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
1037 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1044 /* initialize jack-sensing, too */
1045 static int cxt5045_init(struct hda_codec *codec)
1047 conexant_init(codec);
1048 cxt5045_hp_automute(codec);
1054 CXT5045_LAPTOP_HPSENSE,
1055 CXT5045_LAPTOP_MICSENSE,
1056 CXT5045_LAPTOP_HPMICSENSE,
1058 CXT5045_LAPTOP_HP530,
1059 #ifdef CONFIG_SND_DEBUG
1065 static const char *cxt5045_models[CXT5045_MODELS] = {
1066 [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense",
1067 [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense",
1068 [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense",
1069 [CXT5045_BENQ] = "benq",
1070 [CXT5045_LAPTOP_HP530] = "laptop-hp530",
1071 #ifdef CONFIG_SND_DEBUG
1072 [CXT5045_TEST] = "test",
1076 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
1077 SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
1078 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1079 CXT5045_LAPTOP_HPSENSE),
1080 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
1081 SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
1082 SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
1083 SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
1084 SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
1085 CXT5045_LAPTOP_HPMICSENSE),
1086 SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1087 SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1088 SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1089 SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
1090 CXT5045_LAPTOP_HPMICSENSE),
1091 SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
1095 static int patch_cxt5045(struct hda_codec *codec)
1097 struct conexant_spec *spec;
1100 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1104 codec->pin_amp_workaround = 1;
1106 spec->multiout.max_channels = 2;
1107 spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
1108 spec->multiout.dac_nids = cxt5045_dac_nids;
1109 spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
1110 spec->num_adc_nids = 1;
1111 spec->adc_nids = cxt5045_adc_nids;
1112 spec->capsrc_nids = cxt5045_capsrc_nids;
1113 spec->input_mux = &cxt5045_capture_source;
1114 spec->num_mixers = 1;
1115 spec->mixers[0] = cxt5045_mixers;
1116 spec->num_init_verbs = 1;
1117 spec->init_verbs[0] = cxt5045_init_verbs;
1118 spec->spdif_route = 0;
1119 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes),
1120 spec->channel_mode = cxt5045_modes,
1123 codec->patch_ops = conexant_patch_ops;
1125 board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
1128 switch (board_config) {
1129 case CXT5045_LAPTOP_HPSENSE:
1130 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1131 spec->input_mux = &cxt5045_capture_source;
1132 spec->num_init_verbs = 2;
1133 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1134 spec->mixers[0] = cxt5045_mixers;
1135 codec->patch_ops.init = cxt5045_init;
1137 case CXT5045_LAPTOP_MICSENSE:
1138 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1139 spec->input_mux = &cxt5045_capture_source;
1140 spec->num_init_verbs = 2;
1141 spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
1142 spec->mixers[0] = cxt5045_mixers;
1143 codec->patch_ops.init = cxt5045_init;
1146 case CXT5045_LAPTOP_HPMICSENSE:
1147 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1148 spec->input_mux = &cxt5045_capture_source;
1149 spec->num_init_verbs = 3;
1150 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1151 spec->init_verbs[2] = cxt5045_mic_sense_init_verbs;
1152 spec->mixers[0] = cxt5045_mixers;
1153 codec->patch_ops.init = cxt5045_init;
1156 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1157 spec->input_mux = &cxt5045_capture_source_benq;
1158 spec->num_init_verbs = 1;
1159 spec->init_verbs[0] = cxt5045_benq_init_verbs;
1160 spec->mixers[0] = cxt5045_mixers;
1161 spec->mixers[1] = cxt5045_benq_mixers;
1162 spec->num_mixers = 2;
1163 codec->patch_ops.init = cxt5045_init;
1165 case CXT5045_LAPTOP_HP530:
1166 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1167 spec->input_mux = &cxt5045_capture_source_hp530;
1168 spec->num_init_verbs = 2;
1169 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1170 spec->mixers[0] = cxt5045_mixers_hp530;
1171 codec->patch_ops.init = cxt5045_init;
1173 #ifdef CONFIG_SND_DEBUG
1175 spec->input_mux = &cxt5045_test_capture_source;
1176 spec->mixers[0] = cxt5045_test_mixer;
1177 spec->init_verbs[0] = cxt5045_test_init_verbs;
1183 switch (codec->subsystem_id >> 16) {
1186 /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB
1187 * on NID 0x17. Fix max PCM level to 0 dB
1188 * (originally it has 0x2b steps with 0dB offset 0x14)
1190 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1191 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
1192 (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1193 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1194 (1 << AC_AMPCAP_MUTE_SHIFT));
1202 /* Conexant 5047 specific */
1203 #define CXT5047_SPDIF_OUT 0x11
1205 static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
1206 static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
1207 static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
1209 static struct hda_channel_mode cxt5047_modes[1] = {
1213 static struct hda_input_mux cxt5047_toshiba_capture_source = {
1221 /* turn on/off EAPD (+ mute HP) as a master switch */
1222 static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1223 struct snd_ctl_elem_value *ucontrol)
1225 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1226 struct conexant_spec *spec = codec->spec;
1229 if (!cxt_eapd_put(kcontrol, ucontrol))
1232 /* toggle internal speakers mute depending of presence of
1233 * the headphone jack
1235 bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
1236 /* NOTE: Conexat codec needs the index for *OUTPUT* amp of
1237 * pin widgets unlike other codecs. In this case, we need to
1238 * set index 0x01 for the volume from the mixer amp 0x19.
1240 snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1241 HDA_AMP_MUTE, bits);
1242 bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
1243 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
1244 HDA_AMP_MUTE, bits);
1248 /* mute internal speaker if HP is plugged */
1249 static void cxt5047_hp_automute(struct hda_codec *codec)
1251 struct conexant_spec *spec = codec->spec;
1254 spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1256 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1257 /* See the note in cxt5047_hp_master_sw_put */
1258 snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1259 HDA_AMP_MUTE, bits);
1262 /* toggle input of built-in and mic jack appropriately */
1263 static void cxt5047_hp_automic(struct hda_codec *codec)
1265 static struct hda_verb mic_jack_on[] = {
1266 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1267 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1270 static struct hda_verb mic_jack_off[] = {
1271 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1272 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1275 unsigned int present;
1277 present = snd_hda_jack_detect(codec, 0x15);
1279 snd_hda_sequence_write(codec, mic_jack_on);
1281 snd_hda_sequence_write(codec, mic_jack_off);
1284 /* unsolicited event for HP jack sensing */
1285 static void cxt5047_hp_unsol_event(struct hda_codec *codec,
1288 switch (res >> 26) {
1289 case CONEXANT_HP_EVENT:
1290 cxt5047_hp_automute(codec);
1292 case CONEXANT_MIC_EVENT:
1293 cxt5047_hp_automic(codec);
1298 static struct snd_kcontrol_new cxt5047_base_mixers[] = {
1299 HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
1300 HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
1301 HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT),
1302 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1303 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1304 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
1305 HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
1307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308 .name = "Master Playback Switch",
1309 .info = cxt_eapd_info,
1310 .get = cxt_eapd_get,
1311 .put = cxt5047_hp_master_sw_put,
1312 .private_value = 0x13,
1318 static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
1319 /* See the note in cxt5047_hp_master_sw_put */
1320 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
1321 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1325 static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
1326 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1330 static struct hda_verb cxt5047_init_verbs[] = {
1331 /* Line in, Mic, Built-in Mic */
1332 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1333 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1334 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1336 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1337 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
1338 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
1339 /* Record selector: Mic */
1340 {0x12, AC_VERB_SET_CONNECT_SEL,0x03},
1341 {0x19, AC_VERB_SET_AMP_GAIN_MUTE,
1342 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
1343 {0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
1344 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1345 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
1346 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1347 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
1348 /* SPDIF route: PCM */
1349 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
1350 /* Enable unsolicited events */
1351 {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
1352 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
1356 /* configuration for Toshiba Laptops */
1357 static struct hda_verb cxt5047_toshiba_init_verbs[] = {
1358 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
1362 /* Test configuration for debugging, modelled after the ALC260 test
1365 #ifdef CONFIG_SND_DEBUG
1366 static struct hda_input_mux cxt5047_test_capture_source = {
1369 { "LINE1 pin", 0x0 },
1370 { "MIC1 pin", 0x1 },
1371 { "MIC2 pin", 0x2 },
1376 static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1378 /* Output only controls */
1379 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
1380 HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
1381 HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
1382 HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
1383 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1384 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1385 HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1386 HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1387 HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
1388 HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1389 HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
1390 HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1392 /* Modes for retasking pin widgets */
1393 CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
1394 CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
1396 /* EAPD Switch Control */
1397 CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
1399 /* Loopback mixer controls */
1400 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
1401 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
1402 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
1403 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
1404 HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
1405 HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
1406 HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
1407 HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
1409 HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
1410 HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
1411 HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
1412 HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
1413 HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
1414 HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
1415 HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
1416 HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .name = "Input Source",
1420 .info = conexant_mux_enum_info,
1421 .get = conexant_mux_enum_get,
1422 .put = conexant_mux_enum_put,
1424 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1429 static struct hda_verb cxt5047_test_init_verbs[] = {
1430 /* Enable retasking pins as output, initially without power amp */
1431 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1432 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1433 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1435 /* Disable digital (SPDIF) pins initially, but users can enable
1436 * them via a mixer switch. In the case of SPDIF-out, this initverb
1437 * payload also sets the generation to 0, output to be in "consumer"
1438 * PCM format, copyright asserted, no pre-emphasis and no validity
1441 {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
1443 /* Ensure mic1, mic2, line1 pin widgets take input from the
1444 * OUT1 sum bus when acting as an output.
1446 {0x1a, AC_VERB_SET_CONNECT_SEL, 0},
1447 {0x1b, AC_VERB_SET_CONNECT_SEL, 0},
1449 /* Start with output sum widgets muted and their output gains at min */
1450 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1451 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1453 /* Unmute retasking pin widget output buffers since the default
1454 * state appears to be output. As the pin mode is changed by the
1455 * user the pin mode control will take care of enabling the pin's
1456 * input/output buffers as needed.
1458 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1459 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1460 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1462 /* Mute capture amp left and right */
1463 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1465 /* Set ADC connection select to match default mixer setting (mic1
1468 {0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
1470 /* Mute all inputs to mixer widget (even unconnected ones) */
1471 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
1472 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
1473 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
1474 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
1475 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1476 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
1477 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
1478 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
1485 /* initialize jack-sensing, too */
1486 static int cxt5047_hp_init(struct hda_codec *codec)
1488 conexant_init(codec);
1489 cxt5047_hp_automute(codec);
1495 CXT5047_LAPTOP, /* Laptops w/o EAPD support */
1496 CXT5047_LAPTOP_HP, /* Some HP laptops */
1497 CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */
1498 #ifdef CONFIG_SND_DEBUG
1504 static const char *cxt5047_models[CXT5047_MODELS] = {
1505 [CXT5047_LAPTOP] = "laptop",
1506 [CXT5047_LAPTOP_HP] = "laptop-hp",
1507 [CXT5047_LAPTOP_EAPD] = "laptop-eapd",
1508 #ifdef CONFIG_SND_DEBUG
1509 [CXT5047_TEST] = "test",
1513 static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1514 SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
1515 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1517 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
1521 static int patch_cxt5047(struct hda_codec *codec)
1523 struct conexant_spec *spec;
1526 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1530 codec->pin_amp_workaround = 1;
1532 spec->multiout.max_channels = 2;
1533 spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
1534 spec->multiout.dac_nids = cxt5047_dac_nids;
1535 spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
1536 spec->num_adc_nids = 1;
1537 spec->adc_nids = cxt5047_adc_nids;
1538 spec->capsrc_nids = cxt5047_capsrc_nids;
1539 spec->num_mixers = 1;
1540 spec->mixers[0] = cxt5047_base_mixers;
1541 spec->num_init_verbs = 1;
1542 spec->init_verbs[0] = cxt5047_init_verbs;
1543 spec->spdif_route = 0;
1544 spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
1545 spec->channel_mode = cxt5047_modes,
1547 codec->patch_ops = conexant_patch_ops;
1549 board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1552 switch (board_config) {
1553 case CXT5047_LAPTOP:
1554 spec->num_mixers = 2;
1555 spec->mixers[1] = cxt5047_hp_spk_mixers;
1556 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1558 case CXT5047_LAPTOP_HP:
1559 spec->num_mixers = 2;
1560 spec->mixers[1] = cxt5047_hp_only_mixers;
1561 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1562 codec->patch_ops.init = cxt5047_hp_init;
1564 case CXT5047_LAPTOP_EAPD:
1565 spec->input_mux = &cxt5047_toshiba_capture_source;
1566 spec->num_mixers = 2;
1567 spec->mixers[1] = cxt5047_hp_spk_mixers;
1568 spec->num_init_verbs = 2;
1569 spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
1570 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1572 #ifdef CONFIG_SND_DEBUG
1574 spec->input_mux = &cxt5047_test_capture_source;
1575 spec->mixers[0] = cxt5047_test_mixer;
1576 spec->init_verbs[0] = cxt5047_test_init_verbs;
1577 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1580 spec->vmaster_nid = 0x13;
1584 /* Conexant 5051 specific */
1585 static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1586 static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
1588 static struct hda_channel_mode cxt5051_modes[1] = {
1592 static void cxt5051_update_speaker(struct hda_codec *codec)
1594 struct conexant_spec *spec = codec->spec;
1595 unsigned int pinctl;
1596 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1597 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1601 /* turn on/off EAPD (+ mute HP) as a master switch */
1602 static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1603 struct snd_ctl_elem_value *ucontrol)
1605 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1607 if (!cxt_eapd_put(kcontrol, ucontrol))
1609 cxt5051_update_speaker(codec);
1613 /* toggle input of built-in and mic jack appropriately */
1614 static void cxt5051_portb_automic(struct hda_codec *codec)
1616 struct conexant_spec *spec = codec->spec;
1617 unsigned int present;
1619 if (spec->no_auto_mic)
1621 present = snd_hda_jack_detect(codec, 0x17);
1622 snd_hda_codec_write(codec, 0x14, 0,
1623 AC_VERB_SET_CONNECT_SEL,
1624 present ? 0x01 : 0x00);
1627 /* switch the current ADC according to the jack state */
1628 static void cxt5051_portc_automic(struct hda_codec *codec)
1630 struct conexant_spec *spec = codec->spec;
1631 unsigned int present;
1634 if (spec->no_auto_mic)
1636 present = snd_hda_jack_detect(codec, 0x18);
1638 spec->cur_adc_idx = 1;
1640 spec->cur_adc_idx = 0;
1641 new_adc = spec->adc_nids[spec->cur_adc_idx];
1642 if (spec->cur_adc && spec->cur_adc != new_adc) {
1643 /* stream is running, let's swap the current ADC */
1644 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
1645 spec->cur_adc = new_adc;
1646 snd_hda_codec_setup_stream(codec, new_adc,
1647 spec->cur_adc_stream_tag, 0,
1648 spec->cur_adc_format);
1652 /* mute internal speaker if HP is plugged */
1653 static void cxt5051_hp_automute(struct hda_codec *codec)
1655 struct conexant_spec *spec = codec->spec;
1657 spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1658 cxt5051_update_speaker(codec);
1661 /* unsolicited event for HP jack sensing */
1662 static void cxt5051_hp_unsol_event(struct hda_codec *codec,
1665 int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
1666 switch (res >> 26) {
1667 case CONEXANT_HP_EVENT:
1668 cxt5051_hp_automute(codec);
1670 case CXT5051_PORTB_EVENT:
1671 cxt5051_portb_automic(codec);
1673 case CXT5051_PORTC_EVENT:
1674 cxt5051_portc_automic(codec);
1677 conexant_report_jack(codec, nid);
1680 static struct snd_kcontrol_new cxt5051_mixers[] = {
1681 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1682 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1683 HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT),
1684 HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT),
1685 HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
1686 HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
1687 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1689 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1690 .name = "Master Playback Switch",
1691 .info = cxt_eapd_info,
1692 .get = cxt_eapd_get,
1693 .put = cxt5051_hp_master_sw_put,
1694 .private_value = 0x1a,
1700 static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
1701 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1702 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1703 HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT),
1704 HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT),
1705 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708 .name = "Master Playback Switch",
1709 .info = cxt_eapd_info,
1710 .get = cxt_eapd_get,
1711 .put = cxt5051_hp_master_sw_put,
1712 .private_value = 0x1a,
1718 static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
1719 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT),
1720 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT),
1721 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1724 .name = "Master Playback Switch",
1725 .info = cxt_eapd_info,
1726 .get = cxt_eapd_get,
1727 .put = cxt5051_hp_master_sw_put,
1728 .private_value = 0x1a,
1734 static struct snd_kcontrol_new cxt5051_f700_mixers[] = {
1735 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
1736 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
1737 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1739 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1740 .name = "Master Playback Switch",
1741 .info = cxt_eapd_info,
1742 .get = cxt_eapd_get,
1743 .put = cxt5051_hp_master_sw_put,
1744 .private_value = 0x1a,
1750 static struct hda_verb cxt5051_init_verbs[] = {
1752 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1753 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1754 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1755 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1756 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1757 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1759 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1760 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1762 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1763 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1765 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1766 /* Record selector: Int mic */
1767 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1768 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1769 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1770 /* SPDIF route: PCM */
1771 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1773 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1774 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1775 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1776 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
1780 static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1782 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1783 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1784 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1785 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1787 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1788 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1790 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1791 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1793 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1794 /* Record selector: Int mic */
1795 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1796 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1797 /* SPDIF route: PCM */
1798 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1800 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1801 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1802 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1806 static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1808 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1809 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1810 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1811 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1812 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1813 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1815 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1816 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1818 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1819 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1821 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1822 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
1824 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1825 /* Record selector: Int mic */
1826 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1827 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1828 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1829 /* SPDIF route: PCM */
1830 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1832 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1833 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1834 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1835 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
1836 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1840 static struct hda_verb cxt5051_f700_init_verbs[] = {
1842 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x03},
1843 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1844 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1845 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1847 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1848 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1850 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1851 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1853 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1854 /* Record selector: Int mic */
1855 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1856 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1857 /* SPDIF route: PCM */
1858 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1860 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1861 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1862 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1866 /* initialize jack-sensing, too */
1867 static int cxt5051_init(struct hda_codec *codec)
1869 conexant_init(codec);
1870 conexant_init_jacks(codec);
1871 if (codec->patch_ops.unsol_event) {
1872 cxt5051_hp_automute(codec);
1873 cxt5051_portb_automic(codec);
1874 cxt5051_portc_automic(codec);
1881 CXT5051_LAPTOP, /* Laptops w/ EAPD support */
1882 CXT5051_HP, /* no docking */
1883 CXT5051_HP_DV6736, /* HP without mic switch */
1884 CXT5051_LENOVO_X200, /* Lenovo X200 laptop */
1885 CXT5051_F700, /* HP Compaq Presario F700 */
1889 static const char *cxt5051_models[CXT5051_MODELS] = {
1890 [CXT5051_LAPTOP] = "laptop",
1891 [CXT5051_HP] = "hp",
1892 [CXT5051_HP_DV6736] = "hp-dv6736",
1893 [CXT5051_LENOVO_X200] = "lenovo-x200",
1894 [CXT5051_F700] = "hp 700"
1897 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1898 SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
1899 SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
1900 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
1902 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1903 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
1904 SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
1908 static int patch_cxt5051(struct hda_codec *codec)
1910 struct conexant_spec *spec;
1913 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1917 codec->pin_amp_workaround = 1;
1919 codec->patch_ops = conexant_patch_ops;
1920 codec->patch_ops.init = cxt5051_init;
1922 spec->multiout.max_channels = 2;
1923 spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids);
1924 spec->multiout.dac_nids = cxt5051_dac_nids;
1925 spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
1926 spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
1927 spec->adc_nids = cxt5051_adc_nids;
1928 spec->num_mixers = 1;
1929 spec->mixers[0] = cxt5051_mixers;
1930 spec->num_init_verbs = 1;
1931 spec->init_verbs[0] = cxt5051_init_verbs;
1932 spec->spdif_route = 0;
1933 spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes);
1934 spec->channel_mode = cxt5051_modes;
1936 spec->cur_adc_idx = 0;
1938 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1940 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
1943 switch (board_config) {
1945 spec->mixers[0] = cxt5051_hp_mixers;
1947 case CXT5051_HP_DV6736:
1948 spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
1949 spec->mixers[0] = cxt5051_hp_dv6736_mixers;
1950 spec->no_auto_mic = 1;
1952 case CXT5051_LENOVO_X200:
1953 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
1956 spec->init_verbs[0] = cxt5051_f700_init_verbs;
1957 spec->mixers[0] = cxt5051_f700_mixers;
1958 spec->no_auto_mic = 1;
1965 /* Conexant 5066 specific */
1967 static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
1968 static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
1969 static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
1970 #define CXT5066_SPDIF_OUT 0x21
1972 /* OLPC's microphone port is DC coupled for use with external sensors,
1973 * therefore we use a 50% mic bias in order to center the input signal with
1974 * the DC input range of the codec. */
1975 #define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
1977 static struct hda_channel_mode cxt5066_modes[1] = {
1981 static void cxt5066_update_speaker(struct hda_codec *codec)
1983 struct conexant_spec *spec = codec->spec;
1984 unsigned int pinctl;
1986 snd_printdd("CXT5066: update speaker, hp_present=%d\n",
1990 pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
1991 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1994 /* Port D (HP/LO) */
1995 pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
1996 ? spec->port_d_mode : 0;
1997 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2001 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
2002 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2005 if (spec->dell_automute) {
2006 /* DELL AIO Port Rule: PortA > PortD > IntSpk */
2007 pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
2009 snd_hda_codec_write(codec, 0x1c, 0,
2010 AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
2014 /* turn on/off EAPD (+ mute HP) as a master switch */
2015 static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
2016 struct snd_ctl_elem_value *ucontrol)
2018 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2020 if (!cxt_eapd_put(kcontrol, ucontrol))
2023 cxt5066_update_speaker(codec);
2027 /* OLPC defers mic widget control until when capture is started because the
2028 * microphone LED comes on as soon as these settings are put in place. if we
2029 * did this before recording, it would give the false indication that recording
2030 * is happening when it is not. */
2031 static void cxt5066_olpc_select_mic(struct hda_codec *codec)
2033 struct conexant_spec *spec = codec->spec;
2034 if (!spec->recording)
2037 /* external mic, port B */
2038 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2039 spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0);
2041 /* internal mic, port C */
2042 snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2043 spec->ext_mic_present ? 0 : PIN_VREF80);
2046 /* toggle input of built-in and mic jack appropriately */
2047 static void cxt5066_olpc_automic(struct hda_codec *codec)
2049 struct conexant_spec *spec = codec->spec;
2050 unsigned int present;
2052 present = snd_hda_codec_read(codec, 0x1a, 0,
2053 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2055 snd_printdd("CXT5066: external microphone detected\n");
2057 snd_printdd("CXT5066: external microphone absent\n");
2059 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
2061 spec->ext_mic_present = !!present;
2063 cxt5066_olpc_select_mic(codec);
2066 /* toggle input of built-in digital mic and mic jack appropriately */
2067 static void cxt5066_vostro_automic(struct hda_codec *codec)
2069 unsigned int present;
2071 struct hda_verb ext_mic_present[] = {
2072 /* enable external mic, port B */
2073 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2075 /* switch to external mic input */
2076 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2077 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2079 /* disable internal digital mic */
2080 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2083 static struct hda_verb ext_mic_absent[] = {
2084 /* enable internal mic, port C */
2085 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2087 /* switch to internal mic input */
2088 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2090 /* disable external mic, port B */
2091 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2095 present = snd_hda_jack_detect(codec, 0x1a);
2097 snd_printdd("CXT5066: external microphone detected\n");
2098 snd_hda_sequence_write(codec, ext_mic_present);
2100 snd_printdd("CXT5066: external microphone absent\n");
2101 snd_hda_sequence_write(codec, ext_mic_absent);
2105 /* mute internal speaker if HP is plugged */
2106 static void cxt5066_hp_automute(struct hda_codec *codec)
2108 struct conexant_spec *spec = codec->spec;
2109 unsigned int portA, portD;
2112 portA = snd_hda_jack_detect(codec, 0x19);
2115 portD = snd_hda_jack_detect(codec, 0x1c);
2117 spec->hp_present = !!(portA | portD);
2118 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2119 portA, portD, spec->hp_present);
2120 cxt5066_update_speaker(codec);
2123 /* unsolicited event for jack sensing */
2124 static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res)
2126 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2127 switch (res >> 26) {
2128 case CONEXANT_HP_EVENT:
2129 cxt5066_hp_automute(codec);
2131 case CONEXANT_MIC_EVENT:
2132 cxt5066_olpc_automic(codec);
2137 /* unsolicited event for jack sensing */
2138 static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2140 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2141 switch (res >> 26) {
2142 case CONEXANT_HP_EVENT:
2143 cxt5066_hp_automute(codec);
2145 case CONEXANT_MIC_EVENT:
2146 cxt5066_vostro_automic(codec);
2151 static const struct hda_input_mux cxt5066_analog_mic_boost = {
2162 static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
2163 struct snd_ctl_elem_info *uinfo)
2165 return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
2168 static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2169 struct snd_ctl_elem_value *ucontrol)
2171 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2173 hda_nid_t nid = kcontrol->private_value & 0xff;
2174 int inout = (kcontrol->private_value & 0x100) ?
2175 AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT;
2177 val = snd_hda_codec_read(codec, nid, 0,
2178 AC_VERB_GET_AMP_GAIN_MUTE, inout);
2180 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
2184 static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2185 struct snd_ctl_elem_value *ucontrol)
2187 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2188 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2190 hda_nid_t nid = kcontrol->private_value & 0xff;
2191 int inout = (kcontrol->private_value & 0x100) ?
2192 AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT;
2194 if (!imux->num_items)
2196 idx = ucontrol->value.enumerated.item[0];
2197 if (idx >= imux->num_items)
2198 idx = imux->num_items - 1;
2200 snd_hda_codec_write_cache(codec, nid, 0,
2201 AC_VERB_SET_AMP_GAIN_MUTE,
2202 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
2203 imux->items[idx].index);
2208 static void cxt5066_olpc_capture_prepare(struct hda_codec *codec)
2210 struct conexant_spec *spec = codec->spec;
2211 /* mark as recording and configure the microphone widget so that the
2212 * recording LED comes on. */
2213 spec->recording = 1;
2214 cxt5066_olpc_select_mic(codec);
2217 static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec)
2219 struct conexant_spec *spec = codec->spec;
2220 const struct hda_verb disable_mics[] = {
2221 /* disable external mic, port B */
2222 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2224 /* disble internal mic, port C */
2225 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2229 snd_hda_sequence_write(codec, disable_mics);
2230 spec->recording = 0;
2233 static struct hda_input_mux cxt5066_capture_source = {
2243 static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2244 .ops = &snd_hda_bind_vol,
2246 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2247 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2252 static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2253 .ops = &snd_hda_bind_sw,
2255 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2256 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2261 static struct snd_kcontrol_new cxt5066_mixer_master[] = {
2262 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
2266 static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2268 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2269 .name = "Master Playback Volume",
2270 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2271 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2272 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
2273 .subdevice = HDA_SUBDEV_AMP_FLAG,
2274 .info = snd_hda_mixer_amp_volume_info,
2275 .get = snd_hda_mixer_amp_volume_get,
2276 .put = snd_hda_mixer_amp_volume_put,
2277 .tlv = { .c = snd_hda_mixer_amp_tlv },
2278 /* offset by 28 volume steps to limit minimum gain to -46dB */
2280 HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28),
2285 static struct snd_kcontrol_new cxt5066_mixers[] = {
2287 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2288 .name = "Master Playback Switch",
2289 .info = cxt_eapd_info,
2290 .get = cxt_eapd_get,
2291 .put = cxt5066_hp_master_sw_put,
2292 .private_value = 0x1d,
2296 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2297 .name = "Ext Mic Boost Capture Enum",
2298 .info = cxt5066_mic_boost_mux_enum_info,
2299 .get = cxt5066_mic_boost_mux_enum_get,
2300 .put = cxt5066_mic_boost_mux_enum_put,
2301 .private_value = 0x17,
2304 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
2305 HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
2309 static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2311 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2312 .name = "Int Mic Boost Capture Enum",
2313 .info = cxt5066_mic_boost_mux_enum_info,
2314 .get = cxt5066_mic_boost_mux_enum_get,
2315 .put = cxt5066_mic_boost_mux_enum_put,
2316 .private_value = 0x23 | 0x100,
2318 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
2322 static struct hda_verb cxt5066_init_verbs[] = {
2323 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2324 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2325 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2326 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2329 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2330 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2333 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2334 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2336 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2337 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2340 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2342 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2343 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2344 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2345 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2346 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2347 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2349 /* no digital microphone support yet */
2350 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2352 /* Audio input selector */
2353 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2355 /* SPDIF route: PCM */
2356 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2357 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2359 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2360 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2363 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2365 /* not handling these yet */
2366 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2367 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2368 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2369 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2370 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2371 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2372 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2373 {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2377 static struct hda_verb cxt5066_init_verbs_olpc[] = {
2378 /* Port A: headphones */
2379 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2380 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2382 /* Port B: external microphone */
2383 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2385 /* Port C: internal microphone */
2386 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2388 /* Port D: unused */
2389 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2391 /* Port E: unused, but has primary EAPD */
2392 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2393 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2395 /* Port F: unused */
2396 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2398 /* Port G: internal speakers */
2399 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2400 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2403 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2406 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2408 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2409 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2410 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2411 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2412 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2413 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2414 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2415 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2416 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2417 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2418 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2419 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2421 /* Disable digital microphone port */
2422 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2424 /* Audio input selectors */
2425 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2426 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2429 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2430 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2432 /* enable unsolicited events for Port A and B */
2433 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2434 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2438 static struct hda_verb cxt5066_init_verbs_vostro[] = {
2439 /* Port A: headphones */
2440 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2441 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2443 /* Port B: external microphone */
2444 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2446 /* Port C: unused */
2447 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2449 /* Port D: unused */
2450 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2452 /* Port E: unused, but has primary EAPD */
2453 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2454 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2456 /* Port F: unused */
2457 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2459 /* Port G: internal speakers */
2460 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2461 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2464 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2467 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2469 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2470 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2471 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2472 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2473 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2474 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2475 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2476 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2477 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2478 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2479 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2480 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2482 /* Digital microphone port */
2483 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2485 /* Audio input selectors */
2486 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2487 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2490 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2491 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2493 /* enable unsolicited events for Port A and B */
2494 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2495 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2499 static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2500 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2504 /* initialize jack-sensing, too */
2505 static int cxt5066_init(struct hda_codec *codec)
2507 struct conexant_spec *spec = codec->spec;
2509 snd_printdd("CXT5066: init\n");
2510 conexant_init(codec);
2511 if (codec->patch_ops.unsol_event) {
2512 cxt5066_hp_automute(codec);
2513 if (spec->dell_vostro)
2514 cxt5066_vostro_automic(codec);
2519 static int cxt5066_olpc_init(struct hda_codec *codec)
2521 snd_printdd("CXT5066: init\n");
2522 conexant_init(codec);
2523 cxt5066_hp_automute(codec);
2524 cxt5066_olpc_automic(codec);
2529 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2530 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2531 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2532 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2536 static const char *cxt5066_models[CXT5066_MODELS] = {
2537 [CXT5066_LAPTOP] = "laptop",
2538 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2539 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2540 [CXT5066_DELL_VOSTO] = "dell-vostro"
2543 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2544 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
2546 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2547 CXT5066_DELL_LAPTOP),
2548 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2549 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2553 static int patch_cxt5066(struct hda_codec *codec)
2555 struct conexant_spec *spec;
2558 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2563 codec->patch_ops = conexant_patch_ops;
2564 codec->patch_ops.init = conexant_init;
2566 spec->dell_automute = 0;
2567 spec->multiout.max_channels = 2;
2568 spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
2569 spec->multiout.dac_nids = cxt5066_dac_nids;
2570 spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT;
2571 spec->num_adc_nids = 1;
2572 spec->adc_nids = cxt5066_adc_nids;
2573 spec->capsrc_nids = cxt5066_capsrc_nids;
2574 spec->input_mux = &cxt5066_capture_source;
2576 spec->port_d_mode = PIN_HP;
2578 spec->num_init_verbs = 1;
2579 spec->init_verbs[0] = cxt5066_init_verbs;
2580 spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
2581 spec->channel_mode = cxt5066_modes;
2583 spec->cur_adc_idx = 0;
2585 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
2586 cxt5066_models, cxt5066_cfg_tbl);
2587 switch (board_config) {
2589 case CXT5066_LAPTOP:
2590 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2591 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2593 case CXT5066_DELL_LAPTOP:
2594 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2595 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2597 spec->port_d_mode = PIN_OUT;
2598 spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
2599 spec->num_init_verbs++;
2600 spec->dell_automute = 1;
2602 case CXT5066_OLPC_XO_1_5:
2603 codec->patch_ops.init = cxt5066_olpc_init;
2604 codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event;
2605 spec->init_verbs[0] = cxt5066_init_verbs_olpc;
2606 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2607 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2608 spec->port_d_mode = 0;
2611 spec->multiout.dig_out_nid = 0;
2613 /* input source automatically selected */
2614 spec->input_mux = NULL;
2616 /* our capture hooks which allow us to turn on the microphone LED
2617 * at the right time */
2618 spec->capture_prepare = cxt5066_olpc_capture_prepare;
2619 spec->capture_cleanup = cxt5066_olpc_capture_cleanup;
2621 case CXT5066_DELL_VOSTO:
2622 codec->patch_ops.init = cxt5066_init;
2623 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2624 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2625 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2626 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2627 spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
2628 spec->port_d_mode = 0;
2629 spec->dell_vostro = 1;
2630 snd_hda_attach_beep_device(codec, 0x13);
2633 spec->multiout.dig_out_nid = 0;
2635 /* input source automatically selected */
2636 spec->input_mux = NULL;
2646 static struct hda_codec_preset snd_hda_preset_conexant[] = {
2647 { .id = 0x14f15045, .name = "CX20549 (Venice)",
2648 .patch = patch_cxt5045 },
2649 { .id = 0x14f15047, .name = "CX20551 (Waikiki)",
2650 .patch = patch_cxt5047 },
2651 { .id = 0x14f15051, .name = "CX20561 (Hermosa)",
2652 .patch = patch_cxt5051 },
2653 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2654 .patch = patch_cxt5066 },
2655 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2656 .patch = patch_cxt5066 },
2660 MODULE_ALIAS("snd-hda-codec-id:14f15045");
2661 MODULE_ALIAS("snd-hda-codec-id:14f15047");
2662 MODULE_ALIAS("snd-hda-codec-id:14f15051");
2663 MODULE_ALIAS("snd-hda-codec-id:14f15066");
2664 MODULE_ALIAS("snd-hda-codec-id:14f15067");
2666 MODULE_LICENSE("GPL");
2667 MODULE_DESCRIPTION("Conexant HD-audio codec");
2669 static struct hda_codec_preset_list conexant_list = {
2670 .preset = snd_hda_preset_conexant,
2671 .owner = THIS_MODULE,
2674 static int __init patch_conexant_init(void)
2676 return snd_hda_add_codec_preset(&conexant_list);
2679 static void __exit patch_conexant_exit(void)
2681 snd_hda_delete_codec_preset(&conexant_list);
2684 module_init(patch_conexant_init)
2685 module_exit(patch_conexant_exit)