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