]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - sound/pci/hda/patch_conexant.c
36dd5a6bf874645ce631898251fce8e1179385af
[mcf548x/linux.git] / sound / pci / hda / patch_conexant.c
1 /*
2  * HD audio interface patch for Conexant HDA audio codec
3  *
4  * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
5  *                    Takashi Iwai <tiwai@suse.de>
6  *                    Tobin Davis  <tdavis@dsl-only.net>
7  *
8  *  This driver is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This driver is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include <sound/jack.h>
29
30 #include "hda_codec.h"
31 #include "hda_local.h"
32
33 #define CXT_PIN_DIR_IN              0x00
34 #define CXT_PIN_DIR_OUT             0x01
35 #define CXT_PIN_DIR_INOUT           0x02
36 #define CXT_PIN_DIR_IN_NOMICBIAS    0x03
37 #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
38
39 #define CONEXANT_HP_EVENT       0x37
40 #define CONEXANT_MIC_EVENT      0x38
41
42 /* Conexant 5051 specific */
43
44 #define CXT5051_SPDIF_OUT       0x1C
45 #define CXT5051_PORTB_EVENT     0x38
46 #define CXT5051_PORTC_EVENT     0x39
47
48
49 struct conexant_jack {
50
51         hda_nid_t nid;
52         int type;
53         struct snd_jack *jack;
54
55 };
56
57 struct conexant_spec {
58
59         struct snd_kcontrol_new *mixers[5];
60         int num_mixers;
61         hda_nid_t vmaster_nid;
62
63         const struct hda_verb *init_verbs[5];   /* initialization verbs
64                                                  * don't forget NULL
65                                                  * termination!
66                                                  */
67         unsigned int num_init_verbs;
68
69         /* playback */
70         struct hda_multi_out multiout;  /* playback set-up
71                                          * max_channels, dacs must be set
72                                          * dig_out_nid and hp_nid are optional
73                                          */
74         unsigned int cur_eapd;
75         unsigned int hp_present;
76         unsigned int no_auto_mic;
77         unsigned int need_dac_fix;
78
79         /* capture */
80         unsigned int num_adc_nids;
81         hda_nid_t *adc_nids;
82         hda_nid_t dig_in_nid;           /* digital-in NID; optional */
83
84         unsigned int cur_adc_idx;
85         hda_nid_t cur_adc;
86         unsigned int cur_adc_stream_tag;
87         unsigned int cur_adc_format;
88
89         /* capture source */
90         const struct hda_input_mux *input_mux;
91         hda_nid_t *capsrc_nids;
92         unsigned int cur_mux[3];
93
94         /* channel model */
95         const struct hda_channel_mode *channel_mode;
96         int num_channel_mode;
97
98         /* PCM information */
99         struct hda_pcm pcm_rec[2];      /* used in build_pcms() */
100
101         unsigned int spdif_route;
102
103         /* jack detection */
104         struct snd_array jacks;
105
106         /* dynamic controls, init_verbs and input_mux */
107         struct auto_pin_cfg autocfg;
108         struct hda_input_mux private_imux;
109         hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
110
111         unsigned int dell_automute;
112         unsigned int port_d_mode;
113         unsigned char ext_mic_bias;
114 };
115
116 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
117                                       struct hda_codec *codec,
118                                       struct snd_pcm_substream *substream)
119 {
120         struct conexant_spec *spec = codec->spec;
121         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
122                                              hinfo);
123 }
124
125 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
126                                          struct hda_codec *codec,
127                                          unsigned int stream_tag,
128                                          unsigned int format,
129                                          struct snd_pcm_substream *substream)
130 {
131         struct conexant_spec *spec = codec->spec;
132         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
133                                                 stream_tag,
134                                                 format, substream);
135 }
136
137 static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
138                                          struct hda_codec *codec,
139                                          struct snd_pcm_substream *substream)
140 {
141         struct conexant_spec *spec = codec->spec;
142         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
143 }
144
145 /*
146  * Digital out
147  */
148 static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
149                                           struct hda_codec *codec,
150                                           struct snd_pcm_substream *substream)
151 {
152         struct conexant_spec *spec = codec->spec;
153         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
154 }
155
156 static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
157                                          struct hda_codec *codec,
158                                          struct snd_pcm_substream *substream)
159 {
160         struct conexant_spec *spec = codec->spec;
161         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
162 }
163
164 static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
165                                          struct hda_codec *codec,
166                                          unsigned int stream_tag,
167                                          unsigned int format,
168                                          struct snd_pcm_substream *substream)
169 {
170         struct conexant_spec *spec = codec->spec;
171         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
172                                              stream_tag,
173                                              format, substream);
174 }
175
176 /*
177  * Analog capture
178  */
179 static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
180                                       struct hda_codec *codec,
181                                       unsigned int stream_tag,
182                                       unsigned int format,
183                                       struct snd_pcm_substream *substream)
184 {
185         struct conexant_spec *spec = codec->spec;
186         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
187                                    stream_tag, 0, format);
188         return 0;
189 }
190
191 static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
192                                       struct hda_codec *codec,
193                                       struct snd_pcm_substream *substream)
194 {
195         struct conexant_spec *spec = codec->spec;
196         snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
197         return 0;
198 }
199
200
201
202 static struct hda_pcm_stream conexant_pcm_analog_playback = {
203         .substreams = 1,
204         .channels_min = 2,
205         .channels_max = 2,
206         .nid = 0, /* fill later */
207         .ops = {
208                 .open = conexant_playback_pcm_open,
209                 .prepare = conexant_playback_pcm_prepare,
210                 .cleanup = conexant_playback_pcm_cleanup
211         },
212 };
213
214 static struct hda_pcm_stream conexant_pcm_analog_capture = {
215         .substreams = 1,
216         .channels_min = 2,
217         .channels_max = 2,
218         .nid = 0, /* fill later */
219         .ops = {
220                 .prepare = conexant_capture_pcm_prepare,
221                 .cleanup = conexant_capture_pcm_cleanup
222         },
223 };
224
225
226 static struct hda_pcm_stream conexant_pcm_digital_playback = {
227         .substreams = 1,
228         .channels_min = 2,
229         .channels_max = 2,
230         .nid = 0, /* fill later */
231         .ops = {
232                 .open = conexant_dig_playback_pcm_open,
233                 .close = conexant_dig_playback_pcm_close,
234                 .prepare = conexant_dig_playback_pcm_prepare
235         },
236 };
237
238 static struct hda_pcm_stream conexant_pcm_digital_capture = {
239         .substreams = 1,
240         .channels_min = 2,
241         .channels_max = 2,
242         /* NID is set in alc_build_pcms */
243 };
244
245 static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
246                                       struct hda_codec *codec,
247                                       unsigned int stream_tag,
248                                       unsigned int format,
249                                       struct snd_pcm_substream *substream)
250 {
251         struct conexant_spec *spec = codec->spec;
252         spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
253         spec->cur_adc_stream_tag = stream_tag;
254         spec->cur_adc_format = format;
255         snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
256         return 0;
257 }
258
259 static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
260                                       struct hda_codec *codec,
261                                       struct snd_pcm_substream *substream)
262 {
263         struct conexant_spec *spec = codec->spec;
264         snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
265         spec->cur_adc = 0;
266         return 0;
267 }
268
269 static struct hda_pcm_stream cx5051_pcm_analog_capture = {
270         .substreams = 1,
271         .channels_min = 2,
272         .channels_max = 2,
273         .nid = 0, /* fill later */
274         .ops = {
275                 .prepare = cx5051_capture_pcm_prepare,
276                 .cleanup = cx5051_capture_pcm_cleanup
277         },
278 };
279
280 static int conexant_build_pcms(struct hda_codec *codec)
281 {
282         struct conexant_spec *spec = codec->spec;
283         struct hda_pcm *info = spec->pcm_rec;
284
285         codec->num_pcms = 1;
286         codec->pcm_info = info;
287
288         info->name = "CONEXANT Analog";
289         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
290         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
291                 spec->multiout.max_channels;
292         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
293                 spec->multiout.dac_nids[0];
294         if (codec->vendor_id == 0x14f15051)
295                 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
296                         cx5051_pcm_analog_capture;
297         else
298                 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
299                         conexant_pcm_analog_capture;
300         info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
301         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
302
303         if (spec->multiout.dig_out_nid) {
304                 info++;
305                 codec->num_pcms++;
306                 info->name = "Conexant Digital";
307                 info->pcm_type = HDA_PCM_TYPE_SPDIF;
308                 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
309                         conexant_pcm_digital_playback;
310                 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
311                         spec->multiout.dig_out_nid;
312                 if (spec->dig_in_nid) {
313                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
314                                 conexant_pcm_digital_capture;
315                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
316                                 spec->dig_in_nid;
317                 }
318         }
319
320         return 0;
321 }
322
323 static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
324                                   struct snd_ctl_elem_info *uinfo)
325 {
326         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
327         struct conexant_spec *spec = codec->spec;
328
329         return snd_hda_input_mux_info(spec->input_mux, uinfo);
330 }
331
332 static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
333                                  struct snd_ctl_elem_value *ucontrol)
334 {
335         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
336         struct conexant_spec *spec = codec->spec;
337         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
338
339         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
340         return 0;
341 }
342
343 static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
344                                  struct snd_ctl_elem_value *ucontrol)
345 {
346         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
347         struct conexant_spec *spec = codec->spec;
348         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
349
350         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
351                                      spec->capsrc_nids[adc_idx],
352                                      &spec->cur_mux[adc_idx]);
353 }
354
355 #ifdef CONFIG_SND_HDA_INPUT_JACK
356 static void conexant_free_jack_priv(struct snd_jack *jack)
357 {
358         struct conexant_jack *jacks = jack->private_data;
359         jacks->nid = 0;
360         jacks->jack = NULL;
361 }
362
363 static int conexant_add_jack(struct hda_codec *codec,
364                 hda_nid_t nid, int type)
365 {
366         struct conexant_spec *spec;
367         struct conexant_jack *jack;
368         const char *name;
369         int err;
370
371         spec = codec->spec;
372         snd_array_init(&spec->jacks, sizeof(*jack), 32);
373         jack = snd_array_new(&spec->jacks);
374         name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
375
376         if (!jack)
377                 return -ENOMEM;
378
379         jack->nid = nid;
380         jack->type = type;
381
382         err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
383         if (err < 0)
384                 return err;
385         jack->jack->private_data = jack;
386         jack->jack->private_free = conexant_free_jack_priv;
387         return 0;
388 }
389
390 static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
391 {
392         struct conexant_spec *spec = codec->spec;
393         struct conexant_jack *jacks = spec->jacks.list;
394
395         if (jacks) {
396                 int i;
397                 for (i = 0; i < spec->jacks.used; i++) {
398                         if (jacks->nid == nid) {
399                                 unsigned int present;
400                                 present = snd_hda_jack_detect(codec, nid);
401
402                                 present = (present) ? jacks->type : 0 ;
403
404                                 snd_jack_report(jacks->jack,
405                                                 present);
406                         }
407                         jacks++;
408                 }
409         }
410 }
411
412 static int conexant_init_jacks(struct hda_codec *codec)
413 {
414         struct conexant_spec *spec = codec->spec;
415         int i;
416
417         for (i = 0; i < spec->num_init_verbs; i++) {
418                 const struct hda_verb *hv;
419
420                 hv = spec->init_verbs[i];
421                 while (hv->nid) {
422                         int err = 0;
423                         switch (hv->param ^ AC_USRSP_EN) {
424                         case CONEXANT_HP_EVENT:
425                                 err = conexant_add_jack(codec, hv->nid,
426                                                 SND_JACK_HEADPHONE);
427                                 conexant_report_jack(codec, hv->nid);
428                                 break;
429                         case CXT5051_PORTC_EVENT:
430                         case CONEXANT_MIC_EVENT:
431                                 err = conexant_add_jack(codec, hv->nid,
432                                                 SND_JACK_MICROPHONE);
433                                 conexant_report_jack(codec, hv->nid);
434                                 break;
435                         }
436                         if (err < 0)
437                                 return err;
438                         ++hv;
439                 }
440         }
441         return 0;
442
443 }
444 #else
445 static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
446 {
447 }
448
449 static inline int conexant_init_jacks(struct hda_codec *codec)
450 {
451         return 0;
452 }
453 #endif
454
455 static int conexant_init(struct hda_codec *codec)
456 {
457         struct conexant_spec *spec = codec->spec;
458         int i;
459
460         for (i = 0; i < spec->num_init_verbs; i++)
461                 snd_hda_sequence_write(codec, spec->init_verbs[i]);
462         return 0;
463 }
464
465 static void conexant_free(struct hda_codec *codec)
466 {
467 #ifdef CONFIG_SND_HDA_INPUT_JACK
468         struct conexant_spec *spec = codec->spec;
469         if (spec->jacks.list) {
470                 struct conexant_jack *jacks = spec->jacks.list;
471                 int i;
472                 for (i = 0; i < spec->jacks.used; i++, jacks++) {
473                         if (jacks->jack)
474                                 snd_device_free(codec->bus->card, jacks->jack);
475                 }
476                 snd_array_free(&spec->jacks);
477         }
478 #endif
479         kfree(codec->spec);
480 }
481
482 static struct snd_kcontrol_new cxt_capture_mixers[] = {
483         {
484                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
485                 .name = "Capture Source",
486                 .info = conexant_mux_enum_info,
487                 .get = conexant_mux_enum_get,
488                 .put = conexant_mux_enum_put
489         },
490         {}
491 };
492
493 static const char *slave_vols[] = {
494         "Headphone Playback Volume",
495         "Speaker Playback Volume",
496         NULL
497 };
498
499 static const char *slave_sws[] = {
500         "Headphone Playback Switch",
501         "Speaker Playback Switch",
502         NULL
503 };
504
505 static int conexant_build_controls(struct hda_codec *codec)
506 {
507         struct conexant_spec *spec = codec->spec;
508         unsigned int i;
509         int err;
510
511         for (i = 0; i < spec->num_mixers; i++) {
512                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
513                 if (err < 0)
514                         return err;
515         }
516         if (spec->multiout.dig_out_nid) {
517                 err = snd_hda_create_spdif_out_ctls(codec,
518                                                     spec->multiout.dig_out_nid);
519                 if (err < 0)
520                         return err;
521                 err = snd_hda_create_spdif_share_sw(codec,
522                                                     &spec->multiout);
523                 if (err < 0)
524                         return err;
525                 spec->multiout.share_spdif = 1;
526         } 
527         if (spec->dig_in_nid) {
528                 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
529                 if (err < 0)
530                         return err;
531         }
532
533         /* if we have no master control, let's create it */
534         if (spec->vmaster_nid &&
535             !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
536                 unsigned int vmaster_tlv[4];
537                 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
538                                         HDA_OUTPUT, vmaster_tlv);
539                 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
540                                           vmaster_tlv, slave_vols);
541                 if (err < 0)
542                         return err;
543         }
544         if (spec->vmaster_nid &&
545             !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
546                 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
547                                           NULL, slave_sws);
548                 if (err < 0)
549                         return err;
550         }
551
552         if (spec->input_mux) {
553                 err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
554                 if (err < 0)
555                         return err;
556         }
557
558         return 0;
559 }
560
561 static struct hda_codec_ops conexant_patch_ops = {
562         .build_controls = conexant_build_controls,
563         .build_pcms = conexant_build_pcms,
564         .init = conexant_init,
565         .free = conexant_free,
566 };
567
568 /*
569  * EAPD control
570  * the private value = nid | (invert << 8)
571  */
572
573 #define cxt_eapd_info           snd_ctl_boolean_mono_info
574
575 static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
576                              struct snd_ctl_elem_value *ucontrol)
577 {
578         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
579         struct conexant_spec *spec = codec->spec;
580         int invert = (kcontrol->private_value >> 8) & 1;
581         if (invert)
582                 ucontrol->value.integer.value[0] = !spec->cur_eapd;
583         else
584                 ucontrol->value.integer.value[0] = spec->cur_eapd;
585         return 0;
586
587 }
588
589 static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
590                              struct snd_ctl_elem_value *ucontrol)
591 {
592         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
593         struct conexant_spec *spec = codec->spec;
594         int invert = (kcontrol->private_value >> 8) & 1;
595         hda_nid_t nid = kcontrol->private_value & 0xff;
596         unsigned int eapd;
597
598         eapd = !!ucontrol->value.integer.value[0];
599         if (invert)
600                 eapd = !eapd;
601         if (eapd == spec->cur_eapd)
602                 return 0;
603         
604         spec->cur_eapd = eapd;
605         snd_hda_codec_write_cache(codec, nid,
606                                   0, AC_VERB_SET_EAPD_BTLENABLE,
607                                   eapd ? 0x02 : 0x00);
608         return 1;
609 }
610
611 /* controls for test mode */
612 #ifdef CONFIG_SND_DEBUG
613
614 #define CXT_EAPD_SWITCH(xname, nid, mask) \
615         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
616           .info = cxt_eapd_info, \
617           .get = cxt_eapd_get, \
618           .put = cxt_eapd_put, \
619           .private_value = nid | (mask<<16) }
620
621
622
623 static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
624                                  struct snd_ctl_elem_info *uinfo)
625 {
626         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
627         struct conexant_spec *spec = codec->spec;
628         return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
629                                     spec->num_channel_mode);
630 }
631
632 static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
633                                 struct snd_ctl_elem_value *ucontrol)
634 {
635         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
636         struct conexant_spec *spec = codec->spec;
637         return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
638                                    spec->num_channel_mode,
639                                    spec->multiout.max_channels);
640 }
641
642 static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
643                                 struct snd_ctl_elem_value *ucontrol)
644 {
645         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
646         struct conexant_spec *spec = codec->spec;
647         int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
648                                       spec->num_channel_mode,
649                                       &spec->multiout.max_channels);
650         if (err >= 0 && spec->need_dac_fix)
651                 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
652         return err;
653 }
654
655 #define CXT_PIN_MODE(xname, nid, dir) \
656         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
657           .info = conexant_ch_mode_info, \
658           .get = conexant_ch_mode_get, \
659           .put = conexant_ch_mode_put, \
660           .private_value = nid | (dir<<16) }
661
662 #endif /* CONFIG_SND_DEBUG */
663
664 /* Conexant 5045 specific */
665
666 static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
667 static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
668 static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
669 #define CXT5045_SPDIF_OUT       0x18
670
671 static struct hda_channel_mode cxt5045_modes[1] = {
672         { 2, NULL },
673 };
674
675 static struct hda_input_mux cxt5045_capture_source = {
676         .num_items = 2,
677         .items = {
678                 { "IntMic", 0x1 },
679                 { "ExtMic", 0x2 },
680         }
681 };
682
683 static struct hda_input_mux cxt5045_capture_source_benq = {
684         .num_items = 5,
685         .items = {
686                 { "IntMic", 0x1 },
687                 { "ExtMic", 0x2 },
688                 { "LineIn", 0x3 },
689                 { "CD",     0x4 },
690                 { "Mixer",  0x0 },
691         }
692 };
693
694 static struct hda_input_mux cxt5045_capture_source_hp530 = {
695         .num_items = 2,
696         .items = {
697                 { "ExtMic", 0x1 },
698                 { "IntMic", 0x2 },
699         }
700 };
701
702 /* turn on/off EAPD (+ mute HP) as a master switch */
703 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
704                                     struct snd_ctl_elem_value *ucontrol)
705 {
706         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
707         struct conexant_spec *spec = codec->spec;
708         unsigned int bits;
709
710         if (!cxt_eapd_put(kcontrol, ucontrol))
711                 return 0;
712
713         /* toggle internal speakers mute depending of presence of
714          * the headphone jack
715          */
716         bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
717         snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
718                                  HDA_AMP_MUTE, bits);
719
720         bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
721         snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
722                                  HDA_AMP_MUTE, bits);
723         return 1;
724 }
725
726 /* bind volumes of both NID 0x10 and 0x11 */
727 static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
728         .ops = &snd_hda_bind_vol,
729         .values = {
730                 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
731                 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
732                 0
733         },
734 };
735
736 /* toggle input of built-in and mic jack appropriately */
737 static void cxt5045_hp_automic(struct hda_codec *codec)
738 {
739         static struct hda_verb mic_jack_on[] = {
740                 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
741                 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
742                 {}
743         };
744         static struct hda_verb mic_jack_off[] = {
745                 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
746                 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
747                 {}
748         };
749         unsigned int present;
750
751         present = snd_hda_jack_detect(codec, 0x12);
752         if (present)
753                 snd_hda_sequence_write(codec, mic_jack_on);
754         else
755                 snd_hda_sequence_write(codec, mic_jack_off);
756 }
757
758
759 /* mute internal speaker if HP is plugged */
760 static void cxt5045_hp_automute(struct hda_codec *codec)
761 {
762         struct conexant_spec *spec = codec->spec;
763         unsigned int bits;
764
765         spec->hp_present = snd_hda_jack_detect(codec, 0x11);
766
767         bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 
768         snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
769                                  HDA_AMP_MUTE, bits);
770 }
771
772 /* unsolicited event for HP jack sensing */
773 static void cxt5045_hp_unsol_event(struct hda_codec *codec,
774                                    unsigned int res)
775 {
776         res >>= 26;
777         switch (res) {
778         case CONEXANT_HP_EVENT:
779                 cxt5045_hp_automute(codec);
780                 break;
781         case CONEXANT_MIC_EVENT:
782                 cxt5045_hp_automic(codec);
783                 break;
784
785         }
786 }
787
788 static struct snd_kcontrol_new cxt5045_mixers[] = {
789         HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
790         HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
791         HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
792         HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
793         HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
794         HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
795         HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
796         HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
797         HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
798         HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
799         HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
800         {
801                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
802                 .name = "Master Playback Switch",
803                 .info = cxt_eapd_info,
804                 .get = cxt_eapd_get,
805                 .put = cxt5045_hp_master_sw_put,
806                 .private_value = 0x10,
807         },
808
809         {}
810 };
811
812 static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
813         HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
814         HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
815         HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
816         HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT),
817
818         HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT),
819         HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT),
820         HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT),
821         HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT),
822
823         HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT),
824         HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT),
825
826         {}
827 };
828
829 static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
830         HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
831         HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
832         HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
833         HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
834         HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
835         HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
836         HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
837         HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
838         HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
839         HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
840         HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
841         {
842                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
843                 .name = "Master Playback Switch",
844                 .info = cxt_eapd_info,
845                 .get = cxt_eapd_get,
846                 .put = cxt5045_hp_master_sw_put,
847                 .private_value = 0x10,
848         },
849
850         {}
851 };
852
853 static struct hda_verb cxt5045_init_verbs[] = {
854         /* Line in, Mic */
855         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
856         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
857         /* HP, Amp  */
858         {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
859         {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
860         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
861         {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
862         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
863         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
864         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
865         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
866         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
867         /* Record selector: Int mic */
868         {0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
869         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
870          AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
871         /* SPDIF route: PCM */
872         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
873         { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
874         /* EAPD */
875         {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
876         { } /* end */
877 };
878
879 static struct hda_verb cxt5045_benq_init_verbs[] = {
880         /* Int Mic, Mic */
881         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
882         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
883         /* Line In,HP, Amp  */
884         {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
885         {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
886         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
887         {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
888         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
889         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
890         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
891         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
892         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
893         /* Record selector: Int mic */
894         {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
895         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
896          AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
897         /* SPDIF route: PCM */
898         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
899         {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
900         /* EAPD */
901         {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
902         { } /* end */
903 };
904
905 static struct hda_verb cxt5045_hp_sense_init_verbs[] = {
906         /* pin sensing on HP jack */
907         {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
908         { } /* end */
909 };
910
911 static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
912         /* pin sensing on HP jack */
913         {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
914         { } /* end */
915 };
916
917 #ifdef CONFIG_SND_DEBUG
918 /* Test configuration for debugging, modelled after the ALC260 test
919  * configuration.
920  */
921 static struct hda_input_mux cxt5045_test_capture_source = {
922         .num_items = 5,
923         .items = {
924                 { "MIXER", 0x0 },
925                 { "MIC1 pin", 0x1 },
926                 { "LINE1 pin", 0x2 },
927                 { "HP-OUT pin", 0x3 },
928                 { "CD pin", 0x4 },
929         },
930 };
931
932 static struct snd_kcontrol_new cxt5045_test_mixer[] = {
933
934         /* Output controls */
935         HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
936         HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
937         HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT),
938         HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT),
939         HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
940         HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
941         
942         /* Modes for retasking pin widgets */
943         CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
944         CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
945
946         /* EAPD Switch Control */
947         CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
948
949         /* Loopback mixer controls */
950
951         HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT),
952         HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT),
953         HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT),
954         HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT),
955         HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT),
956         HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT),
957         HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT),
958         HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT),
959         HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT),
960         HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT),
961         {
962                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
963                 .name = "Input Source",
964                 .info = conexant_mux_enum_info,
965                 .get = conexant_mux_enum_get,
966                 .put = conexant_mux_enum_put,
967         },
968         /* Audio input controls */
969         HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
970         HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
971         HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
972         HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
973         HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
974         HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
975         HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
976         HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
977         HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
978         HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
979         { } /* end */
980 };
981
982 static struct hda_verb cxt5045_test_init_verbs[] = {
983         /* Set connections */
984         { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
985         { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
986         { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
987         /* Enable retasking pins as output, initially without power amp */
988         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
989         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
990
991         /* Disable digital (SPDIF) pins initially, but users can enable
992          * them via a mixer switch.  In the case of SPDIF-out, this initverb
993          * payload also sets the generation to 0, output to be in "consumer"
994          * PCM format, copyright asserted, no pre-emphasis and no validity
995          * control.
996          */
997         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
998         {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
999
1000         /* Start with output sum widgets muted and their output gains at min */
1001         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1002         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1003
1004         /* Unmute retasking pin widget output buffers since the default
1005          * state appears to be output.  As the pin mode is changed by the
1006          * user the pin mode control will take care of enabling the pin's
1007          * input/output buffers as needed.
1008          */
1009         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1010         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1011
1012         /* Mute capture amp left and right */
1013         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1014
1015         /* Set ADC connection select to match default mixer setting (mic1
1016          * pin)
1017          */
1018         {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1019         {0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1020
1021         /* Mute all inputs to mixer widget (even unconnected ones) */
1022         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
1023         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
1024         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
1025         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
1026         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1027
1028         { }
1029 };
1030 #endif
1031
1032
1033 /* initialize jack-sensing, too */
1034 static int cxt5045_init(struct hda_codec *codec)
1035 {
1036         conexant_init(codec);
1037         cxt5045_hp_automute(codec);
1038         return 0;
1039 }
1040
1041
1042 enum {
1043         CXT5045_LAPTOP_HPSENSE,
1044         CXT5045_LAPTOP_MICSENSE,
1045         CXT5045_LAPTOP_HPMICSENSE,
1046         CXT5045_BENQ,
1047         CXT5045_LAPTOP_HP530,
1048 #ifdef CONFIG_SND_DEBUG
1049         CXT5045_TEST,
1050 #endif
1051         CXT5045_MODELS
1052 };
1053
1054 static const char *cxt5045_models[CXT5045_MODELS] = {
1055         [CXT5045_LAPTOP_HPSENSE]        = "laptop-hpsense",
1056         [CXT5045_LAPTOP_MICSENSE]       = "laptop-micsense",
1057         [CXT5045_LAPTOP_HPMICSENSE]     = "laptop-hpmicsense",
1058         [CXT5045_BENQ]                  = "benq",
1059         [CXT5045_LAPTOP_HP530]          = "laptop-hp530",
1060 #ifdef CONFIG_SND_DEBUG
1061         [CXT5045_TEST]          = "test",
1062 #endif
1063 };
1064
1065 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
1066         SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
1067         SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1068                            CXT5045_LAPTOP_HPSENSE),
1069         SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
1070         SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
1071         SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
1072         SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
1073         SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
1074                       CXT5045_LAPTOP_HPMICSENSE),
1075         SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1076         SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1077         SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
1078         SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
1079                            CXT5045_LAPTOP_HPMICSENSE),
1080         SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
1081         {}
1082 };
1083
1084 static int patch_cxt5045(struct hda_codec *codec)
1085 {
1086         struct conexant_spec *spec;
1087         int board_config;
1088
1089         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1090         if (!spec)
1091                 return -ENOMEM;
1092         codec->spec = spec;
1093         codec->pin_amp_workaround = 1;
1094
1095         spec->multiout.max_channels = 2;
1096         spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
1097         spec->multiout.dac_nids = cxt5045_dac_nids;
1098         spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
1099         spec->num_adc_nids = 1;
1100         spec->adc_nids = cxt5045_adc_nids;
1101         spec->capsrc_nids = cxt5045_capsrc_nids;
1102         spec->input_mux = &cxt5045_capture_source;
1103         spec->num_mixers = 1;
1104         spec->mixers[0] = cxt5045_mixers;
1105         spec->num_init_verbs = 1;
1106         spec->init_verbs[0] = cxt5045_init_verbs;
1107         spec->spdif_route = 0;
1108         spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes),
1109         spec->channel_mode = cxt5045_modes,
1110
1111
1112         codec->patch_ops = conexant_patch_ops;
1113
1114         board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
1115                                                   cxt5045_models,
1116                                                   cxt5045_cfg_tbl);
1117         switch (board_config) {
1118         case CXT5045_LAPTOP_HPSENSE:
1119                 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1120                 spec->input_mux = &cxt5045_capture_source;
1121                 spec->num_init_verbs = 2;
1122                 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1123                 spec->mixers[0] = cxt5045_mixers;
1124                 codec->patch_ops.init = cxt5045_init;
1125                 break;
1126         case CXT5045_LAPTOP_MICSENSE:
1127                 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1128                 spec->input_mux = &cxt5045_capture_source;
1129                 spec->num_init_verbs = 2;
1130                 spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
1131                 spec->mixers[0] = cxt5045_mixers;
1132                 codec->patch_ops.init = cxt5045_init;
1133                 break;
1134         default:
1135         case CXT5045_LAPTOP_HPMICSENSE:
1136                 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1137                 spec->input_mux = &cxt5045_capture_source;
1138                 spec->num_init_verbs = 3;
1139                 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1140                 spec->init_verbs[2] = cxt5045_mic_sense_init_verbs;
1141                 spec->mixers[0] = cxt5045_mixers;
1142                 codec->patch_ops.init = cxt5045_init;
1143                 break;
1144         case CXT5045_BENQ:
1145                 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1146                 spec->input_mux = &cxt5045_capture_source_benq;
1147                 spec->num_init_verbs = 1;
1148                 spec->init_verbs[0] = cxt5045_benq_init_verbs;
1149                 spec->mixers[0] = cxt5045_mixers;
1150                 spec->mixers[1] = cxt5045_benq_mixers;
1151                 spec->num_mixers = 2;
1152                 codec->patch_ops.init = cxt5045_init;
1153                 break;
1154         case CXT5045_LAPTOP_HP530:
1155                 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
1156                 spec->input_mux = &cxt5045_capture_source_hp530;
1157                 spec->num_init_verbs = 2;
1158                 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
1159                 spec->mixers[0] = cxt5045_mixers_hp530;
1160                 codec->patch_ops.init = cxt5045_init;
1161                 break;
1162 #ifdef CONFIG_SND_DEBUG
1163         case CXT5045_TEST:
1164                 spec->input_mux = &cxt5045_test_capture_source;
1165                 spec->mixers[0] = cxt5045_test_mixer;
1166                 spec->init_verbs[0] = cxt5045_test_init_verbs;
1167                 break;
1168                 
1169 #endif  
1170         }
1171
1172         switch (codec->subsystem_id >> 16) {
1173         case 0x103c:
1174                 /* HP laptop has a really bad sound over 0dB on NID 0x17.
1175                  * Fix max PCM level to 0 dB
1176                  * (originall it has 0x2b steps with 0dB offset 0x14)
1177                  */
1178                 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
1179                                           (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
1180                                           (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1181                                           (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1182                                           (1 << AC_AMPCAP_MUTE_SHIFT));
1183                 break;
1184         }
1185
1186         return 0;
1187 }
1188
1189
1190 /* Conexant 5047 specific */
1191 #define CXT5047_SPDIF_OUT       0x11
1192
1193 static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
1194 static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
1195 static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
1196
1197 static struct hda_channel_mode cxt5047_modes[1] = {
1198         { 2, NULL },
1199 };
1200
1201 static struct hda_input_mux cxt5047_toshiba_capture_source = {
1202         .num_items = 2,
1203         .items = {
1204                 { "ExtMic", 0x2 },
1205                 { "Line-In", 0x1 },
1206         }
1207 };
1208
1209 /* turn on/off EAPD (+ mute HP) as a master switch */
1210 static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1211                                     struct snd_ctl_elem_value *ucontrol)
1212 {
1213         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1214         struct conexant_spec *spec = codec->spec;
1215         unsigned int bits;
1216
1217         if (!cxt_eapd_put(kcontrol, ucontrol))
1218                 return 0;
1219
1220         /* toggle internal speakers mute depending of presence of
1221          * the headphone jack
1222          */
1223         bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
1224         /* NOTE: Conexat codec needs the index for *OUTPUT* amp of
1225          * pin widgets unlike other codecs.  In this case, we need to
1226          * set index 0x01 for the volume from the mixer amp 0x19.
1227          */
1228         snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1229                                  HDA_AMP_MUTE, bits);
1230         bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
1231         snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
1232                                  HDA_AMP_MUTE, bits);
1233         return 1;
1234 }
1235
1236 /* mute internal speaker if HP is plugged */
1237 static void cxt5047_hp_automute(struct hda_codec *codec)
1238 {
1239         struct conexant_spec *spec = codec->spec;
1240         unsigned int bits;
1241
1242         spec->hp_present = snd_hda_jack_detect(codec, 0x13);
1243
1244         bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
1245         /* See the note in cxt5047_hp_master_sw_put */
1246         snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
1247                                  HDA_AMP_MUTE, bits);
1248 }
1249
1250 /* toggle input of built-in and mic jack appropriately */
1251 static void cxt5047_hp_automic(struct hda_codec *codec)
1252 {
1253         static struct hda_verb mic_jack_on[] = {
1254                 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1255                 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1256                 {}
1257         };
1258         static struct hda_verb mic_jack_off[] = {
1259                 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1260                 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1261                 {}
1262         };
1263         unsigned int present;
1264
1265         present = snd_hda_jack_detect(codec, 0x15);
1266         if (present)
1267                 snd_hda_sequence_write(codec, mic_jack_on);
1268         else
1269                 snd_hda_sequence_write(codec, mic_jack_off);
1270 }
1271
1272 /* unsolicited event for HP jack sensing */
1273 static void cxt5047_hp_unsol_event(struct hda_codec *codec,
1274                                   unsigned int res)
1275 {
1276         switch (res >> 26) {
1277         case CONEXANT_HP_EVENT:
1278                 cxt5047_hp_automute(codec);
1279                 break;
1280         case CONEXANT_MIC_EVENT:
1281                 cxt5047_hp_automic(codec);
1282                 break;
1283         }
1284 }
1285
1286 static struct snd_kcontrol_new cxt5047_base_mixers[] = {
1287         HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
1288         HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
1289         HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT),
1290         HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1291         HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1292         HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
1293         HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
1294         {
1295                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1296                 .name = "Master Playback Switch",
1297                 .info = cxt_eapd_info,
1298                 .get = cxt_eapd_get,
1299                 .put = cxt5047_hp_master_sw_put,
1300                 .private_value = 0x13,
1301         },
1302
1303         {}
1304 };
1305
1306 static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
1307         /* See the note in cxt5047_hp_master_sw_put */
1308         HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
1309         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1310         {}
1311 };
1312
1313 static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
1314         HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1315         { } /* end */
1316 };
1317
1318 static struct hda_verb cxt5047_init_verbs[] = {
1319         /* Line in, Mic, Built-in Mic */
1320         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1321         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1322         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1323         /* HP, Speaker  */
1324         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
1325         {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
1326         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
1327         /* Record selector: Mic */
1328         {0x12, AC_VERB_SET_CONNECT_SEL,0x03},
1329         {0x19, AC_VERB_SET_AMP_GAIN_MUTE,
1330          AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
1331         {0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
1332         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1333          AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
1334         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1335          AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
1336         /* SPDIF route: PCM */
1337         { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
1338         /* Enable unsolicited events */
1339         {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
1340         {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
1341         { } /* end */
1342 };
1343
1344 /* configuration for Toshiba Laptops */
1345 static struct hda_verb cxt5047_toshiba_init_verbs[] = {
1346         {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
1347         {}
1348 };
1349
1350 /* Test configuration for debugging, modelled after the ALC260 test
1351  * configuration.
1352  */
1353 #ifdef CONFIG_SND_DEBUG
1354 static struct hda_input_mux cxt5047_test_capture_source = {
1355         .num_items = 4,
1356         .items = {
1357                 { "LINE1 pin", 0x0 },
1358                 { "MIC1 pin", 0x1 },
1359                 { "MIC2 pin", 0x2 },
1360                 { "CD pin", 0x3 },
1361         },
1362 };
1363
1364 static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1365
1366         /* Output only controls */
1367         HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
1368         HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
1369         HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
1370         HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
1371         HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1372         HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1373         HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1374         HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1375         HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
1376         HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1377         HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
1378         HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1379
1380         /* Modes for retasking pin widgets */
1381         CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
1382         CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
1383
1384         /* EAPD Switch Control */
1385         CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
1386
1387         /* Loopback mixer controls */
1388         HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
1389         HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
1390         HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
1391         HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
1392         HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
1393         HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
1394         HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
1395         HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
1396
1397         HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
1398         HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
1399         HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
1400         HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
1401         HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
1402         HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
1403         HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
1404         HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
1405         {
1406                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1407                 .name = "Input Source",
1408                 .info = conexant_mux_enum_info,
1409                 .get = conexant_mux_enum_get,
1410                 .put = conexant_mux_enum_put,
1411         },
1412         HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
1413         HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
1414         HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
1415         HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
1416         HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
1417         HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
1418         HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
1419         HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
1420         HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
1421         HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
1422
1423         { } /* end */
1424 };
1425
1426 static struct hda_verb cxt5047_test_init_verbs[] = {
1427         /* Enable retasking pins as output, initially without power amp */
1428         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1429         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1430         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1431
1432         /* Disable digital (SPDIF) pins initially, but users can enable
1433          * them via a mixer switch.  In the case of SPDIF-out, this initverb
1434          * payload also sets the generation to 0, output to be in "consumer"
1435          * PCM format, copyright asserted, no pre-emphasis and no validity
1436          * control.
1437          */
1438         {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
1439
1440         /* Ensure mic1, mic2, line1 pin widgets take input from the 
1441          * OUT1 sum bus when acting as an output.
1442          */
1443         {0x1a, AC_VERB_SET_CONNECT_SEL, 0},
1444         {0x1b, AC_VERB_SET_CONNECT_SEL, 0},
1445
1446         /* Start with output sum widgets muted and their output gains at min */
1447         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1448         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1449
1450         /* Unmute retasking pin widget output buffers since the default
1451          * state appears to be output.  As the pin mode is changed by the
1452          * user the pin mode control will take care of enabling the pin's
1453          * input/output buffers as needed.
1454          */
1455         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1456         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1457         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1458
1459         /* Mute capture amp left and right */
1460         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1461
1462         /* Set ADC connection select to match default mixer setting (mic1
1463          * pin)
1464          */
1465         {0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
1466
1467         /* Mute all inputs to mixer widget (even unconnected ones) */
1468         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
1469         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
1470         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
1471         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
1472         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1473         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
1474         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
1475         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
1476
1477         { }
1478 };
1479 #endif
1480
1481
1482 /* initialize jack-sensing, too */
1483 static int cxt5047_hp_init(struct hda_codec *codec)
1484 {
1485         conexant_init(codec);
1486         cxt5047_hp_automute(codec);
1487         return 0;
1488 }
1489
1490
1491 enum {
1492         CXT5047_LAPTOP,         /* Laptops w/o EAPD support */
1493         CXT5047_LAPTOP_HP,      /* Some HP laptops */
1494         CXT5047_LAPTOP_EAPD,    /* Laptops with EAPD support */
1495 #ifdef CONFIG_SND_DEBUG
1496         CXT5047_TEST,
1497 #endif
1498         CXT5047_MODELS
1499 };
1500
1501 static const char *cxt5047_models[CXT5047_MODELS] = {
1502         [CXT5047_LAPTOP]        = "laptop",
1503         [CXT5047_LAPTOP_HP]     = "laptop-hp",
1504         [CXT5047_LAPTOP_EAPD]   = "laptop-eapd",
1505 #ifdef CONFIG_SND_DEBUG
1506         [CXT5047_TEST]          = "test",
1507 #endif
1508 };
1509
1510 static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1511         SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
1512         SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1513                            CXT5047_LAPTOP),
1514         SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
1515         {}
1516 };
1517
1518 static int patch_cxt5047(struct hda_codec *codec)
1519 {
1520         struct conexant_spec *spec;
1521         int board_config;
1522
1523         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1524         if (!spec)
1525                 return -ENOMEM;
1526         codec->spec = spec;
1527         codec->pin_amp_workaround = 1;
1528
1529         spec->multiout.max_channels = 2;
1530         spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
1531         spec->multiout.dac_nids = cxt5047_dac_nids;
1532         spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
1533         spec->num_adc_nids = 1;
1534         spec->adc_nids = cxt5047_adc_nids;
1535         spec->capsrc_nids = cxt5047_capsrc_nids;
1536         spec->num_mixers = 1;
1537         spec->mixers[0] = cxt5047_base_mixers;
1538         spec->num_init_verbs = 1;
1539         spec->init_verbs[0] = cxt5047_init_verbs;
1540         spec->spdif_route = 0;
1541         spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
1542         spec->channel_mode = cxt5047_modes,
1543
1544         codec->patch_ops = conexant_patch_ops;
1545
1546         board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1547                                                   cxt5047_models,
1548                                                   cxt5047_cfg_tbl);
1549         switch (board_config) {
1550         case CXT5047_LAPTOP:
1551                 spec->num_mixers = 2;
1552                 spec->mixers[1] = cxt5047_hp_spk_mixers;
1553                 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1554                 break;
1555         case CXT5047_LAPTOP_HP:
1556                 spec->num_mixers = 2;
1557                 spec->mixers[1] = cxt5047_hp_only_mixers;
1558                 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1559                 codec->patch_ops.init = cxt5047_hp_init;
1560                 break;
1561         case CXT5047_LAPTOP_EAPD:
1562                 spec->input_mux = &cxt5047_toshiba_capture_source;
1563                 spec->num_mixers = 2;
1564                 spec->mixers[1] = cxt5047_hp_spk_mixers;
1565                 spec->num_init_verbs = 2;
1566                 spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
1567                 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1568                 break;
1569 #ifdef CONFIG_SND_DEBUG
1570         case CXT5047_TEST:
1571                 spec->input_mux = &cxt5047_test_capture_source;
1572                 spec->mixers[0] = cxt5047_test_mixer;
1573                 spec->init_verbs[0] = cxt5047_test_init_verbs;
1574                 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1575 #endif  
1576         }
1577         spec->vmaster_nid = 0x13;
1578         return 0;
1579 }
1580
1581 /* Conexant 5051 specific */
1582 static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1583 static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
1584
1585 static struct hda_channel_mode cxt5051_modes[1] = {
1586         { 2, NULL },
1587 };
1588
1589 static void cxt5051_update_speaker(struct hda_codec *codec)
1590 {
1591         struct conexant_spec *spec = codec->spec;
1592         unsigned int pinctl;
1593         pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1594         snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1595                             pinctl);
1596 }
1597
1598 /* turn on/off EAPD (+ mute HP) as a master switch */
1599 static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1600                                     struct snd_ctl_elem_value *ucontrol)
1601 {
1602         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1603
1604         if (!cxt_eapd_put(kcontrol, ucontrol))
1605                 return 0;
1606         cxt5051_update_speaker(codec);
1607         return 1;
1608 }
1609
1610 /* toggle input of built-in and mic jack appropriately */
1611 static void cxt5051_portb_automic(struct hda_codec *codec)
1612 {
1613         struct conexant_spec *spec = codec->spec;
1614         unsigned int present;
1615
1616         if (spec->no_auto_mic)
1617                 return;
1618         present = snd_hda_jack_detect(codec, 0x17);
1619         snd_hda_codec_write(codec, 0x14, 0,
1620                             AC_VERB_SET_CONNECT_SEL,
1621                             present ? 0x01 : 0x00);
1622 }
1623
1624 /* switch the current ADC according to the jack state */
1625 static void cxt5051_portc_automic(struct hda_codec *codec)
1626 {
1627         struct conexant_spec *spec = codec->spec;
1628         unsigned int present;
1629         hda_nid_t new_adc;
1630
1631         if (spec->no_auto_mic)
1632                 return;
1633         present = snd_hda_jack_detect(codec, 0x18);
1634         if (present)
1635                 spec->cur_adc_idx = 1;
1636         else
1637                 spec->cur_adc_idx = 0;
1638         new_adc = spec->adc_nids[spec->cur_adc_idx];
1639         if (spec->cur_adc && spec->cur_adc != new_adc) {
1640                 /* stream is running, let's swap the current ADC */
1641                 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
1642                 spec->cur_adc = new_adc;
1643                 snd_hda_codec_setup_stream(codec, new_adc,
1644                                            spec->cur_adc_stream_tag, 0,
1645                                            spec->cur_adc_format);
1646         }
1647 }
1648
1649 /* mute internal speaker if HP is plugged */
1650 static void cxt5051_hp_automute(struct hda_codec *codec)
1651 {
1652         struct conexant_spec *spec = codec->spec;
1653
1654         spec->hp_present = snd_hda_jack_detect(codec, 0x16);
1655         cxt5051_update_speaker(codec);
1656 }
1657
1658 /* unsolicited event for HP jack sensing */
1659 static void cxt5051_hp_unsol_event(struct hda_codec *codec,
1660                                    unsigned int res)
1661 {
1662         int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
1663         switch (res >> 26) {
1664         case CONEXANT_HP_EVENT:
1665                 cxt5051_hp_automute(codec);
1666                 break;
1667         case CXT5051_PORTB_EVENT:
1668                 cxt5051_portb_automic(codec);
1669                 break;
1670         case CXT5051_PORTC_EVENT:
1671                 cxt5051_portc_automic(codec);
1672                 break;
1673         }
1674         conexant_report_jack(codec, nid);
1675 }
1676
1677 static struct snd_kcontrol_new cxt5051_mixers[] = {
1678         HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1679         HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1680         HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT),
1681         HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT),
1682         HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
1683         HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
1684         HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1685         {
1686                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1687                 .name = "Master Playback Switch",
1688                 .info = cxt_eapd_info,
1689                 .get = cxt_eapd_get,
1690                 .put = cxt5051_hp_master_sw_put,
1691                 .private_value = 0x1a,
1692         },
1693
1694         {}
1695 };
1696
1697 static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
1698         HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1699         HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1700         HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT),
1701         HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT),
1702         HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1703         {
1704                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1705                 .name = "Master Playback Switch",
1706                 .info = cxt_eapd_info,
1707                 .get = cxt_eapd_get,
1708                 .put = cxt5051_hp_master_sw_put,
1709                 .private_value = 0x1a,
1710         },
1711
1712         {}
1713 };
1714
1715 static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
1716         HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT),
1717         HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT),
1718         HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1719         {
1720                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1721                 .name = "Master Playback Switch",
1722                 .info = cxt_eapd_info,
1723                 .get = cxt_eapd_get,
1724                 .put = cxt5051_hp_master_sw_put,
1725                 .private_value = 0x1a,
1726         },
1727
1728         {}
1729 };
1730
1731 static struct hda_verb cxt5051_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_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1736         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1737         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1738         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1739         /* SPK  */
1740         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1741         {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1742         /* HP, Amp  */
1743         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1744         {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1745         /* DAC1 */      
1746         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1747         /* Record selector: Int mic */
1748         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1749         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1750         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1751         /* SPDIF route: PCM */
1752         {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1753         /* EAPD */
1754         {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 
1755         {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1756         {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1757         {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
1758         { } /* end */
1759 };
1760
1761 static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1762         /* Line in, Mic */
1763         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1764         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1765         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1766         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
1767         /* SPK  */
1768         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1769         {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1770         /* HP, Amp  */
1771         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1772         {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1773         /* DAC1 */
1774         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1775         /* Record selector: Int mic */
1776         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1777         {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1778         /* SPDIF route: PCM */
1779         {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1780         /* EAPD */
1781         {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1782         {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1783         {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1784         { } /* end */
1785 };
1786
1787 static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1788         /* Line in, Mic */
1789         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1790         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1791         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1792         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1793         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1794         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1795         /* SPK  */
1796         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1797         {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
1798         /* HP, Amp  */
1799         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1800         {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1801         /* Docking HP */
1802         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1803         {0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
1804         /* DAC1 */
1805         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1806         /* Record selector: Int mic */
1807         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1808         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1809         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1810         /* SPDIF route: PCM */
1811         {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1812         /* EAPD */
1813         {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
1814         {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1815         {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
1816         {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
1817         {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
1818         { } /* end */
1819 };
1820
1821 /* initialize jack-sensing, too */
1822 static int cxt5051_init(struct hda_codec *codec)
1823 {
1824         conexant_init(codec);
1825         conexant_init_jacks(codec);
1826         if (codec->patch_ops.unsol_event) {
1827                 cxt5051_hp_automute(codec);
1828                 cxt5051_portb_automic(codec);
1829                 cxt5051_portc_automic(codec);
1830         }
1831         return 0;
1832 }
1833
1834
1835 enum {
1836         CXT5051_LAPTOP,  /* Laptops w/ EAPD support */
1837         CXT5051_HP,     /* no docking */
1838         CXT5051_HP_DV6736,      /* HP without mic switch */
1839         CXT5051_LENOVO_X200,    /* Lenovo X200 laptop */
1840         CXT5051_MODELS
1841 };
1842
1843 static const char *cxt5051_models[CXT5051_MODELS] = {
1844         [CXT5051_LAPTOP]        = "laptop",
1845         [CXT5051_HP]            = "hp",
1846         [CXT5051_HP_DV6736]     = "hp-dv6736",
1847         [CXT5051_LENOVO_X200]   = "lenovo-x200",
1848 };
1849
1850 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1851         SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
1852         SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
1853         SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
1854                       CXT5051_LAPTOP),
1855         SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1856         SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
1857         {}
1858 };
1859
1860 static int patch_cxt5051(struct hda_codec *codec)
1861 {
1862         struct conexant_spec *spec;
1863         int board_config;
1864
1865         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1866         if (!spec)
1867                 return -ENOMEM;
1868         codec->spec = spec;
1869         codec->pin_amp_workaround = 1;
1870
1871         codec->patch_ops = conexant_patch_ops;
1872         codec->patch_ops.init = cxt5051_init;
1873
1874         spec->multiout.max_channels = 2;
1875         spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids);
1876         spec->multiout.dac_nids = cxt5051_dac_nids;
1877         spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
1878         spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
1879         spec->adc_nids = cxt5051_adc_nids;
1880         spec->num_mixers = 1;
1881         spec->mixers[0] = cxt5051_mixers;
1882         spec->num_init_verbs = 1;
1883         spec->init_verbs[0] = cxt5051_init_verbs;
1884         spec->spdif_route = 0;
1885         spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes);
1886         spec->channel_mode = cxt5051_modes;
1887         spec->cur_adc = 0;
1888         spec->cur_adc_idx = 0;
1889
1890         codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1891
1892         board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
1893                                                   cxt5051_models,
1894                                                   cxt5051_cfg_tbl);
1895         switch (board_config) {
1896         case CXT5051_HP:
1897                 spec->mixers[0] = cxt5051_hp_mixers;
1898                 break;
1899         case CXT5051_HP_DV6736:
1900                 spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
1901                 spec->mixers[0] = cxt5051_hp_dv6736_mixers;
1902                 spec->no_auto_mic = 1;
1903                 break;
1904         case CXT5051_LENOVO_X200:
1905                 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
1906                 break;
1907         }
1908
1909         return 0;
1910 }
1911
1912 /* Conexant 5066 specific */
1913
1914 static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
1915 static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
1916 static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
1917 #define CXT5066_SPDIF_OUT       0x21
1918
1919 /* OLPC's microphone port is DC coupled for use with external sensors,
1920  * therefore we use a 50% mic bias in order to center the input signal with
1921  * the DC input range of the codec. */
1922 #define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
1923
1924 static struct hda_channel_mode cxt5066_modes[1] = {
1925         { 2, NULL },
1926 };
1927
1928 static void cxt5066_update_speaker(struct hda_codec *codec)
1929 {
1930         struct conexant_spec *spec = codec->spec;
1931         unsigned int pinctl;
1932
1933         snd_printdd("CXT5066: update speaker, hp_present=%d\n",
1934                 spec->hp_present);
1935
1936         /* Port A (HP) */
1937         pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
1938         snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1939                         pinctl);
1940
1941         /* Port D (HP/LO) */
1942         pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
1943                 ? spec->port_d_mode : 0;
1944         snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1945                         pinctl);
1946
1947         /* CLASS_D AMP */
1948         pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1949         snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1950                         pinctl);
1951
1952         if (spec->dell_automute) {
1953                 /* DELL AIO Port Rule: PortA > PortD > IntSpk */
1954                 pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
1955                         ? PIN_OUT : 0;
1956                 snd_hda_codec_write(codec, 0x1c, 0,
1957                         AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
1958         }
1959 }
1960
1961 /* turn on/off EAPD (+ mute HP) as a master switch */
1962 static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1963                                     struct snd_ctl_elem_value *ucontrol)
1964 {
1965         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1966
1967         if (!cxt_eapd_put(kcontrol, ucontrol))
1968                 return 0;
1969
1970         cxt5066_update_speaker(codec);
1971         return 1;
1972 }
1973
1974 /* toggle input of built-in and mic jack appropriately */
1975 static void cxt5066_automic(struct hda_codec *codec)
1976 {
1977         struct conexant_spec *spec = codec->spec;
1978         struct hda_verb ext_mic_present[] = {
1979                 /* enable external mic, port B */
1980                 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
1981
1982                 /* switch to external mic input */
1983                 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
1984
1985                 /* disable internal mic, port C */
1986                 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
1987                 {}
1988         };
1989         static struct hda_verb ext_mic_absent[] = {
1990                 /* enable internal mic, port C */
1991                 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1992
1993                 /* switch to internal mic input */
1994                 {0x17, AC_VERB_SET_CONNECT_SEL, 1},
1995
1996                 /* disable external mic, port B */
1997                 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
1998                 {}
1999         };
2000         unsigned int present;
2001
2002         present = snd_hda_jack_detect(codec, 0x1a);
2003         if (present) {
2004                 snd_printdd("CXT5066: external microphone detected\n");
2005                 snd_hda_sequence_write(codec, ext_mic_present);
2006         } else {
2007                 snd_printdd("CXT5066: external microphone absent\n");
2008                 snd_hda_sequence_write(codec, ext_mic_absent);
2009         }
2010 }
2011
2012 /* toggle input of built-in digital mic and mic jack appropriately */
2013 static void cxt5066_vostro_automic(struct hda_codec *codec)
2014 {
2015         struct conexant_spec *spec = codec->spec;
2016         unsigned int present;
2017
2018         struct hda_verb ext_mic_present[] = {
2019                 /* enable external mic, port B */
2020                 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias},
2021
2022                 /* switch to external mic input */
2023                 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2024                 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2025
2026                 /* disable internal digital mic */
2027                 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2028                 {}
2029         };
2030         static struct hda_verb ext_mic_absent[] = {
2031                 /* enable internal mic, port C */
2032                 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2033
2034                 /* switch to internal mic input */
2035                 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2036
2037                 /* disable external mic, port B */
2038                 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2039                 {}
2040         };
2041
2042         present = snd_hda_jack_detect(codec, 0x1a);
2043         if (present) {
2044                 snd_printdd("CXT5066: external microphone detected\n");
2045                 snd_hda_sequence_write(codec, ext_mic_present);
2046         } else {
2047                 snd_printdd("CXT5066: external microphone absent\n");
2048                 snd_hda_sequence_write(codec, ext_mic_absent);
2049         }
2050 }
2051
2052 /* mute internal speaker if HP is plugged */
2053 static void cxt5066_hp_automute(struct hda_codec *codec)
2054 {
2055         struct conexant_spec *spec = codec->spec;
2056         unsigned int portA, portD;
2057
2058         /* Port A */
2059         portA = snd_hda_jack_detect(codec, 0x19);
2060
2061         /* Port D */
2062         portD = snd_hda_jack_detect(codec, 0x1c);
2063
2064         spec->hp_present = !!(portA | portD);
2065         snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2066                 portA, portD, spec->hp_present);
2067         cxt5066_update_speaker(codec);
2068 }
2069
2070 /* unsolicited event for jack sensing */
2071 static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2072 {
2073         snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2074         switch (res >> 26) {
2075         case CONEXANT_HP_EVENT:
2076                 cxt5066_hp_automute(codec);
2077                 break;
2078         case CONEXANT_MIC_EVENT:
2079                 cxt5066_automic(codec);
2080                 break;
2081         }
2082 }
2083
2084 /* unsolicited event for jack sensing */
2085 static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2086 {
2087         snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2088         switch (res >> 26) {
2089         case CONEXANT_HP_EVENT:
2090                 cxt5066_hp_automute(codec);
2091                 break;
2092         case CONEXANT_MIC_EVENT:
2093                 cxt5066_vostro_automic(codec);
2094                 break;
2095         }
2096 }
2097
2098 static const struct hda_input_mux cxt5066_analog_mic_boost = {
2099         .num_items = 5,
2100         .items = {
2101                 { "0dB",  0 },
2102                 { "10dB", 1 },
2103                 { "20dB", 2 },
2104                 { "30dB", 3 },
2105                 { "40dB", 4 },
2106         },
2107 };
2108
2109 static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
2110                                            struct snd_ctl_elem_info *uinfo)
2111 {
2112         return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
2113 }
2114
2115 static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2116                                           struct snd_ctl_elem_value *ucontrol)
2117 {
2118         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2119         int val;
2120
2121         val = snd_hda_codec_read(codec, 0x17, 0,
2122                 AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT);
2123
2124         ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
2125         return 0;
2126 }
2127
2128 static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2129                                           struct snd_ctl_elem_value *ucontrol)
2130 {
2131         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2132         const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2133         unsigned int idx;
2134
2135         if (!imux->num_items)
2136                 return 0;
2137         idx = ucontrol->value.enumerated.item[0];
2138         if (idx >= imux->num_items)
2139                 idx = imux->num_items - 1;
2140
2141         snd_hda_codec_write_cache(codec, 0x17, 0,
2142                 AC_VERB_SET_AMP_GAIN_MUTE,
2143                 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
2144                         imux->items[idx].index);
2145
2146         return 1;
2147 }
2148
2149 static struct hda_input_mux cxt5066_capture_source = {
2150         .num_items = 4,
2151         .items = {
2152                 { "Mic B", 0 },
2153                 { "Mic C", 1 },
2154                 { "Mic E", 2 },
2155                 { "Mic F", 3 },
2156         },
2157 };
2158
2159 static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2160         .ops = &snd_hda_bind_vol,
2161         .values = {
2162                 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2163                 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2164                 0
2165         },
2166 };
2167
2168 static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2169         .ops = &snd_hda_bind_sw,
2170         .values = {
2171                 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2172                 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2173                 0
2174         },
2175 };
2176
2177 static struct snd_kcontrol_new cxt5066_mixer_master[] = {
2178         HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
2179         {}
2180 };
2181
2182 static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2183         {
2184                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2185                 .name = "Master Playback Volume",
2186                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2187                                   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2188                                   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
2189                 .info = snd_hda_mixer_amp_volume_info,
2190                 .get = snd_hda_mixer_amp_volume_get,
2191                 .put = snd_hda_mixer_amp_volume_put,
2192                 .tlv = { .c = snd_hda_mixer_amp_tlv },
2193                 /* offset by 28 volume steps to limit minimum gain to -46dB */
2194                 .private_value =
2195                         HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28),
2196         },
2197         {}
2198 };
2199
2200 static struct snd_kcontrol_new cxt5066_mixers[] = {
2201         {
2202                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2203                 .name = "Master Playback Switch",
2204                 .info = cxt_eapd_info,
2205                 .get = cxt_eapd_get,
2206                 .put = cxt5066_hp_master_sw_put,
2207                 .private_value = 0x1d,
2208         },
2209
2210         {
2211                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2212                 .name = "Analog Mic Boost Capture Enum",
2213                 .info = cxt5066_mic_boost_mux_enum_info,
2214                 .get = cxt5066_mic_boost_mux_enum_get,
2215                 .put = cxt5066_mic_boost_mux_enum_put,
2216         },
2217
2218         HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
2219         HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
2220         {}
2221 };
2222
2223 static struct hda_verb cxt5066_init_verbs[] = {
2224         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2225         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2226         {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2227         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2228
2229         /* Speakers  */
2230         {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2231         {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2232
2233         /* HP, Amp  */
2234         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2235         {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2236
2237         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2238         {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2239
2240         /* DAC1 */
2241         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2242
2243         /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2244         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2245         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2246         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2247         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2248         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2249
2250         /* no digital microphone support yet */
2251         {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2252
2253         /* Audio input selector */
2254         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2255
2256         /* SPDIF route: PCM */
2257         {0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2258         {0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2259
2260         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2261         {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2262
2263         /* EAPD */
2264         {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2265
2266         /* not handling these yet */
2267         {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2268         {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2269         {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2270         {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2271         {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2272         {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2273         {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2274         {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2275         { } /* end */
2276 };
2277
2278 static struct hda_verb cxt5066_init_verbs_olpc[] = {
2279         /* Port A: headphones */
2280         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2281         {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2282
2283         /* Port B: external microphone */
2284         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, CXT5066_OLPC_EXT_MIC_BIAS},
2285
2286         /* Port C: internal microphone */
2287         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2288
2289         /* Port D: unused */
2290         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2291
2292         /* Port E: unused, but has primary EAPD */
2293         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2294         {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2295
2296         /* Port F: unused */
2297         {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2298
2299         /* Port G: internal speakers */
2300         {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2301         {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2302
2303         /* DAC1 */
2304         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2305
2306         /* DAC2: unused */
2307         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2308
2309         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2310         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2311         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2312         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2313         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2314         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2315         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2316         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2317         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2318         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2319         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2320         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2321
2322         /* Disable digital microphone port */
2323         {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2324
2325         /* Audio input selectors */
2326         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2327         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2328
2329         /* Disable SPDIF */
2330         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2331         {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2332
2333         /* enable unsolicited events for Port A and B */
2334         {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2335         {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2336         { } /* end */
2337 };
2338
2339 static struct hda_verb cxt5066_init_verbs_vostro[] = {
2340         /* Port A: headphones */
2341         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2342         {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2343
2344         /* Port B: external microphone */
2345         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2346
2347         /* Port C: unused */
2348         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2349
2350         /* Port D: unused */
2351         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2352
2353         /* Port E: unused, but has primary EAPD */
2354         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2355         {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2356
2357         /* Port F: unused */
2358         {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2359
2360         /* Port G: internal speakers */
2361         {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2362         {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2363
2364         /* DAC1 */
2365         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2366
2367         /* DAC2: unused */
2368         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2369
2370         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2371         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2372         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2373         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2374         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2375         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2376         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2377         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2378         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2379         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2380         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2381         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2382
2383         /* Digital microphone port */
2384         {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2385
2386         /* Audio input selectors */
2387         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2388         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2389
2390         /* Disable SPDIF */
2391         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2392         {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2393
2394         /* enable unsolicited events for Port A and B */
2395         {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2396         {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2397         { } /* end */
2398 };
2399
2400 static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2401         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2402         { } /* end */
2403 };
2404
2405 /* initialize jack-sensing, too */
2406 static int cxt5066_init(struct hda_codec *codec)
2407 {
2408         snd_printdd("CXT5066: init\n");
2409         conexant_init(codec);
2410         if (codec->patch_ops.unsol_event) {
2411                 cxt5066_hp_automute(codec);
2412                 cxt5066_automic(codec);
2413         }
2414         return 0;
2415 }
2416
2417 enum {
2418         CXT5066_LAPTOP,                 /* Laptops w/ EAPD support */
2419         CXT5066_DELL_LAPTOP,    /* Dell Laptop */
2420         CXT5066_OLPC_XO_1_5,    /* OLPC XO 1.5 */
2421         CXT5066_DELL_VOSTO,     /* Dell Vostro 1015i */
2422         CXT5066_MODELS
2423 };
2424
2425 static const char *cxt5066_models[CXT5066_MODELS] = {
2426         [CXT5066_LAPTOP]                = "laptop",
2427         [CXT5066_DELL_LAPTOP]   = "dell-laptop",
2428         [CXT5066_OLPC_XO_1_5]   = "olpc-xo-1_5",
2429         [CXT5066_DELL_VOSTO]    = "dell-vostro"
2430 };
2431
2432 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2433         SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
2434                       CXT5066_LAPTOP),
2435         SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2436                       CXT5066_DELL_LAPTOP),
2437         SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
2438         SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
2439         {}
2440 };
2441
2442 static int patch_cxt5066(struct hda_codec *codec)
2443 {
2444         struct conexant_spec *spec;
2445         int board_config;
2446
2447         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2448         if (!spec)
2449                 return -ENOMEM;
2450         codec->spec = spec;
2451
2452         codec->patch_ops = conexant_patch_ops;
2453         codec->patch_ops.init = cxt5066_init;
2454
2455         spec->dell_automute = 0;
2456         spec->multiout.max_channels = 2;
2457         spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
2458         spec->multiout.dac_nids = cxt5066_dac_nids;
2459         spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT;
2460         spec->num_adc_nids = 1;
2461         spec->adc_nids = cxt5066_adc_nids;
2462         spec->capsrc_nids = cxt5066_capsrc_nids;
2463         spec->input_mux = &cxt5066_capture_source;
2464
2465         spec->port_d_mode = PIN_HP;
2466         spec->ext_mic_bias = PIN_VREF80;
2467
2468         spec->num_init_verbs = 1;
2469         spec->init_verbs[0] = cxt5066_init_verbs;
2470         spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
2471         spec->channel_mode = cxt5066_modes;
2472         spec->cur_adc = 0;
2473         spec->cur_adc_idx = 0;
2474
2475         board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
2476                                                   cxt5066_models, cxt5066_cfg_tbl);
2477         switch (board_config) {
2478         default:
2479         case CXT5066_LAPTOP:
2480                 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2481                 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2482                 break;
2483         case CXT5066_DELL_LAPTOP:
2484                 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2485                 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2486
2487                 spec->port_d_mode = PIN_OUT;
2488                 spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
2489                 spec->num_init_verbs++;
2490                 spec->dell_automute = 1;
2491                 break;
2492         case CXT5066_OLPC_XO_1_5:
2493                 codec->patch_ops.unsol_event = cxt5066_unsol_event;
2494                 spec->init_verbs[0] = cxt5066_init_verbs_olpc;
2495                 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2496                 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2497                 spec->port_d_mode = 0;
2498                 spec->ext_mic_bias = CXT5066_OLPC_EXT_MIC_BIAS;
2499
2500                 /* no S/PDIF out */
2501                 spec->multiout.dig_out_nid = 0;
2502
2503                 /* input source automatically selected */
2504                 spec->input_mux = NULL;
2505                 break;
2506         case CXT5066_DELL_VOSTO:
2507                 codec->patch_ops.unsol_event = cxt5066_vostro_event;
2508                 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
2509                 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2510                 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2511                 spec->port_d_mode = 0;
2512
2513                 /* no S/PDIF out */
2514                 spec->multiout.dig_out_nid = 0;
2515
2516                 /* input source automatically selected */
2517                 spec->input_mux = NULL;
2518                 break;
2519         }
2520
2521         return 0;
2522 }
2523
2524 /*
2525  */
2526
2527 static struct hda_codec_preset snd_hda_preset_conexant[] = {
2528         { .id = 0x14f15045, .name = "CX20549 (Venice)",
2529           .patch = patch_cxt5045 },
2530         { .id = 0x14f15047, .name = "CX20551 (Waikiki)",
2531           .patch = patch_cxt5047 },
2532         { .id = 0x14f15051, .name = "CX20561 (Hermosa)",
2533           .patch = patch_cxt5051 },
2534         { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2535           .patch = patch_cxt5066 },
2536         { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2537           .patch = patch_cxt5066 },
2538         {} /* terminator */
2539 };
2540
2541 MODULE_ALIAS("snd-hda-codec-id:14f15045");
2542 MODULE_ALIAS("snd-hda-codec-id:14f15047");
2543 MODULE_ALIAS("snd-hda-codec-id:14f15051");
2544 MODULE_ALIAS("snd-hda-codec-id:14f15066");
2545 MODULE_ALIAS("snd-hda-codec-id:14f15067");
2546
2547 MODULE_LICENSE("GPL");
2548 MODULE_DESCRIPTION("Conexant HD-audio codec");
2549
2550 static struct hda_codec_preset_list conexant_list = {
2551         .preset = snd_hda_preset_conexant,
2552         .owner = THIS_MODULE,
2553 };
2554
2555 static int __init patch_conexant_init(void)
2556 {
2557         return snd_hda_add_codec_preset(&conexant_list);
2558 }
2559
2560 static void __exit patch_conexant_exit(void)
2561 {
2562         snd_hda_delete_codec_preset(&conexant_list);
2563 }
2564
2565 module_init(patch_conexant_init)
2566 module_exit(patch_conexant_exit)