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