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