xref: /openbmc/linux/sound/pci/hda/patch_conexant.c (revision 565d76cb)
1 /*
2  * HD audio interface patch for Conexant HDA audio codec
3  *
4  * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
5  * 		      Takashi Iwai <tiwai@suse.de>
6  * 		      Tobin Davis  <tdavis@dsl-only.net>
7  *
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.
12  *
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.
17  *
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
21  */
22 
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>
29 
30 #include "hda_codec.h"
31 #include "hda_local.h"
32 #include "hda_beep.h"
33 
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
39 
40 #define CONEXANT_HP_EVENT	0x37
41 #define CONEXANT_MIC_EVENT	0x38
42 
43 /* Conexant 5051 specific */
44 
45 #define CXT5051_SPDIF_OUT	0x12
46 #define CXT5051_PORTB_EVENT	0x38
47 #define CXT5051_PORTC_EVENT	0x39
48 
49 #define AUTO_MIC_PORTB		(1 << 1)
50 #define AUTO_MIC_PORTC		(1 << 2)
51 
52 struct pin_dac_pair {
53 	hda_nid_t pin;
54 	hda_nid_t dac;
55 	int type;
56 };
57 
58 struct conexant_spec {
59 
60 	struct snd_kcontrol_new *mixers[5];
61 	int num_mixers;
62 	hda_nid_t vmaster_nid;
63 
64 	const struct hda_verb *init_verbs[5];	/* initialization verbs
65 						 * don't forget NULL
66 						 * termination!
67 						 */
68 	unsigned int num_init_verbs;
69 
70 	/* playback */
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
74 					 */
75 	unsigned int cur_eapd;
76 	unsigned int hp_present;
77 	unsigned int auto_mic;
78 	int auto_mic_ext;		/* autocfg.inputs[] index for ext mic */
79 	unsigned int need_dac_fix;
80 	hda_nid_t slave_dig_outs[2];
81 
82 	/* capture */
83 	unsigned int num_adc_nids;
84 	hda_nid_t *adc_nids;
85 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
86 
87 	unsigned int cur_adc_idx;
88 	hda_nid_t cur_adc;
89 	unsigned int cur_adc_stream_tag;
90 	unsigned int cur_adc_format;
91 
92 	/* capture source */
93 	const struct hda_input_mux *input_mux;
94 	hda_nid_t *capsrc_nids;
95 	unsigned int cur_mux[3];
96 
97 	/* channel model */
98 	const struct hda_channel_mode *channel_mode;
99 	int num_channel_mode;
100 
101 	/* PCM information */
102 	struct hda_pcm pcm_rec[2];	/* used in build_pcms() */
103 
104 	unsigned int spdif_route;
105 
106 	/* dynamic controls, init_verbs and input_mux */
107 	struct auto_pin_cfg autocfg;
108 	struct hda_input_mux private_imux;
109 	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
110 	struct pin_dac_pair dac_info[8];
111 	int dac_info_filled;
112 
113 	unsigned int port_d_mode;
114 	unsigned int auto_mute:1;	/* used in auto-parser */
115 	unsigned int dell_automute:1;
116 	unsigned int dell_vostro:1;
117 	unsigned int ideapad:1;
118 	unsigned int thinkpad:1;
119 	unsigned int hp_laptop:1;
120 	unsigned int asus:1;
121 
122 	unsigned int ext_mic_present;
123 	unsigned int recording;
124 	void (*capture_prepare)(struct hda_codec *codec);
125 	void (*capture_cleanup)(struct hda_codec *codec);
126 
127 	/* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors)
128 	 * through the microphone jack.
129 	 * When the user enables this through a mixer switch, both internal and
130 	 * external microphones are disabled. Gain is fixed at 0dB. In this mode,
131 	 * we also allow the bias to be configured through a separate mixer
132 	 * control. */
133 	unsigned int dc_enable;
134 	unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */
135 	unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
136 
137 	unsigned int beep_amp;
138 };
139 
140 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
141 				      struct hda_codec *codec,
142 				      struct snd_pcm_substream *substream)
143 {
144 	struct conexant_spec *spec = codec->spec;
145 	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
146 					     hinfo);
147 }
148 
149 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
150 					 struct hda_codec *codec,
151 					 unsigned int stream_tag,
152 					 unsigned int format,
153 					 struct snd_pcm_substream *substream)
154 {
155 	struct conexant_spec *spec = codec->spec;
156 	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
157 						stream_tag,
158 						format, substream);
159 }
160 
161 static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
162 					 struct hda_codec *codec,
163 					 struct snd_pcm_substream *substream)
164 {
165 	struct conexant_spec *spec = codec->spec;
166 	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
167 }
168 
169 /*
170  * Digital out
171  */
172 static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
173 					  struct hda_codec *codec,
174 					  struct snd_pcm_substream *substream)
175 {
176 	struct conexant_spec *spec = codec->spec;
177 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
178 }
179 
180 static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
181 					 struct hda_codec *codec,
182 					 struct snd_pcm_substream *substream)
183 {
184 	struct conexant_spec *spec = codec->spec;
185 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
186 }
187 
188 static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
189 					 struct hda_codec *codec,
190 					 unsigned int stream_tag,
191 					 unsigned int format,
192 					 struct snd_pcm_substream *substream)
193 {
194 	struct conexant_spec *spec = codec->spec;
195 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
196 					     stream_tag,
197 					     format, substream);
198 }
199 
200 /*
201  * Analog capture
202  */
203 static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
204 				      struct hda_codec *codec,
205 				      unsigned int stream_tag,
206 				      unsigned int format,
207 				      struct snd_pcm_substream *substream)
208 {
209 	struct conexant_spec *spec = codec->spec;
210 	if (spec->capture_prepare)
211 		spec->capture_prepare(codec);
212 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
213 				   stream_tag, 0, format);
214 	return 0;
215 }
216 
217 static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
218 				      struct hda_codec *codec,
219 				      struct snd_pcm_substream *substream)
220 {
221 	struct conexant_spec *spec = codec->spec;
222 	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
223 	if (spec->capture_cleanup)
224 		spec->capture_cleanup(codec);
225 	return 0;
226 }
227 
228 
229 
230 static struct hda_pcm_stream conexant_pcm_analog_playback = {
231 	.substreams = 1,
232 	.channels_min = 2,
233 	.channels_max = 2,
234 	.nid = 0, /* fill later */
235 	.ops = {
236 		.open = conexant_playback_pcm_open,
237 		.prepare = conexant_playback_pcm_prepare,
238 		.cleanup = conexant_playback_pcm_cleanup
239 	},
240 };
241 
242 static struct hda_pcm_stream conexant_pcm_analog_capture = {
243 	.substreams = 1,
244 	.channels_min = 2,
245 	.channels_max = 2,
246 	.nid = 0, /* fill later */
247 	.ops = {
248 		.prepare = conexant_capture_pcm_prepare,
249 		.cleanup = conexant_capture_pcm_cleanup
250 	},
251 };
252 
253 
254 static struct hda_pcm_stream conexant_pcm_digital_playback = {
255 	.substreams = 1,
256 	.channels_min = 2,
257 	.channels_max = 2,
258 	.nid = 0, /* fill later */
259 	.ops = {
260 		.open = conexant_dig_playback_pcm_open,
261 		.close = conexant_dig_playback_pcm_close,
262 		.prepare = conexant_dig_playback_pcm_prepare
263 	},
264 };
265 
266 static struct hda_pcm_stream conexant_pcm_digital_capture = {
267 	.substreams = 1,
268 	.channels_min = 2,
269 	.channels_max = 2,
270 	/* NID is set in alc_build_pcms */
271 };
272 
273 static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
274 				      struct hda_codec *codec,
275 				      unsigned int stream_tag,
276 				      unsigned int format,
277 				      struct snd_pcm_substream *substream)
278 {
279 	struct conexant_spec *spec = codec->spec;
280 	spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
281 	spec->cur_adc_stream_tag = stream_tag;
282 	spec->cur_adc_format = format;
283 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
284 	return 0;
285 }
286 
287 static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
288 				      struct hda_codec *codec,
289 				      struct snd_pcm_substream *substream)
290 {
291 	struct conexant_spec *spec = codec->spec;
292 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
293 	spec->cur_adc = 0;
294 	return 0;
295 }
296 
297 static struct hda_pcm_stream cx5051_pcm_analog_capture = {
298 	.substreams = 1,
299 	.channels_min = 2,
300 	.channels_max = 2,
301 	.nid = 0, /* fill later */
302 	.ops = {
303 		.prepare = cx5051_capture_pcm_prepare,
304 		.cleanup = cx5051_capture_pcm_cleanup
305 	},
306 };
307 
308 static int conexant_build_pcms(struct hda_codec *codec)
309 {
310 	struct conexant_spec *spec = codec->spec;
311 	struct hda_pcm *info = spec->pcm_rec;
312 
313 	codec->num_pcms = 1;
314 	codec->pcm_info = info;
315 
316 	info->name = "CONEXANT Analog";
317 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
318 	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
319 		spec->multiout.max_channels;
320 	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
321 		spec->multiout.dac_nids[0];
322 	if (codec->vendor_id == 0x14f15051)
323 		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
324 			cx5051_pcm_analog_capture;
325 	else
326 		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
327 			conexant_pcm_analog_capture;
328 	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
329 	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
330 
331 	if (spec->multiout.dig_out_nid) {
332 		info++;
333 		codec->num_pcms++;
334 		info->name = "Conexant Digital";
335 		info->pcm_type = HDA_PCM_TYPE_SPDIF;
336 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
337 			conexant_pcm_digital_playback;
338 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
339 			spec->multiout.dig_out_nid;
340 		if (spec->dig_in_nid) {
341 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
342 				conexant_pcm_digital_capture;
343 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
344 				spec->dig_in_nid;
345 		}
346 		if (spec->slave_dig_outs[0])
347 			codec->slave_dig_outs = spec->slave_dig_outs;
348 	}
349 
350 	return 0;
351 }
352 
353 static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
354 	       			  struct snd_ctl_elem_info *uinfo)
355 {
356 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
357 	struct conexant_spec *spec = codec->spec;
358 
359 	return snd_hda_input_mux_info(spec->input_mux, uinfo);
360 }
361 
362 static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
363 				 struct snd_ctl_elem_value *ucontrol)
364 {
365 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
366 	struct conexant_spec *spec = codec->spec;
367 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
368 
369 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
370 	return 0;
371 }
372 
373 static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
374 				 struct snd_ctl_elem_value *ucontrol)
375 {
376 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
377 	struct conexant_spec *spec = codec->spec;
378 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
379 
380 	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
381 				     spec->capsrc_nids[adc_idx],
382 				     &spec->cur_mux[adc_idx]);
383 }
384 
385 static int conexant_init_jacks(struct hda_codec *codec)
386 {
387 #ifdef CONFIG_SND_HDA_INPUT_JACK
388 	struct conexant_spec *spec = codec->spec;
389 	int i;
390 
391 	for (i = 0; i < spec->num_init_verbs; i++) {
392 		const struct hda_verb *hv;
393 
394 		hv = spec->init_verbs[i];
395 		while (hv->nid) {
396 			int err = 0;
397 			switch (hv->param ^ AC_USRSP_EN) {
398 			case CONEXANT_HP_EVENT:
399 				err = snd_hda_input_jack_add(codec, hv->nid,
400 						SND_JACK_HEADPHONE, NULL);
401 				snd_hda_input_jack_report(codec, hv->nid);
402 				break;
403 			case CXT5051_PORTC_EVENT:
404 			case CONEXANT_MIC_EVENT:
405 				err = snd_hda_input_jack_add(codec, hv->nid,
406 						SND_JACK_MICROPHONE, NULL);
407 				snd_hda_input_jack_report(codec, hv->nid);
408 				break;
409 			}
410 			if (err < 0)
411 				return err;
412 			++hv;
413 		}
414 	}
415 #endif /* CONFIG_SND_HDA_INPUT_JACK */
416 	return 0;
417 }
418 
419 static int conexant_init(struct hda_codec *codec)
420 {
421 	struct conexant_spec *spec = codec->spec;
422 	int i;
423 
424 	for (i = 0; i < spec->num_init_verbs; i++)
425 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
426 	return 0;
427 }
428 
429 static void conexant_free(struct hda_codec *codec)
430 {
431 	snd_hda_input_jack_free(codec);
432 	snd_hda_detach_beep_device(codec);
433 	kfree(codec->spec);
434 }
435 
436 static struct snd_kcontrol_new cxt_capture_mixers[] = {
437 	{
438 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
439 		.name = "Capture Source",
440 		.info = conexant_mux_enum_info,
441 		.get = conexant_mux_enum_get,
442 		.put = conexant_mux_enum_put
443 	},
444 	{}
445 };
446 
447 #ifdef CONFIG_SND_HDA_INPUT_BEEP
448 /* additional beep mixers; the actual parameters are overwritten at build */
449 static struct snd_kcontrol_new cxt_beep_mixer[] = {
450 	HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
451 	HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
452 	{ } /* end */
453 };
454 #endif
455 
456 static const char * const slave_vols[] = {
457 	"Headphone Playback Volume",
458 	"Speaker Playback Volume",
459 	NULL
460 };
461 
462 static const char * const slave_sws[] = {
463 	"Headphone Playback Switch",
464 	"Speaker Playback Switch",
465 	NULL
466 };
467 
468 static int conexant_build_controls(struct hda_codec *codec)
469 {
470 	struct conexant_spec *spec = codec->spec;
471 	unsigned int i;
472 	int err;
473 
474 	for (i = 0; i < spec->num_mixers; i++) {
475 		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
476 		if (err < 0)
477 			return err;
478 	}
479 	if (spec->multiout.dig_out_nid) {
480 		err = snd_hda_create_spdif_out_ctls(codec,
481 						    spec->multiout.dig_out_nid);
482 		if (err < 0)
483 			return err;
484 		err = snd_hda_create_spdif_share_sw(codec,
485 						    &spec->multiout);
486 		if (err < 0)
487 			return err;
488 		spec->multiout.share_spdif = 1;
489 	}
490 	if (spec->dig_in_nid) {
491 		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
492 		if (err < 0)
493 			return err;
494 	}
495 
496 	/* if we have no master control, let's create it */
497 	if (spec->vmaster_nid &&
498 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
499 		unsigned int vmaster_tlv[4];
500 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
501 					HDA_OUTPUT, vmaster_tlv);
502 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
503 					  vmaster_tlv, slave_vols);
504 		if (err < 0)
505 			return err;
506 	}
507 	if (spec->vmaster_nid &&
508 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
509 		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
510 					  NULL, slave_sws);
511 		if (err < 0)
512 			return err;
513 	}
514 
515 	if (spec->input_mux) {
516 		err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
517 		if (err < 0)
518 			return err;
519 	}
520 
521 #ifdef CONFIG_SND_HDA_INPUT_BEEP
522 	/* create beep controls if needed */
523 	if (spec->beep_amp) {
524 		struct snd_kcontrol_new *knew;
525 		for (knew = cxt_beep_mixer; knew->name; knew++) {
526 			struct snd_kcontrol *kctl;
527 			kctl = snd_ctl_new1(knew, codec);
528 			if (!kctl)
529 				return -ENOMEM;
530 			kctl->private_value = spec->beep_amp;
531 			err = snd_hda_ctl_add(codec, 0, kctl);
532 			if (err < 0)
533 				return err;
534 		}
535 	}
536 #endif
537 
538 	return 0;
539 }
540 
541 #ifdef CONFIG_SND_HDA_POWER_SAVE
542 static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
543 {
544 	snd_hda_shutup_pins(codec);
545 	return 0;
546 }
547 #endif
548 
549 static struct hda_codec_ops conexant_patch_ops = {
550 	.build_controls = conexant_build_controls,
551 	.build_pcms = conexant_build_pcms,
552 	.init = conexant_init,
553 	.free = conexant_free,
554 #ifdef CONFIG_SND_HDA_POWER_SAVE
555 	.suspend = conexant_suspend,
556 #endif
557 	.reboot_notify = snd_hda_shutup_pins,
558 };
559 
560 #ifdef CONFIG_SND_HDA_INPUT_BEEP
561 #define set_beep_amp(spec, nid, idx, dir) \
562 	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
563 #else
564 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
565 #endif
566 
567 /*
568  * EAPD control
569  * the private value = nid | (invert << 8)
570  */
571 
572 #define cxt_eapd_info		snd_ctl_boolean_mono_info
573 
574 static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
575 			     struct snd_ctl_elem_value *ucontrol)
576 {
577 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
578 	struct conexant_spec *spec = codec->spec;
579 	int invert = (kcontrol->private_value >> 8) & 1;
580 	if (invert)
581 		ucontrol->value.integer.value[0] = !spec->cur_eapd;
582 	else
583 		ucontrol->value.integer.value[0] = spec->cur_eapd;
584 	return 0;
585 
586 }
587 
588 static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
589 			     struct snd_ctl_elem_value *ucontrol)
590 {
591 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
592 	struct conexant_spec *spec = codec->spec;
593 	int invert = (kcontrol->private_value >> 8) & 1;
594 	hda_nid_t nid = kcontrol->private_value & 0xff;
595 	unsigned int eapd;
596 
597 	eapd = !!ucontrol->value.integer.value[0];
598 	if (invert)
599 		eapd = !eapd;
600 	if (eapd == spec->cur_eapd)
601 		return 0;
602 
603 	spec->cur_eapd = eapd;
604 	snd_hda_codec_write_cache(codec, nid,
605 				  0, AC_VERB_SET_EAPD_BTLENABLE,
606 				  eapd ? 0x02 : 0x00);
607 	return 1;
608 }
609 
610 /* controls for test mode */
611 #ifdef CONFIG_SND_DEBUG
612 
613 #define CXT_EAPD_SWITCH(xname, nid, mask) \
614 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
615 	  .info = cxt_eapd_info, \
616 	  .get = cxt_eapd_get, \
617 	  .put = cxt_eapd_put, \
618 	  .private_value = nid | (mask<<16) }
619 
620 
621 
622 static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
623 				 struct snd_ctl_elem_info *uinfo)
624 {
625 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
626 	struct conexant_spec *spec = codec->spec;
627 	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
628 				    spec->num_channel_mode);
629 }
630 
631 static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
632 				struct snd_ctl_elem_value *ucontrol)
633 {
634 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
635 	struct conexant_spec *spec = codec->spec;
636 	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
637 				   spec->num_channel_mode,
638 				   spec->multiout.max_channels);
639 }
640 
641 static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
642 				struct snd_ctl_elem_value *ucontrol)
643 {
644 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
645 	struct conexant_spec *spec = codec->spec;
646 	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
647 				      spec->num_channel_mode,
648 				      &spec->multiout.max_channels);
649 	if (err >= 0 && spec->need_dac_fix)
650 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
651 	return err;
652 }
653 
654 #define CXT_PIN_MODE(xname, nid, dir) \
655 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
656 	  .info = conexant_ch_mode_info, \
657 	  .get = conexant_ch_mode_get, \
658 	  .put = conexant_ch_mode_put, \
659 	  .private_value = nid | (dir<<16) }
660 
661 #endif /* CONFIG_SND_DEBUG */
662 
663 /* Conexant 5045 specific */
664 
665 static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
666 static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
667 static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
668 #define CXT5045_SPDIF_OUT	0x18
669 
670 static struct hda_channel_mode cxt5045_modes[1] = {
671 	{ 2, NULL },
672 };
673 
674 static struct hda_input_mux cxt5045_capture_source = {
675 	.num_items = 2,
676 	.items = {
677 		{ "IntMic", 0x1 },
678 		{ "ExtMic", 0x2 },
679 	}
680 };
681 
682 static struct hda_input_mux cxt5045_capture_source_benq = {
683 	.num_items = 5,
684 	.items = {
685 		{ "IntMic", 0x1 },
686 		{ "ExtMic", 0x2 },
687 		{ "LineIn", 0x3 },
688 		{ "CD",     0x4 },
689 		{ "Mixer",  0x0 },
690 	}
691 };
692 
693 static struct hda_input_mux cxt5045_capture_source_hp530 = {
694 	.num_items = 2,
695 	.items = {
696 		{ "ExtMic", 0x1 },
697 		{ "IntMic", 0x2 },
698 	}
699 };
700 
701 /* turn on/off EAPD (+ mute HP) as a master switch */
702 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
703 				    struct snd_ctl_elem_value *ucontrol)
704 {
705 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
706 	struct conexant_spec *spec = codec->spec;
707 	unsigned int bits;
708 
709 	if (!cxt_eapd_put(kcontrol, ucontrol))
710 		return 0;
711 
712 	/* toggle internal speakers mute depending of presence of
713 	 * the headphone jack
714 	 */
715 	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
716 	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
717 				 HDA_AMP_MUTE, bits);
718 
719 	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
720 	snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
721 				 HDA_AMP_MUTE, bits);
722 	return 1;
723 }
724 
725 /* bind volumes of both NID 0x10 and 0x11 */
726 static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
727 	.ops = &snd_hda_bind_vol,
728 	.values = {
729 		HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
730 		HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
731 		0
732 	},
733 };
734 
735 /* toggle input of built-in and mic jack appropriately */
736 static void cxt5045_hp_automic(struct hda_codec *codec)
737 {
738 	static struct hda_verb mic_jack_on[] = {
739 		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
740 		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
741 		{}
742 	};
743 	static struct hda_verb mic_jack_off[] = {
744 		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
745 		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
746 		{}
747 	};
748 	unsigned int present;
749 
750 	present = snd_hda_jack_detect(codec, 0x12);
751 	if (present)
752 		snd_hda_sequence_write(codec, mic_jack_on);
753 	else
754 		snd_hda_sequence_write(codec, mic_jack_off);
755 }
756 
757 
758 /* mute internal speaker if HP is plugged */
759 static void cxt5045_hp_automute(struct hda_codec *codec)
760 {
761 	struct conexant_spec *spec = codec->spec;
762 	unsigned int bits;
763 
764 	spec->hp_present = snd_hda_jack_detect(codec, 0x11);
765 
766 	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
767 	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
768 				 HDA_AMP_MUTE, bits);
769 }
770 
771 /* unsolicited event for HP jack sensing */
772 static void cxt5045_hp_unsol_event(struct hda_codec *codec,
773 				   unsigned int res)
774 {
775 	res >>= 26;
776 	switch (res) {
777 	case CONEXANT_HP_EVENT:
778 		cxt5045_hp_automute(codec);
779 		break;
780 	case CONEXANT_MIC_EVENT:
781 		cxt5045_hp_automic(codec);
782 		break;
783 
784 	}
785 }
786 
787 static struct snd_kcontrol_new cxt5045_mixers[] = {
788 	HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
789 	HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
790 	HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
791 	HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
792 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
793 	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
794 	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
795 	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
796 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
797 	HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
798 	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
799 	{
800 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
801 		.name = "Master Playback Switch",
802 		.info = cxt_eapd_info,
803 		.get = cxt_eapd_get,
804 		.put = cxt5045_hp_master_sw_put,
805 		.private_value = 0x10,
806 	},
807 
808 	{}
809 };
810 
811 static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
812 	HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
813 	HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
814 	HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
815 	HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT),
816 
817 	HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT),
818 	HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT),
819 	HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT),
820 	HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT),
821 
822 	HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT),
823 	HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT),
824 
825 	{}
826 };
827 
828 static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
829 	HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
830 	HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
831 	HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
832 	HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
833 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
834 	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
835 	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
836 	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
837 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
838 	HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
839 	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
840 	{
841 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
842 		.name = "Master Playback Switch",
843 		.info = cxt_eapd_info,
844 		.get = cxt_eapd_get,
845 		.put = cxt5045_hp_master_sw_put,
846 		.private_value = 0x10,
847 	},
848 
849 	{}
850 };
851 
852 static struct hda_verb cxt5045_init_verbs[] = {
853 	/* Line in, Mic */
854 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
855 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
856 	/* HP, Amp  */
857 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
858 	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
859 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
860 	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
861 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
862 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
863 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
864 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
865 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
866 	/* Record selector: Internal mic */
867 	{0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
868 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
869 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
870 	/* SPDIF route: PCM */
871 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
872 	{ 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
873 	/* EAPD */
874 	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */
875 	{ } /* end */
876 };
877 
878 static struct hda_verb cxt5045_benq_init_verbs[] = {
879 	/* Internal Mic, Mic */
880 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
881 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
882 	/* Line In,HP, Amp  */
883 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
884 	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
885 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
886 	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
887 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
888 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
889 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
890 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
891 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
892 	/* Record selector: Internal mic */
893 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
894 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
895 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
896 	/* SPDIF route: PCM */
897 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
898 	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
899 	/* EAPD */
900 	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
901 	{ } /* end */
902 };
903 
904 static struct hda_verb cxt5045_hp_sense_init_verbs[] = {
905 	/* pin sensing on HP jack */
906 	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
907 	{ } /* end */
908 };
909 
910 static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
911 	/* pin sensing on HP jack */
912 	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
913 	{ } /* end */
914 };
915 
916 #ifdef CONFIG_SND_DEBUG
917 /* Test configuration for debugging, modelled after the ALC260 test
918  * configuration.
919  */
920 static struct hda_input_mux cxt5045_test_capture_source = {
921 	.num_items = 5,
922 	.items = {
923 		{ "MIXER", 0x0 },
924 		{ "MIC1 pin", 0x1 },
925 		{ "LINE1 pin", 0x2 },
926 		{ "HP-OUT pin", 0x3 },
927 		{ "CD pin", 0x4 },
928         },
929 };
930 
931 static struct snd_kcontrol_new cxt5045_test_mixer[] = {
932 
933 	/* Output controls */
934 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
935 	HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
936 	HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT),
937 	HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT),
938 	HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
939 	HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
940 
941 	/* Modes for retasking pin widgets */
942 	CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
943 	CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
944 
945 	/* EAPD Switch Control */
946 	CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
947 
948 	/* Loopback mixer controls */
949 
950 	HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT),
951 	HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT),
952 	HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT),
953 	HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT),
954 	HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT),
955 	HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT),
956 	HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT),
957 	HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT),
958 	HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT),
959 	HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT),
960 	{
961 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
962 		.name = "Input Source",
963 		.info = conexant_mux_enum_info,
964 		.get = conexant_mux_enum_get,
965 		.put = conexant_mux_enum_put,
966 	},
967 	/* Audio input controls */
968 	HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
969 	HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
970 	HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
971 	HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
972 	HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
973 	HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
974 	HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
975 	HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
976 	HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
977 	HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
978 	{ } /* end */
979 };
980 
981 static struct hda_verb cxt5045_test_init_verbs[] = {
982 	/* Set connections */
983 	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
984 	{ 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
985 	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
986 	/* Enable retasking pins as output, initially without power amp */
987 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
988 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
989 
990 	/* Disable digital (SPDIF) pins initially, but users can enable
991 	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
992 	 * payload also sets the generation to 0, output to be in "consumer"
993 	 * PCM format, copyright asserted, no pre-emphasis and no validity
994 	 * control.
995 	 */
996 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
997 	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
998 
999 	/* Start with output sum widgets muted and their output gains at min */
1000 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1001 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1002 
1003 	/* Unmute retasking pin widget output buffers since the default
1004 	 * state appears to be output.  As the pin mode is changed by the
1005 	 * user the pin mode control will take care of enabling the pin's
1006 	 * input/output buffers as needed.
1007 	 */
1008 	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1009 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1010 
1011 	/* Mute capture amp left and right */
1012 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1013 
1014 	/* Set ADC connection select to match default mixer setting (mic1
1015 	 * pin)
1016 	 */
1017 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1018 	{0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1019 
1020 	/* Mute all inputs to mixer widget (even unconnected ones) */
1021 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
1022 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
1023 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
1024 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
1025 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1026 
1027 	{ }
1028 };
1029 #endif
1030 
1031 
1032 /* initialize jack-sensing, too */
1033 static int cxt5045_init(struct hda_codec *codec)
1034 {
1035 	conexant_init(codec);
1036 	cxt5045_hp_automute(codec);
1037 	return 0;
1038 }
1039 
1040 
1041 enum {
1042 	CXT5045_LAPTOP_HPSENSE,
1043 	CXT5045_LAPTOP_MICSENSE,
1044 	CXT5045_LAPTOP_HPMICSENSE,
1045 	CXT5045_BENQ,
1046 	CXT5045_LAPTOP_HP530,
1047 #ifdef CONFIG_SND_DEBUG
1048 	CXT5045_TEST,
1049 #endif
1050 	CXT5045_MODELS
1051 };
1052 
1053 static const char * const cxt5045_models[CXT5045_MODELS] = {
1054 	[CXT5045_LAPTOP_HPSENSE]	= "laptop-hpsense",
1055 	[CXT5045_LAPTOP_MICSENSE]	= "laptop-micsense",
1056 	[CXT5045_LAPTOP_HPMICSENSE]	= "laptop-hpmicsense",
1057 	[CXT5045_BENQ]			= "benq",
1058 	[CXT5045_LAPTOP_HP530]		= "laptop-hp530",
1059 #ifdef CONFIG_SND_DEBUG
1060 	[CXT5045_TEST]		= "test",
1061 #endif
1062 };
1063 
1064 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
1065 	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
1066 	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1067 			   CXT5045_LAPTOP_HPSENSE),
1068 	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
1069 	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
1070 	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
1071 	SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
1072 	SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
1073 		      CXT5045_LAPTOP_HPMICSENSE),
1074 	SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1075 	SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1076 	SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1077 	SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
1078 			   CXT5045_LAPTOP_HPMICSENSE),
1079 	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
1080 	{}
1081 };
1082 
1083 static int patch_cxt5045(struct hda_codec *codec)
1084 {
1085 	struct conexant_spec *spec;
1086 	int board_config;
1087 
1088 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1089 	if (!spec)
1090 		return -ENOMEM;
1091 	codec->spec = spec;
1092 	codec->pin_amp_workaround = 1;
1093 
1094 	spec->multiout.max_channels = 2;
1095 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
1096 	spec->multiout.dac_nids = cxt5045_dac_nids;
1097 	spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
1098 	spec->num_adc_nids = 1;
1099 	spec->adc_nids = cxt5045_adc_nids;
1100 	spec->capsrc_nids = cxt5045_capsrc_nids;
1101 	spec->input_mux = &cxt5045_capture_source;
1102 	spec->num_mixers = 1;
1103 	spec->mixers[0] = cxt5045_mixers;
1104 	spec->num_init_verbs = 1;
1105 	spec->init_verbs[0] = cxt5045_init_verbs;
1106 	spec->spdif_route = 0;
1107 	spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
1108 	spec->channel_mode = cxt5045_modes;
1109 
1110 	set_beep_amp(spec, 0x16, 0, 1);
1111 
1112 	codec->patch_ops = conexant_patch_ops;
1113 
1114 	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
1115 						  cxt5045_models,
1116 						  cxt5045_cfg_tbl);
1117 	switch (board_config) {
1118 	case CXT5045_LAPTOP_HPSENSE:
1119 		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1120 		spec->input_mux = &cxt5045_capture_source;
1121 		spec->num_init_verbs = 2;
1122 		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1123 		spec->mixers[0] = cxt5045_mixers;
1124 		codec->patch_ops.init = cxt5045_init;
1125 		break;
1126 	case CXT5045_LAPTOP_MICSENSE:
1127 		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1128 		spec->input_mux = &cxt5045_capture_source;
1129 		spec->num_init_verbs = 2;
1130 		spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
1131 		spec->mixers[0] = cxt5045_mixers;
1132 		codec->patch_ops.init = cxt5045_init;
1133 		break;
1134 	default:
1135 	case CXT5045_LAPTOP_HPMICSENSE:
1136 		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1137 		spec->input_mux = &cxt5045_capture_source;
1138 		spec->num_init_verbs = 3;
1139 		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1140 		spec->init_verbs[2] = cxt5045_mic_sense_init_verbs;
1141 		spec->mixers[0] = cxt5045_mixers;
1142 		codec->patch_ops.init = cxt5045_init;
1143 		break;
1144 	case CXT5045_BENQ:
1145 		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1146 		spec->input_mux = &cxt5045_capture_source_benq;
1147 		spec->num_init_verbs = 1;
1148 		spec->init_verbs[0] = cxt5045_benq_init_verbs;
1149 		spec->mixers[0] = cxt5045_mixers;
1150 		spec->mixers[1] = cxt5045_benq_mixers;
1151 		spec->num_mixers = 2;
1152 		codec->patch_ops.init = cxt5045_init;
1153 		break;
1154 	case CXT5045_LAPTOP_HP530:
1155 		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1156 		spec->input_mux = &cxt5045_capture_source_hp530;
1157 		spec->num_init_verbs = 2;
1158 		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1159 		spec->mixers[0] = cxt5045_mixers_hp530;
1160 		codec->patch_ops.init = cxt5045_init;
1161 		break;
1162 #ifdef CONFIG_SND_DEBUG
1163 	case CXT5045_TEST:
1164 		spec->input_mux = &cxt5045_test_capture_source;
1165 		spec->mixers[0] = cxt5045_test_mixer;
1166 		spec->init_verbs[0] = cxt5045_test_init_verbs;
1167 		break;
1168 
1169 #endif
1170 	}
1171 
1172 	switch (codec->subsystem_id >> 16) {
1173 	case 0x103c:
1174 	case 0x1631:
1175 	case 0x1734:
1176 	case 0x17aa:
1177 		/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
1178 		 * really bad sound over 0dB on NID 0x17. Fix max PCM level to
1179 		 * 0 dB (originally it has 0x2b steps with 0dB offset 0x14)
1180 		 */
1181 		snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1182 					  (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
1183 					  (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1184 					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1185 					  (1 << AC_AMPCAP_MUTE_SHIFT));
1186 		break;
1187 	}
1188 
1189 	if (spec->beep_amp)
1190 		snd_hda_attach_beep_device(codec, spec->beep_amp);
1191 
1192 	return 0;
1193 }
1194 
1195 
1196 /* Conexant 5047 specific */
1197 #define CXT5047_SPDIF_OUT	0x11
1198 
1199 static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
1200 static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
1201 static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
1202 
1203 static struct hda_channel_mode cxt5047_modes[1] = {
1204 	{ 2, NULL },
1205 };
1206 
1207 static struct hda_input_mux cxt5047_toshiba_capture_source = {
1208 	.num_items = 2,
1209 	.items = {
1210 		{ "ExtMic", 0x2 },
1211 		{ "Line-In", 0x1 },
1212 	}
1213 };
1214 
1215 /* turn on/off EAPD (+ mute HP) as a master switch */
1216 static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1217 				    struct snd_ctl_elem_value *ucontrol)
1218 {
1219 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1220 	struct conexant_spec *spec = codec->spec;
1221 	unsigned int bits;
1222 
1223 	if (!cxt_eapd_put(kcontrol, ucontrol))
1224 		return 0;
1225 
1226 	/* toggle internal speakers mute depending of presence of
1227 	 * the headphone jack
1228 	 */
1229 	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
1230 	/* NOTE: Conexat codec needs the index for *OUTPUT* amp of
1231 	 * pin widgets unlike other codecs.  In this case, we need to
1232 	 * set index 0x01 for the volume from the mixer amp 0x19.
1233 	 */
1234 	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1235 				 HDA_AMP_MUTE, bits);
1236 	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
1237 	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
1238 				 HDA_AMP_MUTE, bits);
1239 	return 1;
1240 }
1241 
1242 /* mute internal speaker if HP is plugged */
1243 static void cxt5047_hp_automute(struct hda_codec *codec)
1244 {
1245 	struct conexant_spec *spec = codec->spec;
1246 	unsigned int bits;
1247 
1248 	spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1249 
1250 	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1251 	/* See the note in cxt5047_hp_master_sw_put */
1252 	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1253 				 HDA_AMP_MUTE, bits);
1254 }
1255 
1256 /* toggle input of built-in and mic jack appropriately */
1257 static void cxt5047_hp_automic(struct hda_codec *codec)
1258 {
1259 	static struct hda_verb mic_jack_on[] = {
1260 		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1261 		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1262 		{}
1263 	};
1264 	static struct hda_verb mic_jack_off[] = {
1265 		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1266 		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1267 		{}
1268 	};
1269 	unsigned int present;
1270 
1271 	present = snd_hda_jack_detect(codec, 0x15);
1272 	if (present)
1273 		snd_hda_sequence_write(codec, mic_jack_on);
1274 	else
1275 		snd_hda_sequence_write(codec, mic_jack_off);
1276 }
1277 
1278 /* unsolicited event for HP jack sensing */
1279 static void cxt5047_hp_unsol_event(struct hda_codec *codec,
1280 				  unsigned int res)
1281 {
1282 	switch (res >> 26) {
1283 	case CONEXANT_HP_EVENT:
1284 		cxt5047_hp_automute(codec);
1285 		break;
1286 	case CONEXANT_MIC_EVENT:
1287 		cxt5047_hp_automic(codec);
1288 		break;
1289 	}
1290 }
1291 
1292 static struct snd_kcontrol_new cxt5047_base_mixers[] = {
1293 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
1294 	HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
1295 	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1296 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1297 	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1298 	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
1299 	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
1300 	{
1301 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1302 		.name = "Master Playback Switch",
1303 		.info = cxt_eapd_info,
1304 		.get = cxt_eapd_get,
1305 		.put = cxt5047_hp_master_sw_put,
1306 		.private_value = 0x13,
1307 	},
1308 
1309 	{}
1310 };
1311 
1312 static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
1313 	/* See the note in cxt5047_hp_master_sw_put */
1314 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
1315 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1316 	{}
1317 };
1318 
1319 static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
1320 	HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1321 	{ } /* end */
1322 };
1323 
1324 static struct hda_verb cxt5047_init_verbs[] = {
1325 	/* Line in, Mic, Built-in Mic */
1326 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1327 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1328 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1329 	/* HP, Speaker  */
1330 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1331 	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
1332 	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
1333 	/* Record selector: Mic */
1334 	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
1335 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
1336 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
1337 	{0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
1338 	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1339 	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
1340 	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1341 	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
1342 	/* SPDIF route: PCM */
1343 	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
1344 	/* Enable unsolicited events */
1345 	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
1346 	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
1347 	{ } /* end */
1348 };
1349 
1350 /* configuration for Toshiba Laptops */
1351 static struct hda_verb cxt5047_toshiba_init_verbs[] = {
1352 	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
1353 	{}
1354 };
1355 
1356 /* Test configuration for debugging, modelled after the ALC260 test
1357  * configuration.
1358  */
1359 #ifdef CONFIG_SND_DEBUG
1360 static struct hda_input_mux cxt5047_test_capture_source = {
1361 	.num_items = 4,
1362 	.items = {
1363 		{ "LINE1 pin", 0x0 },
1364 		{ "MIC1 pin", 0x1 },
1365 		{ "MIC2 pin", 0x2 },
1366 		{ "CD pin", 0x3 },
1367         },
1368 };
1369 
1370 static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1371 
1372 	/* Output only controls */
1373 	HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
1374 	HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
1375 	HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
1376 	HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
1377 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1378 	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1379 	HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1380 	HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1381 	HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
1382 	HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1383 	HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
1384 	HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1385 
1386 	/* Modes for retasking pin widgets */
1387 	CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
1388 	CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
1389 
1390 	/* EAPD Switch Control */
1391 	CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
1392 
1393 	/* Loopback mixer controls */
1394 	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
1395 	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
1396 	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
1397 	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
1398 	HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
1399 	HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
1400 	HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
1401 	HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
1402 
1403 	HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
1404 	HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
1405 	HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
1406 	HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
1407 	HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
1408 	HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
1409 	HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
1410 	HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
1411 	{
1412 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1413 		.name = "Input Source",
1414 		.info = conexant_mux_enum_info,
1415 		.get = conexant_mux_enum_get,
1416 		.put = conexant_mux_enum_put,
1417 	},
1418 	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1419 
1420 	{ } /* end */
1421 };
1422 
1423 static struct hda_verb cxt5047_test_init_verbs[] = {
1424 	/* Enable retasking pins as output, initially without power amp */
1425 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1426 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1427 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1428 
1429 	/* Disable digital (SPDIF) pins initially, but users can enable
1430 	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
1431 	 * payload also sets the generation to 0, output to be in "consumer"
1432 	 * PCM format, copyright asserted, no pre-emphasis and no validity
1433 	 * control.
1434 	 */
1435 	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
1436 
1437 	/* Ensure mic1, mic2, line1 pin widgets take input from the
1438 	 * OUT1 sum bus when acting as an output.
1439 	 */
1440 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0},
1441 	{0x1b, AC_VERB_SET_CONNECT_SEL, 0},
1442 
1443 	/* Start with output sum widgets muted and their output gains at min */
1444 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1445 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1446 
1447 	/* Unmute retasking pin widget output buffers since the default
1448 	 * state appears to be output.  As the pin mode is changed by the
1449 	 * user the pin mode control will take care of enabling the pin's
1450 	 * input/output buffers as needed.
1451 	 */
1452 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1453 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1454 	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1455 
1456 	/* Mute capture amp left and right */
1457 	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1458 
1459 	/* Set ADC connection select to match default mixer setting (mic1
1460 	 * pin)
1461 	 */
1462 	{0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
1463 
1464 	/* Mute all inputs to mixer widget (even unconnected ones) */
1465 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
1466 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
1467 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
1468 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
1469 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1470 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
1471 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
1472 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
1473 
1474 	{ }
1475 };
1476 #endif
1477 
1478 
1479 /* initialize jack-sensing, too */
1480 static int cxt5047_hp_init(struct hda_codec *codec)
1481 {
1482 	conexant_init(codec);
1483 	cxt5047_hp_automute(codec);
1484 	return 0;
1485 }
1486 
1487 
1488 enum {
1489 	CXT5047_LAPTOP,		/* Laptops w/o EAPD support */
1490 	CXT5047_LAPTOP_HP,	/* Some HP laptops */
1491 	CXT5047_LAPTOP_EAPD,	/* Laptops with EAPD support */
1492 #ifdef CONFIG_SND_DEBUG
1493 	CXT5047_TEST,
1494 #endif
1495 	CXT5047_MODELS
1496 };
1497 
1498 static const char * const cxt5047_models[CXT5047_MODELS] = {
1499 	[CXT5047_LAPTOP]	= "laptop",
1500 	[CXT5047_LAPTOP_HP]	= "laptop-hp",
1501 	[CXT5047_LAPTOP_EAPD]	= "laptop-eapd",
1502 #ifdef CONFIG_SND_DEBUG
1503 	[CXT5047_TEST]		= "test",
1504 #endif
1505 };
1506 
1507 static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1508 	SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
1509 	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1510 			   CXT5047_LAPTOP),
1511 	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
1512 	{}
1513 };
1514 
1515 static int patch_cxt5047(struct hda_codec *codec)
1516 {
1517 	struct conexant_spec *spec;
1518 	int board_config;
1519 
1520 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1521 	if (!spec)
1522 		return -ENOMEM;
1523 	codec->spec = spec;
1524 	codec->pin_amp_workaround = 1;
1525 
1526 	spec->multiout.max_channels = 2;
1527 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
1528 	spec->multiout.dac_nids = cxt5047_dac_nids;
1529 	spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
1530 	spec->num_adc_nids = 1;
1531 	spec->adc_nids = cxt5047_adc_nids;
1532 	spec->capsrc_nids = cxt5047_capsrc_nids;
1533 	spec->num_mixers = 1;
1534 	spec->mixers[0] = cxt5047_base_mixers;
1535 	spec->num_init_verbs = 1;
1536 	spec->init_verbs[0] = cxt5047_init_verbs;
1537 	spec->spdif_route = 0;
1538 	spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
1539 	spec->channel_mode = cxt5047_modes,
1540 
1541 	codec->patch_ops = conexant_patch_ops;
1542 
1543 	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1544 						  cxt5047_models,
1545 						  cxt5047_cfg_tbl);
1546 	switch (board_config) {
1547 	case CXT5047_LAPTOP:
1548 		spec->num_mixers = 2;
1549 		spec->mixers[1] = cxt5047_hp_spk_mixers;
1550 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1551 		break;
1552 	case CXT5047_LAPTOP_HP:
1553 		spec->num_mixers = 2;
1554 		spec->mixers[1] = cxt5047_hp_only_mixers;
1555 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1556 		codec->patch_ops.init = cxt5047_hp_init;
1557 		break;
1558 	case CXT5047_LAPTOP_EAPD:
1559 		spec->input_mux = &cxt5047_toshiba_capture_source;
1560 		spec->num_mixers = 2;
1561 		spec->mixers[1] = cxt5047_hp_spk_mixers;
1562 		spec->num_init_verbs = 2;
1563 		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
1564 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1565 		break;
1566 #ifdef CONFIG_SND_DEBUG
1567 	case CXT5047_TEST:
1568 		spec->input_mux = &cxt5047_test_capture_source;
1569 		spec->mixers[0] = cxt5047_test_mixer;
1570 		spec->init_verbs[0] = cxt5047_test_init_verbs;
1571 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1572 #endif
1573 	}
1574 	spec->vmaster_nid = 0x13;
1575 
1576 	switch (codec->subsystem_id >> 16) {
1577 	case 0x103c:
1578 		/* HP laptops have really bad sound over 0 dB on NID 0x10.
1579 		 * Fix max PCM level to 0 dB (originally it has 0x1e steps
1580 		 * with 0 dB offset 0x17)
1581 		 */
1582 		snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
1583 					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1584 					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1585 					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1586 					  (1 << AC_AMPCAP_MUTE_SHIFT));
1587 		break;
1588 	}
1589 
1590 	return 0;
1591 }
1592 
1593 /* Conexant 5051 specific */
1594 static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1595 static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
1596 
1597 static struct hda_channel_mode cxt5051_modes[1] = {
1598 	{ 2, NULL },
1599 };
1600 
1601 static void cxt5051_update_speaker(struct hda_codec *codec)
1602 {
1603 	struct conexant_spec *spec = codec->spec;
1604 	unsigned int pinctl;
1605 	/* headphone pin */
1606 	pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
1607 	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1608 			    pinctl);
1609 	/* speaker pin */
1610 	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1611 	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1612 			    pinctl);
1613 	/* on ideapad there is an aditional speaker (subwoofer) to mute */
1614 	if (spec->ideapad)
1615 		snd_hda_codec_write(codec, 0x1b, 0,
1616 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
1617 				    pinctl);
1618 }
1619 
1620 /* turn on/off EAPD (+ mute HP) as a master switch */
1621 static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1622 				    struct snd_ctl_elem_value *ucontrol)
1623 {
1624 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1625 
1626 	if (!cxt_eapd_put(kcontrol, ucontrol))
1627 		return 0;
1628 	cxt5051_update_speaker(codec);
1629 	return 1;
1630 }
1631 
1632 /* toggle input of built-in and mic jack appropriately */
1633 static void cxt5051_portb_automic(struct hda_codec *codec)
1634 {
1635 	struct conexant_spec *spec = codec->spec;
1636 	unsigned int present;
1637 
1638 	if (!(spec->auto_mic & AUTO_MIC_PORTB))
1639 		return;
1640 	present = snd_hda_jack_detect(codec, 0x17);
1641 	snd_hda_codec_write(codec, 0x14, 0,
1642 			    AC_VERB_SET_CONNECT_SEL,
1643 			    present ? 0x01 : 0x00);
1644 }
1645 
1646 /* switch the current ADC according to the jack state */
1647 static void cxt5051_portc_automic(struct hda_codec *codec)
1648 {
1649 	struct conexant_spec *spec = codec->spec;
1650 	unsigned int present;
1651 	hda_nid_t new_adc;
1652 
1653 	if (!(spec->auto_mic & AUTO_MIC_PORTC))
1654 		return;
1655 	present = snd_hda_jack_detect(codec, 0x18);
1656 	if (present)
1657 		spec->cur_adc_idx = 1;
1658 	else
1659 		spec->cur_adc_idx = 0;
1660 	new_adc = spec->adc_nids[spec->cur_adc_idx];
1661 	if (spec->cur_adc && spec->cur_adc != new_adc) {
1662 		/* stream is running, let's swap the current ADC */
1663 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
1664 		spec->cur_adc = new_adc;
1665 		snd_hda_codec_setup_stream(codec, new_adc,
1666 					   spec->cur_adc_stream_tag, 0,
1667 					   spec->cur_adc_format);
1668 	}
1669 }
1670 
1671 /* mute internal speaker if HP is plugged */
1672 static void cxt5051_hp_automute(struct hda_codec *codec)
1673 {
1674 	struct conexant_spec *spec = codec->spec;
1675 
1676 	spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1677 	cxt5051_update_speaker(codec);
1678 }
1679 
1680 /* unsolicited event for HP jack sensing */
1681 static void cxt5051_hp_unsol_event(struct hda_codec *codec,
1682 				   unsigned int res)
1683 {
1684 	int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
1685 	switch (res >> 26) {
1686 	case CONEXANT_HP_EVENT:
1687 		cxt5051_hp_automute(codec);
1688 		break;
1689 	case CXT5051_PORTB_EVENT:
1690 		cxt5051_portb_automic(codec);
1691 		break;
1692 	case CXT5051_PORTC_EVENT:
1693 		cxt5051_portc_automic(codec);
1694 		break;
1695 	}
1696 	snd_hda_input_jack_report(codec, nid);
1697 }
1698 
1699 static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
1700 	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1701 	{
1702 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1703 		.name = "Master Playback Switch",
1704 		.info = cxt_eapd_info,
1705 		.get = cxt_eapd_get,
1706 		.put = cxt5051_hp_master_sw_put,
1707 		.private_value = 0x1a,
1708 	},
1709 	{}
1710 };
1711 
1712 static struct snd_kcontrol_new cxt5051_capture_mixers[] = {
1713 	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1714 	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1715 	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
1716 	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
1717 	HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
1718 	HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
1719 	{}
1720 };
1721 
1722 static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
1723 	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1724 	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1725 	HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT),
1726 	HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT),
1727 	{}
1728 };
1729 
1730 static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
1731 	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
1732 	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
1733 	{}
1734 };
1735 
1736 static struct snd_kcontrol_new cxt5051_f700_mixers[] = {
1737 	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
1738 	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
1739 	{}
1740 };
1741 
1742 static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
1743 	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1744 	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1745 	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
1746 	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
1747 	{}
1748 };
1749 
1750 static struct hda_verb cxt5051_init_verbs[] = {
1751 	/* Line in, Mic */
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},
1758 	/* SPK  */
1759 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1760 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1761 	/* HP, Amp  */
1762 	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1763 	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1764 	/* DAC1 */
1765 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1766 	/* Record selector: Internal 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_PIN_WIDGET_CONTROL, PIN_OUT},
1772 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1773 	/* EAPD */
1774 	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1775 	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1776 	{ } /* end */
1777 };
1778 
1779 static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1780 	/* Line in, Mic */
1781 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1782 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1783 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1784 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1785 	/* SPK  */
1786 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1787 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1788 	/* HP, Amp  */
1789 	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1790 	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1791 	/* DAC1 */
1792 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1793 	/* Record selector: Internal mic */
1794 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1795 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1796 	/* SPDIF route: PCM */
1797 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1798 	/* EAPD */
1799 	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1800 	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1801 	{ } /* end */
1802 };
1803 
1804 static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1805 	/* Line in, Mic */
1806 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1807 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1808 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1809 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1810 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1811 	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1812 	/* SPK  */
1813 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1814 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1815 	/* HP, Amp  */
1816 	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1817 	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1818 	/* Docking HP */
1819 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1820 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
1821 	/* DAC1 */
1822 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1823 	/* Record selector: Internal mic */
1824 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1825 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1826 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1827 	/* SPDIF route: PCM */
1828 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* needed for W500 Advanced Mini Dock 250410 */
1829 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1830 	/* EAPD */
1831 	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1832 	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1833 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1834 	{ } /* end */
1835 };
1836 
1837 static struct hda_verb cxt5051_f700_init_verbs[] = {
1838 	/* Line in, Mic */
1839 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1840 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1841 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1842 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1843 	/* SPK  */
1844 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1845 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1846 	/* HP, Amp  */
1847 	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1848 	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1849 	/* DAC1 */
1850 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1851 	/* Record selector: Internal mic */
1852 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1853 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1854 	/* SPDIF route: PCM */
1855 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1856 	/* EAPD */
1857 	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1858 	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1859 	{ } /* end */
1860 };
1861 
1862 static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
1863 				 unsigned int event)
1864 {
1865 	snd_hda_codec_write(codec, nid, 0,
1866 			    AC_VERB_SET_UNSOLICITED_ENABLE,
1867 			    AC_USRSP_EN | event);
1868 	snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
1869 	snd_hda_input_jack_report(codec, nid);
1870 }
1871 
1872 static struct hda_verb cxt5051_ideapad_init_verbs[] = {
1873 	/* Subwoofer */
1874 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1875 	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1876 	{ } /* end */
1877 };
1878 
1879 /* initialize jack-sensing, too */
1880 static int cxt5051_init(struct hda_codec *codec)
1881 {
1882 	struct conexant_spec *spec = codec->spec;
1883 
1884 	conexant_init(codec);
1885 	conexant_init_jacks(codec);
1886 
1887 	if (spec->auto_mic & AUTO_MIC_PORTB)
1888 		cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
1889 	if (spec->auto_mic & AUTO_MIC_PORTC)
1890 		cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT);
1891 
1892 	if (codec->patch_ops.unsol_event) {
1893 		cxt5051_hp_automute(codec);
1894 		cxt5051_portb_automic(codec);
1895 		cxt5051_portc_automic(codec);
1896 	}
1897 	return 0;
1898 }
1899 
1900 
1901 enum {
1902 	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
1903 	CXT5051_HP,	/* no docking */
1904 	CXT5051_HP_DV6736,	/* HP without mic switch */
1905 	CXT5051_LENOVO_X200,	/* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
1906 	CXT5051_F700,       /* HP Compaq Presario F700 */
1907 	CXT5051_TOSHIBA,	/* Toshiba M300 & co */
1908 	CXT5051_IDEAPAD,	/* Lenovo IdeaPad Y430 */
1909 	CXT5051_MODELS
1910 };
1911 
1912 static const char *const cxt5051_models[CXT5051_MODELS] = {
1913 	[CXT5051_LAPTOP]	= "laptop",
1914 	[CXT5051_HP]		= "hp",
1915 	[CXT5051_HP_DV6736]	= "hp-dv6736",
1916 	[CXT5051_LENOVO_X200]	= "lenovo-x200",
1917 	[CXT5051_F700]          = "hp-700",
1918 	[CXT5051_TOSHIBA]	= "toshiba",
1919 	[CXT5051_IDEAPAD]	= "ideapad",
1920 };
1921 
1922 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1923 	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
1924 	SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
1925 	SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
1926 	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA),
1927 	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
1928 		      CXT5051_LAPTOP),
1929 	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1930 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
1931 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
1932 	{}
1933 };
1934 
1935 static int patch_cxt5051(struct hda_codec *codec)
1936 {
1937 	struct conexant_spec *spec;
1938 	int board_config;
1939 
1940 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1941 	if (!spec)
1942 		return -ENOMEM;
1943 	codec->spec = spec;
1944 	codec->pin_amp_workaround = 1;
1945 
1946 	codec->patch_ops = conexant_patch_ops;
1947 	codec->patch_ops.init = cxt5051_init;
1948 
1949 	spec->multiout.max_channels = 2;
1950 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids);
1951 	spec->multiout.dac_nids = cxt5051_dac_nids;
1952 	spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
1953 	spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
1954 	spec->adc_nids = cxt5051_adc_nids;
1955 	spec->num_mixers = 2;
1956 	spec->mixers[0] = cxt5051_capture_mixers;
1957 	spec->mixers[1] = cxt5051_playback_mixers;
1958 	spec->num_init_verbs = 1;
1959 	spec->init_verbs[0] = cxt5051_init_verbs;
1960 	spec->spdif_route = 0;
1961 	spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes);
1962 	spec->channel_mode = cxt5051_modes;
1963 	spec->cur_adc = 0;
1964 	spec->cur_adc_idx = 0;
1965 
1966 	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
1967 
1968 	codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1969 
1970 	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
1971 						  cxt5051_models,
1972 						  cxt5051_cfg_tbl);
1973 	spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
1974 	switch (board_config) {
1975 	case CXT5051_HP:
1976 		spec->mixers[0] = cxt5051_hp_mixers;
1977 		break;
1978 	case CXT5051_HP_DV6736:
1979 		spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
1980 		spec->mixers[0] = cxt5051_hp_dv6736_mixers;
1981 		spec->auto_mic = 0;
1982 		break;
1983 	case CXT5051_LENOVO_X200:
1984 		spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
1985 		/* Thinkpad X301 does not have S/PDIF wired and no ability
1986 		   to use a docking station. */
1987 		if (codec->subsystem_id == 0x17aa211f)
1988 			spec->multiout.dig_out_nid = 0;
1989 		break;
1990 	case CXT5051_F700:
1991 		spec->init_verbs[0] = cxt5051_f700_init_verbs;
1992 		spec->mixers[0] = cxt5051_f700_mixers;
1993 		spec->auto_mic = 0;
1994 		break;
1995 	case CXT5051_TOSHIBA:
1996 		spec->mixers[0] = cxt5051_toshiba_mixers;
1997 		spec->auto_mic = AUTO_MIC_PORTB;
1998 		break;
1999 	case CXT5051_IDEAPAD:
2000 		spec->init_verbs[spec->num_init_verbs++] =
2001 			cxt5051_ideapad_init_verbs;
2002 		spec->ideapad = 1;
2003 		break;
2004 	}
2005 
2006 	if (spec->beep_amp)
2007 		snd_hda_attach_beep_device(codec, spec->beep_amp);
2008 
2009 	return 0;
2010 }
2011 
2012 /* Conexant 5066 specific */
2013 
2014 static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
2015 static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
2016 static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
2017 static hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
2018 
2019 /* OLPC's microphone port is DC coupled for use with external sensors,
2020  * therefore we use a 50% mic bias in order to center the input signal with
2021  * the DC input range of the codec. */
2022 #define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
2023 
2024 static struct hda_channel_mode cxt5066_modes[1] = {
2025 	{ 2, NULL },
2026 };
2027 
2028 #define HP_PRESENT_PORT_A	(1 << 0)
2029 #define HP_PRESENT_PORT_D	(1 << 1)
2030 #define hp_port_a_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_A)
2031 #define hp_port_d_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_D)
2032 
2033 static void cxt5066_update_speaker(struct hda_codec *codec)
2034 {
2035 	struct conexant_spec *spec = codec->spec;
2036 	unsigned int pinctl;
2037 
2038 	snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
2039 		    spec->hp_present, spec->cur_eapd);
2040 
2041 	/* Port A (HP) */
2042 	pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
2043 	snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2044 			pinctl);
2045 
2046 	/* Port D (HP/LO) */
2047 	pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
2048 	if (spec->dell_automute || spec->thinkpad) {
2049 		/* Mute if Port A is connected */
2050 		if (hp_port_a_present(spec))
2051 			pinctl = 0;
2052 	} else {
2053 		/* Thinkpad/Dell doesn't give pin-D status */
2054 		if (!hp_port_d_present(spec))
2055 			pinctl = 0;
2056 	}
2057 	snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2058 			pinctl);
2059 
2060 	/* CLASS_D AMP */
2061 	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
2062 	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2063 			pinctl);
2064 }
2065 
2066 /* turn on/off EAPD (+ mute HP) as a master switch */
2067 static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
2068 				    struct snd_ctl_elem_value *ucontrol)
2069 {
2070 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2071 
2072 	if (!cxt_eapd_put(kcontrol, ucontrol))
2073 		return 0;
2074 
2075 	cxt5066_update_speaker(codec);
2076 	return 1;
2077 }
2078 
2079 static const struct hda_input_mux cxt5066_olpc_dc_bias = {
2080 	.num_items = 3,
2081 	.items = {
2082 		{ "Off", PIN_IN },
2083 		{ "50%", PIN_VREF50 },
2084 		{ "80%", PIN_VREF80 },
2085 	},
2086 };
2087 
2088 static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec)
2089 {
2090 	struct conexant_spec *spec = codec->spec;
2091 	/* Even though port F is the DC input, the bias is controlled on port B.
2092 	 * we also leave that port as an active input (but unselected) in DC mode
2093 	 * just in case that is necessary to make the bias setting take effect. */
2094 	return snd_hda_codec_write_cache(codec, 0x1a, 0,
2095 		AC_VERB_SET_PIN_WIDGET_CONTROL,
2096 		cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index);
2097 }
2098 
2099 /* OLPC defers mic widget control until when capture is started because the
2100  * microphone LED comes on as soon as these settings are put in place. if we
2101  * did this before recording, it would give the false indication that recording
2102  * is happening when it is not. */
2103 static void cxt5066_olpc_select_mic(struct hda_codec *codec)
2104 {
2105 	struct conexant_spec *spec = codec->spec;
2106 	if (!spec->recording)
2107 		return;
2108 
2109 	if (spec->dc_enable) {
2110 		/* in DC mode we ignore presence detection and just use the jack
2111 		 * through our special DC port */
2112 		const struct hda_verb enable_dc_mode[] = {
2113 			/* disble internal mic, port C */
2114 			{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2115 
2116 			/* enable DC capture, port F */
2117 			{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2118 			{},
2119 		};
2120 
2121 		snd_hda_sequence_write(codec, enable_dc_mode);
2122 		/* port B input disabled (and bias set) through the following call */
2123 		cxt5066_set_olpc_dc_bias(codec);
2124 		return;
2125 	}
2126 
2127 	/* disable DC (port F) */
2128 	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
2129 
2130 	/* external mic, port B */
2131 	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2132 		spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0);
2133 
2134 	/* internal mic, port C */
2135 	snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2136 		spec->ext_mic_present ? 0 : PIN_VREF80);
2137 }
2138 
2139 /* toggle input of built-in and mic jack appropriately */
2140 static void cxt5066_olpc_automic(struct hda_codec *codec)
2141 {
2142 	struct conexant_spec *spec = codec->spec;
2143 	unsigned int present;
2144 
2145 	if (spec->dc_enable) /* don't do presence detection in DC mode */
2146 		return;
2147 
2148 	present = snd_hda_codec_read(codec, 0x1a, 0,
2149 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2150 	if (present)
2151 		snd_printdd("CXT5066: external microphone detected\n");
2152 	else
2153 		snd_printdd("CXT5066: external microphone absent\n");
2154 
2155 	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
2156 		present ? 0 : 1);
2157 	spec->ext_mic_present = !!present;
2158 
2159 	cxt5066_olpc_select_mic(codec);
2160 }
2161 
2162 /* toggle input of built-in digital mic and mic jack appropriately */
2163 static void cxt5066_vostro_automic(struct hda_codec *codec)
2164 {
2165 	unsigned int present;
2166 
2167 	struct hda_verb ext_mic_present[] = {
2168 		/* enable external mic, port B */
2169 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2170 
2171 		/* switch to external mic input */
2172 		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
2173 		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
2174 
2175 		/* disable internal digital mic */
2176 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2177 		{}
2178 	};
2179 	static struct hda_verb ext_mic_absent[] = {
2180 		/* enable internal mic, port C */
2181 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2182 
2183 		/* switch to internal mic input */
2184 		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
2185 
2186 		/* disable external mic, port B */
2187 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2188 		{}
2189 	};
2190 
2191 	present = snd_hda_jack_detect(codec, 0x1a);
2192 	if (present) {
2193 		snd_printdd("CXT5066: external microphone detected\n");
2194 		snd_hda_sequence_write(codec, ext_mic_present);
2195 	} else {
2196 		snd_printdd("CXT5066: external microphone absent\n");
2197 		snd_hda_sequence_write(codec, ext_mic_absent);
2198 	}
2199 }
2200 
2201 /* toggle input of built-in digital mic and mic jack appropriately */
2202 static void cxt5066_ideapad_automic(struct hda_codec *codec)
2203 {
2204 	unsigned int present;
2205 
2206 	struct hda_verb ext_mic_present[] = {
2207 		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
2208 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2209 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2210 		{}
2211 	};
2212 	static struct hda_verb ext_mic_absent[] = {
2213 		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
2214 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2215 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2216 		{}
2217 	};
2218 
2219 	present = snd_hda_jack_detect(codec, 0x1b);
2220 	if (present) {
2221 		snd_printdd("CXT5066: external microphone detected\n");
2222 		snd_hda_sequence_write(codec, ext_mic_present);
2223 	} else {
2224 		snd_printdd("CXT5066: external microphone absent\n");
2225 		snd_hda_sequence_write(codec, ext_mic_absent);
2226 	}
2227 }
2228 
2229 
2230 /* toggle input of built-in digital mic and mic jack appropriately */
2231 static void cxt5066_asus_automic(struct hda_codec *codec)
2232 {
2233 	unsigned int present;
2234 
2235 	present = snd_hda_jack_detect(codec, 0x1b);
2236 	snd_printdd("CXT5066: external microphone present=%d\n", present);
2237 	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
2238 			    present ? 1 : 0);
2239 }
2240 
2241 
2242 /* toggle input of built-in digital mic and mic jack appropriately */
2243 static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
2244 {
2245 	unsigned int present;
2246 
2247 	present = snd_hda_jack_detect(codec, 0x1b);
2248 	snd_printdd("CXT5066: external microphone present=%d\n", present);
2249 	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
2250 			    present ? 1 : 3);
2251 }
2252 
2253 
2254 /* toggle input of built-in digital mic and mic jack appropriately
2255    order is: external mic -> dock mic -> interal mic */
2256 static void cxt5066_thinkpad_automic(struct hda_codec *codec)
2257 {
2258 	unsigned int ext_present, dock_present;
2259 
2260 	static struct hda_verb ext_mic_present[] = {
2261 		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
2262 		{0x17, AC_VERB_SET_CONNECT_SEL, 1},
2263 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2264 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2265 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2266 		{}
2267 	};
2268 	static struct hda_verb dock_mic_present[] = {
2269 		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
2270 		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
2271 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2272 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2273 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2274 		{}
2275 	};
2276 	static struct hda_verb ext_mic_absent[] = {
2277 		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
2278 		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2279 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2280 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2281 		{}
2282 	};
2283 
2284 	ext_present = snd_hda_jack_detect(codec, 0x1b);
2285 	dock_present = snd_hda_jack_detect(codec, 0x1a);
2286 	if (ext_present) {
2287 		snd_printdd("CXT5066: external microphone detected\n");
2288 		snd_hda_sequence_write(codec, ext_mic_present);
2289 	} else if (dock_present) {
2290 		snd_printdd("CXT5066: dock microphone detected\n");
2291 		snd_hda_sequence_write(codec, dock_mic_present);
2292 	} else {
2293 		snd_printdd("CXT5066: external microphone absent\n");
2294 		snd_hda_sequence_write(codec, ext_mic_absent);
2295 	}
2296 }
2297 
2298 /* mute internal speaker if HP is plugged */
2299 static void cxt5066_hp_automute(struct hda_codec *codec)
2300 {
2301 	struct conexant_spec *spec = codec->spec;
2302 	unsigned int portA, portD;
2303 
2304 	/* Port A */
2305 	portA = snd_hda_jack_detect(codec, 0x19);
2306 
2307 	/* Port D */
2308 	portD = snd_hda_jack_detect(codec, 0x1c);
2309 
2310 	spec->hp_present = portA ? HP_PRESENT_PORT_A : 0;
2311 	spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0;
2312 	snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2313 		portA, portD, spec->hp_present);
2314 	cxt5066_update_speaker(codec);
2315 }
2316 
2317 /* Dispatch the right mic autoswitch function */
2318 static void cxt5066_automic(struct hda_codec *codec)
2319 {
2320 	struct conexant_spec *spec = codec->spec;
2321 
2322 	if (spec->dell_vostro)
2323 		cxt5066_vostro_automic(codec);
2324 	else if (spec->ideapad)
2325 		cxt5066_ideapad_automic(codec);
2326 	else if (spec->thinkpad)
2327 		cxt5066_thinkpad_automic(codec);
2328 	else if (spec->hp_laptop)
2329 		cxt5066_hp_laptop_automic(codec);
2330 	else if (spec->asus)
2331 		cxt5066_asus_automic(codec);
2332 }
2333 
2334 /* unsolicited event for jack sensing */
2335 static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res)
2336 {
2337 	struct conexant_spec *spec = codec->spec;
2338 	snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2339 	switch (res >> 26) {
2340 	case CONEXANT_HP_EVENT:
2341 		cxt5066_hp_automute(codec);
2342 		break;
2343 	case CONEXANT_MIC_EVENT:
2344 		/* ignore mic events in DC mode; we're always using the jack */
2345 		if (!spec->dc_enable)
2346 			cxt5066_olpc_automic(codec);
2347 		break;
2348 	}
2349 }
2350 
2351 /* unsolicited event for jack sensing */
2352 static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2353 {
2354 	snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2355 	switch (res >> 26) {
2356 	case CONEXANT_HP_EVENT:
2357 		cxt5066_hp_automute(codec);
2358 		break;
2359 	case CONEXANT_MIC_EVENT:
2360 		cxt5066_automic(codec);
2361 		break;
2362 	}
2363 }
2364 
2365 
2366 static const struct hda_input_mux cxt5066_analog_mic_boost = {
2367 	.num_items = 5,
2368 	.items = {
2369 		{ "0dB",  0 },
2370 		{ "10dB", 1 },
2371 		{ "20dB", 2 },
2372 		{ "30dB", 3 },
2373 		{ "40dB", 4 },
2374 	},
2375 };
2376 
2377 static void cxt5066_set_mic_boost(struct hda_codec *codec)
2378 {
2379 	struct conexant_spec *spec = codec->spec;
2380 	snd_hda_codec_write_cache(codec, 0x17, 0,
2381 		AC_VERB_SET_AMP_GAIN_MUTE,
2382 		AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
2383 			cxt5066_analog_mic_boost.items[spec->mic_boost].index);
2384 	if (spec->ideapad || spec->thinkpad) {
2385 		/* adjust the internal mic as well...it is not through 0x17 */
2386 		snd_hda_codec_write_cache(codec, 0x23, 0,
2387 			AC_VERB_SET_AMP_GAIN_MUTE,
2388 			AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT |
2389 				cxt5066_analog_mic_boost.
2390 					items[spec->mic_boost].index);
2391 	}
2392 }
2393 
2394 static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
2395 					   struct snd_ctl_elem_info *uinfo)
2396 {
2397 	return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
2398 }
2399 
2400 static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2401 					  struct snd_ctl_elem_value *ucontrol)
2402 {
2403 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2404 	struct conexant_spec *spec = codec->spec;
2405 	ucontrol->value.enumerated.item[0] = spec->mic_boost;
2406 	return 0;
2407 }
2408 
2409 static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2410 					  struct snd_ctl_elem_value *ucontrol)
2411 {
2412 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2413 	struct conexant_spec *spec = codec->spec;
2414 	const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2415 	unsigned int idx;
2416 	idx = ucontrol->value.enumerated.item[0];
2417 	if (idx >= imux->num_items)
2418 		idx = imux->num_items - 1;
2419 
2420 	spec->mic_boost = idx;
2421 	if (!spec->dc_enable)
2422 		cxt5066_set_mic_boost(codec);
2423 	return 1;
2424 }
2425 
2426 static void cxt5066_enable_dc(struct hda_codec *codec)
2427 {
2428 	const struct hda_verb enable_dc_mode[] = {
2429 		/* disable gain */
2430 		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2431 
2432 		/* switch to DC input */
2433 		{0x17, AC_VERB_SET_CONNECT_SEL, 3},
2434 		{}
2435 	};
2436 
2437 	/* configure as input source */
2438 	snd_hda_sequence_write(codec, enable_dc_mode);
2439 	cxt5066_olpc_select_mic(codec); /* also sets configured bias */
2440 }
2441 
2442 static void cxt5066_disable_dc(struct hda_codec *codec)
2443 {
2444 	/* reconfigure input source */
2445 	cxt5066_set_mic_boost(codec);
2446 	/* automic also selects the right mic if we're recording */
2447 	cxt5066_olpc_automic(codec);
2448 }
2449 
2450 static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol,
2451 			     struct snd_ctl_elem_value *ucontrol)
2452 {
2453 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2454 	struct conexant_spec *spec = codec->spec;
2455 	ucontrol->value.integer.value[0] = spec->dc_enable;
2456 	return 0;
2457 }
2458 
2459 static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol,
2460 			     struct snd_ctl_elem_value *ucontrol)
2461 {
2462 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2463 	struct conexant_spec *spec = codec->spec;
2464 	int dc_enable = !!ucontrol->value.integer.value[0];
2465 
2466 	if (dc_enable == spec->dc_enable)
2467 		return 0;
2468 
2469 	spec->dc_enable = dc_enable;
2470 	if (dc_enable)
2471 		cxt5066_enable_dc(codec);
2472 	else
2473 		cxt5066_disable_dc(codec);
2474 
2475 	return 1;
2476 }
2477 
2478 static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol,
2479 					   struct snd_ctl_elem_info *uinfo)
2480 {
2481 	return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo);
2482 }
2483 
2484 static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol,
2485 					  struct snd_ctl_elem_value *ucontrol)
2486 {
2487 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2488 	struct conexant_spec *spec = codec->spec;
2489 	ucontrol->value.enumerated.item[0] = spec->dc_input_bias;
2490 	return 0;
2491 }
2492 
2493 static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol,
2494 					  struct snd_ctl_elem_value *ucontrol)
2495 {
2496 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2497 	struct conexant_spec *spec = codec->spec;
2498 	const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2499 	unsigned int idx;
2500 
2501 	idx = ucontrol->value.enumerated.item[0];
2502 	if (idx >= imux->num_items)
2503 		idx = imux->num_items - 1;
2504 
2505 	spec->dc_input_bias = idx;
2506 	if (spec->dc_enable)
2507 		cxt5066_set_olpc_dc_bias(codec);
2508 	return 1;
2509 }
2510 
2511 static void cxt5066_olpc_capture_prepare(struct hda_codec *codec)
2512 {
2513 	struct conexant_spec *spec = codec->spec;
2514 	/* mark as recording and configure the microphone widget so that the
2515 	 * recording LED comes on. */
2516 	spec->recording = 1;
2517 	cxt5066_olpc_select_mic(codec);
2518 }
2519 
2520 static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec)
2521 {
2522 	struct conexant_spec *spec = codec->spec;
2523 	const struct hda_verb disable_mics[] = {
2524 		/* disable external mic, port B */
2525 		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2526 
2527 		/* disble internal mic, port C */
2528 		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2529 
2530 		/* disable DC capture, port F */
2531 		{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2532 		{},
2533 	};
2534 
2535 	snd_hda_sequence_write(codec, disable_mics);
2536 	spec->recording = 0;
2537 }
2538 
2539 static void conexant_check_dig_outs(struct hda_codec *codec,
2540 				    hda_nid_t *dig_pins,
2541 				    int num_pins)
2542 {
2543 	struct conexant_spec *spec = codec->spec;
2544 	hda_nid_t *nid_loc = &spec->multiout.dig_out_nid;
2545 	int i;
2546 
2547 	for (i = 0; i < num_pins; i++, dig_pins++) {
2548 		unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins);
2549 		if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE)
2550 			continue;
2551 		if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1)
2552 			continue;
2553 		if (spec->slave_dig_outs[0])
2554 			nid_loc++;
2555 		else
2556 			nid_loc = spec->slave_dig_outs;
2557 	}
2558 }
2559 
2560 static struct hda_input_mux cxt5066_capture_source = {
2561 	.num_items = 4,
2562 	.items = {
2563 		{ "Mic B", 0 },
2564 		{ "Mic C", 1 },
2565 		{ "Mic E", 2 },
2566 		{ "Mic F", 3 },
2567 	},
2568 };
2569 
2570 static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2571 	.ops = &snd_hda_bind_vol,
2572 	.values = {
2573 		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2574 		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2575 		0
2576 	},
2577 };
2578 
2579 static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2580 	.ops = &snd_hda_bind_sw,
2581 	.values = {
2582 		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2583 		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2584 		0
2585 	},
2586 };
2587 
2588 static struct snd_kcontrol_new cxt5066_mixer_master[] = {
2589 	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
2590 	{}
2591 };
2592 
2593 static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2594 	{
2595 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2596 		.name = "Master Playback Volume",
2597 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2598 				  SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2599 				  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
2600 		.subdevice = HDA_SUBDEV_AMP_FLAG,
2601 		.info = snd_hda_mixer_amp_volume_info,
2602 		.get = snd_hda_mixer_amp_volume_get,
2603 		.put = snd_hda_mixer_amp_volume_put,
2604 		.tlv = { .c = snd_hda_mixer_amp_tlv },
2605 		/* offset by 28 volume steps to limit minimum gain to -46dB */
2606 		.private_value =
2607 			HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28),
2608 	},
2609 	{}
2610 };
2611 
2612 static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
2613 	{
2614 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2615 		.name = "DC Mode Enable Switch",
2616 		.info = snd_ctl_boolean_mono_info,
2617 		.get = cxt5066_olpc_dc_get,
2618 		.put = cxt5066_olpc_dc_put,
2619 	},
2620 	{
2621 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2622 		.name = "DC Input Bias Enum",
2623 		.info = cxt5066_olpc_dc_bias_enum_info,
2624 		.get = cxt5066_olpc_dc_bias_enum_get,
2625 		.put = cxt5066_olpc_dc_bias_enum_put,
2626 	},
2627 	{}
2628 };
2629 
2630 static struct snd_kcontrol_new cxt5066_mixers[] = {
2631 	{
2632 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2633 		.name = "Master Playback Switch",
2634 		.info = cxt_eapd_info,
2635 		.get = cxt_eapd_get,
2636 		.put = cxt5066_hp_master_sw_put,
2637 		.private_value = 0x1d,
2638 	},
2639 
2640 	{
2641 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2642 		.name = "Analog Mic Boost Capture Enum",
2643 		.info = cxt5066_mic_boost_mux_enum_info,
2644 		.get = cxt5066_mic_boost_mux_enum_get,
2645 		.put = cxt5066_mic_boost_mux_enum_put,
2646 	},
2647 
2648 	HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
2649 	HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
2650 	{}
2651 };
2652 
2653 static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2654 	{
2655 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2656 		.name = "Internal Mic Boost Capture Enum",
2657 		.info = cxt5066_mic_boost_mux_enum_info,
2658 		.get = cxt5066_mic_boost_mux_enum_get,
2659 		.put = cxt5066_mic_boost_mux_enum_put,
2660 		.private_value = 0x23 | 0x100,
2661 	},
2662 	{}
2663 };
2664 
2665 static struct hda_verb cxt5066_init_verbs[] = {
2666 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2667 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2668 	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2669 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2670 
2671 	/* Speakers  */
2672 	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2673 	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2674 
2675 	/* HP, Amp  */
2676 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2677 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2678 
2679 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2680 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2681 
2682 	/* DAC1 */
2683 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2684 
2685 	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2686 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2687 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2688 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2689 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2690 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2691 
2692 	/* no digital microphone support yet */
2693 	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2694 
2695 	/* Audio input selector */
2696 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2697 
2698 	/* SPDIF route: PCM */
2699 	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2700 	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2701 
2702 	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2703 	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2704 
2705 	/* EAPD */
2706 	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2707 
2708 	/* not handling these yet */
2709 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2710 	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2711 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2712 	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2713 	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2714 	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2715 	{0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2716 	{0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2717 	{ } /* end */
2718 };
2719 
2720 static struct hda_verb cxt5066_init_verbs_olpc[] = {
2721 	/* Port A: headphones */
2722 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2723 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2724 
2725 	/* Port B: external microphone */
2726 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2727 
2728 	/* Port C: internal microphone */
2729 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2730 
2731 	/* Port D: unused */
2732 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2733 
2734 	/* Port E: unused, but has primary EAPD */
2735 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2736 	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2737 
2738 	/* Port F: external DC input through microphone port */
2739 	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2740 
2741 	/* Port G: internal speakers */
2742 	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2743 	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2744 
2745 	/* DAC1 */
2746 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2747 
2748 	/* DAC2: unused */
2749 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2750 
2751 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2752 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2753 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2754 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2755 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2756 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2757 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2758 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2759 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2760 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2761 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2762 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2763 
2764 	/* Disable digital microphone port */
2765 	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2766 
2767 	/* Audio input selectors */
2768 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2769 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2770 
2771 	/* Disable SPDIF */
2772 	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2773 	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2774 
2775 	/* enable unsolicited events for Port A and B */
2776 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2777 	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2778 	{ } /* end */
2779 };
2780 
2781 static struct hda_verb cxt5066_init_verbs_vostro[] = {
2782 	/* Port A: headphones */
2783 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2784 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2785 
2786 	/* Port B: external microphone */
2787 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2788 
2789 	/* Port C: unused */
2790 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2791 
2792 	/* Port D: unused */
2793 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2794 
2795 	/* Port E: unused, but has primary EAPD */
2796 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2797 	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2798 
2799 	/* Port F: unused */
2800 	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2801 
2802 	/* Port G: internal speakers */
2803 	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2804 	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2805 
2806 	/* DAC1 */
2807 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2808 
2809 	/* DAC2: unused */
2810 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2811 
2812 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2813 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2814 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2815 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2816 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2817 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2818 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2819 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2820 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2821 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2822 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2823 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2824 
2825 	/* Digital microphone port */
2826 	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2827 
2828 	/* Audio input selectors */
2829 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2830 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2831 
2832 	/* Disable SPDIF */
2833 	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2834 	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2835 
2836 	/* enable unsolicited events for Port A and B */
2837 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2838 	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2839 	{ } /* end */
2840 };
2841 
2842 static struct hda_verb cxt5066_init_verbs_ideapad[] = {
2843 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2844 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2845 	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2846 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2847 
2848 	/* Speakers  */
2849 	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2850 	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2851 
2852 	/* HP, Amp  */
2853 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2854 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2855 
2856 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2857 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2858 
2859 	/* DAC1 */
2860 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2861 
2862 	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2863 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2864 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2865 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2866 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2867 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2868 	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
2869 
2870 	/* Audio input selector */
2871 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
2872 	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
2873 
2874 	/* SPDIF route: PCM */
2875 	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2876 	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2877 
2878 	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2879 	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2880 
2881 	/* internal microphone */
2882 	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
2883 
2884 	/* EAPD */
2885 	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2886 
2887 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2888 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2889 	{ } /* end */
2890 };
2891 
2892 static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
2893 	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2894 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2895 
2896 	/* Port G: internal speakers  */
2897 	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2898 	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2899 
2900 	/* Port A: HP, Amp  */
2901 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2902 	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2903 
2904 	/* Port B: Mic Dock */
2905 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2906 
2907 	/* Port C: Mic */
2908 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2909 
2910 	/* Port D: HP Dock, Amp */
2911 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2912 	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2913 
2914 	/* DAC1 */
2915 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2916 
2917 	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2918 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2919 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2920 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2921 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2922 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2923 	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
2924 
2925 	/* Audio input selector */
2926 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
2927 	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
2928 
2929 	/* SPDIF route: PCM */
2930 	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2931 	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2932 
2933 	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2934 	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2935 
2936 	/* internal microphone */
2937 	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
2938 
2939 	/* EAPD */
2940 	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2941 
2942 	/* enable unsolicited events for Port A, B, C and D */
2943 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2944 	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2945 	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2946 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2947 	{ } /* end */
2948 };
2949 
2950 static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2951 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2952 	{ } /* end */
2953 };
2954 
2955 
2956 static struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
2957 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
2958 	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2959 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2960 	{ } /* end */
2961 };
2962 
2963 /* initialize jack-sensing, too */
2964 static int cxt5066_init(struct hda_codec *codec)
2965 {
2966 	snd_printdd("CXT5066: init\n");
2967 	conexant_init(codec);
2968 	if (codec->patch_ops.unsol_event) {
2969 		cxt5066_hp_automute(codec);
2970 		cxt5066_automic(codec);
2971 	}
2972 	cxt5066_set_mic_boost(codec);
2973 	return 0;
2974 }
2975 
2976 static int cxt5066_olpc_init(struct hda_codec *codec)
2977 {
2978 	struct conexant_spec *spec = codec->spec;
2979 	snd_printdd("CXT5066: init\n");
2980 	conexant_init(codec);
2981 	cxt5066_hp_automute(codec);
2982 	if (!spec->dc_enable) {
2983 		cxt5066_set_mic_boost(codec);
2984 		cxt5066_olpc_automic(codec);
2985 	} else {
2986 		cxt5066_enable_dc(codec);
2987 	}
2988 	return 0;
2989 }
2990 
2991 enum {
2992 	CXT5066_LAPTOP,		/* Laptops w/ EAPD support */
2993 	CXT5066_DELL_LAPTOP,	/* Dell Laptop */
2994 	CXT5066_OLPC_XO_1_5,	/* OLPC XO 1.5 */
2995 	CXT5066_DELL_VOSTRO,	/* Dell Vostro 1015i */
2996 	CXT5066_IDEAPAD,	/* Lenovo IdeaPad U150 */
2997 	CXT5066_THINKPAD,	/* Lenovo ThinkPad T410s, others? */
2998 	CXT5066_ASUS,		/* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
2999 	CXT5066_HP_LAPTOP,      /* HP Laptop */
3000 	CXT5066_MODELS
3001 };
3002 
3003 static const char * const cxt5066_models[CXT5066_MODELS] = {
3004 	[CXT5066_LAPTOP]	= "laptop",
3005 	[CXT5066_DELL_LAPTOP]	= "dell-laptop",
3006 	[CXT5066_OLPC_XO_1_5]	= "olpc-xo-1_5",
3007 	[CXT5066_DELL_VOSTRO]	= "dell-vostro",
3008 	[CXT5066_IDEAPAD]	= "ideapad",
3009 	[CXT5066_THINKPAD]	= "thinkpad",
3010 	[CXT5066_ASUS]		= "asus",
3011 	[CXT5066_HP_LAPTOP]	= "hp-laptop",
3012 };
3013 
3014 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
3015 	SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
3016 	SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
3017 	SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
3018 	SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
3019 	SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
3020 	SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
3021 	SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
3022 	SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
3023 	SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
3024 	SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
3025 	SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
3026 	SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
3027 	SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
3028 	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
3029 	SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
3030 	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
3031 		      CXT5066_LAPTOP),
3032 	SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
3033 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
3034 	SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
3035 	SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
3036  	SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
3037 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
3038 	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
3039 	{}
3040 };
3041 
3042 static int patch_cxt5066(struct hda_codec *codec)
3043 {
3044 	struct conexant_spec *spec;
3045 	int board_config;
3046 
3047 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3048 	if (!spec)
3049 		return -ENOMEM;
3050 	codec->spec = spec;
3051 
3052 	codec->patch_ops = conexant_patch_ops;
3053 	codec->patch_ops.init = conexant_init;
3054 
3055 	spec->dell_automute = 0;
3056 	spec->multiout.max_channels = 2;
3057 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
3058 	spec->multiout.dac_nids = cxt5066_dac_nids;
3059 	conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
3060 	    ARRAY_SIZE(cxt5066_digout_pin_nids));
3061 	spec->num_adc_nids = 1;
3062 	spec->adc_nids = cxt5066_adc_nids;
3063 	spec->capsrc_nids = cxt5066_capsrc_nids;
3064 	spec->input_mux = &cxt5066_capture_source;
3065 
3066 	spec->port_d_mode = PIN_HP;
3067 
3068 	spec->num_init_verbs = 1;
3069 	spec->init_verbs[0] = cxt5066_init_verbs;
3070 	spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
3071 	spec->channel_mode = cxt5066_modes;
3072 	spec->cur_adc = 0;
3073 	spec->cur_adc_idx = 0;
3074 
3075 	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
3076 
3077 	board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3078 						  cxt5066_models, cxt5066_cfg_tbl);
3079 	switch (board_config) {
3080 	default:
3081 	case CXT5066_LAPTOP:
3082 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3083 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3084 		break;
3085 	case CXT5066_DELL_LAPTOP:
3086 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3087 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3088 
3089 		spec->port_d_mode = PIN_OUT;
3090 		spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
3091 		spec->num_init_verbs++;
3092 		spec->dell_automute = 1;
3093 		break;
3094 	case CXT5066_ASUS:
3095 	case CXT5066_HP_LAPTOP:
3096 		codec->patch_ops.init = cxt5066_init;
3097 		codec->patch_ops.unsol_event = cxt5066_unsol_event;
3098 		spec->init_verbs[spec->num_init_verbs] =
3099 			cxt5066_init_verbs_hp_laptop;
3100 		spec->num_init_verbs++;
3101 		spec->hp_laptop = board_config == CXT5066_HP_LAPTOP;
3102 		spec->asus = board_config == CXT5066_ASUS;
3103 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3104 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3105 		/* no S/PDIF out */
3106 		if (board_config == CXT5066_HP_LAPTOP)
3107 			spec->multiout.dig_out_nid = 0;
3108 		/* input source automatically selected */
3109 		spec->input_mux = NULL;
3110 		spec->port_d_mode = 0;
3111 		spec->mic_boost = 3; /* default 30dB gain */
3112 		break;
3113 
3114 	case CXT5066_OLPC_XO_1_5:
3115 		codec->patch_ops.init = cxt5066_olpc_init;
3116 		codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event;
3117 		spec->init_verbs[0] = cxt5066_init_verbs_olpc;
3118 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
3119 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc;
3120 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3121 		spec->port_d_mode = 0;
3122 		spec->mic_boost = 3; /* default 30dB gain */
3123 
3124 		/* no S/PDIF out */
3125 		spec->multiout.dig_out_nid = 0;
3126 
3127 		/* input source automatically selected */
3128 		spec->input_mux = NULL;
3129 
3130 		/* our capture hooks which allow us to turn on the microphone LED
3131 		 * at the right time */
3132 		spec->capture_prepare = cxt5066_olpc_capture_prepare;
3133 		spec->capture_cleanup = cxt5066_olpc_capture_cleanup;
3134 		break;
3135 	case CXT5066_DELL_VOSTRO:
3136 		codec->patch_ops.init = cxt5066_init;
3137 		codec->patch_ops.unsol_event = cxt5066_unsol_event;
3138 		spec->init_verbs[0] = cxt5066_init_verbs_vostro;
3139 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
3140 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3141 		spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
3142 		spec->port_d_mode = 0;
3143 		spec->dell_vostro = 1;
3144 		spec->mic_boost = 3; /* default 30dB gain */
3145 
3146 		/* no S/PDIF out */
3147 		spec->multiout.dig_out_nid = 0;
3148 
3149 		/* input source automatically selected */
3150 		spec->input_mux = NULL;
3151 		break;
3152 	case CXT5066_IDEAPAD:
3153 		codec->patch_ops.init = cxt5066_init;
3154 		codec->patch_ops.unsol_event = cxt5066_unsol_event;
3155 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3156 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3157 		spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
3158 		spec->port_d_mode = 0;
3159 		spec->ideapad = 1;
3160 		spec->mic_boost = 2;	/* default 20dB gain */
3161 
3162 		/* no S/PDIF out */
3163 		spec->multiout.dig_out_nid = 0;
3164 
3165 		/* input source automatically selected */
3166 		spec->input_mux = NULL;
3167 		break;
3168 	case CXT5066_THINKPAD:
3169 		codec->patch_ops.init = cxt5066_init;
3170 		codec->patch_ops.unsol_event = cxt5066_unsol_event;
3171 		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3172 		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3173 		spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
3174 		spec->thinkpad = 1;
3175 		spec->port_d_mode = PIN_OUT;
3176 		spec->mic_boost = 2;	/* default 20dB gain */
3177 
3178 		/* no S/PDIF out */
3179 		spec->multiout.dig_out_nid = 0;
3180 
3181 		/* input source automatically selected */
3182 		spec->input_mux = NULL;
3183 		break;
3184 	}
3185 
3186 	if (spec->beep_amp)
3187 		snd_hda_attach_beep_device(codec, spec->beep_amp);
3188 
3189 	return 0;
3190 }
3191 
3192 /*
3193  * Automatic parser for CX20641 & co
3194  */
3195 
3196 static hda_nid_t cx_auto_adc_nids[] = { 0x14 };
3197 
3198 /* get the connection index of @nid in the widget @mux */
3199 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
3200 				hda_nid_t nid)
3201 {
3202 	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
3203 	int i, nums;
3204 
3205 	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
3206 	for (i = 0; i < nums; i++)
3207 		if (conn[i] == nid)
3208 			return i;
3209 	return -1;
3210 }
3211 
3212 /* get an unassigned DAC from the given list.
3213  * Return the nid if found and reduce the DAC list, or return zero if
3214  * not found
3215  */
3216 static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
3217 				    hda_nid_t *dacs, int *num_dacs)
3218 {
3219 	int i, nums = *num_dacs;
3220 	hda_nid_t ret = 0;
3221 
3222 	for (i = 0; i < nums; i++) {
3223 		if (get_connection_index(codec, pin, dacs[i]) >= 0) {
3224 			ret = dacs[i];
3225 			break;
3226 		}
3227 	}
3228 	if (!ret)
3229 		return 0;
3230 	if (--nums > 0)
3231 		memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t));
3232 	*num_dacs = nums;
3233 	return ret;
3234 }
3235 
3236 #define MAX_AUTO_DACS	5
3237 
3238 /* fill analog DAC list from the widget tree */
3239 static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
3240 {
3241 	hda_nid_t nid, end_nid;
3242 	int nums = 0;
3243 
3244 	end_nid = codec->start_nid + codec->num_nodes;
3245 	for (nid = codec->start_nid; nid < end_nid; nid++) {
3246 		unsigned int wcaps = get_wcaps(codec, nid);
3247 		unsigned int type = get_wcaps_type(wcaps);
3248 		if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) {
3249 			dacs[nums++] = nid;
3250 			if (nums >= MAX_AUTO_DACS)
3251 				break;
3252 		}
3253 	}
3254 	return nums;
3255 }
3256 
3257 /* fill pin_dac_pair list from the pin and dac list */
3258 static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
3259 			      int num_pins, hda_nid_t *dacs, int *rest,
3260 			      struct pin_dac_pair *filled, int type)
3261 {
3262 	int i, nums;
3263 
3264 	nums = 0;
3265 	for (i = 0; i < num_pins; i++) {
3266 		filled[nums].pin = pins[i];
3267 		filled[nums].type = type;
3268 		filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
3269 		nums++;
3270 	}
3271 	return nums;
3272 }
3273 
3274 /* parse analog output paths */
3275 static void cx_auto_parse_output(struct hda_codec *codec)
3276 {
3277 	struct conexant_spec *spec = codec->spec;
3278 	struct auto_pin_cfg *cfg = &spec->autocfg;
3279 	hda_nid_t dacs[MAX_AUTO_DACS];
3280 	int i, j, nums, rest;
3281 
3282 	rest = fill_cx_auto_dacs(codec, dacs);
3283 	/* parse all analog output pins */
3284 	nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
3285 				  dacs, &rest, spec->dac_info,
3286 				  AUTO_PIN_LINE_OUT);
3287 	nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
3288 				  dacs, &rest, spec->dac_info + nums,
3289 				  AUTO_PIN_HP_OUT);
3290 	nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
3291 				  dacs, &rest, spec->dac_info + nums,
3292 				  AUTO_PIN_SPEAKER_OUT);
3293 	spec->dac_info_filled = nums;
3294 	/* fill multiout struct */
3295 	for (i = 0; i < nums; i++) {
3296 		hda_nid_t dac = spec->dac_info[i].dac;
3297 		if (!dac)
3298 			continue;
3299 		switch (spec->dac_info[i].type) {
3300 		case AUTO_PIN_LINE_OUT:
3301 			spec->private_dac_nids[spec->multiout.num_dacs] = dac;
3302 			spec->multiout.num_dacs++;
3303 			break;
3304 		case AUTO_PIN_HP_OUT:
3305 		case AUTO_PIN_SPEAKER_OUT:
3306 			if (!spec->multiout.hp_nid) {
3307 				spec->multiout.hp_nid = dac;
3308 				break;
3309 			}
3310 			for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++)
3311 				if (!spec->multiout.extra_out_nid[j]) {
3312 					spec->multiout.extra_out_nid[j] = dac;
3313 					break;
3314 				}
3315 			break;
3316 		}
3317 	}
3318 	spec->multiout.dac_nids = spec->private_dac_nids;
3319 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3320 
3321 	if (cfg->hp_outs > 0)
3322 		spec->auto_mute = 1;
3323 	spec->vmaster_nid = spec->private_dac_nids[0];
3324 }
3325 
3326 /* auto-mute/unmute speaker and line outs according to headphone jack */
3327 static void cx_auto_hp_automute(struct hda_codec *codec)
3328 {
3329 	struct conexant_spec *spec = codec->spec;
3330 	struct auto_pin_cfg *cfg = &spec->autocfg;
3331 	int i, present;
3332 
3333 	if (!spec->auto_mute)
3334 		return;
3335 	present = 0;
3336 	for (i = 0; i < cfg->hp_outs; i++) {
3337 		if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) {
3338 			present = 1;
3339 			break;
3340 		}
3341 	}
3342 	for (i = 0; i < cfg->line_outs; i++) {
3343 		snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
3344 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
3345 				    present ? 0 : PIN_OUT);
3346 	}
3347 	for (i = 0; !present && i < cfg->line_outs; i++)
3348 		if (snd_hda_jack_detect(codec, cfg->line_out_pins[i]))
3349 			present = 1;
3350 	for (i = 0; i < cfg->speaker_outs; i++) {
3351 		snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
3352 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
3353 				    present ? 0 : PIN_OUT);
3354 	}
3355 }
3356 
3357 /* automatic switch internal and external mic */
3358 static void cx_auto_automic(struct hda_codec *codec)
3359 {
3360 	struct conexant_spec *spec = codec->spec;
3361 	struct auto_pin_cfg *cfg = &spec->autocfg;
3362 	struct hda_input_mux *imux = &spec->private_imux;
3363 	int ext_idx = spec->auto_mic_ext;
3364 
3365 	if (!spec->auto_mic)
3366 		return;
3367 	if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) {
3368 		snd_hda_codec_write(codec, spec->adc_nids[0], 0,
3369 				    AC_VERB_SET_CONNECT_SEL,
3370 				    imux->items[ext_idx].index);
3371 	} else {
3372 		snd_hda_codec_write(codec, spec->adc_nids[0], 0,
3373 				    AC_VERB_SET_CONNECT_SEL,
3374 				    imux->items[!ext_idx].index);
3375 	}
3376 }
3377 
3378 static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
3379 {
3380 	int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
3381 	switch (res >> 26) {
3382 	case CONEXANT_HP_EVENT:
3383 		cx_auto_hp_automute(codec);
3384 		snd_hda_input_jack_report(codec, nid);
3385 		break;
3386 	case CONEXANT_MIC_EVENT:
3387 		cx_auto_automic(codec);
3388 		snd_hda_input_jack_report(codec, nid);
3389 		break;
3390 	}
3391 }
3392 
3393 /* return true if it's an internal-mic pin */
3394 static int is_int_mic(struct hda_codec *codec, hda_nid_t pin)
3395 {
3396 	unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
3397 	return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
3398 		snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT;
3399 }
3400 
3401 /* return true if it's an external-mic pin */
3402 static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin)
3403 {
3404 	unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
3405 	return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
3406 		snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL &&
3407 		(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT);
3408 }
3409 
3410 /* check whether the pin config is suitable for auto-mic switching;
3411  * auto-mic is enabled only when one int-mic and one-ext mic exist
3412  */
3413 static void cx_auto_check_auto_mic(struct hda_codec *codec)
3414 {
3415 	struct conexant_spec *spec = codec->spec;
3416 	struct auto_pin_cfg *cfg = &spec->autocfg;
3417 
3418 	if (is_ext_mic(codec, cfg->inputs[0].pin) &&
3419 	    is_int_mic(codec, cfg->inputs[1].pin)) {
3420 		spec->auto_mic = 1;
3421 		spec->auto_mic_ext = 1;
3422 		return;
3423 	}
3424 	if (is_int_mic(codec, cfg->inputs[1].pin) &&
3425 	    is_ext_mic(codec, cfg->inputs[0].pin)) {
3426 		spec->auto_mic = 1;
3427 		spec->auto_mic_ext = 0;
3428 		return;
3429 	}
3430 }
3431 
3432 static void cx_auto_parse_input(struct hda_codec *codec)
3433 {
3434 	struct conexant_spec *spec = codec->spec;
3435 	struct auto_pin_cfg *cfg = &spec->autocfg;
3436 	struct hda_input_mux *imux;
3437 	int i;
3438 
3439 	imux = &spec->private_imux;
3440 	for (i = 0; i < cfg->num_inputs; i++) {
3441 		int idx = get_connection_index(codec, spec->adc_nids[0],
3442 					       cfg->inputs[i].pin);
3443 		if (idx >= 0) {
3444 			const char *label;
3445 			label = hda_get_autocfg_input_label(codec, cfg, i);
3446 			snd_hda_add_imux_item(imux, label, idx, NULL);
3447 		}
3448 	}
3449 	if (imux->num_items == 2 && cfg->num_inputs == 2)
3450 		cx_auto_check_auto_mic(codec);
3451 	if (imux->num_items > 1 && !spec->auto_mic)
3452 		spec->input_mux = imux;
3453 }
3454 
3455 /* get digital-input audio widget corresponding to the given pin */
3456 static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin)
3457 {
3458 	hda_nid_t nid, end_nid;
3459 
3460 	end_nid = codec->start_nid + codec->num_nodes;
3461 	for (nid = codec->start_nid; nid < end_nid; nid++) {
3462 		unsigned int wcaps = get_wcaps(codec, nid);
3463 		unsigned int type = get_wcaps_type(wcaps);
3464 		if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) {
3465 			if (get_connection_index(codec, nid, pin) >= 0)
3466 				return nid;
3467 		}
3468 	}
3469 	return 0;
3470 }
3471 
3472 static void cx_auto_parse_digital(struct hda_codec *codec)
3473 {
3474 	struct conexant_spec *spec = codec->spec;
3475 	struct auto_pin_cfg *cfg = &spec->autocfg;
3476 	hda_nid_t nid;
3477 
3478 	if (cfg->dig_outs &&
3479 	    snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1)
3480 		spec->multiout.dig_out_nid = nid;
3481 	if (cfg->dig_in_pin)
3482 		spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin);
3483 }
3484 
3485 #ifdef CONFIG_SND_HDA_INPUT_BEEP
3486 static void cx_auto_parse_beep(struct hda_codec *codec)
3487 {
3488 	struct conexant_spec *spec = codec->spec;
3489 	hda_nid_t nid, end_nid;
3490 
3491 	end_nid = codec->start_nid + codec->num_nodes;
3492 	for (nid = codec->start_nid; nid < end_nid; nid++)
3493 		if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
3494 			set_beep_amp(spec, nid, 0, HDA_OUTPUT);
3495 			break;
3496 		}
3497 }
3498 #else
3499 #define cx_auto_parse_beep(codec)
3500 #endif
3501 
3502 static int cx_auto_parse_auto_config(struct hda_codec *codec)
3503 {
3504 	struct conexant_spec *spec = codec->spec;
3505 	int err;
3506 
3507 	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
3508 	if (err < 0)
3509 		return err;
3510 
3511 	cx_auto_parse_output(codec);
3512 	cx_auto_parse_input(codec);
3513 	cx_auto_parse_digital(codec);
3514 	cx_auto_parse_beep(codec);
3515 	return 0;
3516 }
3517 
3518 static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins,
3519 				 hda_nid_t *pins)
3520 {
3521 	int i;
3522 	for (i = 0; i < num_pins; i++) {
3523 		if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
3524 			snd_hda_codec_write(codec, pins[i], 0,
3525 					    AC_VERB_SET_EAPD_BTLENABLE, 0x02);
3526 	}
3527 }
3528 
3529 static void select_connection(struct hda_codec *codec, hda_nid_t pin,
3530 			      hda_nid_t src)
3531 {
3532 	int idx = get_connection_index(codec, pin, src);
3533 	if (idx >= 0)
3534 		snd_hda_codec_write(codec, pin, 0,
3535 				    AC_VERB_SET_CONNECT_SEL, idx);
3536 }
3537 
3538 static void cx_auto_init_output(struct hda_codec *codec)
3539 {
3540 	struct conexant_spec *spec = codec->spec;
3541 	struct auto_pin_cfg *cfg = &spec->autocfg;
3542 	hda_nid_t nid;
3543 	int i;
3544 
3545 	for (i = 0; i < spec->multiout.num_dacs; i++)
3546 		snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0,
3547 				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
3548 
3549 	for (i = 0; i < cfg->hp_outs; i++)
3550 		snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
3551 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
3552 	if (spec->auto_mute) {
3553 		for (i = 0; i < cfg->hp_outs; i++) {
3554 			snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
3555 				    AC_VERB_SET_UNSOLICITED_ENABLE,
3556 				    AC_USRSP_EN | CONEXANT_HP_EVENT);
3557 		}
3558 		cx_auto_hp_automute(codec);
3559 	} else {
3560 		for (i = 0; i < cfg->line_outs; i++)
3561 			snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
3562 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3563 		for (i = 0; i < cfg->speaker_outs; i++)
3564 			snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
3565 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3566 	}
3567 
3568 	for (i = 0; i < spec->dac_info_filled; i++) {
3569 		nid = spec->dac_info[i].dac;
3570 		if (!nid)
3571 			nid = spec->multiout.dac_nids[0];
3572 		select_connection(codec, spec->dac_info[i].pin, nid);
3573 	}
3574 
3575 	/* turn on EAPD */
3576 	cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins);
3577 	cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins);
3578 	cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins);
3579 }
3580 
3581 static void cx_auto_init_input(struct hda_codec *codec)
3582 {
3583 	struct conexant_spec *spec = codec->spec;
3584 	struct auto_pin_cfg *cfg = &spec->autocfg;
3585 	int i;
3586 
3587 	for (i = 0; i < spec->num_adc_nids; i++)
3588 		snd_hda_codec_write(codec, spec->adc_nids[i], 0,
3589 				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0));
3590 
3591 	for (i = 0; i < cfg->num_inputs; i++) {
3592 		unsigned int type;
3593 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
3594 			type = PIN_VREF80;
3595 		else
3596 			type = PIN_IN;
3597 		snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
3598 				    AC_VERB_SET_PIN_WIDGET_CONTROL, type);
3599 	}
3600 
3601 	if (spec->auto_mic) {
3602 		int ext_idx = spec->auto_mic_ext;
3603 		snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0,
3604 				    AC_VERB_SET_UNSOLICITED_ENABLE,
3605 				    AC_USRSP_EN | CONEXANT_MIC_EVENT);
3606 		cx_auto_automic(codec);
3607 	} else {
3608 		for (i = 0; i < spec->num_adc_nids; i++) {
3609 			snd_hda_codec_write(codec, spec->adc_nids[i], 0,
3610 					    AC_VERB_SET_CONNECT_SEL,
3611 					    spec->private_imux.items[0].index);
3612 		}
3613 	}
3614 }
3615 
3616 static void cx_auto_init_digital(struct hda_codec *codec)
3617 {
3618 	struct conexant_spec *spec = codec->spec;
3619 	struct auto_pin_cfg *cfg = &spec->autocfg;
3620 
3621 	if (spec->multiout.dig_out_nid)
3622 		snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0,
3623 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3624 	if (spec->dig_in_nid)
3625 		snd_hda_codec_write(codec, cfg->dig_in_pin, 0,
3626 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
3627 }
3628 
3629 static int cx_auto_init(struct hda_codec *codec)
3630 {
3631 	/*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
3632 	cx_auto_init_output(codec);
3633 	cx_auto_init_input(codec);
3634 	cx_auto_init_digital(codec);
3635 	return 0;
3636 }
3637 
3638 static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
3639 			      const char *dir, int cidx,
3640 			      hda_nid_t nid, int hda_dir, int amp_idx)
3641 {
3642 	static char name[32];
3643 	static struct snd_kcontrol_new knew[] = {
3644 		HDA_CODEC_VOLUME(name, 0, 0, 0),
3645 		HDA_CODEC_MUTE(name, 0, 0, 0),
3646 	};
3647 	static char *sfx[2] = { "Volume", "Switch" };
3648 	int i, err;
3649 
3650 	for (i = 0; i < 2; i++) {
3651 		struct snd_kcontrol *kctl;
3652 		knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
3653 							    hda_dir);
3654 		knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
3655 		knew[i].index = cidx;
3656 		snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]);
3657 		kctl = snd_ctl_new1(&knew[i], codec);
3658 		if (!kctl)
3659 			return -ENOMEM;
3660 		err = snd_hda_ctl_add(codec, nid, kctl);
3661 		if (err < 0)
3662 			return err;
3663 		if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
3664 			break;
3665 	}
3666 	return 0;
3667 }
3668 
3669 #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir)		\
3670 	cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
3671 
3672 #define cx_auto_add_pb_volume(codec, nid, str, idx)			\
3673 	cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
3674 
3675 static int cx_auto_build_output_controls(struct hda_codec *codec)
3676 {
3677 	struct conexant_spec *spec = codec->spec;
3678 	int i, err;
3679 	int num_line = 0, num_hp = 0, num_spk = 0;
3680 	static const char * const texts[3] = { "Front", "Surround", "CLFE" };
3681 
3682 	if (spec->dac_info_filled == 1)
3683 		return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac,
3684 					     "Master", 0);
3685 	for (i = 0; i < spec->dac_info_filled; i++) {
3686 		const char *label;
3687 		int idx, type;
3688 		if (!spec->dac_info[i].dac)
3689 			continue;
3690 		type = spec->dac_info[i].type;
3691 		if (type == AUTO_PIN_LINE_OUT)
3692 			type = spec->autocfg.line_out_type;
3693 		switch (type) {
3694 		case AUTO_PIN_LINE_OUT:
3695 		default:
3696 			label = texts[num_line++];
3697 			idx = 0;
3698 			break;
3699 		case AUTO_PIN_HP_OUT:
3700 			label = "Headphone";
3701 			idx = num_hp++;
3702 			break;
3703 		case AUTO_PIN_SPEAKER_OUT:
3704 			label = "Speaker";
3705 			idx = num_spk++;
3706 			break;
3707 		}
3708 		err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac,
3709 					    label, idx);
3710 		if (err < 0)
3711 			return err;
3712 	}
3713 	return 0;
3714 }
3715 
3716 static int cx_auto_build_input_controls(struct hda_codec *codec)
3717 {
3718 	struct conexant_spec *spec = codec->spec;
3719 	struct auto_pin_cfg *cfg = &spec->autocfg;
3720 	static const char *prev_label;
3721 	int i, err, cidx, conn_len;
3722 	hda_nid_t conn[HDA_MAX_CONNECTIONS];
3723 
3724 	int multi_adc_volume = 0; /* If the ADC nid has several input volumes */
3725 	int adc_nid = spec->adc_nids[0];
3726 
3727 	conn_len = snd_hda_get_connections(codec, adc_nid, conn,
3728 					   HDA_MAX_CONNECTIONS);
3729 	if (conn_len < 0)
3730 		return conn_len;
3731 
3732 	multi_adc_volume = cfg->num_inputs > 1 && conn_len > 1;
3733 	if (!multi_adc_volume) {
3734 		err = cx_auto_add_volume(codec, "Capture", "", 0, adc_nid,
3735 					 HDA_INPUT);
3736 		if (err < 0)
3737 			return err;
3738 	}
3739 
3740 	prev_label = NULL;
3741 	cidx = 0;
3742 	for (i = 0; i < cfg->num_inputs; i++) {
3743 		hda_nid_t nid = cfg->inputs[i].pin;
3744 		const char *label;
3745 		int j;
3746 		int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP;
3747 		if (!pin_amp && !multi_adc_volume)
3748 			continue;
3749 
3750 		label = hda_get_autocfg_input_label(codec, cfg, i);
3751 		if (label == prev_label)
3752 			cidx++;
3753 		else
3754 			cidx = 0;
3755 		prev_label = label;
3756 
3757 		if (pin_amp) {
3758 			err = cx_auto_add_volume(codec, label, " Boost", cidx,
3759 						 nid, HDA_INPUT);
3760 			if (err < 0)
3761 				return err;
3762 		}
3763 
3764 		if (!multi_adc_volume)
3765 			continue;
3766 		for (j = 0; j < conn_len; j++) {
3767 			if (conn[j] == nid) {
3768 				err = cx_auto_add_volume_idx(codec, label,
3769 				    " Capture", cidx, adc_nid, HDA_INPUT, j);
3770 				if (err < 0)
3771 					return err;
3772 				break;
3773 			}
3774 		}
3775 	}
3776 	return 0;
3777 }
3778 
3779 static int cx_auto_build_controls(struct hda_codec *codec)
3780 {
3781 	int err;
3782 
3783 	err = cx_auto_build_output_controls(codec);
3784 	if (err < 0)
3785 		return err;
3786 	err = cx_auto_build_input_controls(codec);
3787 	if (err < 0)
3788 		return err;
3789 	return conexant_build_controls(codec);
3790 }
3791 
3792 static struct hda_codec_ops cx_auto_patch_ops = {
3793 	.build_controls = cx_auto_build_controls,
3794 	.build_pcms = conexant_build_pcms,
3795 	.init = cx_auto_init,
3796 	.free = conexant_free,
3797 	.unsol_event = cx_auto_unsol_event,
3798 #ifdef CONFIG_SND_HDA_POWER_SAVE
3799 	.suspend = conexant_suspend,
3800 #endif
3801 	.reboot_notify = snd_hda_shutup_pins,
3802 };
3803 
3804 static int patch_conexant_auto(struct hda_codec *codec)
3805 {
3806 	struct conexant_spec *spec;
3807 	int err;
3808 
3809 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3810 	if (!spec)
3811 		return -ENOMEM;
3812 	codec->spec = spec;
3813 	spec->adc_nids = cx_auto_adc_nids;
3814 	spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids);
3815 	spec->capsrc_nids = spec->adc_nids;
3816 	err = cx_auto_parse_auto_config(codec);
3817 	if (err < 0) {
3818 		kfree(codec->spec);
3819 		codec->spec = NULL;
3820 		return err;
3821 	}
3822 	codec->patch_ops = cx_auto_patch_ops;
3823 	if (spec->beep_amp)
3824 		snd_hda_attach_beep_device(codec, spec->beep_amp);
3825 	return 0;
3826 }
3827 
3828 /*
3829  */
3830 
3831 static struct hda_codec_preset snd_hda_preset_conexant[] = {
3832 	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
3833 	  .patch = patch_cxt5045 },
3834 	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
3835 	  .patch = patch_cxt5047 },
3836 	{ .id = 0x14f15051, .name = "CX20561 (Hermosa)",
3837 	  .patch = patch_cxt5051 },
3838 	{ .id = 0x14f15066, .name = "CX20582 (Pebble)",
3839 	  .patch = patch_cxt5066 },
3840 	{ .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
3841 	  .patch = patch_cxt5066 },
3842 	{ .id = 0x14f15068, .name = "CX20584",
3843 	  .patch = patch_cxt5066 },
3844 	{ .id = 0x14f15069, .name = "CX20585",
3845 	  .patch = patch_cxt5066 },
3846 	{ .id = 0x14f1506e, .name = "CX20590",
3847 	  .patch = patch_cxt5066 },
3848 	{ .id = 0x14f15097, .name = "CX20631",
3849 	  .patch = patch_conexant_auto },
3850 	{ .id = 0x14f15098, .name = "CX20632",
3851 	  .patch = patch_conexant_auto },
3852 	{ .id = 0x14f150a1, .name = "CX20641",
3853 	  .patch = patch_conexant_auto },
3854 	{ .id = 0x14f150a2, .name = "CX20642",
3855 	  .patch = patch_conexant_auto },
3856 	{ .id = 0x14f150ab, .name = "CX20651",
3857 	  .patch = patch_conexant_auto },
3858 	{ .id = 0x14f150ac, .name = "CX20652",
3859 	  .patch = patch_conexant_auto },
3860 	{ .id = 0x14f150b8, .name = "CX20664",
3861 	  .patch = patch_conexant_auto },
3862 	{ .id = 0x14f150b9, .name = "CX20665",
3863 	  .patch = patch_conexant_auto },
3864 	{} /* terminator */
3865 };
3866 
3867 MODULE_ALIAS("snd-hda-codec-id:14f15045");
3868 MODULE_ALIAS("snd-hda-codec-id:14f15047");
3869 MODULE_ALIAS("snd-hda-codec-id:14f15051");
3870 MODULE_ALIAS("snd-hda-codec-id:14f15066");
3871 MODULE_ALIAS("snd-hda-codec-id:14f15067");
3872 MODULE_ALIAS("snd-hda-codec-id:14f15068");
3873 MODULE_ALIAS("snd-hda-codec-id:14f15069");
3874 MODULE_ALIAS("snd-hda-codec-id:14f1506e");
3875 MODULE_ALIAS("snd-hda-codec-id:14f15097");
3876 MODULE_ALIAS("snd-hda-codec-id:14f15098");
3877 MODULE_ALIAS("snd-hda-codec-id:14f150a1");
3878 MODULE_ALIAS("snd-hda-codec-id:14f150a2");
3879 MODULE_ALIAS("snd-hda-codec-id:14f150ab");
3880 MODULE_ALIAS("snd-hda-codec-id:14f150ac");
3881 MODULE_ALIAS("snd-hda-codec-id:14f150b8");
3882 MODULE_ALIAS("snd-hda-codec-id:14f150b9");
3883 
3884 MODULE_LICENSE("GPL");
3885 MODULE_DESCRIPTION("Conexant HD-audio codec");
3886 
3887 static struct hda_codec_preset_list conexant_list = {
3888 	.preset = snd_hda_preset_conexant,
3889 	.owner = THIS_MODULE,
3890 };
3891 
3892 static int __init patch_conexant_init(void)
3893 {
3894 	return snd_hda_add_codec_preset(&conexant_list);
3895 }
3896 
3897 static void __exit patch_conexant_exit(void)
3898 {
3899 	snd_hda_delete_codec_preset(&conexant_list);
3900 }
3901 
3902 module_init(patch_conexant_init)
3903 module_exit(patch_conexant_exit)
3904